inn-2.6.4/0000755000175200017520000000000014002373703011720 5ustar iuliusiuliusinn-2.6.4/nnrpd/0000755000175200017520000000000014002373701013037 5ustar iuliusiuliusinn-2.6.4/nnrpd/post.h0000644000175200017520000000341314002373703014200 0ustar iuliusiulius/* $Id: post.h 10038 2016-06-01 20:08:10Z iulius $ ** ** NetNews Reading Protocol server. */ typedef enum _HEADERTYPE { HTobs, HTreq, HTstd } HEADERTYPE; typedef struct _HEADER { const char * Name; bool CanSet; HEADERTYPE Type; int Size; char * Value; /* Just after ':' in header. */ char * Body; /* Where actual body begins. */ int Len; /* Body length excluding trailing white spaces. */ } HEADER; #define HDR(_x) (Table[(_x)].Body) #define HDR_SET(_x, _y) \ do { \ Table[(_x)].Body = _y; \ Table[(_x)].Value = _y; \ if (_y == NULL) { \ Table[(_x)].Len = 0; \ } else { \ Table[(_x)].Len = strlen(_y); \ } \ } while (0) #define HDR_CLEAR(_x) \ do { \ Table[(_x)].Body = NULL; \ Table[(_x)].Value = NULL; \ Table[(_x)].Len = 0; \ } while (0) #define HDR__PATH 0 #define HDR__FROM 1 #define HDR__NEWSGROUPS 2 #define HDR__SUBJECT 3 #define HDR__CONTROL 4 #define HDR__FOLLOWUPTO 6 #define HDR__DATE 7 #define HDR__ORGANIZATION 8 #define HDR__LINES 9 #define HDR__SENDER 10 #define HDR__APPROVED 11 #define HDR__DISTRIBUTION 13 #define HDR__EXPIRES 14 #define HDR__MESSAGEID 15 #define HDR__INJECTION_DATE 26 #define HDR__INJECTION_INFO 27 #define HDR__CC 34 #define HDR__BCC 35 #define HDR__TO 36 inn-2.6.4/nnrpd/nnrpd.c0000644000175200017520000013571114002373703014336 0ustar iuliusiulius/* $Id: nnrpd.c 10320 2018-12-29 13:46:28Z iulius $ ** ** NNTP server for readers (NNRP) for InterNetNews. ** ** This server doesn't do any real load-limiting, except for what has ** proven empirically necessary (i.e. look at GRPscandir). */ #include "config.h" #include "portable/alloca.h" #include "clibrary.h" #include "portable/setproctitle.h" #include "portable/socket.h" #include #include #if defined(INN_BSDI_HOST) # include #endif #if HAVE_GETSPNAM # include #endif #include #include "inn/innconf.h" #include "inn/libinn.h" #include "inn/messages.h" #include "inn/network.h" #include "inn/network-innbind.h" #include "inn/newsuser.h" #include "inn/ov.h" #include "inn/version.h" #define MAINLINE #include "nnrpd.h" #include "tls.h" #if defined(HAVE_OPENSSL) extern SSL *tls_conn; #endif #if defined(HAVE_OPENSSL) || defined(HAVE_SASL) bool encryption_layer_on = false; #endif static void Usage(void) __attribute__ ((__noreturn__)); /* ** If we have getloadavg, include the appropriate header file. Otherwise, ** just assume that we always have a load of 0. */ #if HAVE_GETLOADAVG # if HAVE_SYS_LOADAVG_H # include # endif #else static int getloadavg(double loadavg[], int nelem) { int i; for (i = 0; i < nelem && i < 3; i++) loadavg[i] = 0; return i; } #endif #define MAXPATTERNDEFINE 10 #define CMDany -1 typedef struct _CMDENT { const char * Name; void (*Function)(int, char **); bool Needauth; int Minac; int Maxac; bool Stripspaces; const char * Help; } CMDENT; char *ACTIVE = NULL; char *ACTIVETIMES = NULL; char *HISTORY = NULL; char *NEWSGROUPS = NULL; char *NNRPACCESS = NULL; static char *LocalLogFileName = NULL; static char *LocalLogDirName; struct history *History; static double STATstart; static double STATfinish; static char *PushedBack; static sig_atomic_t ChangeTrace; bool DaemonMode = false; bool ForeGroundMode = false; static const char *HostErrorStr; bool GetHostByAddr = true; /* Formerly DO_NNRP_GETHOSTBYADDR. */ const char *NNRPinstance = ""; /* Default values for the syntaxchecks parameter in inn.conf. */ bool laxmid = false; #ifdef DO_PERL bool PerlLoaded = false; #endif #ifdef DO_PYTHON bool PY_use_dynamic = false; #endif static char CMDfetchhelp[] = "[message-ID|number]"; /* ** { command base name, function to call, need authentication, ** min args, max args, strip spaces, help string } */ static CMDENT CMDtable[] = { { "ARTICLE", CMDfetch, true, 1, 2, true, CMDfetchhelp }, /* Parse AUTHINFO in a special way so as to keep white spaces * in usernames and passwords. */ { "AUTHINFO", CMDauthinfo, false, 3, CMDany, false, "USER name|PASS password" #ifdef HAVE_SASL "|SASL mechanism [initial-response]" #endif "|GENERIC program [argument ...]" }, { "BODY", CMDfetch, true, 1, 2, true, CMDfetchhelp }, { "CAPABILITIES", CMDcapabilities,false, 1, 2, true, "[keyword]" }, #if defined(HAVE_ZLIB) { "COMPRESS", CMDcompress, false, 2, 2, true, "DEFLATE" }, #endif { "DATE", CMDdate, false, 1, 1, true, NULL }, { "GROUP", CMDgroup, true, 2, 2, true, "newsgroup" }, { "HDR", CMDpat , true, 2, 3, true, "header [message-ID|range]" }, { "HEAD", CMDfetch, true, 1, 2, true, CMDfetchhelp }, { "HELP", CMDhelp, false, 1, 1, true, NULL }, { "IHAVE", CMDpost, true, 2, 2, true, "message-ID" }, { "LAST", CMDnextlast, true, 1, 1, true, NULL }, { "LIST", CMDlist, true, 1, 3, true, "[ACTIVE [wildmat]|ACTIVE.TIMES [wildmat]|COUNTS [wildmat]|DISTRIB.PATS" "|DISTRIBUTIONS|HEADERS [MSGID|RANGE]|MODERATORS|MOTD|NEWSGROUPS [wildmat]" "|OVERVIEW.FMT|SUBSCRIPTIONS [wildmat]]" }, { "LISTGROUP", CMDgroup, true, 1, 3, true, "[newsgroup [range]]" }, { "MODE", CMDmode, false, 2, 2, true, "READER" }, { "NEWGROUPS", CMDnewgroups, true, 3, 4, true, "[yy]yymmdd hhmmss [GMT]" }, { "NEWNEWS", CMDnewnews, true, 4, 5, true, "wildmat [yy]yymmdd hhmmss [GMT]" }, { "NEXT", CMDnextlast, true, 1, 1, true, NULL }, { "OVER", CMDover, true, 1, 2, true, "[range]" }, { "POST", CMDpost, true, 1, 1, true, NULL }, { "QUIT", CMDquit, false, 1, 1, true, NULL }, /* SLAVE (which was ill-defined in RFC 977) was removed from the NNTP * protocol in RFC 3977. */ { "SLAVE", CMD_unimp, false, 1, 1, true, NULL }, #ifdef HAVE_OPENSSL { "STARTTLS", CMDstarttls, false, 1, 1, true, NULL }, #endif { "STAT", CMDfetch, true, 1, 2, true, CMDfetchhelp }, { "XGTITLE", CMDxgtitle, true, 1, 2, true, "[wildmat]" }, { "XHDR", CMDpat, true, 2, 3, true, "header [message-ID|range]" }, { "XOVER", CMDover, true, 1, 2, true, "[range]" }, { "XPAT", CMDpat, true, 4, CMDany, true, "header message-ID|range pattern [pattern ...]" }, { NULL, CMD_unimp, false, 0, 0, true, NULL } }; static const char *const timer_name[] = { "idle", "newnews", "readart", "checkart", "nntpread", "nntpwrite", }; /* ** Log a summary status message and exit. */ void ExitWithStats(int x, bool readconf) { double usertime; double systime; line_free(&NNTPline); fflush(stdout); STATfinish = TMRnow_double(); if (GetResourceUsage(&usertime, &systime) < 0) { usertime = 0; systime = 0; } GRPreport(); if (ARTcount) syslog(L_NOTICE, "%s exit articles %ld groups %ld", Client.host, ARTcount, GRPcount); if (POSTreceived || POSTrejected) syslog(L_NOTICE, "%s posts received %ld rejected %ld", Client.host, POSTreceived, POSTrejected); syslog(L_NOTICE, "%s times user %.3f system %.3f idle %.3f elapsed %.3f", Client.host, usertime, systime, IDLEtime, STATfinish - STATstart); /* Tracking code - Make entries in the logfile(s) to show that we have * finished with this session. */ if (!readconf && PERMaccessconf && PERMaccessconf->readertrack) { syslog(L_NOTICE, "%s Tracking Disabled (%s)", Client.host, Username); if (LLOGenable) { fprintf(locallog, "%s Tracking Disabled (%s)\n", Client.host, Username); fclose(locallog); syslog(L_NOTICE,"%s Local Logging ends (%s) %s", Client.host, Username, LocalLogFileName); } } if (ARTget) syslog(L_NOTICE, "%s artstats get %ld time %ld size %ld", Client.host, ARTget, ARTgettime, ARTgetsize); if (!readconf && PERMaccessconf && PERMaccessconf->nnrpdoverstats && OVERcount) syslog(L_NOTICE, "%s overstats count %ld hit %ld miss %ld time %ld size %ld dbz %ld seek %ld get %ld artcheck %ld", Client.host, OVERcount, OVERhit, OVERmiss, OVERtime, OVERsize, OVERdbz, OVERseek, OVERget, OVERartcheck); #ifdef HAVE_OPENSSL if (tls_conn) { SSL_shutdown(tls_conn); SSL_free(tls_conn); tls_conn = NULL; } #endif #ifdef HAVE_SASL if (sasl_conn) { sasl_dispose(&sasl_conn); sasl_conn = NULL; sasl_ssf = 0; sasl_maxout = NNTP_MAXLEN_COMMAND; } sasl_done(); #endif /* HAVE_SASL */ #if defined(HAVE_ZLIB) if (compression_layer_on) { inflateEnd(zstream_in); free(zstream_in); free(zbuf_in); deflateEnd(zstream_out); free(zstream_out); free(zbuf_out); } #endif /* HAVE_ZLIB */ if (DaemonMode) { shutdown(STDIN_FILENO, 2); shutdown(STDOUT_FILENO, 2); shutdown(STDERR_FILENO, 2); close(STDIN_FILENO); close(STDOUT_FILENO); close(STDERR_FILENO); } OVclose(); SMshutdown(); #ifdef DO_PYTHON PY_close_python(); #endif /* DO_PYTHON */ if (History) HISclose(History); if (innconf->timer != 0) { TMRsummary(Client.host, timer_name); TMRfree(); } if (LocalLogFileName != NULL) free(LocalLogFileName); closelog(); exit(x); } /* ** The HELP command. */ void CMDhelp(int ac UNUSED, char *av[] UNUSED) { CMDENT *cp; char *p, *q; static const char *newsmaster = NEWSMASTER; Reply("%d Legal commands\r\n", NNTP_INFO_HELP); for (cp = CMDtable; cp->Name; cp++) { if (cp->Function == CMD_unimp) continue; if (cp->Help == NULL) Printf(" %s\r\n", cp->Name); else Printf(" %s %s\r\n", cp->Name, cp->Help); } if (PERMaccessconf && (VirtualPathlen > 0)) { if (PERMaccessconf->newsmaster) { if (strchr(PERMaccessconf->newsmaster, '@') == NULL) { Printf("Report problems to <%s@%s>.\r\n", PERMaccessconf->newsmaster, PERMaccessconf->domain); } else { Printf("Report problems to <%s>.\r\n", PERMaccessconf->newsmaster); } } else { /* Sigh, pickup from newsmaster anyway. */ if ((p = strchr(newsmaster, '@')) == NULL) Printf("Report problems to <%s@%s>.\r\n", newsmaster, PERMaccessconf->domain); else { q = xstrndup(newsmaster, p - newsmaster); Printf("Report problems to <%s@%s>.\r\n", q, PERMaccessconf->domain); free(q); } } } else { if (strchr(newsmaster, '@') == NULL) Printf("Report problems to <%s@%s>.\r\n", newsmaster, innconf->fromhost); else Printf("Report problems to <%s>.\r\n", newsmaster); } Printf(".\r\n"); } /* ** The CAPABILITIES command. ** ** nnrpd does not advertise the MODE-READER capability; only innd may ** advertise it. */ void CMDcapabilities(int ac, char *av[]) { if (ac == 2 && !IsValidKeyword(av[1])) { Reply("%d Syntax error in keyword\r\n", NNTP_ERR_SYNTAX); return; } Reply("%d Capability list:\r\n", NNTP_INFO_CAPABILITIES); Printf("VERSION 2\r\n"); Printf("IMPLEMENTATION %s\r\n", INN_VERSION_STRING); #ifdef HAVE_SASL const char *mechlist = NULL; /* Check for available SASL mechanisms. * Start the string with a space for the strstr() calls afterwards. */ sasl_listmech(sasl_conn, NULL, " ", " ", "", &mechlist, NULL, NULL); #endif /* The client is not already authenticated. */ if ((!PERMauthorized || PERMneedauth || PERMcanauthenticate)) { Printf("AUTHINFO"); /* No arguments if the server does not permit any authentication * commands in its current state (either a compression layer other * than the one negotiated along with TLS is active, or the user * has no way to authenticate successfully). */ if ( #if defined(HAVE_ZLIB) (!compression_layer_on || tls_compression_on) && #endif /* HAVE_ZLIB */ PERMcanauthenticate) { #ifdef HAVE_OPENSSL if (PERMcanauthenticatewithoutSSL || encryption_layer_on) { #endif /* AUTHINFO USER is advertised only if a TLS layer is active, * if compiled with TLS support. */ Printf(" USER"); #ifdef HAVE_OPENSSL } else { # ifdef HAVE_SASL /* Remove unsecure PLAIN, LOGIN and EXTERNAL SASL mechanisms, * if compiled with TLS support and a TLS layer is not active. */ if (mechlist != NULL) { char *p; if ((p = strstr(mechlist, " PLAIN")) != NULL && (p[6] == '\0' || p[6] == ' ')) { memmove(p, p+6, strlen(p)-5); } if ((p = strstr(mechlist, " LOGIN")) != NULL && (p[6] == '\0' || p[6] == ' ')) { memmove(p, p+6, strlen(p)-5); } if ((p = strstr(mechlist, " EXTERNAL")) != NULL && (p[9] == '\0' || p[9] == ' ')) { memmove(p, p+9, strlen(p)-8); } } # endif /* HAVE_SASL */ } #endif /* HAVE_OPENSSL */ #ifdef HAVE_SASL /* Check whether at least one SASL mechanism is available. */ if (mechlist != NULL && strlen(mechlist) > 2) { Printf(" SASL"); } #endif } Printf("\r\n"); } #if defined(HAVE_ZLIB) /* A compression layer is not active. */ if (!compression_layer_on) { Printf("COMPRESS DEFLATE\r\n"); } #endif /* HAVE_ZLIB */ if (PERMcanread) { Printf("HDR\r\n"); } if (PERMaccessconf->allowihave && PERMcanpost) { Printf("IHAVE\r\n"); } Printf("LIST ACTIVE ACTIVE.TIMES COUNTS DISTRIB.PATS DISTRIBUTIONS" " HEADERS MODERATORS MOTD NEWSGROUPS OVERVIEW.FMT SUBSCRIPTIONS\r\n"); if (PERMaccessconf->allownewnews && PERMcanread) { Printf("NEWNEWS\r\n"); } if (PERMcanread) { Printf("OVER\r\n"); } if (PERMcanpost) { Printf("POST\r\n"); } Printf("READER\r\n"); #if defined(HAVE_SASL) /* Check whether at least one SASL mechanism is available. * The SASL capability has to be advertised, even after authentication, * so that the client can detect a possible active down-negotiation * attack. */ if (mechlist != NULL && strlen(mechlist) > 2) { Printf("SASL%s\r\n", mechlist); } #endif /* HAVE_SASL */ #if defined(HAVE_OPENSSL) /* A TLS layer is not active, a compression layer is not active, * and the client is not already authenticated. */ if (!encryption_layer_on # if defined(HAVE_ZLIB) && !compression_layer_on # endif /* HAVE_ZLIB */ && (!PERMauthorized || PERMneedauth || PERMcanauthenticate)) { Printf("STARTTLS\r\n"); } #endif /* HAVE_OPENSSL */ if (PERMcanread) { Printf("XPAT\r\n"); } Printf(".\r\n"); } /* ** Catch-all for unimplemented functions. */ void CMD_unimp(int ac UNUSED, char *av[]) { Reply("%d \"%s\" not implemented; try \"HELP\"\r\n", NNTP_ERR_COMMAND, av[0]); } /* ** The QUIT command. */ void CMDquit(int ac UNUSED, char *av[] UNUSED) { Reply("%d Bye!\r\n", NNTP_OK_QUIT); ExitWithStats(0, false); } /* ** Convert an address to a hostname. Don't trust the reverse lookup ** since anyone can fake reverse DNS entries. */ static bool Address2Name(struct sockaddr *sa, socklen_t len, char *hostname, size_t size) { static const char MISMATCH[] = "reverse lookup validation failed"; struct addrinfo hints, *ai, *host; char *p; int ret; bool valid = false; /* Get the official hostname, store it away. */ ret = getnameinfo(sa, len, hostname, size, NULL, 0, NI_NAMEREQD); if (ret != 0) { HostErrorStr = gai_strerror(ret); return false; } /* Get addresses for this host. */ memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; ret = getaddrinfo(hostname, NULL, &hints, &ai); if (ret != 0) { HostErrorStr = gai_strerror(ret); return false; } /* Make sure one of those addresses is the address we got. */ for (host = ai; host != NULL; host = host->ai_next) if (network_sockaddr_equal(sa, host->ai_addr)) { valid = true; break; } freeaddrinfo(ai); /* Lowercase the returned name since wildmats are case-sensitive. */ if (valid) { for (p = hostname; *p != '\0'; p++) if (isupper((unsigned char) *p)) *p = tolower((unsigned char) *p); return true; } else { HostErrorStr = MISMATCH; return false; } } /* ** Determine hostname and IP of the client, amongst other information. */ static void GetClientInfo(unsigned short port) { static const char *default_host_error = "unknown error"; struct sockaddr_storage ssc, sss; struct sockaddr *sac = (struct sockaddr *) &ssc; struct sockaddr *sas = (struct sockaddr *) &sss; socklen_t length; size_t size; memset(&Client, 0, sizeof(Client)); strlcpy(Client.host, "?", sizeof(Client.host)); /* Get the peer's name. */ length = sizeof(ssc); if (getpeername(STDIN_FILENO, sac, &length) < 0) { if (!isatty(STDIN_FILENO)) { sysnotice("? can't getpeername"); Reply("%d Can't get your name. Goodbye!\r\n", NNTP_ERR_ACCESS); ExitWithStats(1, true); } strlcpy(Client.host, "localhost", sizeof(Client.host)); } else { /* Figure out client's IP address/hostname. */ HostErrorStr = default_host_error; if (!network_sockaddr_sprint(Client.ip, sizeof(Client.ip), sac)) { notice("? can't get client numeric address: %s", HostErrorStr); Reply("%d Can't get your numeric address. Goodbye!\r\n", NNTP_ERR_ACCESS); ExitWithStats(1, true); } if (GetHostByAddr) { HostErrorStr = default_host_error; if (!Address2Name(sac, length, Client.host, sizeof(Client.host))) { notice("? reverse lookup for %s failed: %s -- using IP" " address for access", Client.ip, HostErrorStr); strlcpy(Client.host, Client.ip, sizeof(Client.host)); } } else { strlcpy(Client.host, Client.ip, sizeof(Client.host)); } /* Figure out server's IP address/hostname. */ length = sizeof(sss); if (getsockname(STDIN_FILENO, sas, &length) < 0) { sysnotice("%s can't getsockname", Client.host); Reply("%d Can't figure out where you connected to. Goodbye!\r\n", NNTP_ERR_ACCESS); ExitWithStats(1, true); } HostErrorStr = default_host_error; size = sizeof(Client.serverip); if (!network_sockaddr_sprint(Client.serverip, size, sas)) { notice("? can't get server numeric address: %s", HostErrorStr); Reply("%d Can't get my own numeric address. Goodbye!\r\n", NNTP_ERR_ACCESS); ExitWithStats(1, true); } if (GetHostByAddr) { HostErrorStr = default_host_error; size = sizeof(Client.serverhost); if (!Address2Name(sas, length, Client.serverhost, size)) { notice("? reverse lookup for %s failed: %s -- using IP" " address for access", Client.serverip, HostErrorStr); strlcpy(Client.serverhost, Client.serverip, sizeof(Client.serverhost)); } } else { strlcpy(Client.serverhost, Client.serverip, sizeof(Client.serverhost)); } /* Get port numbers. */ Client.port = network_sockaddr_port(sac); Client.serverport = network_sockaddr_port(sas); } #if defined(INN_BSDI_HOST) /* Setting TCP_NODELAY to nnrpd fixes a problem of slow downloading * of overviews and slow answers on some architectures (like BSD/OS * where TCP delayed acknowledgements are enabled). */ int nodelay = 1; setsockopt(STDIN_FILENO, IPPROTO_TCP, TCP_NODELAY, &nodelay, sizeof(nodelay)); #endif notice("%s (%s) connect - port %u", Client.host, Client.ip, port); } /* ** Write a buffer, via compression layer and/or SASL security layer ** and/or TLS if necessary. */ void write_buffer(const char *buff, ssize_t len) { const char *p; ssize_t n; TMRstart(TMR_NNTPWRITE); p = buff; #if defined(HAVE_ZLIB) if (compression_layer_on) { int r; zstream_out->next_in = (unsigned char *) p; zstream_out->avail_in = len; zstream_out->next_out = zbuf_out; zstream_out->avail_out = zbuf_out_size; do { /* Grow the output buffer if needed. */ if (zstream_out->avail_out == 0) { size_t newsize = zbuf_out_size * 2; zbuf_out = xrealloc(zbuf_out, newsize); zstream_out->next_out = zbuf_out + zbuf_out_size; zstream_out->avail_out = zbuf_out_size; zbuf_out_size = newsize; } r = deflate(zstream_out, zstream_flush_needed ? Z_PARTIAL_FLUSH : Z_NO_FLUSH); if (!(r == Z_OK || r == Z_BUF_ERROR || r == Z_STREAM_END)) { sysnotice("deflate() failed: %d; %s", r, zstream_out->msg != NULL ? zstream_out->msg : "no detail"); return; } } while (r == Z_OK && zstream_out->avail_out == 0); p = (char *) zbuf_out; len = zbuf_out_size - zstream_out->avail_out; zstream_flush_needed = false; } #endif /* HAVE_ZLIB */ while (len > 0) { const char *out; unsigned outlen; #if defined(HAVE_SASL) if (sasl_conn != NULL && sasl_ssf > 0) { int r; /* Can only encode as much as the client can handle at one time. */ n = (len > sasl_maxout) ? sasl_maxout : len; if ((r = sasl_encode(sasl_conn, p, n, &out, &outlen)) != SASL_OK) { const char *ed = sasl_errdetail(sasl_conn); sysnotice("sasl_encode() failed: %s; %s", sasl_errstring(r, NULL, NULL), ed != NULL ? ed : "no detail"); return; } } else #endif /* HAVE_SASL */ { /* Output the entire unencoded string. */ n = len; out = p; outlen = len; } len -= n; p += n; #ifdef HAVE_OPENSSL if (tls_conn) { int r; Again: r = SSL_write(tls_conn, out, outlen); switch (SSL_get_error(tls_conn, r)) { case SSL_ERROR_NONE: case SSL_ERROR_SYSCALL: break; case SSL_ERROR_WANT_WRITE: goto Again; break; case SSL_ERROR_SSL: SSL_shutdown(tls_conn); tls_conn = NULL; errno = ECONNRESET; break; case SSL_ERROR_ZERO_RETURN: break; } } else #endif /* HAVE_OPENSSL */ do { n = write(STDIN_FILENO, out, outlen); } while (n == -1 && errno == EINTR); } TMRstop(TMR_NNTPWRITE); } /* ** Send formatted output, possibly with debugging output. */ static void __attribute__((__format__(printf, 1, 0))) VPrintf(const char *fmt, va_list args, int dotrace) { char buff[2048], *p; ssize_t len; len = vsnprintf(buff, sizeof(buff), fmt, args); if (len < 0) len = 0; else if ((size_t)len >= sizeof(buff)) len = sizeof(buff) - 1; write_buffer(buff, len); if (dotrace && Tracing) { int oerrno = errno; /* Copy output, but strip trailing CR-LF. Note we're assuming here * that no output line can ever be longer than 2045 characters. */ p = buff + strlen(buff) - 1; while (p >= buff && (*p == '\n' || *p == '\r')) *p-- = '\0'; syslog(L_TRACE, "%s > %s", Client.host, buff); errno = oerrno; } } /* ** Send a reply, possibly with debugging output. ** Reply() is used for answers which can possibly be traced (response codes). ** Printf() is used in other cases. */ void Reply(const char *fmt, ...) { va_list args; #if defined(HAVE_ZLIB) /* For single-line responses, immediately flush the output stream. */ zstream_flush_needed = true; #endif /* HAVE_ZLIB */ va_start(args, fmt); VPrintf(fmt, args, 1); va_end(args); } void Printf(const char *fmt, ...) { va_list args; #if defined(HAVE_ZLIB) /* Last line of a multi-line data block response. * Time to flush the compressed output stream. * Check that only when the compression layer is active. */ if (compression_layer_on && strlen(fmt) == 3 && strcasecmp(fmt, ".\r\n") == 0) { zstream_flush_needed = true; } #endif /* HAVE_ZLIB */ va_start(args, fmt); VPrintf(fmt, args, 0); va_end(args); } #ifdef HAVE_SIGACTION #define NO_SIGACTION_UNUSED UNUSED #else #define NO_SIGACTION_UNUSED #endif /* ** Got a signal; toggle tracing. */ static void ToggleTrace(int s NO_SIGACTION_UNUSED) { ChangeTrace = true; #ifndef HAVE_SIGACTION xsignal(s, ToggleTrace); #endif } /* ** Got a SIGPIPE; exit cleanly. */ static void CatchPipe(int s UNUSED) { ExitWithStats(0, false); } /* ** Got a signal; wait for children. */ static void WaitChild(int s NO_SIGACTION_UNUSED) { int pid; for (;;) { pid = waitpid(-1, NULL, WNOHANG); if (pid <= 0) break; } #ifndef HAVE_SIGACTION xsignal(s, WaitChild); #endif } static void SetupDaemon(void) { bool val; val = true; if (SMsetup(SM_PREOPEN, (void *)&val) && !SMinit()) { syslog(L_NOTICE, "can't initialize storage method, %s", SMerrorstr); Reply("%d NNTP server unavailable. Try later!\r\n", NNTP_FAIL_TERMINATING); ExitWithStats(1, true); } OVextra = overview_extra_fields(false); if (OVextra == NULL) { /* overview_extra_fields() should already have logged something * useful. */ Reply("%d NNTP server unavailable. Try later!\r\n", NNTP_FAIL_TERMINATING); ExitWithStats(1, true); } overhdr_xref = overview_index("Xref", OVextra); if (!OVopen(OV_READ)) { /* This shouldn't really happen. */ syslog(L_NOTICE, "can't open overview %m"); Reply("%d NNTP server unavailable. Try later!\r\n", NNTP_FAIL_TERMINATING); ExitWithStats(1, true); } if (!OVctl(OVCACHEKEEP, &val)) { syslog(L_NOTICE, "can't enable overview cache %m"); Reply("%d NNTP server unavailable. Try later!\r\n", NNTP_FAIL_TERMINATING); ExitWithStats(1, true); } } /* ** Print a usage message and exit. */ static void Usage(void) { fprintf(stderr, "Usage error.\n"); exit(1); } int main(int argc, char *argv[]) { const char *name; CMDENT *cp; char buff[NNTP_MAXLEN_COMMAND]; char **av; int ac; READTYPE r; int i; unsigned int j; char **v; char *Reject; int timeout; unsigned int vid=0; int count=123456789; struct timeval tv; unsigned short ListenPort = NNTP_PORT; char *ListenAddr = NULL; char *ListenAddr6 = NULL; int *lfds; fd_set lfdset, lfdsetread; unsigned int lfdcount; int lfdreadcount; bool lfdokay; int lfdmax = 0; int fd = -1; pid_t pid = -1; FILE *pidfile; int clienttimeout; char *ConfFile = NULL; char *path; bool validcommandtoolong; int respawn = 0; setproctitle_init(argc, argv); /* Parse arguments. Must xstrdup() optarg if used because setproctitle * may clobber it! */ Reject = NULL; LLOGenable = false; GRPcur = NULL; MaxBytesPerSecond = 0; strlcpy(Username, "unknown", sizeof(Username)); /* Set up the pathname, first thing, and teach our error handlers about * the name of the program. */ name = argv[0]; if (name == NULL || *name == '\0') name = "nnrpd"; else { const char *p; /* We take the last "/" in the path. */ p = strrchr(name, '/'); if (p != NULL) name = p + 1; } message_program_name = xstrdup(name); openlog(message_program_name, L_OPENLOG_FLAGS | LOG_PID, LOG_INN_PROG); message_handlers_die(1, message_log_syslog_crit); message_handlers_warn(1, message_log_syslog_warning); message_handlers_notice(1, message_log_syslog_notice); /* Initialize the character class tables for message-IDs. */ InitializeMessageIDcclass(); if (!innconf_read(NULL)) exit(1); #ifdef HAVE_SASL if (sasl_server_init(sasl_callbacks, "INN") != SASL_OK) { syslog(L_FATAL, "sasl_server_init() failed"); exit(1); } #endif /* HAVE_SASL */ #ifdef HAVE_OPENSSL while ((i = getopt(argc, argv, "4:6:b:c:Dfi:I:nop:P:r:s:St")) != EOF) #else while ((i = getopt(argc, argv, "4:6:b:c:Dfi:I:nop:P:r:s:t")) != EOF) #endif /* HAVE_OPENSSL */ switch (i) { default: Usage(); /* NOTREACHED */ case '4': /* Bind to a certain IPv4 address. */ case 'b': if (ListenAddr != NULL) die("-b and -4 are the same and both may not be given"); ListenAddr = xstrdup(optarg); break; case '6': /* Bind to a certain IPv6 address. */ ListenAddr6 = xstrdup(optarg); break; case 'c': /* Use alternate readers.conf. */ ConfFile = concatpath(innconf->pathetc, optarg); break; case 'D': /* Standalone daemon mode. */ DaemonMode = true; break; case 'P': /* Prespawn count in daemon mode. */ respawn = atoi(optarg); break; case 'f': /* Don't fork on daemon mode. */ ForeGroundMode = true; break; case 'i': /* Initial command. */ PushedBack = xstrdup(optarg); break; case 'I': /* Instance. */ NNRPinstance = xstrdup(optarg); break; case 'n': /* No DNS lookups. */ GetHostByAddr = false; break; case 'o': Offlinepost = true; /* Offline posting only. */ break; case 'p': /* TCP port for daemon mode. */ ListenPort = atoi(optarg); break; case 'r': /* Reject connection message. */ Reject = xstrdup(optarg); break; case 's': /* Unused title string. */ break; case 't': /* Tracing. */ Tracing = true; break; #ifdef HAVE_OPENSSL case 'S': /* Force the negotiation of an encryption layer. */ initialSSL = true; break; #endif /* HAVE_OPENSSL */ } argc -= optind; if (argc) Usage(); /* Make other processes happier if someone is reading. This allows other * processes like overchan to keep up when there are lots of readers. * Note that this is cumulative with nicekids. */ if (innconf->nicennrpd != 0) nice(innconf->nicennrpd); HISTORY = concatpath(innconf->pathdb, INN_PATH_HISTORY); ACTIVE = concatpath(innconf->pathdb, INN_PATH_ACTIVE); ACTIVETIMES = concatpath(innconf->pathdb, INN_PATH_ACTIVETIMES); NEWSGROUPS = concatpath(innconf->pathdb, INN_PATH_NEWSGROUPS); if(ConfFile) NNRPACCESS = ConfFile; else NNRPACCESS = concatpath(innconf->pathetc,INN_PATH_NNRPACCESS); /* Initialize the checks to perform or not on article syntax. */ if ((innconf->syntaxchecks != NULL) && (innconf->syntaxchecks->count > 0)) { for (j = 0; j < innconf->syntaxchecks->count; j++) { if (innconf->syntaxchecks->strings[j] != NULL) { if (strcmp(innconf->syntaxchecks->strings[j], "laxmid") == 0) { laxmid = true; } else if (strcmp(innconf->syntaxchecks->strings[j], "no-laxmid") == 0) { laxmid = false; } else { syslog(L_NOTICE, "Unknown \"%s\" value in syntaxchecks " "parameter in inn.conf", innconf->syntaxchecks->strings[j]); } } } } if (DaemonMode) { /* Allocate an lfds array to hold the file descriptors * for IPv4 and/or IPv6 connections. */ if (ListenAddr == NULL && ListenAddr6 == NULL) { network_innbind_all(SOCK_STREAM, ListenPort, &lfds, &lfdcount); } else { if (ListenAddr != NULL && ListenAddr6 != NULL) lfdcount = 2; else lfdcount = 1; lfds = xmalloc(lfdcount * sizeof(int)); i = 0; if (ListenAddr6 != NULL) { lfds[i++] = network_innbind_ipv6(SOCK_STREAM, ListenAddr6, ListenPort); } if (ListenAddr != NULL) { lfds[i] = network_innbind_ipv4(SOCK_STREAM, ListenAddr, ListenPort); } } /* Bail if we couldn't listen on any sockets. */ lfdokay = false; for (j = 0; j < lfdcount; j++) { if (lfds[j] < 0) continue; lfdokay = true; } if (!lfdokay) die("can't bind to any addresses"); /* If started as root, switch to news uid. Unlike other parts of INN, we * don't die if we can't become the news user. As long as we're not * running as root, everything's fine; it's okay to write the things we * write as a member of the news group. */ if (getuid() == 0) { ensure_news_user_grp(true, true); } /* Detach. */ if (!ForeGroundMode) { daemonize("/"); } if (ListenPort == NNTP_PORT) strlcpy(buff, "nnrpd.pid", sizeof(buff)); else snprintf(buff, sizeof(buff), "nnrpd-%d.pid", ListenPort); path = concatpath(innconf->pathrun, buff); pidfile = fopen(path, "w"); free(path); if (pidfile == NULL) { syslog(L_ERROR, "cannot write %s %m", buff); exit(1); } fprintf(pidfile,"%lu\n", (unsigned long) getpid()); fclose(pidfile); /* Set signal handle to care for dead children. */ if (!respawn) xsignal(SIGCHLD, WaitChild); /* Arrange to toggle tracing. */ xsignal(SIGHUP, ToggleTrace); setproctitle("accepting connections"); /* Initialize the listener file descriptors set. */ FD_ZERO(&lfdset); for (j = 0; j < lfdcount; j++) { if (listen(lfds[j], 128) < 0) { if (j != 0 && errno == EADDRINUSE) continue; syslog(L_ERROR, "can't listen to socket"); } else { /* Remember the largest descriptor number * that is to be tested by select(). */ FD_SET(lfds[j], &lfdset); if (lfdmax < lfds[j]) lfdmax = lfds[j]; } } if (respawn) { /* Pre-forked mode. */ for (;;) { if (respawn > 0) { --respawn; pid = fork(); if (pid == 0) { do { fd = -1; /* Copy the master set because lfdsetread * will be modified. */ lfdsetread = lfdset; lfdreadcount = select(lfdmax + 1, &lfdsetread, NULL, NULL, NULL); if (lfdreadcount > 0) { for (j = 0; j < lfdcount; j++) { if (FD_ISSET(lfds[j], &lfdsetread)) { fd = accept(lfds[j], NULL, NULL); /* Only handle the first match. Future * calls to select() will handle possible * other matches. */ if (fd >= 0) break; } } } } while (fd < 0); break; } } for (;;) { if (respawn == 0) pid = wait(NULL); else pid = waitpid(-1, NULL, WNOHANG); if (pid <= 0) break; ++respawn; } } } else { /* Fork on demand. */ do { fd = -1; /* Copy the master set because lfdsetread will be modified. */ lfdsetread = lfdset; lfdreadcount = select(lfdmax + 1, &lfdsetread, NULL, NULL, NULL); if (lfdreadcount > 0) { for (j = 0; j < lfdcount; j++) { if (FD_ISSET(lfds[j], &lfdsetread)) { fd = accept(lfds[j], NULL, NULL); /* Only handle the first match. Future calls * to select() will handle possible other matches. */ if (fd >= 0) break; } } } if (fd < 0) continue; for (j = 0; j <= innconf->maxforks && (pid = fork()) < 0; j++) { if (j == innconf->maxforks) { syslog(L_FATAL, "can't fork (dropping connection): %m"); continue; } syslog(L_NOTICE, "can't fork (waiting): %m"); sleep(1); } if (ChangeTrace) { Tracing = Tracing ? false : true; syslog(L_TRACE, "trace %sabled", Tracing ? "en" : "dis"); ChangeTrace = false; } if (pid != 0) close(fd); } while (pid != 0); } /* Child process starts here. */ setproctitle("connected"); for (j = 0; j < lfdcount; j++) { close(lfds[j]); } dup2(fd, 0); close(fd); dup2(0, 1); dup2(0, 2); if (innconf->timer != 0) TMRinit(TMR_MAX); STATstart = TMRnow_double(); SetupDaemon(); /* If we are a daemon, innd didn't make us nice, so be nice kids. */ if (innconf->nicekids) { if (nice(innconf->nicekids) < 0) syslog(L_ERROR, "Could not nice child to %ld: %m", innconf->nicekids); } /* Only automatically reap children in the listening process. */ xsignal(SIGCHLD, SIG_DFL); } else { if (innconf->timer != 0) TMRinit(TMR_MAX); STATstart = TMRnow_double(); SetupDaemon(); /* Arrange to toggle tracing. */ xsignal(SIGHUP, ToggleTrace); } /* DaemonMode */ #ifdef HAVE_OPENSSL if (initialSSL) { tls_init(); if (tls_start_servertls(0, 1) == -1) { GetClientInfo(ListenPort); notice("%s failure to negotiate TLS session", Client.host); Reply("%d Encrypted TLS connection failed\r\n", NNTP_FAIL_TERMINATING); ExitWithStats(1, false); } encryption_layer_on = true; # if defined(HAVE_ZLIB) && OPENSSL_VERSION_NUMBER >= 0x00090800fL /* Check whether a compression layer has just been added. * SSL_get_current_compression() is defined in OpenSSL versions >= 0.9.8 * final release. */ tls_compression_on = (SSL_get_current_compression(tls_conn) != NULL); compression_layer_on = tls_compression_on; # endif /* HAVE_ZLIB && OPENSSL >= v0.9.8 */ } #endif /* HAVE_OPENSSL */ /* If requested, check the load average. */ if (innconf->nnrpdloadlimit != 0) { double load[1]; if (getloadavg(load, 1) < 0) warn("cannot obtain system load"); else { if ((unsigned long)(load[0] + 0.5) > innconf->nnrpdloadlimit) { GetClientInfo(ListenPort); notice("%s load %.2f > %lu", Client.host, load[0], innconf->nnrpdloadlimit); Reply("%d load at %.2f, try later\r\n", NNTP_FAIL_TERMINATING, load[0]); ExitWithStats(1, true); } } } /* Catch SIGPIPE so that we can exit out of long write loops. */ xsignal(SIGPIPE, CatchPipe); /* Get permissions and see if we can talk to this client. */ GetClientInfo(ListenPort); PERMgetinitialaccess(NNRPACCESS); PERMgetaccess(true); PERMgetpermissions(); if (!PERMcanread && !PERMcanpost && !PERMneedauth) { syslog(L_NOTICE, "%s no_permission", Client.host); Reply("%d You have no permission to talk. Goodbye!\r\n", NNTP_ERR_ACCESS); ExitWithStats(1, false); } /* Proceed with initialization. */ setproctitle("%s connect", Client.host); /* Were we told to reject connections? */ if (Reject) { syslog(L_NOTICE, "%s rejected %s", Client.host, Reject); Reply("%d %s\r\n", NNTP_FAIL_TERMINATING, is_valid_utf8(Reject) ? Reject : "Connection rejected"); ExitWithStats(0, false); } if (PERMaccessconf) { if (PERMaccessconf->readertrack) PERMaccessconf->readertrack = TrackClient(Client.host, Username, sizeof(Username)); } else { if (innconf->readertrack) innconf->readertrack = TrackClient(Client.host, Username, sizeof(Username)); } if ((PERMaccessconf && PERMaccessconf->readertrack) || (!PERMaccessconf && innconf->readertrack)) { int len; syslog(L_NOTICE, "%s Tracking Enabled (%s)", Client.host, Username); pid=getpid(); gettimeofday(&tv,NULL); count += pid; vid = tv.tv_sec ^ tv.tv_usec ^ pid ^ count; len = strlen("innconf->pathlog") + strlen("/tracklogs/log-") + BUFSIZ; LocalLogFileName = xmalloc(len); sprintf(LocalLogFileName, "%s/tracklogs/log-%u", innconf->pathlog, vid); if ((locallog = fopen(LocalLogFileName, "w")) == NULL) { LocalLogDirName = concatpath(innconf->pathlog, "tracklogs"); MakeDirectory(LocalLogDirName, false); free(LocalLogDirName); } if (locallog == NULL && (locallog = fopen(LocalLogFileName, "w")) == NULL) { syslog(L_ERROR, "%s Local Logging failed (%s) %s: %m", Client.host, Username, LocalLogFileName); } else { syslog(L_NOTICE, "%s Local Logging begins (%s) %s",Client.host, Username, LocalLogFileName); fprintf(locallog, "%s Tracking Enabled (%s)\n", Client.host, Username); fflush(locallog); LLOGenable = true; } } #ifdef HAVE_SASL SASLnewserver(); #endif /* HAVE_SASL */ if (PERMaccessconf) { Reply("%d %s InterNetNews NNRP server %s ready (%s)\r\n", (PERMcanpost || (PERMcanauthenticate && PERMcanpostgreeting)) ? NNTP_OK_BANNER_POST : NNTP_OK_BANNER_NOPOST, PERMaccessconf->pathhost, INN_VERSION_STRING, (!PERMneedauth && PERMcanpost) ? "posting ok" : "no posting"); clienttimeout = PERMaccessconf->clienttimeout; } else { Reply("%d %s InterNetNews NNRP server %s ready (%s)\r\n", (PERMcanpost || (PERMcanauthenticate && PERMcanpostgreeting)) ? NNTP_OK_BANNER_POST : NNTP_OK_BANNER_NOPOST, innconf->pathhost, INN_VERSION_STRING, (!PERMneedauth && PERMcanpost) ? "posting ok" : "no posting"); clienttimeout = innconf->clienttimeout; } line_init(&NNTPline); /* Main dispatch loop. */ for (timeout = innconf->initialtimeout, av = NULL, ac = 0; ; timeout = clienttimeout) { alloca_free(); TMRstart(TMR_NNTPWRITE); fflush(stdout); TMRstop(TMR_NNTPWRITE); 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", Client.host, PushedBack); ac = nArgify(PushedBack, &av, 1); r = RTok; } else { size_t len; size_t lenstripped = 0; const char *p; char *q; r = line_read(&NNTPline, timeout, &p, &len, &lenstripped); switch (r) { default: syslog(L_ERROR, "%s internal %d in main", Client.host, r); /* FALLTHROUGH */ case RTtimeout: if (timeout < clienttimeout) syslog(L_NOTICE, "%s timeout short", Client.host); else syslog(L_NOTICE, "%s timeout", Client.host); ExitWithStats(1, false); break; case RTok: /* len does not count CRLF. */ if (len + lenstripped <= sizeof(buff)) { /* line_read guarantees null termination. */ memcpy(buff, p, len + 1); /* Do some input processing, check for blank line. */ if (buff[0] != '\0') ac = nArgify(buff, &av, 1); if (Tracing) { /* Do not log passwords if AUTHINFO PASS, * AUTHINFO SASL PLAIN or AUTHINFO SASL EXTERNAL * are used. (Only one space between SASL and * PLAIN/EXTERNAL should be put; otherwise, the * whole command will be logged). * AUTHINFO SASL LOGIN does not use an initial response; * therefore, there is nothing to hide here. */ if (ac > 1 && strcasecmp(av[0], "AUTHINFO") == 0) { if (strncasecmp(av[1], "PASS", 4) == 0) syslog(L_TRACE, "%s < AUTHINFO PASS ********", Client.host); else if (strncasecmp(av[1], "SASL PLAIN", 10) == 0) syslog(L_TRACE, "%s < AUTHINFO SASL PLAIN ********", Client.host); else if (strncasecmp(av[1], "SASL EXTERNAL", 13) == 0) syslog(L_TRACE, "%s < AUTHINFO SASL EXTERNAL ********", Client.host); else syslog(L_TRACE, "%s < %s", Client.host, buff); } else { syslog(L_TRACE, "%s < %s", Client.host, buff); } } if (buff[0] == '\0') continue; break; } /* FALLTHROUGH */ case RTlong: /* The line is too long but we have to make sure that * no recognized command has been sent. */ q = (char *)p; ac = nArgify(q, &av, 1); validcommandtoolong = false; for (cp = CMDtable; cp->Name; cp++) { if ((cp->Function != CMD_unimp) && (ac > 0 && strcasecmp(cp->Name, av[0]) == 0)) { validcommandtoolong = true; break; } } Reply("%d Line too long\r\n", validcommandtoolong ? NNTP_ERR_SYNTAX : NNTP_ERR_COMMAND); continue; case RTeof: /* Handled below. */ break; } } /* Client gone? */ if (r == RTeof) break; if (ac == 0) continue; /* Find command. */ for (cp = CMDtable; cp->Name; cp++) if (strcasecmp(cp->Name, av[0]) == 0) break; /* If no command has been recognized. */ if (cp->Name == NULL) { if ((int)strlen(buff) > 40) syslog(L_NOTICE, "%s unrecognized %.40s...", Client.host, buff); else syslog(L_NOTICE, "%s unrecognized %s", Client.host, buff); if (strcasecmp(av[0], "XYZZY") == 0) { /* Acknowledge the magic word from the Colossal Cave Adventure computer game. */ Reply("%d Nothing happens\r\n", NNTP_ERR_COMMAND); } else { Reply("%d What?\r\n", NNTP_ERR_COMMAND); } continue; } /* Go on parsing the command. */ ac--; ac += reArgify(av[ac], &av[ac], cp->Stripspaces ? -1 : cp->Minac - ac - 1, cp->Stripspaces); /* Check whether all arguments do not exceed their allowed size. */ if (ac > 1) { validcommandtoolong = false; for (v = av; *v; v++) if (strlen(*v) > NNTP_MAXLEN_ARG) { validcommandtoolong = true; Reply("%d Argument too long\r\n", NNTP_ERR_SYNTAX); break; } if (validcommandtoolong) continue; } /* Check usage. */ if ((cp->Minac != CMDany && ac < cp->Minac) || (cp->Maxac != CMDany && ac > cp->Maxac)) { Reply("%d Syntax is: %s %s\r\n", NNTP_ERR_SYNTAX, cp->Name, cp->Help ? cp->Help : "(no argument allowed)"); continue; } /* Check permissions and dispatch. */ if (cp->Needauth && PERMneedauth) { Reply("%d Authentication required for command\r\n", NNTP_FAIL_AUTH_NEEDED); continue; } setproctitle("%s %s", Client.host, av[0]); (*cp->Function)(ac, av); if (PushedBack) break; if (PERMaccessconf) clienttimeout = PERMaccessconf->clienttimeout; else clienttimeout = innconf->clienttimeout; } ExitWithStats(0, false); /* NOTREACHED */ return 1; } inn-2.6.4/nnrpd/newnews.c0000644000175200017520000001715314002373703014702 0ustar iuliusiulius/* $Id: newnews.c 10012 2016-05-05 12:41:10Z iulius $ ** ** The NEWNEWS command. */ #include "config.h" #include "clibrary.h" #include "inn/innconf.h" #include "inn/messages.h" #include "inn/wire.h" #include "nnrpd.h" #include "inn/ov.h" #include "cache.h" #define GROUP_LIST_DELTA 10 static bool FindHeader(ARTHANDLE *art, const char **pp, const char **qp, const char* hdr, size_t hdrlen UNUSED) { const char *p, *p1, *q; bool Nocr = true; p = wire_findheader(art->data, art->len, hdr, true); if (p == NULL) return false; q = p; for (p1 = NULL; p < art->data + art->len; p++) { if (p1 != NULL && *p1 == '\r' && *p == '\n') { Nocr = false; break; } if (*p == '\n') { Nocr = true; break; } p1 = p; } if (p >= art->data + art->len) return false; if (!Nocr) p = p1; *pp = p; *qp = q; return true; } /* ** Get Xref: header. */ static char * GetXref(ARTHANDLE *art) { const char *p, *q; if (!FindHeader(art, &p, &q, "xref", sizeof("xref"))) return NULL; return xstrndup(q, p - q); } /* ** Split newsgroup list into array of newsgroups. Return static pointer, ** or NULL if there are no newsgroup. */ static char ** GetGroups(char *p) { static int size; static char **list; int i; char *q; static char *Xrefbuf = NULL; char *Xref = p; if (size == 0) { size = GROUP_LIST_DELTA; list = xmalloc((size + 1) * sizeof(char *)); } Xref = p; for (Xref++; *Xref == ' '; Xref++); if ((Xref = strchr(Xref, ' ')) == NULL) return NULL; for (Xref++; *Xref == ' '; Xref++); if (!Xrefbuf) Xrefbuf = xmalloc(BIG_BUFFER); strlcpy(Xrefbuf, Xref, BIG_BUFFER); if ((q = strchr(Xrefbuf, '\t')) != NULL) *q = '\0'; p = Xrefbuf; for (i = 0 ; ;i++) { while (ISWHITE(*p)) p++; if (*p == '\0' || *p == '\n') break; if (i >= size - 1) { size += GROUP_LIST_DELTA; list = xrealloc(list, (size + 1) * sizeof(char *)); } for (list[i] = p; *p && *p != '\n' && !ISWHITE(*p); p++) { if (*p == ':') *p = '\0'; } if (*p) *p++ = '\0'; } list[i] = NULL; return i ? list : NULL; } static bool HaveSeen(bool AllGroups, char *group, char **groups, char **xrefs) { char *list[2]; list[1] = NULL; for ( ; *xrefs; xrefs++) { list[0] = *xrefs; if ((!AllGroups && PERMmatch(groups, list)) && (!PERMspecified || PERMmatch(PERMreadlist, list))) { if (!strcmp(*xrefs, group)) return false; else return true; } } return false; } static char **groups; static char xref_header[] = "Xref"; static void process_newnews(char *group, bool AllGroups, time_t date) { int low, high; char **xrefs; int count; void *handle; char *p; time_t arrived; ARTHANDLE *art = NULL; TOKEN token; char *data; int len; char *grplist[2]; time_t now; grplist[0] = group; grplist[1] = NULL; if (PERMspecified && !PERMmatch(PERMreadlist, grplist)) return; if (!AllGroups && !PERMmatch(groups, grplist)) return; if (!OVgroupstats(group, &low, &high, &count, NULL)) return; ARTlow = low; ARThigh = high; if ((handle = OVopensearch(group, ARTlow, ARThigh)) != NULL) { ARTNUM artnum; unsigned long artcount = 0; struct cvector *vector = NULL; if (innconf->nfsreader) { time(&now); /* Move the start time back nfsreaderdelay seconds * as we are an NFS reader. */ if (date >= (time_t) innconf->nfsreaderdelay) date -= innconf->nfsreaderdelay; } while (OVsearch(handle, &artnum, &data, &len, &token, &arrived)) { if (innconf->nfsreader != 0 && (time_t) (arrived + innconf->nfsreaderdelay) > now) continue; if (len == 0 || date > arrived) continue; vector = overview_split(data, len, NULL, vector); if (overhdr_xref == -1) { if ((art = SMretrieve(token, RETR_HEAD)) == NULL) continue; p = GetXref(art); SMfreearticle(art); } else { if (PERMaccessconf->nnrpdcheckart && !ARTinstorebytoken(token)) continue; /* We only care about the newsgroup list here, virtual * hosting isn't relevant. */ p = overview_get_extra_header(vector, xref_header); } if (p == NULL) continue; xrefs = GetGroups(p); free(p); if (xrefs == NULL) continue; if (HaveSeen(AllGroups, group, groups, xrefs)) continue; p = overview_get_standard_header(vector, OVERVIEW_MESSAGE_ID); if (p == NULL) continue; ++artcount; cache_add(HashMessageID(p), token); Printf("%s\r\n", p); free(p); } OVclosesearch(handle); notice("%s newnews %s %lu", Client.host, group, artcount); if (vector) cvector_free(vector); } } /* ** NEWNEWS wildmat date time [GMT] ** Return the message-ID of any articles after the specified date. */ void CMDnewnews(int ac, char *av[]) { char *p, *q; char *path; bool AllGroups; char line[BIG_BUFFER]; time_t date; QIOSTATE *qp; int i; bool local = true; TMRstart(TMR_NEWNEWS); /* Check the arguments and parse the date. */ if (ac > 4) { if (strcasecmp(av[4], "GMT") == 0) local = false; else { Reply("%d Syntax error for \"GMT\"\r\n", NNTP_ERR_SYNTAX); TMRstop(TMR_NEWNEWS); return; } } /* Parse the newsgroups. */ AllGroups = (strcmp(av[1], "*") == 0); if (!AllGroups && !NGgetlist(&groups, av[1])) { Reply("%d Bad newsgroup specifier %s\r\n", NNTP_ERR_SYNTAX, av[1]); TMRstop(TMR_NEWNEWS); return; } /* Parse the date. */ date = parsedate_nntp(av[2], av[3], local); if (date == (time_t) -1) { Reply("%d Bad date\r\n", NNTP_ERR_SYNTAX); TMRstop(TMR_NEWNEWS); return; } /* Check authorizations. */ if (!PERMaccessconf->allownewnews) { Reply("%d NEWNEWS command disabled by administrator\r\n", PERMcanauthenticate ? NNTP_FAIL_AUTH_NEEDED : NNTP_ERR_ACCESS); TMRstop(TMR_NEWNEWS); return; } if (!PERMcanread) { Reply("%d Read access denied\r\n", PERMcanauthenticate ? NNTP_FAIL_AUTH_NEEDED : NNTP_ERR_ACCESS); TMRstop(TMR_NEWNEWS); return; } snprintf(line, sizeof(line), "%s %s %s %s", av[1], av[2], av[3], local ? "local" : "GMT"); notice("%s newnews %s", Client.host, line); /* Optimization in case client asks for !* (no groups). */ if (strcmp(av[1], "!*") == 0) { Reply("%d No new news\r\n", NNTP_OK_NEWNEWS); Printf(".\r\n"); TMRstop(TMR_NEWNEWS); return; } /* Make other processes happier if someone uses NEWNEWS. */ if (innconf->nicenewnews != 0) { nice(innconf->nicenewnews); innconf->nicenewnews = 0; } if (strcspn(av[1], "\\!*[?]") == strlen(av[1])) { /* Optimise case -- don't need to scan the active file pattern * matching. */ Reply("%d New news follows\r\n", NNTP_OK_NEWNEWS); for (i = 0; groups[i]; ++i) { process_newnews(groups[i], AllGroups, date); } } else { path = concatpath(innconf->pathdb, INN_PATH_ACTIVE); qp = QIOopen(path); if (qp == NULL) { if (errno == ENOENT) { Reply("%d Can't open active\r\n", NNTP_FAIL_ACTION); } else { syswarn("%s can't fopen %s", Client.host, path); Reply("%d Can't open active\r\n", NNTP_FAIL_ACTION); } free(path); TMRstop(TMR_NEWNEWS); return; } free(path); Reply("%d New news follows\r\n", NNTP_OK_NEWNEWS); while ((p = QIOread(qp)) != NULL) { for (q = p; *q != '\0'; q++) { if (*q == ' ' || *q == '\t') { *q = '\0'; break; } } process_newnews(p, AllGroups, date); } QIOclose(qp); } Printf(".\r\n"); TMRstop(TMR_NEWNEWS); } inn-2.6.4/nnrpd/perl.c0000644000175200017520000002747014002373703014161 0ustar iuliusiulius/* $Id: perl.c 10305 2018-12-02 14:21:56Z iulius $ ** ** Embedded Perl support for INN. ** ** Originally written by Christophe Wolfhugel (although ** he wouldn't recognize it any more, so don't blame him) and modified, ** expanded, and tweaked by James Brister, Dave Hayes, Andrew Gierth, and ** Russ Allbery among others. ** ** This file should contain all innd-specific Perl linkage. Linkage ** applicable to both innd and nnrpd should go into lib/perl.c instead. ** ** We are assuming Perl 5.004 or later. */ #include "config.h" #include "clibrary.h" #include "inn/innconf.h" #include "nnrpd.h" #include "inn/nntp.h" #include "inn/paths.h" #include "post.h" /* Skip this entire file if DO_PERL (./configure --with-perl) isn't set. */ #ifdef DO_PERL #include #pragma GCC diagnostic ignored "-Wredundant-decls" #include #pragma GCC diagnostic warning "-Wredundant-decls" #include #include "ppport.h" #include "innperl.h" extern HEADER Table[], *EndOfTable; extern char **OtherHeaders; extern int OtherCount; extern bool HeadersModified; extern bool PerlLoaded; /* #define DEBUG_MODIFY only if you want to see verbose output. */ #ifdef DEBUG_MODIFY static FILE *flog; void dumpTable(const char *msg); #endif /* DEBUG_MODIFY */ char * HandleHeaders(char *article) { dSP; HEADER *hp; HV *attribs; HV *hdr; SV *body; int rc; char *p, *q; static char buf[256]; int i; size_t len; char *s,*t; HE *scan; SV *modswitch; int OtherSize; char *argv[] = { NULL }; bool failure; SV *errsv; if(!PerlLoaded) { loadPerl(); } if (!PerlFilterActive) return NULL; /* Not really necessary. */ #ifdef DEBUG_MODIFY if ((flog = fopen("/var/news/log/nnrpdperlerrror", "a+")) == NULL) { syslog(L_ERROR,"Whoops. Can't open error log: %m"); } #endif /* DEBUG_MODIFY */ ENTER; SAVETMPS; /* Create the Perl attributes hash. */ attribs = perl_get_hv("attributes", true); (void) hv_store(attribs, "hostname", 8, newSVpv(Client.host, 0), 0); (void) hv_store(attribs, "ipaddress", 9, newSVpv(Client.ip, 0), 0); (void) hv_store(attribs, "port", 4, newSViv(Client.port), 0); (void) hv_store(attribs, "interface", 9, newSVpv(Client.serverhost, 0), 0); (void) hv_store(attribs, "intipaddr", 9, newSVpv(Client.serverip, 0), 0); (void) hv_store(attribs, "intport", 7, newSViv(Client.serverport), 0); /* Create the Perl header hash. */ hdr = perl_get_hv("hdr", true); for (hp = Table; hp < EndOfTable; hp++) { if (hp->Body) (void) hv_store(hdr, (char *) hp->Name, strlen(hp->Name), newSVpv(hp->Body, 0), 0); } /* Also store other headers. */ OtherSize = OtherCount; for (i = 0; i < OtherCount; i++) { p = OtherHeaders[i]; if (p == NULL) { syslog(L_ERROR, "Null header number %d copying headers for Perl", i); continue; } s = strchr(p, ':'); if (s == NULL) { syslog(L_ERROR, "Bad header copying headers for Perl: '%s'", p); continue; } s++; t = (*s == ' ' ? s + 1 : s); (void) hv_store(hdr, p, (s - p) - 1, newSVpv(t, 0), 0); } /* Store user. */ sv_setpv(perl_get_sv("user", true), PERMuser); /* Store body. */ body = perl_get_sv("body", true); sv_setpv(body, article); /* Call the filtering function. */ /* No need for PUSHMARK(SP) with call_argv(). */ rc = perl_call_argv("filter_post", G_EVAL|G_SCALAR, argv); SPAGAIN; /* Restore headers if they have just been modified by the filter. */ modswitch = perl_get_sv("modify_headers", false); HeadersModified = false; if (SvTRUE(modswitch)) { HeadersModified = true; i = 0; #ifdef DEBUG_MODIFY dumpTable("Before mod"); #endif /* DEBUG_MODIFY */ hv_iterinit(hdr); while ((scan = hv_iternext(hdr)) != NULL) { /* Get the values. We replace the known ones with these * new values. */ p = HePV(scan, len); s = SvPV(HeVAL(scan), PL_na); #ifdef DEBUG_MODIFY fprintf(flog,"Hash iter: '%s','%s'\n", p, s); #endif /* DEBUG_MODIFY */ /* See if it is a table header. */ for (hp = Table; hp < EndOfTable; hp++) { if (strcasecmp(p, hp->Name) == 0) { char *copy = xstrdup(s); HDR_SET(hp - Table, copy); hp->Len = TrimSpaces(hp->Value); for (q = hp->Value ; ISWHITE(*q) || *q == '\n' ; q++) continue; hp->Body = q; if (hp->Len == 0) { free(hp->Value); hp->Value = hp->Body = NULL; } break; } } if (hp != EndOfTable) continue; /* Add to other headers if not empty. */ if (TrimSpaces(s) > 0) { if (i >= OtherSize - 1) { OtherSize += 20; OtherHeaders = xrealloc(OtherHeaders, OtherSize * sizeof(char *)); } t = concat(p, ": ", s, (char *) 0); OtherHeaders[i++] = t; } } OtherCount = i; #ifdef DEBUG_MODIFY dumpTable("After mod"); #endif /* DEBUG_MODIFY */ } hv_undef(attribs); hv_undef(hdr); sv_setsv(body, &PL_sv_undef); buf[0] = '\0'; /* Check $@. */ errsv = ERRSV; if (SvTRUE(errsv)) { failure = true; syslog(L_ERROR, "Perl function filter_post died: %s", SvPV(errsv, PL_na)); (void)POPs; } else { failure = false; if (rc == 1) { p = POPp; if (p != NULL && *p != '\0') strlcpy(buf, p, sizeof(buf)); } } PUTBACK; FREETMPS; LEAVE; if (failure) PerlFilter(false); if (buf[0] != '\0') return buf; #ifdef DEBUG_MODIFY fclose(flog); #endif /* DEBUG_MODIFY */ return NULL; } void loadPerl(void) { char *path; path = concatpath(innconf->pathfilter, INN_PATH_PERL_FILTER_NNRPD); PERLsetup(NULL, path, "filter_post"); free(path); PerlFilter(true); PerlLoaded = true; } void perlAccess(char *user, struct vector *access_vec) { dSP; HV *attribs; SV *sv; int rc, i; char *key, *val, *buffer; SV *errsv; if (!PerlFilterActive) return; ENTER; SAVETMPS; attribs = perl_get_hv("attributes", true); (void) hv_store(attribs, "hostname", 8, newSVpv(Client.host, 0), 0); (void) hv_store(attribs, "ipaddress", 9, newSVpv(Client.ip, 0), 0); (void) hv_store(attribs, "port", 4, newSViv(Client.port), 0); (void) hv_store(attribs, "interface", 9, newSVpv(Client.serverhost, 0), 0); (void) hv_store(attribs, "intipaddr", 9, newSVpv(Client.serverip, 0), 0); (void) hv_store(attribs, "intport", 7, newSViv(Client.serverport), 0); (void) hv_store(attribs, "username", 8, newSVpv(user, 0), 0); PUSHMARK(SP); PUTBACK; if (perl_get_cv("access", 0) == NULL) { syslog(L_ERROR, "Perl function access not defined"); Reply("%d Internal error (3). Goodbye!\r\n", NNTP_FAIL_TERMINATING); ExitWithStats(1, true); } rc = perl_call_pv("access", G_EVAL|G_ARRAY); SPAGAIN; if (rc == 0) { /* Error occured, same as checking $@. */ errsv = ERRSV; syslog(L_ERROR, "Perl function access died: %s", SvPV(errsv, PL_na)); Reply("%d Internal error (1). Goodbye!\r\n", NNTP_FAIL_TERMINATING); ExitWithStats(1, true); } if ((rc % 2) != 0) { syslog(L_ERROR, "Perl function access returned an odd number of arguments: %i", rc); Reply("%d Internal error (2). Goodbye!\r\n", NNTP_FAIL_TERMINATING); ExitWithStats(1, true); } vector_resize(access_vec, (rc / 2)); buffer = xmalloc(BIG_BUFFER); for (i = (rc / 2); i >= 1; i--) { sv = POPs; val = SvPV(sv, PL_na); sv = POPs; key = SvPV(sv, PL_na); strlcpy(buffer, key, BIG_BUFFER); strlcat(buffer, ": \"", BIG_BUFFER); strlcat(buffer, val, BIG_BUFFER); strlcat(buffer, "\"\n", BIG_BUFFER); vector_add(access_vec, buffer); } free(buffer); hv_undef(attribs); PUTBACK; FREETMPS; LEAVE; } void perlAuthInit(void) { dSP; int rc; SV *errsv; if (!PerlFilterActive) return; if (perl_get_cv("auth_init", 0) == NULL) { return; } ENTER; SAVETMPS; PUSHMARK(SP); PUTBACK; rc = perl_call_pv("auth_init", G_EVAL|G_DISCARD); SPAGAIN; errsv = ERRSV; if (SvTRUE(errsv)) { /* Check $@. */ syslog(L_ERROR, "Perl function authenticate died: %s", SvPV(errsv, PL_na)); Reply("%d Internal error (1). Goodbye!\r\n", NNTP_FAIL_TERMINATING); ExitWithStats(1, true); } while (rc--) { (void)POPs; } PUTBACK; FREETMPS; LEAVE; } void perlAuthenticate(char *user, char *passwd, int *code, char *errorstring, char *newUser) { dSP; HV *attribs; int rc; char *p; SV *errsv; if (!PerlFilterActive) *code = NNTP_FAIL_AUTHINFO_BAD; if (perl_get_cv("authenticate", 0) == NULL) { syslog(L_ERROR, "Perl function authenticate not defined"); Reply("%d Internal error (3). Goodbye!\r\n", NNTP_FAIL_TERMINATING); ExitWithStats(1, true); } ENTER; SAVETMPS; attribs = perl_get_hv("attributes", true); (void) hv_store(attribs, "hostname", 8, newSVpv(Client.host, 0), 0); (void) hv_store(attribs, "ipaddress", 9, newSVpv(Client.ip, 0), 0); (void) hv_store(attribs, "port", 4, newSViv(Client.port), 0); (void) hv_store(attribs, "interface", 9, newSVpv(Client.serverhost, 0), 0); (void) hv_store(attribs, "intipaddr", 9, newSVpv(Client.serverip, 0), 0); (void) hv_store(attribs, "intport", 7, newSViv(Client.serverport), 0); (void) hv_store(attribs, "username", 8, newSVpv(user, 0), 0); (void) hv_store(attribs, "password", 8, newSVpv(passwd, 0), 0); PUSHMARK(SP); PUTBACK; rc = perl_call_pv("authenticate", G_EVAL|G_ARRAY); SPAGAIN; if (rc == 0 ) { /* Error occurred, same as checking $@. */ errsv = ERRSV; syslog(L_ERROR, "Perl function authenticate died: %s", SvPV(errsv, PL_na)); Reply("%d Internal error (1). Goodbye!\r\n", NNTP_FAIL_TERMINATING); ExitWithStats(1, false); } if ((rc != 3) && (rc != 2)) { syslog(L_ERROR, "Perl function authenticate returned wrong number of results: %d", rc); Reply("%d Internal error (2). Goodbye!\r\n", NNTP_FAIL_TERMINATING); ExitWithStats(1, false); } /* FIXME: Change the structure of the code so that we don't have to rely * on keeping these sizes in sync with the buffers that are passed into * this function. */ if (rc == 3) { p = POPp; strlcpy(newUser, p, BIG_BUFFER); } p = POPp; strlcpy(errorstring, p, BIG_BUFFER); *code = POPi; hv_undef(attribs); PUTBACK; FREETMPS; LEAVE; } #ifdef DEBUG_MODIFY void dumpTable (const char *msg) { HEADER *hp; int i; fprintf(flog, "===BEGIN TABLE DUMP: %s\n", msg); for (hp = Table; hp < EndOfTable; hp++) { fprintf(flog, " Name: '%s'",hp->Name); fflush(flog); fprintf(flog, " Size: '%d'", hp->Size); fflush(flog); fprintf(flog, " Value: '%s'\n", ((hp->Value == NULL) ? "(NULL)" : hp->Value)); fflush(flog); } for (i=0; i. ** ** Author: Kenichi Okada ** Created: 2000-02-22 */ #ifdef HAVE_OPENSSL #ifndef TLS_H #define TLS_H /* When building with "make warnings", ensure that INN does not * use deprecated interfaces from OpenSSL. */ #if defined(DEBUG) # define OPENSSL_API_COMPAT 0x010100000L #endif #include #include #include #include #include #include #include #include #if !defined(OPENSSL_NO_EC) && defined(TLSEXT_ECPOINTFORMAT_uncompressed) # include # include # define HAVE_OPENSSL_ECC #endif /* Protocol support. */ #define INN_TLS_SSLv2 1 #define INN_TLS_SSLv3 2 #define INN_TLS_TLSv1 4 #define INN_TLS_TLSv1_1 8 #define INN_TLS_TLSv1_2 16 #define INN_TLS_TLSv1_3 32 /* Init TLS engine. */ int tls_init_serverengine(int verifydepth, /* Depth to verify. */ int askcert, /* 1 = Verify client. */ int requirecert, /* 1 = Another client verify? */ char *tls_CAfile, char *tls_CApath, char *tls_cert_file, char *tls_key_file, bool prefer_server_ciphers, bool tls_compression, struct vector *tls_protocols, char *tls_ciphers, char *tls_ciphers13, char *tls_ec_curve); /* Init TLS. */ int tls_init(void); /* Start TLS negotiation. */ int tls_start_servertls(int readfd, int writefd); ssize_t SSL_writev(SSL *ssl, const struct iovec *vector, int count); #endif /* TLS_H */ #endif /* HAVE_OPENSSL */ inn-2.6.4/nnrpd/perm.c0000644000175200017520000017127314002373703014163 0ustar iuliusiulius/* $Id: perm.c 10117 2016-11-06 14:23:27Z iulius $ ** ** How to figure out where a user comes from, and what that user can do once ** we know who sie is. */ #include "config.h" #include "clibrary.h" #include #include #include #include "conffile.h" #include "inn/network.h" #include "inn/innconf.h" #include "innperl.h" #include "nnrpd.h" #include "tls.h" /* Needed on AIX 4.1 to get fd_set and friends. */ #ifdef HAVE_SYS_SELECT_H # include #endif #if defined(HAVE_OPENSSL) || defined(HAVE_SASL) extern bool encryption_layer_on; #endif /* HAVE_OPENSSL || HAVE_SASL */ /* Data types. */ typedef struct _CONFCHAIN { CONFFILE *f; struct _CONFCHAIN *parent; } CONFCHAIN; typedef struct _METHOD { char *name; char *program; int type; /* Type of auth (perl, python or external)/ */ char *users; /* Only used for auth_methods, not for res_methods. */ char **extra_logs; } METHOD; typedef struct _AUTHGROUP { char *name; char *key; #if defined(HAVE_OPENSSL) || defined(HAVE_SASL) int require_ssl; #endif char *hosts; METHOD **res_methods; METHOD **auth_methods; char *default_user; char *default_domain; char *localaddress; char *access_script; int access_type; /* Type of access (Perl or Python). */ char *dynamic_script; int dynamic_type; /* Type of dynamic authorization (Python only). */ } AUTHGROUP; typedef struct _GROUP { char *name; struct _GROUP *above; AUTHGROUP *auth; ACCESSGROUP *access; } GROUP; /* Function declarations. */ static void PERMreadfile(char *filename); static void authdecl_parse(AUTHGROUP*, CONFFILE*, CONFTOKEN*); static void accessdecl_parse(ACCESSGROUP *curaccess, CONFFILE *f, CONFTOKEN *tok); static void method_parse(METHOD*, CONFFILE*, CONFTOKEN*, int); static void add_authgroup(AUTHGROUP*); static void add_accessgroup(ACCESSGROUP*); static void strip_accessgroups(void); static METHOD *copy_method(METHOD*); static void free_method(METHOD*); static AUTHGROUP *copy_authgroup(AUTHGROUP*); static void free_authgroup(AUTHGROUP*); static ACCESSGROUP *copy_accessgroup(ACCESSGROUP*); static void free_accessgroup(ACCESSGROUP*); static void CompressList(char*); static bool MatchHost(char*, char*, char*); static int MatchUser(char*, char*); static char *ResolveUser(AUTHGROUP*); static char *AuthenticateUser(AUTHGROUP*, char*, char*, int*, char*); static void GrowArray(void*, void*); static void PERMvectortoaccess(ACCESSGROUP *acc, const char *name, struct vector *acccess_vec) UNUSED; /* Global variables. */ static AUTHGROUP **auth_realms; static AUTHGROUP *success_auth; static ACCESSGROUP **access_realms; static char *ConfigBit; static int ConfigBitsize; extern bool PerlLoaded; #define PERMlbrace 1 #define PERMrbrace 2 #define PERMgroup 3 #define PERMauth 4 #define PERMaccess 5 #define PERMhost 6 #define PERMauthprog 7 #define PERMresolv 8 #define PERMresprog 9 #define PERMdefuser 10 #define PERMdefdomain 11 #define PERMusers 12 #define PERMnewsgroups 13 #define PERMread 14 #define PERMpost 15 #define PERMaccessrp 16 #define PERMalsolog 18 #define PERMprogram 19 #define PERMinclude 20 #define PERMkey 21 #define PERMlocaltime 22 #define PERMstrippath 23 #define PERMnnrpdperlfilter 24 #define PERMnnrpdpythonfilter 25 #define PERMfromhost 26 #define PERMpathhost 27 #define PERMorganization 28 #define PERMmoderatormailer 29 #define PERMdomain 30 #define PERMcomplaints 31 #define PERMspoolfirst 32 #define PERMcheckincludedtext 33 #define PERMclienttimeout 34 #define PERMlocalmaxartsize 35 #define PERMreadertrack 36 #define PERMstrippostcc 37 #define PERMaddinjectiondate 38 #define PERMaddinjectionpostingaccount 39 #define PERMaddinjectionpostinghost 40 #define PERMnnrpdposthost 41 #define PERMnnrpdpostport 42 #define PERMnnrpdoverstats 43 #define PERMbackoff_auth 44 #define PERMbackoff_db 45 #define PERMbackoff_k 46 #define PERMbackoff_postfast 47 #define PERMbackoff_postslow 48 #define PERMbackoff_trigger 49 #define PERMnnrpdcheckart 50 #define PERMnnrpdauthsender 51 #define PERMvirtualhost 52 #define PERMnewsmaster 53 #define PERMlocaladdress 54 #define PERMrejectwith 55 #define PERMmaxbytespersecond 56 #define PERMperl_auth 57 #define PERMpython_auth 58 #define PERMperl_access 59 #define PERMpython_access 60 #define PERMpython_dynamic 61 #if defined(HAVE_OPENSSL) || defined(HAVE_SASL) #define PERMrequire_ssl 62 #define PERMMAX 63 #else #define PERMMAX 62 #endif #define TEST_CONFIG(a, b) \ { \ int byte, offset; \ offset = a % 8; \ byte = (a - offset) / 8; \ b = ((ConfigBit[byte] & (1 << offset)) != 0) ? true : false; \ } #define SET_CONFIG(a) \ { \ int byte, offset; \ offset = a % 8; \ byte = (a - offset) / 8; \ ConfigBit[byte] |= (1 << offset); \ } #define CLEAR_CONFIG(a) \ { \ int byte, offset; \ offset = a % 8; \ byte = (a - offset) / 8; \ ConfigBit[byte] &= ~(1 << offset); \ } static CONFTOKEN PERMtoks[] = { { PERMlbrace, (char *) "{" }, { PERMrbrace, (char *) "}" }, { PERMgroup, (char *) "group" }, { PERMauth, (char *) "auth" }, { PERMaccess, (char *) "access" }, { PERMhost, (char *) "hosts:" }, { PERMauthprog, (char *) "auth:" }, { PERMresolv, (char *) "res" }, { PERMresprog, (char *) "res:" }, { PERMdefuser, (char *) "default:" }, { PERMdefdomain, (char *) "default-domain:" }, { PERMusers, (char *) "users:" }, { PERMnewsgroups, (char *) "newsgroups:" }, { PERMread, (char *) "read:" }, { PERMpost, (char *) "post:" }, { PERMaccessrp, (char *) "access:" }, { PERMalsolog, (char *) "log:" }, { PERMprogram, (char *) "program:" }, { PERMinclude, (char *) "include" }, { PERMkey, (char *) "key:" }, { PERMlocaltime, (char *) "localtime:" }, { PERMstrippath, (char *) "strippath:" }, { PERMnnrpdperlfilter, (char *) "perlfilter:" }, { PERMnnrpdpythonfilter, (char *) "pythonfilter:" }, { PERMfromhost, (char *) "fromhost:" }, { PERMpathhost, (char *) "pathhost:" }, { PERMorganization, (char *) "organization:" }, { PERMmoderatormailer, (char *) "moderatormailer:" }, { PERMdomain, (char *) "domain:" }, { PERMcomplaints, (char *) "complaints:" }, { PERMspoolfirst, (char *) "spoolfirst:" }, { PERMcheckincludedtext, (char *) "checkincludedtext:" }, { PERMclienttimeout, (char *) "clienttimeout:" }, { PERMlocalmaxartsize, (char *) "localmaxartsize:" }, { PERMreadertrack, (char *) "readertrack:" }, { PERMstrippostcc, (char *) "strippostcc:" }, { PERMaddinjectiondate, (char *) "addinjectiondate:" }, { PERMaddinjectionpostingaccount, (char *) "addinjectionpostingaccount:" }, { PERMaddinjectionpostinghost, (char *) "addinjectionpostinghost:" }, { PERMnnrpdposthost, (char *) "nnrpdposthost:" }, { PERMnnrpdpostport, (char *) "nnrpdpostport:" }, { PERMnnrpdoverstats, (char *) "nnrpdoverstats:" }, { PERMbackoff_auth, (char *) "backoff_auth:" }, { PERMbackoff_db, (char *) "backoff_db:" }, { PERMbackoff_k, (char *) "backoff_k:" }, { PERMbackoff_postfast, (char *) "backoff_postfast:" }, { PERMbackoff_postslow, (char *) "backoff_postslow:" }, { PERMbackoff_trigger, (char *) "backoff_trigger:" }, { PERMnnrpdcheckart, (char *) "nnrpdcheckart:" }, { PERMnnrpdauthsender, (char *) "nnrpdauthsender:" }, { PERMvirtualhost, (char *) "virtualhost:" }, { PERMnewsmaster, (char *) "newsmaster:" }, { PERMlocaladdress, (char *) "localaddress:" }, { PERMrejectwith, (char *) "reject_with:" }, { PERMmaxbytespersecond, (char *) "max_rate:" }, { PERMperl_auth, (char *) "perl_auth:" }, { PERMpython_auth, (char *) "python_auth:" }, { PERMperl_access, (char *) "perl_access:" }, { PERMpython_access, (char *) "python_access:" }, { PERMpython_dynamic, (char *) "python_dynamic:" }, #if defined(HAVE_OPENSSL) || defined(HAVE_SASL) { PERMrequire_ssl, (char *) "require_ssl:" }, #endif { 0, (char *) NULL } }; /* Function definitions. */ static void GrowArray(void *data, void *el) { int i; void ***array = data; if (*array == NULL) { *array = xmalloc(2 * sizeof(void *)); i = 0; } else { for (i = 0; (*array)[i]; i++) ; *array = xrealloc(*array, (i + 2) * sizeof(void *)); } (*array)[i++] = el; (*array)[i] = 0; } static METHOD * copy_method(METHOD *orig) { METHOD *ret; int i; ret = xmalloc(sizeof(METHOD)); memset(ConfigBit, '\0', ConfigBitsize); ret->name = xstrdup(orig->name); if (orig->program != NULL) { ret->program = xstrdup(orig->program); } else { ret->program = NULL; } if (orig->users) ret->users = xstrdup(orig->users); else ret->users = 0; ret->extra_logs = 0; if (orig->extra_logs) { for (i = 0; orig->extra_logs[i]; i++) GrowArray(&ret->extra_logs, xstrdup(orig->extra_logs[i])); } ret->type = orig->type; return(ret); } static void free_method(METHOD *del) { int j; if (del->extra_logs) { for (j = 0; del->extra_logs[j]; j++) free(del->extra_logs[j]); free(del->extra_logs); } if (del->program) free(del->program); if (del->users) free(del->users); free(del->name); free(del); } static AUTHGROUP * copy_authgroup(AUTHGROUP *orig) { AUTHGROUP *ret; int i; if (!orig) return(0); ret = xmalloc(sizeof(AUTHGROUP)); memset(ConfigBit, '\0', ConfigBitsize); if (orig->name) ret->name = xstrdup(orig->name); else ret->name = 0; if (orig->key) ret->key = xstrdup(orig->key); else ret->key = 0; if (orig->hosts) ret->hosts = xstrdup(orig->hosts); else ret->hosts = 0; #if defined(HAVE_OPENSSL) || defined(HAVE_SASL) ret->require_ssl = orig->require_ssl; #endif ret->res_methods = 0; if (orig->res_methods) { for (i = 0; orig->res_methods[i]; i++) GrowArray(&ret->res_methods, copy_method(orig->res_methods[i]));; } ret->auth_methods = 0; if (orig->auth_methods) { for (i = 0; orig->auth_methods[i]; i++) GrowArray(&ret->auth_methods, copy_method(orig->auth_methods[i])); } if (orig->default_user) ret->default_user = xstrdup(orig->default_user); else ret->default_user = 0; if (orig->default_domain) ret->default_domain = xstrdup(orig->default_domain); else ret->default_domain = 0; if (orig->localaddress) ret->localaddress = xstrdup(orig->localaddress); else ret->localaddress = 0; if (orig->access_script) ret->access_script = xstrdup(orig->access_script); else ret->access_script = 0; if (orig->access_type) ret->access_type = orig->access_type; else ret->access_type = 0; if (orig->dynamic_script) ret->dynamic_script = xstrdup(orig->dynamic_script); else ret->dynamic_script = 0; if (orig->dynamic_type) ret->dynamic_type = orig->dynamic_type; else ret->dynamic_type = 0; return(ret); } static ACCESSGROUP * copy_accessgroup(ACCESSGROUP *orig) { ACCESSGROUP *ret; if (!orig) return(0); ret = xmalloc(sizeof(ACCESSGROUP)); memset(ConfigBit, '\0', ConfigBitsize); /* Copy all anyway, and update for local strings. */ *ret = *orig; if (orig->name) ret->name = xstrdup(orig->name); if (orig->key) ret->key = xstrdup(orig->key); if (orig->read) ret->read = xstrdup(orig->read); if (orig->post) ret->post = xstrdup(orig->post); if (orig->users) ret->users = xstrdup(orig->users); if (orig->rejectwith) ret->rejectwith = xstrdup(orig->rejectwith); if (orig->fromhost) ret->fromhost = xstrdup(orig->fromhost); if (orig->pathhost) ret->pathhost = xstrdup(orig->pathhost); if (orig->organization) ret->organization = xstrdup(orig->organization); if (orig->moderatormailer) ret->moderatormailer = xstrdup(orig->moderatormailer); if (orig->domain) ret->domain = xstrdup(orig->domain); if (orig->complaints) ret->complaints = xstrdup(orig->complaints); if (orig->nnrpdposthost) ret->nnrpdposthost = xstrdup(orig->nnrpdposthost); if (orig->backoff_db) ret->backoff_db = xstrdup(orig->backoff_db); if (orig->newsmaster) ret->newsmaster = xstrdup(orig->newsmaster); return(ret); } static void SetDefaultAuth(AUTHGROUP *curauth UNUSED) { #if defined(HAVE_OPENSSL) || defined(HAVE_SASL) curauth->require_ssl = false; #endif } void SetDefaultAccess(ACCESSGROUP *curaccess) { curaccess->allownewnews = innconf->allownewnews;; curaccess->allowihave = false; curaccess->locpost = false; curaccess->allowapproved = false; curaccess->localtime = false; curaccess->strippath = false; curaccess->nnrpdperlfilter = true; curaccess->nnrpdpythonfilter = true; curaccess->fromhost = NULL; if (innconf->fromhost) curaccess->fromhost = xstrdup(innconf->fromhost); curaccess->pathhost = NULL; if (innconf->pathhost) curaccess->pathhost = xstrdup(innconf->pathhost); curaccess->organization = NULL; if (innconf->organization) curaccess->organization = xstrdup(innconf->organization); curaccess->moderatormailer = NULL; if (innconf->moderatormailer) curaccess->moderatormailer = xstrdup(innconf->moderatormailer); curaccess->domain = NULL; if (innconf->domain) curaccess->domain = xstrdup(innconf->domain); curaccess->complaints = NULL; if (innconf->complaints) curaccess->complaints = xstrdup(innconf->complaints); curaccess->spoolfirst = innconf->spoolfirst; curaccess->checkincludedtext = innconf->checkincludedtext; curaccess->clienttimeout = innconf->clienttimeout; curaccess->localmaxartsize = innconf->localmaxartsize; curaccess->readertrack = innconf->readertrack; curaccess->strippostcc = innconf->strippostcc; curaccess->addinjectiondate = innconf->addinjectiondate; curaccess->addinjectionpostingaccount = innconf->addinjectionpostingaccount; curaccess->addinjectionpostinghost = innconf->addinjectionpostinghost; curaccess->nnrpdposthost = innconf->nnrpdposthost; curaccess->nnrpdpostport = innconf->nnrpdpostport; curaccess->nnrpdoverstats = innconf->nnrpdoverstats; curaccess->backoff_auth = innconf->backoffauth; curaccess->backoff_db = NULL; if (innconf->backoffdb && *innconf->backoffdb != '\0') curaccess->backoff_db = xstrdup(innconf->backoffdb); curaccess->backoff_k = innconf->backoffk; curaccess->backoff_postfast = innconf->backoffpostfast; curaccess->backoff_postslow = innconf->backoffpostslow; curaccess->backoff_trigger = innconf->backofftrigger; curaccess->nnrpdcheckart = innconf->nnrpdcheckart; curaccess->nnrpdauthsender = innconf->nnrpdauthsender; curaccess->virtualhost = false; curaccess->newsmaster = NULL; curaccess->maxbytespersecond = 0; } static void free_authgroup(AUTHGROUP *del) { int i; if (del->name) free(del->name); if (del->key) free(del->key); if (del->hosts) free(del->hosts); if (del->res_methods) { for (i = 0; del->res_methods[i]; i++) free_method(del->res_methods[i]); free(del->res_methods); } if (del->auth_methods) { for (i = 0; del->auth_methods[i]; i++) free_method(del->auth_methods[i]); free(del->auth_methods); } if (del->default_user) free(del->default_user); if (del->default_domain) free(del->default_domain); if (del->localaddress) free(del->localaddress); if (del->access_script) free(del->access_script); if (del->dynamic_script) free(del->dynamic_script); free(del); } static void free_accessgroup(ACCESSGROUP *del) { if (del->name) free(del->name); if (del->key) free(del->key); if (del->read) free(del->read); if (del->post) free(del->post); if (del->users) free(del->users); if (del->rejectwith) free(del->rejectwith); if (del->fromhost) free(del->fromhost); if (del->pathhost) free(del->pathhost); if (del->organization) free(del->organization); if (del->moderatormailer) free(del->moderatormailer); if (del->domain) free(del->domain); if (del->complaints) free(del->complaints); if (del->nnrpdposthost) free(del->nnrpdposthost); if (del->backoff_db) free(del->backoff_db); if (del->newsmaster) free(del->newsmaster); free(del); } static void ReportError(CONFFILE *f, const char *err) { syslog(L_ERROR, "%s syntax error in %s(%d), %s", Client.host, f->filename, f->lineno, err); Reply("%d NNTP server unavailable. Try later!\r\n", NNTP_FAIL_TERMINATING); ExitWithStats(1, true); } static void method_parse(METHOD *method, CONFFILE *f, CONFTOKEN *tok, int auth) { int oldtype; oldtype = tok->type; tok = CONFgettoken(0, f); if (tok == NULL) { ReportError(f, "Expected value."); } switch (oldtype) { case PERMalsolog: GrowArray(&method->extra_logs, xstrdup(tok->name)); break; case PERMusers: if (!auth) { ReportError(f, "Unexpected users: directive in file."); } else if (method->users) { ReportError(f, "Multiple users: directive in file."); } method->users = xstrdup(tok->name); break; case PERMprogram: if (method->program) { ReportError(f, "Multiple program: directives in auth/res declaration."); } method->program = xstrdup(tok->name); break; } } static void authdecl_parse(AUTHGROUP *curauth, CONFFILE *f, CONFTOKEN *tok) { int oldtype; #if defined(HAVE_OPENSSL) || defined(HAVE_SASL) int boolval; #endif METHOD *m; bool bit; char buff[SMBUF], *oldname, *p; oldtype = tok->type; oldname = tok->name; tok = CONFgettoken(PERMtoks, f); if (tok == NULL) { ReportError(f, "Expected value."); } TEST_CONFIG(oldtype, bit); if (bit) { snprintf(buff, sizeof(buff), "Duplicated '%s' field in auth group.", oldname); ReportError(f, buff); } #if defined(HAVE_OPENSSL) || defined(HAVE_SASL) if (strcasecmp(tok->name, "on") == 0 || strcasecmp(tok->name, "true") == 0 || strcasecmp(tok->name, "yes") == 0) boolval = true; else if (strcasecmp(tok->name, "off") == 0 || strcasecmp(tok->name, "false") == 0 || strcasecmp(tok->name, "no") == 0) boolval = false; else boolval = -1; #endif switch (oldtype) { case PERMkey: curauth->key = xstrdup(tok->name); SET_CONFIG(PERMkey); break; #if defined(HAVE_OPENSSL) || defined(HAVE_SASL) case PERMrequire_ssl: if (boolval != -1) curauth->require_ssl = boolval; SET_CONFIG(PERMrequire_ssl); break; #endif case PERMhost: curauth->hosts = xstrdup(tok->name); CompressList(curauth->hosts); SET_CONFIG(PERMhost); /* nnrpd.c downcases the names of connecting hosts. We should * therefore also downcase the wildmat patterns to make sure there * aren't any surprises. DNS is case-insensitive. */ for (p = curauth->hosts; *p; p++) if (isupper((unsigned char) *p)) *p = tolower((unsigned char) *p); break; case PERMdefdomain: curauth->default_domain = xstrdup(tok->name); SET_CONFIG(PERMdefdomain); break; case PERMdefuser: curauth->default_user = xstrdup(tok->name); SET_CONFIG(PERMdefuser); break; case PERMresolv: case PERMresprog: m = xcalloc(1, sizeof(METHOD)); memset(ConfigBit, '\0', ConfigBitsize); GrowArray(&curauth->res_methods, m); if (oldtype == PERMresprog) m->program = xstrdup(tok->name); else { m->name = xstrdup(tok->name); tok = CONFgettoken(PERMtoks, f); if (tok == NULL || tok->type != PERMlbrace) { ReportError(f, "Expected '{' after 'res'."); } tok = CONFgettoken(PERMtoks, f); while (tok != NULL && tok->type != PERMrbrace) { method_parse(m, f, tok, 0); tok = CONFgettoken(PERMtoks, f); } if (m->program == NULL) { ReportError(f, "Missing 'program:' key."); } if (tok == NULL) { ReportError(f, "Unexpected EOF."); } } break; case PERMauth: case PERMperl_auth: case PERMpython_auth: case PERMauthprog: m = xcalloc(1, sizeof(METHOD)); memset(ConfigBit, '\0', ConfigBitsize); GrowArray(&curauth->auth_methods, m); if (oldtype == PERMauthprog) { m->type = PERMauthprog; m->program = xstrdup(tok->name); } else if (oldtype == PERMperl_auth) { #ifdef DO_PERL m->type = PERMperl_auth; m->program = xstrdup(tok->name); #else ReportError(f, "perl_auth can not be used in readers.conf: INN not compiled with Perl support enabled."); #endif } else if (oldtype == PERMpython_auth) { #ifdef DO_PYTHON m->type = PERMpython_auth; m->program = xstrdup(tok->name); #else ReportError(f, "python_auth can not be used in readers.conf: INN not compiled with Python support enabled."); #endif } else { m->name = xstrdup(tok->name); tok = CONFgettoken(PERMtoks, f); if (tok == NULL || tok->type != PERMlbrace) { ReportError(f, "Expected '{' after 'auth'."); } tok = CONFgettoken(PERMtoks, f); while (tok != NULL && tok->type != PERMrbrace) { method_parse(m, f, tok, 1); tok = CONFgettoken(PERMtoks, f); } if (tok == NULL) { ReportError(f, "Unexpected EOF."); } } break; case PERMperl_access: #ifdef DO_PERL curauth->access_script = xstrdup(tok->name); curauth->access_type = PERMperl_access; #else ReportError(f, "perl_access can not be used in readers.conf: INN not compiled with Perl support enabled."); #endif break; case PERMpython_access: #ifdef DO_PYTHON curauth->access_script = xstrdup(tok->name); curauth->access_type = PERMpython_access; #else ReportError(f, "python_access can not be used in readers.conf: INN not compiled with Python support enabled."); #endif break; case PERMpython_dynamic: #ifdef DO_PYTHON curauth->dynamic_script = xstrdup(tok->name); curauth->dynamic_type = PERMpython_dynamic; #else ReportError(f, "python_dynamic can not be used in readers.conf: INN not compiled with Python support enabled."); #endif break; case PERMlocaladdress: curauth->localaddress = xstrdup(tok->name); CompressList(curauth->localaddress); SET_CONFIG(PERMlocaladdress); break; default: snprintf(buff, sizeof(buff), "Unexpected token '%s'.", tok->name); ReportError(f, buff); break; } } static void accessdecl_parse(ACCESSGROUP *curaccess, CONFFILE *f, CONFTOKEN *tok) { int oldtype, boolval; bool bit; char buff[SMBUF], *oldname; oldtype = tok->type; oldname = tok->name; tok = CONFgettoken(0, f); if (tok == NULL) { ReportError(f, "Expected value."); } TEST_CONFIG(oldtype, bit); if (bit) { snprintf(buff, sizeof(buff), "Duplicated '%s' field in access group.", oldname); ReportError(f, buff); } if (strcasecmp(tok->name, "on") == 0 || strcasecmp(tok->name, "true") == 0 || strcasecmp(tok->name, "yes") == 0) boolval = true; else if (strcasecmp(tok->name, "off") == 0 || strcasecmp(tok->name, "false") == 0 || strcasecmp(tok->name, "no") == 0) boolval = false; else boolval = -1; switch (oldtype) { case PERMkey: curaccess->key = xstrdup(tok->name); SET_CONFIG(oldtype); break; case PERMusers: curaccess->users = xstrdup(tok->name); CompressList(curaccess->users); SET_CONFIG(oldtype); break; case PERMrejectwith: curaccess->rejectwith = xstrdup(tok->name); SET_CONFIG(oldtype); break; case PERMnewsgroups: TEST_CONFIG(PERMread, bit); if (bit) { /* Syntax error... can't set read: or post: _and_ use * newsgroups:. */ ReportError(f, "read: newsgroups already set."); } TEST_CONFIG(PERMpost, bit); if (bit) { /* Syntax error... can't set read: or post: _and_ use * newsgroups:. */ ReportError(f, "post: newsgroups already set."); } curaccess->read = xstrdup(tok->name); CompressList(curaccess->read); curaccess->post = xstrdup(tok->name); CompressList(curaccess->post); SET_CONFIG(oldtype); SET_CONFIG(PERMread); SET_CONFIG(PERMpost); break; case PERMread: curaccess->read = xstrdup(tok->name); CompressList(curaccess->read); SET_CONFIG(oldtype); break; case PERMpost: curaccess->post = xstrdup(tok->name); CompressList(curaccess->post); SET_CONFIG(oldtype); break; case PERMaccessrp: TEST_CONFIG(PERMread, bit); if (bit && strchr(tok->name, 'R') == NULL) { free(curaccess->read); curaccess->read = 0; CLEAR_CONFIG(PERMread); } TEST_CONFIG(PERMpost, bit); if (bit && strchr(tok->name, 'P') == NULL) { free(curaccess->post); curaccess->post = 0; CLEAR_CONFIG(PERMpost); } curaccess->allowapproved = (strchr(tok->name, 'A') != NULL); curaccess->allownewnews = (strchr(tok->name, 'N') != NULL); curaccess->allowihave = (strchr(tok->name, 'I') != NULL); curaccess->locpost = (strchr(tok->name, 'L') != NULL); SET_CONFIG(oldtype); break; case PERMlocaltime: if (boolval != -1) curaccess->localtime = boolval; SET_CONFIG(oldtype); break; case PERMstrippath: if (boolval != -1) curaccess->strippath = boolval; SET_CONFIG(oldtype); break; case PERMnnrpdperlfilter: if (boolval != -1) curaccess->nnrpdperlfilter = boolval; SET_CONFIG(oldtype); break; case PERMnnrpdpythonfilter: if (boolval != -1) curaccess->nnrpdpythonfilter = boolval; SET_CONFIG(oldtype); break; case PERMfromhost: if (curaccess->fromhost) free(curaccess->fromhost); curaccess->fromhost = xstrdup(tok->name); SET_CONFIG(oldtype); break; case PERMpathhost: if (curaccess->pathhost) free(curaccess->pathhost); curaccess->pathhost = xstrdup(tok->name); SET_CONFIG(oldtype); break; case PERMorganization: if (curaccess->organization) free(curaccess->organization); curaccess->organization = xstrdup(tok->name); SET_CONFIG(oldtype); break; case PERMmoderatormailer: if (curaccess->moderatormailer) free(curaccess->moderatormailer); curaccess->moderatormailer = xstrdup(tok->name); SET_CONFIG(oldtype); break; case PERMdomain: if (curaccess->domain) free(curaccess->domain); curaccess->domain = xstrdup(tok->name); SET_CONFIG(oldtype); break; case PERMcomplaints: if (curaccess->complaints) free(curaccess->complaints); curaccess->complaints = xstrdup(tok->name); SET_CONFIG(oldtype); break; case PERMspoolfirst: if (boolval != -1) curaccess->spoolfirst = boolval; SET_CONFIG(oldtype); break; case PERMcheckincludedtext: if (boolval != -1) curaccess->checkincludedtext = boolval; SET_CONFIG(oldtype); break; case PERMclienttimeout: curaccess->clienttimeout = atoi(tok->name); SET_CONFIG(oldtype); break; case PERMlocalmaxartsize: curaccess->localmaxartsize = strtoul(tok->name, NULL, 10); SET_CONFIG(oldtype); break; case PERMreadertrack: if (boolval != -1) curaccess->readertrack = boolval; SET_CONFIG(oldtype); break; case PERMstrippostcc: if (boolval != -1) curaccess->strippostcc = boolval; SET_CONFIG(oldtype); break; case PERMaddinjectiondate: if (boolval != -1) curaccess->addinjectiondate = boolval; SET_CONFIG(oldtype); break; case PERMaddinjectionpostingaccount: if (boolval != -1) curaccess->addinjectionpostingaccount = boolval; SET_CONFIG(oldtype); break; case PERMaddinjectionpostinghost: if (boolval != -1) curaccess->addinjectionpostinghost = boolval; SET_CONFIG(oldtype); break; case PERMnnrpdposthost: if (curaccess->nnrpdposthost) free(curaccess->nnrpdposthost); curaccess->nnrpdposthost = xstrdup(tok->name); SET_CONFIG(oldtype); break; case PERMnnrpdpostport: curaccess->nnrpdpostport = strtoul(tok->name, NULL, 10); SET_CONFIG(oldtype); break; case PERMnnrpdoverstats: if (boolval != -1) curaccess->nnrpdoverstats = boolval; SET_CONFIG(oldtype); break; case PERMbackoff_auth: if (boolval != -1) curaccess->backoff_auth = boolval; SET_CONFIG(oldtype); break; case PERMbackoff_db: if (curaccess->backoff_db) free(curaccess->backoff_db); curaccess->backoff_db = xstrdup(tok->name); SET_CONFIG(oldtype); break; case PERMbackoff_k: curaccess->backoff_k = strtoul(tok->name, NULL, 10); SET_CONFIG(oldtype); break; case PERMbackoff_postfast: curaccess->backoff_postfast = strtoul(tok->name, NULL, 10); SET_CONFIG(oldtype); break; case PERMbackoff_postslow: curaccess->backoff_postslow = strtoul(tok->name, NULL, 10); SET_CONFIG(oldtype); break; case PERMbackoff_trigger: curaccess->backoff_trigger = strtoul(tok->name, NULL, 10); SET_CONFIG(oldtype); break; case PERMnnrpdcheckart: if (boolval != -1) curaccess->nnrpdcheckart = boolval; SET_CONFIG(oldtype); break; case PERMnnrpdauthsender: if (boolval != -1) curaccess->nnrpdauthsender = boolval; SET_CONFIG(oldtype); break; case PERMvirtualhost: if (boolval != -1) curaccess->virtualhost = boolval; SET_CONFIG(oldtype); break; case PERMnewsmaster: if (curaccess->newsmaster) free(curaccess->newsmaster); curaccess->newsmaster = xstrdup(tok->name); SET_CONFIG(oldtype); break; case PERMmaxbytespersecond: curaccess->maxbytespersecond = atol(tok->name); SET_CONFIG(oldtype); break; default: snprintf(buff, sizeof(buff), "Unexpected token '%s'.", tok->name); ReportError(f, buff); break; } } static void PERMvectortoaccess(ACCESSGROUP *acc, const char *name, struct vector *access_vec) { CONFTOKEN *tok = NULL; CONFFILE *file; char *str; unsigned int i; file = xcalloc(1, sizeof(CONFFILE)); file->array = access_vec->strings; file->array_len = access_vec->count; memset(ConfigBit, '\0', ConfigBitsize); SetDefaultAccess(acc); str = xstrdup(name); acc->name = str; file->filename = str; for (i = 0; i <= access_vec->count; i++) { tok = CONFgettoken(PERMtoks, file); if (tok != NULL) { accessdecl_parse(acc, file, tok); } } /* No need to free str here; it is used by acc, and will be * free'd when the access block is free'd. */ free(file); return; } static void PERMreadfile(char *filename) { CONFCHAIN *cf = NULL, *hold = NULL; CONFTOKEN *tok = NULL; int inwhat; GROUP *curgroup = NULL, *newgroup = NULL; ACCESSGROUP *curaccess = NULL; AUTHGROUP *curauth = NULL; int oldtype; char *str = NULL; char *path = NULL; char buff[SMBUF]; if(filename != NULL) { syslog(L_TRACE, "Reading access from %s", filename == NULL ? "(NULL)" : filename); } cf = xmalloc(sizeof(CONFCHAIN)); if ((cf->f = CONFfopen(filename)) == NULL) { syslog(L_ERROR, "%s cannot open %s: %m", Client.host, filename); Reply("%d NNTP server unavailable. Try later!\r\n", NNTP_FAIL_TERMINATING); ExitWithStats(1, true); } cf->parent = 0; /* Are we editing an auth or access group? */ inwhat = 0; curgroup = 0; tok = CONFgettoken(PERMtoks, cf->f); while (tok != NULL) { if (inwhat == 0) { /* Top-level parser. */ switch (tok->type) { /* Include a child file. */ case PERMinclude: tok = CONFgettoken(0, cf->f); if (tok == NULL) { ReportError(cf->f, "Expected filename after 'include'."); } hold = xmalloc(sizeof(CONFCHAIN)); hold->parent = cf; /* Unless the filename's path is fully qualified, open it * relative to . */ path = concatpath(innconf->pathetc, tok->name); hold->f = CONFfopen(path); free(path); if (hold->f == NULL) { ReportError(cf->f, "Could not open 'include' filename."); } cf = hold; goto again; break; /* Nested group declaration. */ case PERMgroup: tok = CONFgettoken(PERMtoks, cf->f); if (tok == NULL) { ReportError(cf->f, "Unexpected EOF at group name."); } newgroup = xmalloc(sizeof(GROUP)); newgroup->above = curgroup; newgroup->name = xstrdup(tok->name); memset(ConfigBit, '\0', ConfigBitsize); tok = CONFgettoken(PERMtoks, cf->f); if (tok == NULL || tok->type != PERMlbrace) { ReportError(cf->f, "Expected '{' after group name."); } /* Nested group declaration. */ if (curgroup) { newgroup->auth = copy_authgroup(curgroup->auth); newgroup->access = copy_accessgroup(curgroup->access); } else { newgroup->auth = 0; newgroup->access = 0; } curgroup = newgroup; break; /* Beginning of an auth or access group declaration. */ case PERMauth: case PERMaccess: oldtype = tok->type; if ((tok = CONFgettoken(PERMtoks, cf->f)) == NULL) { ReportError(cf->f, "Expected identifier."); } str = xstrdup(tok->name); tok = CONFgettoken(PERMtoks, cf->f); if (tok == NULL || tok->type != PERMlbrace) { ReportError(cf->f, "Expected '{'."); } switch (oldtype) { case PERMauth: if (curgroup && curgroup->auth) { curauth = copy_authgroup(curgroup->auth); } else { curauth = xcalloc(1, sizeof(AUTHGROUP)); memset(ConfigBit, '\0', ConfigBitsize); SetDefaultAuth(curauth); } curauth->name = str; inwhat = 1; break; case PERMaccess: if (curgroup && curgroup->access) curaccess = copy_accessgroup(curgroup->access); else { curaccess = xcalloc(1, sizeof(ACCESSGROUP)); memset(ConfigBit, '\0', ConfigBitsize); SetDefaultAccess(curaccess); } curaccess->name = str; inwhat = 2; break; } break; /* End of a group declaration. */ case PERMrbrace: if (curgroup == NULL) { ReportError(cf->f, "Unmatched '}'."); } newgroup = curgroup; curgroup = curgroup->above; if (newgroup->auth) free_authgroup(newgroup->auth); if (newgroup->access) free_accessgroup(newgroup->access); free(newgroup->name); free(newgroup); break; /* Stuff that belongs to an auth group. */ case PERMhost: #if defined(HAVE_OPENSSL) || defined(HAVE_SASL) case PERMrequire_ssl: #endif case PERMauthprog: case PERMresprog: case PERMdefuser: case PERMdefdomain: if (curgroup == NULL) { curgroup = xcalloc(1, sizeof(GROUP)); memset(ConfigBit, '\0', ConfigBitsize); } if (curgroup->auth == NULL) { curgroup->auth = xcalloc(1, sizeof(AUTHGROUP)); memset(ConfigBit, '\0', ConfigBitsize); SetDefaultAuth(curgroup->auth); } authdecl_parse(curgroup->auth, cf->f, tok); break; /* Stuff that belongs to an access group. */ case PERMusers: case PERMrejectwith: case PERMnewsgroups: case PERMread: case PERMpost: case PERMaccessrp: case PERMlocaltime: case PERMstrippath: case PERMnnrpdperlfilter: case PERMnnrpdpythonfilter: case PERMfromhost: case PERMpathhost: case PERMorganization: case PERMmoderatormailer: case PERMdomain: case PERMcomplaints: case PERMspoolfirst: case PERMcheckincludedtext: case PERMclienttimeout: case PERMlocalmaxartsize: case PERMreadertrack: case PERMstrippostcc: case PERMaddinjectiondate: case PERMaddinjectionpostingaccount: case PERMaddinjectionpostinghost: case PERMnnrpdposthost: case PERMnnrpdpostport: case PERMnnrpdoverstats: case PERMbackoff_auth: case PERMbackoff_db: case PERMbackoff_k: case PERMbackoff_postfast: case PERMbackoff_postslow: case PERMbackoff_trigger: case PERMnnrpdcheckart: case PERMnnrpdauthsender: case PERMvirtualhost: case PERMnewsmaster: if (!curgroup) { curgroup = xcalloc(1, sizeof(GROUP)); memset(ConfigBit, '\0', ConfigBitsize); } if (!curgroup->access) { curgroup->access = xcalloc(1, sizeof(ACCESSGROUP)); memset(ConfigBit, '\0', ConfigBitsize); SetDefaultAccess(curgroup->access); } accessdecl_parse(curgroup->access, cf->f, tok); break; default: snprintf(buff, sizeof(buff), "Unexpected token: %s", tok->name); ReportError(cf->f, buff); break; } } else if (inwhat == 1) { /* Auth group parser. */ if (tok->type == PERMrbrace) { inwhat = 0; if (curauth->name && MatchHost(curauth->hosts, Client.host, Client.ip)) { if (!MatchHost(curauth->localaddress, Client.serverhost, Client.serverip)) { syslog(L_TRACE, "Auth strategy '%s' does not match localhost. Removing.", curauth->name == NULL ? "(NULL)" : curauth->name); free_authgroup(curauth); } else add_authgroup(curauth); } else { syslog(L_TRACE, "Auth strategy '%s' does not match client. Removing.", curauth->name == NULL ? "(NULL)" : curauth->name); free_authgroup(curauth); } curauth = NULL; goto again; } authdecl_parse(curauth, cf->f, tok); } else if (inwhat == 2) { /* Access group parser. */ if (tok->type == PERMrbrace) { inwhat = 0; if (curaccess->name) add_accessgroup(curaccess); else free_accessgroup(curaccess); curaccess = NULL; goto again; } accessdecl_parse(curaccess, cf->f, tok); } else { /* Should never happen. */ syslog(L_TRACE, "SHOULD NEVER HAPPEN!"); } again: /* Go back up the 'include' chain. */ tok = CONFgettoken(PERMtoks, cf->f); while (tok == NULL && cf) { hold = cf; cf = hold->parent; CONFfclose(hold->f); free(hold); if (cf) { tok = CONFgettoken(PERMtoks, cf->f); } } } return; } void PERMgetinitialaccess(char *readersconf) { int i; auth_realms = NULL; access_realms = NULL; success_auth = NULL; #ifdef HAVE_SASL PERMcanauthenticate = true; #else PERMcanauthenticate = false; #endif #if defined(HAVE_OPENSSL) || defined(HAVE_SASL) PERMcanauthenticatewithoutSSL = false; #endif PERMgroupmadeinvalid = false; PERMcanpostgreeting = false; PERMcanread = PERMcanpost = false; PERMreadlist = PERMpostlist = NULL; PERMaccessconf = NULL; if (ConfigBit == NULL) { if (PERMMAX % 8 == 0) { ConfigBitsize = PERMMAX/8; } else { ConfigBitsize = (PERMMAX - (PERMMAX % 8))/8 + 1; } ConfigBit = xcalloc(ConfigBitsize, 1); } /* Parse the readers.conf file. */ PERMreadfile(readersconf); /* Remove unused access groups. */ strip_accessgroups(); if (auth_realms == NULL) { /* No one can talk, empty file. */ syslog(L_NOTICE, "%s no_permission", Client.host); Reply("%d You have no permission to talk. Goodbye!\r\n", NNTP_ERR_ACCESS); ExitWithStats(1, true); } /* auth_realms are all expected to match the user. * Be careful whether an encryption layer is required, though. */ for (i = 0; auth_realms[i] != NULL; i++) { if (auth_realms[i]->auth_methods != NULL) { PERMcanauthenticate = true; #if defined(HAVE_OPENSSL) || defined(HAVE_SASL) if (!auth_realms[i]->require_ssl) PERMcanauthenticatewithoutSSL = true; #endif } /* We assume that an access or dynamic script will allow * the user to post when authenticated, so that a 200 greeting * code can be sent. */ if (auth_realms[i]->access_script != NULL || auth_realms[i]->dynamic_script != NULL) PERMcanpostgreeting = true; } } void PERMgetaccess(bool initialconnection) { char *uname; int i; if (ConfigBit == NULL) { if (PERMMAX % 8 == 0) { ConfigBitsize = PERMMAX/8; } else { ConfigBitsize = (PERMMAX - (PERMMAX % 8))/8 + 1; } ConfigBit = xcalloc(ConfigBitsize, 1); } if (auth_realms == NULL) { return; } for (i = 0; auth_realms[i] != NULL; i++) { ; } uname = NULL; while (uname == NULL && i-- > 0) { #if defined(HAVE_OPENSSL) || defined(HAVE_SASL) /* If an encryption layer is required, check that the connection * really uses one. */ if (auth_realms[i]->require_ssl && !encryption_layer_on) { continue; } #endif if ((uname = ResolveUser(auth_realms[i])) != NULL) { PERMauthorized = true; } if (uname == NULL && auth_realms[i]->default_user != NULL) { uname = xstrdup(auth_realms[i]->default_user); } } if (uname != NULL) { strlcpy(PERMuser, uname, sizeof(PERMuser)); free(uname); uname = strchr(PERMuser, '@'); if (uname == NULL && auth_realms[i]->default_domain != NULL) { /* Append the default domain to the username. */ strlcat(PERMuser, "@", sizeof(PERMuser)); strlcat(PERMuser, auth_realms[i]->default_domain, sizeof(PERMuser)); } PERMneedauth = false; success_auth = auth_realms[i]; syslog(L_TRACE, "%s res %s", Client.host, PERMuser); } else if (initialconnection && !PERMcanauthenticate) { /* Couldn't resolve the user. */ syslog(L_NOTICE, "%s no_user", Client.host); Reply("%d Could not get your access name. Goodbye!\r\n", NNTP_ERR_ACCESS); ExitWithStats(1, true); } else { PERMneedauth = true; } if (initialconnection) { /* Check maximum allowed permissions for any host that matches (for * the greeting string). */ for (i = 0; access_realms[i] != NULL; i++) { if (!PERMcanread) { PERMcanread = (access_realms[i]->read != NULL); } if (!PERMcanpost) { PERMcanpost = (access_realms[i]->post != NULL); } if (!PERMcanpostgreeting) { PERMcanpostgreeting = (access_realms[i]->post != NULL); } } if (i == 0) { /* No applicable access groups. Zeroing all these makes INN * return permission denied to client. */ PERMcanread = PERMcanpost = PERMneedauth = false; } } } void PERMlogin(char *uname, char *pass, int *code, char *errorstr) { int i = 0; char *runame; if (ConfigBit == NULL) { if (PERMMAX % 8 == 0) ConfigBitsize = PERMMAX/8; else ConfigBitsize = (PERMMAX - (PERMMAX % 8))/8 + 1; ConfigBit = xcalloc(ConfigBitsize, 1); } /* The check in CMDauthinfo uses the value of PERMneedauth to know if * authentication succeeded or not. By default, authentication doesn't * succeed. */ PERMneedauth = true; if(auth_realms != NULL) { for (i = 0; auth_realms[i]; i++) { ; } } runame = NULL; while (runame == NULL && i--) runame = AuthenticateUser(auth_realms[i], uname, pass, code, errorstr); if (runame) { strlcpy(PERMuser, runame, sizeof(PERMuser)); free(runame); uname = strchr(PERMuser, '@'); if (!uname && auth_realms[i]->default_domain) { /* Append the default domain to the username. */ strlcat(PERMuser, "@", sizeof(PERMuser)); strlcat(PERMuser, auth_realms[i]->default_domain, sizeof(PERMuser)); } PERMneedauth = false; PERMauthorized = true; PERMcanauthenticate = false; success_auth = auth_realms[i]; } } static int MatchUser(char *pat, char *user) { char *cp, **list; char *userlist[2]; int ret; if (!pat) return(1); if (!user || !*user) return(0); cp = xstrdup(pat); list = 0; NGgetlist(&list, cp); userlist[0] = user; userlist[1] = 0; ret = PERMmatch(list, userlist); free(cp); free(list[0]); free(list); return(ret); } void PERMgetpermissions(void) { int i; char *cp, **list; char *user[2]; static ACCESSGROUP *noaccessconf; if (ConfigBit == NULL) { if (PERMMAX % 8 == 0) ConfigBitsize = PERMMAX/8; else ConfigBitsize = (PERMMAX - (PERMMAX % 8))/8 + 1; ConfigBit = xcalloc(ConfigBitsize, 1); } if (!success_auth) { /* If we haven't successfully authenticated, we can't do anything. */ syslog(L_TRACE, "%s no_success_auth", Client.host); if (!noaccessconf) noaccessconf = xmalloc(sizeof(ACCESSGROUP)); PERMaccessconf = noaccessconf; SetDefaultAccess(PERMaccessconf); return; #ifdef DO_PERL } else if ((success_auth->access_script != NULL) && (success_auth->access_type == PERMperl_access)) { char *uname; char *cpp, *script_path; char **args; struct vector *access_vec; i = 0; cpp = xstrdup(success_auth->access_script); args = 0; Argify(cpp, &args); script_path = concat(args[0], (char *) 0); if ((script_path != NULL) && (strlen(script_path) > 0)) { if(!PerlLoaded) { loadPerl(); } PERLsetup(NULL, script_path, "access"); free(script_path); uname = xstrdup(PERMuser); access_vec = vector_new(); perlAccess(uname, access_vec); free(uname); access_realms[0] = xcalloc(1, sizeof(ACCESSGROUP)); PERMvectortoaccess(access_realms[0], "perl_access-block", access_vec); vector_free(access_vec); } else { syslog(L_ERROR, "No script specified in perl_access method.\n"); Reply("%d NNTP server unavailable. Try later!\r\n", NNTP_FAIL_TERMINATING); ExitWithStats(1, true); } free(cpp); free(args); #endif /* DO_PERL */ #ifdef DO_PYTHON } else if ((success_auth->access_script != NULL) && (success_auth->access_type == PERMpython_access)) { char *uname; char *cpp, *script_path; char **args; struct vector *access_vec; i = 0; cpp = xstrdup(success_auth->access_script); args = 0; Argify(cpp, &args); script_path = concat(args[0], (char *) 0); if ((script_path != NULL) && (strlen(script_path) > 0)) { uname = xstrdup(PERMuser); access_vec = vector_new(); PY_access(script_path, access_vec, uname); free(script_path); free(uname); free(args); access_realms[0] = xcalloc(1, sizeof(ACCESSGROUP)); memset(access_realms[0], 0, sizeof(ACCESSGROUP)); PERMvectortoaccess(access_realms[0], "python_access-block", access_vec); vector_free(access_vec); } else { syslog(L_ERROR, "No script specified in python_access method.\n"); Reply("%d NNTP server unavailable. Try later!\r\n", NNTP_FAIL_TERMINATING); ExitWithStats(1, true); } free(cpp); #endif /* DO_PYTHON */ } else { for (i = 0; access_realms[i]; i++) ; user[0] = PERMuser; user[1] = 0; while (i--) { if ((!success_auth->key && !access_realms[i]->key) || (access_realms[i]->key && success_auth->key && strcmp(access_realms[i]->key, success_auth->key) == 0)) { if (!access_realms[i]->users) break; else if (!*PERMuser) continue; cp = xstrdup(access_realms[i]->users); list = 0; NGgetlist(&list, cp); if (PERMmatch(list, user)) { syslog(L_TRACE, "%s match_user %s %s", Client.host, PERMuser, access_realms[i]->users); free(cp); free(list[0]); free(list); break; } else syslog(L_TRACE, "%s no_match_user %s %s", Client.host, PERMuser, access_realms[i]->users); free(cp); free(list[0]); free(list); } } } if (i >= 0) { /* Found the right access group. */ if (access_realms[i]->rejectwith) { syslog(L_NOTICE, "%s rejected by rule (%s)", Client.host, access_realms[i]->rejectwith); Reply("%d Permission denied: %s\r\n", NNTP_FAIL_TERMINATING, access_realms[i]->rejectwith); ExitWithStats(1, true); } if (access_realms[i]->read) { cp = xstrdup(access_realms[i]->read); PERMspecified = NGgetlist(&PERMreadlist, cp); free(cp); PERMcanread = true; } else { syslog(L_TRACE, "%s no_read %s", Client.host, access_realms[i]->name); PERMcanread = false; } if (access_realms[i]->post) { cp = xstrdup(access_realms[i]->post); NGgetlist(&PERMpostlist, cp); free(cp); PERMcanpost = true; } else { syslog(L_TRACE, "%s no_post %s", Client.host, access_realms[i]->name); PERMcanpost = false; } PERMaccessconf = access_realms[i]; MaxBytesPerSecond = PERMaccessconf->maxbytespersecond; if (PERMaccessconf->virtualhost) { if (PERMaccessconf->domain == NULL) { syslog(L_ERROR, "%s virtualhost needs domain parameter (%s).", Client.host, PERMaccessconf->name); Reply("%d NNTP server unavailable. Try later!\r\n", NNTP_FAIL_TERMINATING); ExitWithStats(1, true); } if (VirtualPath) free(VirtualPath); if (strcasecmp(innconf->pathhost, PERMaccessconf->pathhost) == 0) { /* Use domain, if pathhost in access realm matches one in * inn.conf to differentiate virtual host. */ if (innconf->domain != NULL && strcasecmp(innconf->domain, PERMaccessconf->domain) == 0) { syslog(L_ERROR, "%s domain parameter (%s) in readers.conf must be different from the one in inn.conf.", Client.host, PERMaccessconf->name); Reply("%d NNTP server unavailable. Try later!\r\n", NNTP_FAIL_TERMINATING); ExitWithStats(1, true); } VirtualPath = concat(PERMaccessconf->domain, "!", (char *) 0); } else { VirtualPath = concat(PERMaccessconf->pathhost, "!", (char *) 0); } VirtualPathlen = strlen(VirtualPath); } else VirtualPathlen = 0; } else { if (!noaccessconf) noaccessconf = xmalloc(sizeof(ACCESSGROUP)); PERMaccessconf = noaccessconf; SetDefaultAccess(PERMaccessconf); syslog(L_TRACE, "%s no_access_realm", Client.host); } /* Check if dynamic access control is enabled; if so, init it. */ #ifdef DO_PYTHON if ((success_auth->dynamic_type == PERMpython_dynamic) && success_auth->dynamic_script) { PY_dynamic_init(success_auth->dynamic_script); } #endif /* DO_PYTHON */ } /* Strip blanks out of a string. */ static void CompressList(char *list) { char *cpto; bool inword = false; for (cpto = list; *list; ) { if (strchr("\n \t,", *list) != NULL) { list++; if(inword) { *cpto++ = ','; inword = false; } } else { *cpto++ = *list++; inword = true; } } *cpto = '\0'; } static bool MatchHost(char *hostlist, char *host, char *ip) { int i; char *cp, *pat, *mask; char **list = NULL; bool match = false; /* If no hostlist are specified, by default they match. */ if (hostlist == NULL) return true; cp = xstrdup(hostlist); NGgetlist(&list, cp); /* Start searching from the end of the list. The default is no access. */ for (i = 0; list[i] != NULL; i++) ; while (!match && i-- > 0) { pat = list[i]; match = uwildmat(host, pat); if (!match && ip != NULL && *ip != '\0') { match = uwildmat(ip, pat); if (match) break; mask = strchr(pat, '/'); if (mask == NULL) continue; *mask = '\0'; mask++; match = network_addr_match(ip, pat, mask); } } free(list[0]); free(list); free(cp); return match; } static void add_authgroup(AUTHGROUP *group) { int i; if (auth_realms == NULL) { i = 0; auth_realms = xmalloc(2 * sizeof(AUTHGROUP *)); } else { for (i = 0; auth_realms[i]; i++) ; auth_realms = xrealloc(auth_realms, (i + 2) * sizeof(AUTHGROUP *)); } auth_realms[i] = group; auth_realms[i+1] = 0; } static void add_accessgroup(ACCESSGROUP *group) { int i; if (access_realms == NULL) { i = 0; access_realms = xmalloc(2 * sizeof(ACCESSGROUP *)); } else { for (i = 0; access_realms[i]; i++) ; access_realms = xrealloc(access_realms, (i + 2) * sizeof(ACCESSGROUP *)); } access_realms[i] = group; access_realms[i+1] = 0; } /* ** Clean out access groups that don't apply to any of our auth groups. */ static void strip_accessgroups(void) { int i, j; /* Flag the access group as used or not. */ if(access_realms != NULL) { for (j = 0; access_realms[j] != NULL; j++) { access_realms[j]->used = 0; } } else { syslog(L_TRACE, "No access realms to check!"); return; } /* If there are auth realms to check... */ if(auth_realms != NULL) { /* ... Then for each auth realm... */ for (i = 0; auth_realms[i] != NULL; i++) { /* ... for each access realm... */ for (j = 0; access_realms[j] != NULL; j++) { /* If the access realm isn't already in use... */ if (! access_realms[j]->used) { /* Check to see if both the access_realm key and * auth_realm key are NULL... */ if (!access_realms[j]->key && !auth_realms[i]->key) { /* If so, mark the realm in use and continue on... */ access_realms[j]->used = 1; } else { /* If not, check to see if both the access_realm and auth_realm are NOT _both_ NULL, and see if they are equal... */ if (access_realms[j]->key && auth_realms[i]->key && strcmp(access_realms[j]->key, auth_realms[i]->key) == 0) { /* And if so, mark the realm in use. */ access_realms[j]->used = 1; } } } } } } else { syslog(L_TRACE, "No auth realms to check!"); } /* Strip out unused access groups. */ i = j = 0; while (access_realms[i] != NULL) { if (access_realms[i]->used) access_realms[j++] = access_realms[i]; else syslog(L_TRACE, "%s removing irrelevant access group %s", Client.host, access_realms[i]->name); i++; } access_realms[j] = 0; } /* ** Execute a series of resolvers to get the remote username. If one is ** found, return it in newly allocated space; otherwise, return NULL. */ static char * ResolveUser(AUTHGROUP *auth) { int i, j; char *command; char *user = NULL; char *resdir; char *tmp; if (auth->res_methods == NULL) return NULL; #if defined(HAVE_OPENSSL) || defined(HAVE_SASL) /* If an encryption layer is required, check that the connection * really uses one. */ if (auth->require_ssl && !encryption_layer_on) return NULL; #endif tmp = concatpath(innconf->pathbin, INN_PATH_AUTHDIR); resdir = concatpath(tmp, INN_PATH_AUTHDIR_NOPASS); free(tmp); for (i = 0; auth->res_methods[i]; i++) { command = auth->res_methods[i]->program; syslog(L_TRACE, "%s res starting resolver %s", Client.host, command); if (auth->res_methods[i]->extra_logs) { for (j = 0; auth->res_methods[i]->extra_logs[j]; j++) syslog(L_NOTICE, "%s res also-log: %s", Client.host, auth->res_methods[i]->extra_logs[j]); } user = auth_external(&Client, command, resdir, NULL, NULL); if (user == NULL) syslog(L_TRACE, "%s res resolver failed", Client.host); else { syslog(L_TRACE, "%s res resolver successful, user %s", Client.host, user); break; } } free(resdir); return user; } /* ** Execute a series of authenticators to get the remote username. If one is ** found, return it in newly allocated space; otherwise, return NULL. Also ** handles running the Perl and Python authentication functions. */ static char * AuthenticateUser(AUTHGROUP *auth, char *username, char *password, int *code UNUSED, char *errorstr UNUSED) { int i, j; char *command; char *user = NULL; char *resdir; char *tmp; if (auth->auth_methods == NULL) return NULL; #if defined(HAVE_OPENSSL) || defined(HAVE_SASL) /* If an encryption layer is required, check that the connection * really uses one. */ if (auth->require_ssl && !encryption_layer_on) return NULL; #endif tmp = concatpath(innconf->pathbin, INN_PATH_AUTHDIR); resdir = concatpath(tmp, INN_PATH_AUTHDIR_PASSWD); free(tmp); for (i = 0; auth->auth_methods[i]; i++) { if (auth->auth_methods[i]->type == PERMperl_auth) { #ifdef DO_PERL char *script_path, *cp; char **args; char newUser[BIG_BUFFER]; cp = xstrdup(auth->auth_methods[i]->program); args = 0; Argify(cp, &args); script_path = concat(args[0], (char *) 0); if ((script_path != NULL) && (strlen(script_path) > 0)) { if (!PerlLoaded) loadPerl(); PERLsetup(NULL, script_path, "authenticate"); free(script_path); perlAuthInit(); newUser[0] = '\0'; perlAuthenticate(username, password, code, errorstr, newUser); if (*code == NNTP_OK_AUTHINFO) { if (newUser[0] != '\0') user = xstrdup(newUser); else user = xstrdup(username); syslog(L_NOTICE, "%s user %s", Client.host, user); if (LLOGenable) { fprintf(locallog, "%s user %s\n", Client.host, user); fflush(locallog); } break; } else { syslog(L_NOTICE, "%s bad_auth", Client.host); } } else { syslog(L_ERROR, "no script specified in auth method"); } #endif /* DO_PERL */ } else if (auth->auth_methods[i]->type == PERMpython_auth) { #ifdef DO_PYTHON char *script_path, *cp; char **args; char newUser[BIG_BUFFER]; cp = xstrdup(auth->auth_methods[i]->program); args = 0; Argify(cp, &args); script_path = concat(args[0], (char *) 0); if ((script_path != NULL) && (strlen(script_path) > 0)) { newUser[0] = '\0'; PY_authenticate(script_path, username, password, code, errorstr, newUser); free(script_path); if (*code == NNTP_OK_AUTHINFO) { if (newUser[0] != '\0') user = xstrdup(newUser); else user = xstrdup(username); syslog(L_NOTICE, "%s user %s", Client.host, user); if (LLOGenable) { fprintf(locallog, "%s user %s\n", Client.host, user); fflush(locallog); } break; } else if (*code < 0) { syslog(L_NOTICE, "PY_authenticate(): authentication skipped due to no Python authentication method defined."); } else { syslog(L_NOTICE, "%s bad_auth", Client.host); } } else { syslog(L_ERROR, "no script specified in auth method"); } #endif /* DO_PYTHON */ } else { if (auth->auth_methods[i]->users && !MatchUser(auth->auth_methods[i]->users, username)) continue; command = auth->auth_methods[i]->program; syslog(L_TRACE, "%s res starting authenticator %s", Client.host, command); if (auth->auth_methods[i]->extra_logs) { for (j = 0; auth->auth_methods[i]->extra_logs[j]; j++) syslog(L_NOTICE, "%s auth also-log: %s", Client.host, auth->auth_methods[i]->extra_logs[j]); } user = auth_external(&Client, command, resdir, username, password); if (user == NULL) syslog(L_TRACE, "%s auth authenticator failed", Client.host); else { syslog(L_TRACE, "%s auth authenticator successful, user %s", Client.host, user); break; } } } free(resdir); return user; } inn-2.6.4/nnrpd/zlib.c0000644000175200017520000000526514002373703014155 0ustar iuliusiulius/* $Id: zlib.c 10135 2017-01-12 21:09:58Z iulius $ ** ** COMPRESS functionality. RFC 8054. */ #include "config.h" #include "clibrary.h" #include "inn/messages.h" #include "nnrpd.h" #if defined(HAVE_ZLIB) # define ZBUFSIZE 65536 # define MEM_LEVEL 9 # define WINDOW_BITS (-15) /* Raw deflate. */ bool compression_layer_on = false; bool tls_compression_on = false; z_stream *zstream_in = NULL; z_stream *zstream_out = NULL; bool zstream_inflate_needed = false; bool zstream_flush_needed = false; unsigned char *zbuf_in = NULL; unsigned char *zbuf_out = NULL; size_t zbuf_in_size = NNTP_MAXLEN_COMMAND; /* Initial size of the input * buffer. Can be reallocated. */ size_t zbuf_in_allocated = 0; size_t zbuf_out_size = ZBUFSIZE; /* Initial size of the output buffer. * Can be reallocated, when needed. */ /* ** Wrappers for our memory management functions. */ static voidpf zalloc(voidpf opaque UNUSED, uInt items, uInt size) { return (voidpf) xcalloc(items, size); } static void zfree(voidpf opaque UNUSED, voidpf address) { free(address); } /* ** The function called by nnrpd to initialize compression support. Calls ** both deflateInit2 and inflateInit2, and then checks the result. ** ** Returns false on error. */ bool zlib_init(void) { int result; zstream_in = (z_stream *) xmalloc(sizeof(z_stream)); zstream_out = (z_stream *) xmalloc(sizeof(z_stream)); /* Allocate the buffer for compressed input data given to inflate(). */ zbuf_in = (unsigned char *) xmalloc(zbuf_in_size); /* Allocate the buffer for compressed output data produced by deflate(). */ zbuf_out = (unsigned char *) xmalloc(zbuf_out_size); zstream_in->zalloc = zalloc; zstream_in->zfree = zfree; zstream_in->opaque = Z_NULL; zstream_in->next_in = Z_NULL; zstream_in->avail_in = 0; zstream_out->zalloc = zalloc; zstream_out->zfree = zfree; zstream_out->opaque = Z_NULL; result = inflateInit2(zstream_in, WINDOW_BITS); if (result != Z_OK) { syslog(L_NOTICE, "inflateInit2() failed with error %d", result); free(zstream_in); free(zstream_out); free(zbuf_in); free(zbuf_out); return false; } result = deflateInit2(zstream_out, Z_BEST_COMPRESSION, Z_DEFLATED, WINDOW_BITS, MEM_LEVEL, Z_DEFAULT_STRATEGY); if (result != Z_OK) { syslog(L_NOTICE, "deflateInit2() failed with error %d", result); inflateEnd(zstream_in); free(zstream_in); free(zstream_out); free(zbuf_in); free(zbuf_out); return false; } return true; } #endif /* HAVE_ZLIB */ inn-2.6.4/nnrpd/tls.c0000644000175200017520000006723214002373703014021 0ustar iuliusiulius/* $Id: tls.c 10348 2019-09-17 19:01:33Z iulius $ ** ** tls.c -- TLS functions. ** Copyright (C) 2000 Kenichi Okada . ** ** Author: Kenichi Okada ** Created: 2000-02-22 */ #include "config.h" #include "clibrary.h" #include #include #include #include "nnrpd.h" #include "inn/innconf.h" /* Outside the ifdef so that make depend works even ifndef HAVE_OPENSSL. */ #include "tls.h" #ifdef HAVE_OPENSSL /* We must keep some of the info available. */ static bool tls_initialized = false; static int verify_depth; static int verify_error = X509_V_OK; static int do_dump = 0; static SSL_CTX *CTX = NULL; SSL *tls_conn = NULL; #define CCERT_BUFSIZ 256 int tls_serverengine = 0; int tls_serveractive = 0; /* Available or not. */ char *tls_peer_subject = NULL; char *tls_peer_issuer = NULL; char *tls_peer_fingerprint = NULL; int tls_clientactive = 0; /* Available or not. */ char *tls_peer_CN= NULL; char *tls_issuer_CN = NULL; const char *tls_protocol = NULL; const char *tls_cipher_name = NULL; int tls_cipher_usebits = 0; int tls_cipher_algbits = 0; int tls_loglevel = 0; /* ** Taken from OpenSSL apps/s_cb.c. ** Tim -- this seems to just be giving logging messages. */ static void apps_ssl_info_callback(const SSL *s, int where, int ret) { const char *str; int w; if (tls_loglevel==0) return; w = where & ~SSL_ST_MASK; if (w & SSL_ST_CONNECT) str = "SSL_connect"; else if (w & SSL_ST_ACCEPT) str = "SSL_accept"; else str = "undefined"; if (where & SSL_CB_LOOP) { if (tls_serverengine && (tls_loglevel >= 2)) syslog(L_NOTICE, "%s:%s", str, SSL_state_string_long(s)); } else if (where & SSL_CB_ALERT) { str = (where & SSL_CB_READ) ? "read" : "write"; if ((tls_serverengine && (tls_loglevel >= 2)) || ((ret & 0xff) != SSL3_AD_CLOSE_NOTIFY)) syslog(L_NOTICE, "SSL3 alert %s:%s:%s", str, SSL_alert_type_string_long(ret), SSL_alert_desc_string_long(ret)); } else if (where & SSL_CB_EXIT) { if (ret == 0) syslog(L_ERROR, "%s:failed in %s", str, SSL_state_string_long(s)); else if (ret < 0) { syslog(L_ERROR, "%s:error in %s", str, SSL_state_string_long(s)); } } } /* ** Hardcoded DH parameter files. ** These are pre-defined DH groups recommended by RFC 7919 (Appendix A), ** that have been audited and therefore supposed to be more ** resistant to attacks than ones randomly generated. */ static const char file_ffdhe2048[] = \ "-----BEGIN DH PARAMETERS-----\n\ MIIBCAKCAQEA//////////+t+FRYortKmq/cViAnPTzx2LnFg84tNpWp4TZBFGQz\n\ +8yTnc4kmz75fS/jY2MMddj2gbICrsRhetPfHtXV/WVhJDP1H18GbtCFY2VVPe0a\n\ 87VXE15/V8k1mE8McODmi3fipona8+/och3xWKE2rec1MKzKT0g6eXq8CrGCsyT7\n\ YdEIqUuyyOP7uWrat2DX9GgdT0Kj3jlN9K5W7edjcrsZCwenyO4KbXCeAvzhzffi\n\ 7MA0BM0oNC9hkXL+nOmFg/+OTxIy7vKBg8P+OxtMb61zO7X8vC7CIAXFjvGDfRaD\n\ ssbzSibBsu/6iGtCOGEoXJf//////////wIBAg==\n\ -----END DH PARAMETERS-----\n"; static const char file_ffdhe4096[] = \ "-----BEGIN DH PARAMETERS-----\n\ MIICCAKCAgEA//////////+t+FRYortKmq/cViAnPTzx2LnFg84tNpWp4TZBFGQz\n\ +8yTnc4kmz75fS/jY2MMddj2gbICrsRhetPfHtXV/WVhJDP1H18GbtCFY2VVPe0a\n\ 87VXE15/V8k1mE8McODmi3fipona8+/och3xWKE2rec1MKzKT0g6eXq8CrGCsyT7\n\ YdEIqUuyyOP7uWrat2DX9GgdT0Kj3jlN9K5W7edjcrsZCwenyO4KbXCeAvzhzffi\n\ 7MA0BM0oNC9hkXL+nOmFg/+OTxIy7vKBg8P+OxtMb61zO7X8vC7CIAXFjvGDfRaD\n\ ssbzSibBsu/6iGtCOGEfz9zeNVs7ZRkDW7w09N75nAI4YbRvydbmyQd62R0mkff3\n\ 7lmMsPrBhtkcrv4TCYUTknC0EwyTvEN5RPT9RFLi103TZPLiHnH1S/9croKrnJ32\n\ nuhtK8UiNjoNq8Uhl5sN6todv5pC1cRITgq80Gv6U93vPBsg7j/VnXwl5B0rZp4e\n\ 8W5vUsMWTfT7eTDp5OWIV7asfV9C1p9tGHdjzx1VA0AEh/VbpX4xzHpxNciG77Qx\n\ iu1qHgEtnmgyqQdgCpGBMMRtx3j5ca0AOAkpmaMzy4t6Gh25PXFAADwqTs6p+Y0K\n\ zAqCkc3OyX3Pjsm1Wn+IpGtNtahR9EGC4caKAH5eZV9q//////////8CAQI=\n\ -----END DH PARAMETERS-----\n"; static const char file_ffdhe8192[] = \ "-----BEGIN DH PARAMETERS-----\n\ MIIECAKCBAEA//////////+t+FRYortKmq/cViAnPTzx2LnFg84tNpWp4TZBFGQz\n\ +8yTnc4kmz75fS/jY2MMddj2gbICrsRhetPfHtXV/WVhJDP1H18GbtCFY2VVPe0a\n\ 87VXE15/V8k1mE8McODmi3fipona8+/och3xWKE2rec1MKzKT0g6eXq8CrGCsyT7\n\ YdEIqUuyyOP7uWrat2DX9GgdT0Kj3jlN9K5W7edjcrsZCwenyO4KbXCeAvzhzffi\n\ 7MA0BM0oNC9hkXL+nOmFg/+OTxIy7vKBg8P+OxtMb61zO7X8vC7CIAXFjvGDfRaD\n\ ssbzSibBsu/6iGtCOGEfz9zeNVs7ZRkDW7w09N75nAI4YbRvydbmyQd62R0mkff3\n\ 7lmMsPrBhtkcrv4TCYUTknC0EwyTvEN5RPT9RFLi103TZPLiHnH1S/9croKrnJ32\n\ nuhtK8UiNjoNq8Uhl5sN6todv5pC1cRITgq80Gv6U93vPBsg7j/VnXwl5B0rZp4e\n\ 8W5vUsMWTfT7eTDp5OWIV7asfV9C1p9tGHdjzx1VA0AEh/VbpX4xzHpxNciG77Qx\n\ iu1qHgEtnmgyqQdgCpGBMMRtx3j5ca0AOAkpmaMzy4t6Gh25PXFAADwqTs6p+Y0K\n\ zAqCkc3OyX3Pjsm1Wn+IpGtNtahR9EGC4caKAH5eDdkCC/1ktkUDbHpOZ30sOFMq\n\ OiO6RELK9T6mO7RUMpt2JMiRe91kscD9TLOOjDNMcBw6za0GV/zP7HGbH1w+TkYE\n\ HziBR/tM/bR3pSRx96mpaRC4VTIu22NA2KAO8JI1BRHjCr7B//njom5/sp+MGDAj\n\ w1h+ONoAd9m0dj5OS5Syu8GUxmUed8r5ku6qwCMqKBv2s6c5wSJhFoIK6NtYR6Z8\n\ vvnJCRtGLVOM1ysDdGrnf15iKSwxFWKoRlBdyC24VDOK5J9SNclbkReMzy3Vys70\n\ A+ydGBDGJysEWztx+dxrgNY/3UqOmtseaWKmlSbUMWHBpB1XDXk42tSkDjKcz/Rq\n\ qjatAEz2AMg4HkJaMdlRrmT9sj/OyVCdQ2h/62nt0cxeC4zDvfZLEO+GtjFCo6uI\n\ KVVbL3R8kyZlyywPHMAb1wIpOIg50q8F5FRQSseLdYKCKEbAujXDX1xZFgzARv2C\n\ UVQfxoychrAiu3CZh2pGDnRRqKkxCXA/7hwhfmw4JuUsUappHg5CPPyZ6eMWUMEh\n\ e2JIFs2tmpX51bgBlIjZwKCh/jB1pXfiMYP4HUo/L6RXHvyM4LqKT+i2hV3+crCm\n\ bt7S+6v75Yow+vq+HF1xqH4vdB74wf6G/qa7/eUwZ38Nl9EdSfeoRD0IIuUGqfRh\n\ TgEeKpSDj/iM1oyLt8XGQkz//////////wIBAg==\n\ -----END DH PARAMETERS-----\n"; /* ** Load hardcoded DH parameters. */ static DH * load_dh_buffer (const char *buffer, size_t len) { BIO *bio; DH *dh = NULL; bio = BIO_new_mem_buf((char *) buffer, len); if (bio == NULL) return NULL; dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL); /* If (dh == NULL) log error? */ BIO_free(bio); return dh; } /* ** Generate ephemeral DH key. Because this can take a long ** time to compute, we use precomputed parameters of the common ** key sizes. ** Depending on OpenSSL Security Level, a minimal length for ** DH parameters is required: ** ** ** These values can be static (once loaded or computed) since ** the OpenSSL library can effectively generate random keys ** from the information provided. ** ** EDH keying is slightly less efficient than static RSA keying, ** but it offers Perfect Forward Secrecy (PFS). ** ** FIXME: support user-specified files, to eliminate risk of ** "small group" attacks. */ static DH * tmp_dh_cb(SSL *s UNUSED, int export UNUSED, int keylength UNUSED) { DH *r = NULL; static DH *ffdhe2048 = NULL; static DH *ffdhe4096 = NULL; static DH *ffdhe8192 = NULL; int level = 2; /* Default security level. */ /* Security levels have been introduced in OpenSSL 1.1.0. */ #if OPENSSL_VERSION_NUMBER >= 0x010100000L && !defined(LIBRESSL_VERSION_NUMBER) level = SSL_get_security_level(s); #endif switch(level) { case 0: /* Everything is permitted. */ case 1: /* DH keys shorter than 1024 bits are prohibited. */ case 2: /* DH keys shorter than 2048 bits are prohibited. */ if (ffdhe2048 == NULL) { ffdhe2048 = load_dh_buffer(file_ffdhe2048, sizeof(file_ffdhe2048)); } r = ffdhe2048; break; case 3: /* DH keys shorter than 3072 bits are prohibited. */ if (ffdhe4096 == NULL) { ffdhe4096 = load_dh_buffer(file_ffdhe4096, sizeof(file_ffdhe4096)); } r = ffdhe4096; break; case 4: /* DH keys shorter than 7680 bits are prohibited. */ default: if (ffdhe8192 == NULL) { ffdhe8192 = load_dh_buffer(file_ffdhe8192, sizeof(file_ffdhe8192)); } r = ffdhe8192; } return r; } /* ** Taken from OpenSSL apps/s_cb.c. */ static int verify_callback(int ok, X509_STORE_CTX * ctx) { char buf[256]; X509 *err_cert; int err; int depth; syslog(L_NOTICE,"Doing a peer verify"); err_cert = X509_STORE_CTX_get_current_cert(ctx); err = X509_STORE_CTX_get_error(ctx); depth = X509_STORE_CTX_get_error_depth(ctx); if ((tls_serveractive) && (tls_loglevel >= 1)) { if (err_cert != NULL) { X509_NAME_oneline(X509_get_subject_name(err_cert), buf, sizeof(buf)); syslog(L_NOTICE, "Peer cert verify depth=%d %s", depth, buf); } else { syslog(L_NOTICE, "Peer cert verify depth=%d ", depth); } } if (ok==0) { syslog(L_NOTICE, "verify error:num=%d:%s", err, X509_verify_cert_error_string(err)); if (verify_depth >= depth) { ok = 1; verify_error = X509_V_OK; } else { ok = 0; verify_error = X509_V_ERR_CERT_CHAIN_TOO_LONG; } } switch (err) { case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT: X509_NAME_oneline(X509_get_issuer_name(err_cert), buf, sizeof(buf)); syslog(L_NOTICE, "issuer= %s", buf); break; case X509_V_ERR_CERT_NOT_YET_VALID: case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD: syslog(L_NOTICE, "cert not yet valid"); break; case X509_V_ERR_CERT_HAS_EXPIRED: case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD: syslog(L_NOTICE, "cert has expired"); break; } if ((tls_serveractive) && (tls_loglevel >= 1)) syslog(L_NOTICE, "verify return:%d", ok); return (ok); } /* ** Taken from OpenSSL crypto/bio/b_dump.c, modified to save a lot of strcpy ** and strcat by Matti Aarnio. */ #define TRUNCATE #define DUMP_WIDTH 16 static int tls_dump(const char *s, int len) { int ret = 0; char buf[160 + 1]; char *ss; int i; int j; int rows; int trunc; unsigned char ch; trunc = 0; #ifdef TRUNCATE for (; (len > 0) && ((s[len - 1] == ' ') || (s[len - 1] == '\0')); len--) trunc++; #endif rows = (len / DUMP_WIDTH); if ((rows * DUMP_WIDTH) < len) rows++; for (i = 0; i < rows; i++) { buf[0] = '\0'; /* Start with empty string. */ ss = buf; snprintf(ss, sizeof(buf), "%04x ", i * DUMP_WIDTH); ss += strlen(ss); for (j = 0; j < DUMP_WIDTH; j++) { if (((i * DUMP_WIDTH) + j) >= len) { strlcpy(ss, " ", sizeof(buf) - (ss - buf)); } else { ch = ((unsigned char) *((const char *)(s) + i * DUMP_WIDTH + j)) & 0xff; snprintf(ss, sizeof(buf) - (ss - buf), "%02x%c", ch, j == 7 ? '|' : ' '); ss += 3; } } ss += strlen(ss); *ss += ' '; for (j = 0; j < DUMP_WIDTH; j++) { if (((i * DUMP_WIDTH) + j) >= len) break; ch = ((unsigned char) *((const char *)(s) + i * DUMP_WIDTH + j)) & 0xff; *ss += (((ch >= ' ') && (ch <= '~')) ? ch : '.'); if (j == 7) *ss += ' '; } *ss = 0; /* If this is the last call, then update the ddt_dump thing so that * we will move the selection point in the debug window. */ if (tls_loglevel>0) syslog(L_NOTICE, "%s", buf); ret += strlen(buf); } #ifdef TRUNCATE if (trunc > 0) { snprintf(buf, sizeof(buf), "%04x - \n", len+ trunc); if (tls_loglevel>0) syslog(L_NOTICE, "%s", buf); ret += strlen(buf); } #endif return (ret); } /* ** Set up the cert things on the server side. We do need both the ** private key (in key_file) and the cert (in cert_file). ** Both files may be identical. ** ** This function is taken from OpenSSL apps/s_cb.c. */ static int set_cert_stuff(SSL_CTX * ctx, char *cert_file, char *key_file) { struct stat buf; if (cert_file != NULL) { if (SSL_CTX_use_certificate_file(ctx, cert_file, SSL_FILETYPE_PEM) <= 0) { syslog(L_ERROR, "unable to get certificate from '%s'", cert_file); return (0); } if (key_file == NULL) key_file = cert_file; /* Check ownership and permissions of key file. * Look at the real file (stat) and not a possible symlink (lstat). */ if (stat(key_file, &buf) == -1) { syslog(L_ERROR, "unable to stat private key '%s'", key_file); return (0); } /* Check that the key file is a real file, isn't world-readable, and * that we can read it. */ if (!S_ISREG(buf.st_mode) || (buf.st_mode & 0007) != 0 || access(key_file, R_OK) < 0) { syslog(L_ERROR, "bad ownership or permissions on private key" " '%s': private key must be a regular file, readable by" " nnrpd, and not world-readable", key_file); return (0); } if (SSL_CTX_use_PrivateKey_file(ctx, key_file, SSL_FILETYPE_PEM) <= 0) { syslog(L_ERROR, "unable to get private key from '%s'", key_file); return (0); } /* Now we know that a key and cert have been set against * the SSL context. */ if (!SSL_CTX_check_private_key(ctx)) { syslog(L_ERROR, "private key does not match the certificate public key"); return (0); } } return (1); } #ifdef HAVE_OPENSSL_ECC /* ** Provide an ECKEY from a curve name. ** Accepts a NULL pointer as the name. ** ** Returns the key, or NULL on error. */ static EC_KEY * eckey_from_name(char *name) { EC_KEY *eckey; size_t ncurves, nitems, i; EC_builtin_curve *builtin_curves; const char *sname; if (name == NULL) { return (NULL); } /* See EC_GROUP_new(3) for the details of this expressive dance. */ ncurves = EC_get_builtin_curves(NULL, 0); /* Number of curves. */ builtin_curves = xmalloc(ncurves * sizeof(EC_builtin_curve)); nitems = EC_get_builtin_curves(builtin_curves, ncurves); if (nitems != ncurves) { syslog(L_ERROR, "got %lu curves from EC_get_builtin_curves, " "expected %lu", (unsigned long) nitems, (unsigned long) ncurves); } for (i = 0; i < nitems; i++) { sname = OBJ_nid2sn(builtin_curves[i].nid); if (strcmp(sname, name) == 0) { break; } } if (i == nitems) { syslog(L_ERROR, "tlseccurve '%s' not found", name); free(builtin_curves); return (NULL); } eckey = EC_KEY_new_by_curve_name(builtin_curves[i].nid); free(builtin_curves); return (eckey); } #endif /* HAVE_OPENSSL_ECC */ /* ** This is the setup routine for the SSL server. As nnrpd might be called ** more than once, we only want to do the initialization one time. ** ** The skeleton of this function is taken from OpenSSL apps/s_server.c. ** ** Returns -1 on error. */ int tls_init_serverengine(int verifydepth, int askcert, int requirecert, char *tls_CAfile, char *tls_CApath, char *tls_cert_file, char *tls_key_file, bool prefer_server_ciphers, bool tls_compression, struct vector *tls_proto_vect, char *tls_ciphers, char *tls_ciphers13 UNUSED, char *tls_ec_curve UNUSED) { int off = 0; int verify_flags = SSL_VERIFY_NONE; char *CApath; char *CAfile; char *s_cert_file; char *s_key_file; struct stat buf; size_t tls_protos = 0; size_t i; #ifdef HAVE_OPENSSL_ECC EC_KEY *eckey; #endif if (tls_serverengine) return (0); /* Already running. */ if (tls_loglevel >= 2) syslog(L_NOTICE, "starting TLS engine"); /* New functions have been introduced in OpenSSL 1.1.0. */ #if OPENSSL_VERSION_NUMBER < 0x010100000L SSL_load_error_strings(); SSLeay_add_ssl_algorithms(); CTX = SSL_CTX_new(SSLv23_server_method()); #else OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS | OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL); CTX = SSL_CTX_new(TLS_server_method()); #endif if (CTX == NULL) { return (-1); }; off |= SSL_OP_ALL; /* Work around all known bugs. */ SSL_CTX_set_options(CTX, off); SSL_CTX_set_info_callback(CTX, apps_ssl_info_callback); SSL_CTX_sess_set_cache_size(CTX, 128); if (strlen(tls_CAfile) == 0) CAfile = NULL; else CAfile = tls_CAfile; if (strlen(tls_CApath) == 0) CApath = NULL; else CApath = tls_CApath; if ((!SSL_CTX_load_verify_locations(CTX, CAfile, CApath)) || (!SSL_CTX_set_default_verify_paths(CTX))) { if (tls_loglevel >= 2) syslog(L_ERROR, "TLS engine: cannot load CA data"); return (-1); } if (strlen(tls_cert_file) == 0) s_cert_file = NULL; else s_cert_file = tls_cert_file; if (strlen(tls_key_file) == 0) s_key_file = NULL; else s_key_file = tls_key_file; if (!set_cert_stuff(CTX, s_cert_file, s_key_file)) { if (tls_loglevel >= 2) syslog(L_ERROR, "TLS engine: cannot load cert/key data"); return (-1); } /* Load some randomization data from /dev/urandom, if it exists. * FIXME: should also check for ".rand" file, update it on exit. */ if (stat("/dev/urandom", &buf) == 0) RAND_load_file("/dev/urandom", 16 * 1024); SSL_CTX_set_tmp_dh_callback(CTX, tmp_dh_cb); SSL_CTX_set_options(CTX, SSL_OP_SINGLE_DH_USE); #ifdef HAVE_OPENSSL_ECC SSL_CTX_set_options(CTX, SSL_OP_SINGLE_ECDH_USE); /* We set a curve here by name if provided * or we use OpenSSL (>= 1.0.2) auto-selection * or we default to NIST P-256. */ eckey = eckey_from_name(tls_ec_curve); if (eckey != NULL) { SSL_CTX_set_tmp_ecdh(CTX, eckey); } else { # if OPENSSL_VERSION_NUMBER < 0x010100000L # if OPENSSL_VERSION_NUMBER >= 0x01000200fL /* Function supported since OpenSSL 1.0.2. * Removed since OpenSSL 1.1.0, supporting ECDH by default with * the most appropriate parameters. */ SSL_CTX_set_ecdh_auto(CTX, 1); # else SSL_CTX_set_tmp_ecdh(CTX, EC_KEY_new_by_curve_name(NID_X9_62_prime256v1)); # endif /* SSL_CTX_set_ecdh_auto */ # endif /* OpenSSL version < 1.1.0 */ } #endif /* HAVE_OPENSSL_ECC */ #ifdef SSL_OP_CIPHER_SERVER_PREFERENCE if (prefer_server_ciphers) { SSL_CTX_set_options(CTX, SSL_OP_CIPHER_SERVER_PREFERENCE); } else { #if OPENSSL_VERSION_NUMBER >= 0x0009080dfL /* Function first added in OpenSSL 0.9.8m. */ SSL_CTX_clear_options(CTX, SSL_OP_CIPHER_SERVER_PREFERENCE); #endif } #endif if ((tls_proto_vect != NULL) && (tls_proto_vect->count > 0)) { for (i = 0; i < tls_proto_vect->count; i++) { if (tls_proto_vect->strings[i] != NULL) { if (strcmp(tls_proto_vect->strings[i], "SSLv2") == 0) { tls_protos |= INN_TLS_SSLv2; } else if (strcmp(tls_proto_vect->strings[i], "SSLv3") == 0) { tls_protos |= INN_TLS_SSLv3; } else if (strcmp(tls_proto_vect->strings[i], "TLSv1") == 0) { tls_protos |= INN_TLS_TLSv1; } else if (strcmp(tls_proto_vect->strings[i], "TLSv1.1") == 0) { tls_protos |= INN_TLS_TLSv1_1; } else if (strcmp(tls_proto_vect->strings[i], "TLSv1.2") == 0) { tls_protos |= INN_TLS_TLSv1_2; } else if (strcmp(tls_proto_vect->strings[i], "TLSv1.3") == 0) { tls_protos |= INN_TLS_TLSv1_3; } else { syslog(L_ERROR, "TLS engine: unknown protocol '%s' in tlsprotocols", tls_proto_vect->strings[i]); } } } } else { /* Default value: allow only TLS protocols. */ tls_protos = (INN_TLS_TLSv1 | INN_TLS_TLSv1_1 | INN_TLS_TLSv1_2 | INN_TLS_TLSv1_3); } if ((tls_protos & INN_TLS_SSLv2) == 0) { SSL_CTX_set_options(CTX, SSL_OP_NO_SSLv2); } if ((tls_protos & INN_TLS_SSLv3) == 0) { SSL_CTX_set_options(CTX, SSL_OP_NO_SSLv3); } if ((tls_protos & INN_TLS_TLSv1) == 0) { SSL_CTX_set_options(CTX, SSL_OP_NO_TLSv1); } if ((tls_protos & INN_TLS_TLSv1_1) == 0) { #ifdef SSL_OP_NO_TLSv1_1 SSL_CTX_set_options(CTX, SSL_OP_NO_TLSv1_1); #endif } if ((tls_protos & INN_TLS_TLSv1_2) == 0) { #ifdef SSL_OP_NO_TLSv1_2 SSL_CTX_set_options(CTX, SSL_OP_NO_TLSv1_2); #endif } if ((tls_protos & INN_TLS_TLSv1_3) == 0) { #ifdef SSL_OP_NO_TLSv1_3 SSL_CTX_set_options(CTX, SSL_OP_NO_TLSv1_3); #endif } if (tls_ciphers != NULL) { if (SSL_CTX_set_cipher_list(CTX, tls_ciphers) == 0) { syslog(L_ERROR, "TLS engine: cannot set cipher list"); return (-1); } } #if OPENSSL_VERSION_NUMBER >= 0x01010100fL && defined(SSL_OP_NO_TLSv1_3) /* New API added in OpenSSL 1.1.1 for TLSv1.3 cipher suites. * Also check that SSL_OP_NO_TLSv1_3 is defined (to fix a build * issue with LibreSSL considered as version 2, but without the * same API as OpenSSL). */ if (tls_ciphers13 != NULL) { if (SSL_CTX_set_ciphersuites(CTX, tls_ciphers13) == 0) { syslog(L_ERROR, "TLS engine: cannot set ciphersuites"); return (-1); } } #endif if (tls_compression) { #if defined(SSL_OP_NO_COMPRESSION) && OPENSSL_VERSION_NUMBER >= 0x0009080dfL /* Function first added in OpenSSL 0.9.8m. */ SSL_CTX_clear_options(CTX, SSL_OP_NO_COMPRESSION); #endif } else { #ifdef SSL_OP_NO_COMPRESSION /* Option implemented in OpenSSL 1.0.0. */ SSL_CTX_set_options(CTX, SSL_OP_NO_COMPRESSION); #elif OPENSSL_VERSION_NUMBER >= 0x00090800fL /* Workaround for OpenSSL 0.9.8. */ sk_SSL_COMP_zero(SSL_COMP_get_compression_methods()); #endif } verify_depth = verifydepth; if (askcert!=0) verify_flags |= SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE; if (requirecert) verify_flags |= SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT | SSL_VERIFY_CLIENT_ONCE; SSL_CTX_set_verify(CTX, verify_flags, verify_callback); SSL_CTX_set_client_CA_list(CTX, SSL_load_client_CA_file(CAfile)); tls_serverengine = 1; return (0); } /* ** The function called by nnrpd to initialize the TLS support. Calls ** tls_init_serverengine and checks the result. On any sort of failure, ** nnrpd will exit. ** ** Returns -1 on error. */ int tls_init(void) { int ssl_result; if (tls_initialized) return 0; ssl_result = tls_init_serverengine(5, /* Depth to verify. */ 0, /* Can client auth? */ 0, /* Required client to auth? */ innconf->tlscafile, innconf->tlscapath, innconf->tlscertfile, innconf->tlskeyfile, innconf->tlspreferserverciphers, innconf->tlscompression, innconf->tlsprotocols, innconf->tlsciphers, innconf->tlsciphers13, innconf->tlseccurve); if (ssl_result == -1) { Reply("%d Error initializing TLS\r\n", initialSSL ? NNTP_FAIL_TERMINATING : NNTP_ERR_STARTTLS); syslog(L_ERROR, "error initializing TLS: " "[CA_file: %s] [CA_path: %s] [cert_file: %s] [key_file: %s]", innconf->tlscafile, innconf->tlscapath, innconf->tlscertfile, innconf->tlskeyfile); if (initialSSL) ExitWithStats(1, false); return -1; } tls_initialized = true; return 0; } /* ** Taken from OpenSSL apps/s_cb.c. */ static long bio_dump_cb(BIO * bio, int cmd, const char *argp, int argi, long argl UNUSED, long ret) { if (!do_dump) return (ret); if (cmd == (BIO_CB_READ | BIO_CB_RETURN)) { syslog(L_NOTICE, "read from %08lX [%08lX] (%d bytes => %ld (0x%lX))", (unsigned long) bio, (unsigned long) argp, argi, ret, (unsigned long) ret); tls_dump(argp, (int) ret); return (ret); } else if (cmd == (BIO_CB_WRITE | BIO_CB_RETURN)) { syslog(L_NOTICE, "write to %08lX [%08lX] (%d bytes => %ld (0x%lX))", (unsigned long) bio, (unsigned long) argp, argi, ret, (unsigned long) ret); tls_dump(argp, (int) ret); } return (ret); } /* ** This is the actual startup routine for the connection. We expect ** that the buffers are flushed and the "382 Continue with TLS negociation" ** was sent to the client (if using STARTTLS), so that we can immediately ** start the TLS handshake process. ** ** layerbits and authid are filled in on success; authid is only ** filled in if the client authenticated. */ int tls_start_servertls(int readfd, int writefd) { int sts; int keepalive; SSL_SESSION *session; SSL_CIPHER *cipher; if (!tls_serverengine) { /* It should never happen. */ syslog(L_ERROR, "tls_engine not running"); return (-1); } if (tls_loglevel >= 1) syslog(L_NOTICE, "setting up TLS connection"); if (tls_conn == NULL) { tls_conn = (SSL *) SSL_new(CTX); } if (tls_conn == NULL) { return (-1); } SSL_clear(tls_conn); #if defined(SOL_SOCKET) && defined(SO_KEEPALIVE) /* Set KEEPALIVE to catch broken socket connections. */ keepalive = 1; if (setsockopt(readfd, SOL_SOCKET, SO_KEEPALIVE, &keepalive, sizeof(keepalive)) < 0) syslog(L_ERROR, "fd %d can't setsockopt(KEEPALIVE) %m", readfd); if (setsockopt(writefd, SOL_SOCKET, SO_KEEPALIVE, &keepalive, sizeof(keepalive)) < 0) syslog(L_ERROR, "fd %d can't setsockopt(KEEPALIVE) %m", writefd); #endif /* SOL_SOCKET && SO_KEEPALIVE */ /* Set the file descriptors for SSL to use. */ if (SSL_set_rfd(tls_conn, readfd)==0) { return (-1); } if (SSL_set_wfd(tls_conn, writefd)==0) { return (-1); } /* This is the actual handshake routine. It will do all the negotiations * and will check the client cert etc. */ SSL_set_accept_state(tls_conn); /* We do have an SSL_set_fd() and now suddenly a BIO_ routine is called? * Well there is a BIO below the SSL routines that is automatically * created for us, so we can use it for debugging purposes. */ if (tls_loglevel >= 3) BIO_set_callback(SSL_get_rbio(tls_conn), bio_dump_cb); /* Dump the negotiation for loglevels 3 and 4. */ if (tls_loglevel >= 3) do_dump = 1; if ((sts = SSL_accept(tls_conn)) <= 0) { session = SSL_get_session(tls_conn); if (session) { SSL_CTX_remove_session(CTX, session); } if (tls_conn) SSL_free(tls_conn); tls_conn = NULL; return (-1); } /* Only loglevel 4 dumps everything. */ if (tls_loglevel < 4) do_dump = 0; tls_protocol = SSL_get_version(tls_conn); cipher = (SSL_CIPHER *) SSL_get_current_cipher(tls_conn); tls_cipher_name = SSL_CIPHER_get_name(cipher); tls_cipher_usebits = SSL_CIPHER_get_bits(cipher, &tls_cipher_algbits); tls_serveractive = 1; syslog(L_NOTICE, "starttls: %s with cipher %s (%d/%d bits) no authentication", tls_protocol, tls_cipher_name, tls_cipher_usebits, tls_cipher_algbits); return (0); } ssize_t SSL_writev (SSL *ssl, const struct iovec *vector, int count) { static char *buffer = NULL; static size_t allocsize = 0; char *bp; size_t bytes, to_copy; int i; /* Find the total number of bytes to be written. */ bytes = 0; for (i = 0; i < count; ++i) bytes += vector[i].iov_len; /* Allocate a buffer to hold the data. */ if (NULL == buffer) { size_t to_alloc = (bytes > 0 ? bytes : 1); buffer = (char *) xmalloc(to_alloc); allocsize = to_alloc; } else if (bytes > allocsize) { buffer = (char *) xrealloc (buffer, bytes); allocsize = bytes; } /* Copy the data into BUFFER. */ to_copy = bytes; bp = buffer; for (i = 0; i < count; ++i) { #define min(a, b) ((a) > (b) ? (b) : (a)) size_t copy = min (vector[i].iov_len, to_copy); memcpy (bp, vector[i].iov_base, copy); bp += copy; to_copy -= copy; if (to_copy == 0) break; } return SSL_write (ssl, buffer, bytes); } #endif /* HAVE_OPENSSL */ inn-2.6.4/nnrpd/line.c0000644000175200017520000002714014002373703014140 0ustar iuliusiulius/* $Id: line.c 9979 2015-12-11 20:40:29Z iulius $ ** ** Line by line reading support from sockets/pipes. ** ** Written by Alex Kiernan . ** ** This code implements an infinitely (well size_t) long single line ** read routine. To protect against eating all available memory, it ** actually starts discarding characters if you try to send more than ** the maximum article size in a single line. ** */ #include "config.h" #include "clibrary.h" #include #ifdef HAVE_SYS_SELECT_H # include #endif #include "inn/messages.h" #include "nnrpd.h" #include #include "tls.h" #ifdef HAVE_OPENSSL extern SSL *tls_conn; #endif /* ** Free a previously allocated line structure. */ void line_free(struct line *line) { static const struct line nullline = {0, 0, 0, 0}; if (line && line->start) { free(line->start); *line = nullline; } } #ifdef HAVE_OPENSSL /* ** Alarm signal handler for client timeout. */ static void alarmHandler(int s UNUSED) { SSL_shutdown(tls_conn); tls_conn = NULL; errno = ECONNRESET; } #endif /* ** Initialise a new line structure. */ void line_init(struct line *line) { assert(line); line->allocated = NNTP_MAXLEN_COMMAND; line->where = line->start = xmalloc(line->allocated); line->remaining = 0; } /* ** Reset a line structure. */ void line_reset(struct line *line) { assert(line); line->where = line->start; line->remaining = 0; } /* ** Timeout is used only if HAVE_OPENSSL is defined. */ static ssize_t line_doread(void *p, size_t len, int timeout UNUSED) { ssize_t n; do { #if defined(HAVE_ZLIB) /* Process data that may already be available in the zlib buffer. */ if (compression_layer_on && (zstream_in->avail_in > 0 || zstream_inflate_needed)) { int r; zstream_in->next_out = p; zstream_in->avail_out = len; r = inflate(zstream_in, Z_SYNC_FLUSH); if (!(r == Z_OK || r == Z_BUF_ERROR || r == Z_STREAM_END)) { sysnotice("inflate() failed: %d; %s", r, zstream_in->msg != NULL ? zstream_in->msg : "no detail"); n = -1; break; } /* Check whether inflate() has finished to process its input. * If not, we need to call it again, even though avail_in is 0. */ zstream_inflate_needed = (r != Z_STREAM_END); if (zstream_in->avail_out < len) { /* Some data has been uncompressed. Treat it now. */ n = len - zstream_in->avail_out; break; } /* If we reach here, then it means that inflate() needs more * input, so we go on reading data on the wire. */ } #endif /* HAVE_ZLIB */ #ifdef HAVE_OPENSSL if (tls_conn) { int err; xsignal(SIGALRM, alarmHandler); do { alarm(timeout); n = SSL_read(tls_conn, p, len); alarm(0); if (tls_conn == NULL) { break; } err = SSL_get_error(tls_conn, n); switch (err) { case SSL_ERROR_SYSCALL: break; case SSL_ERROR_SSL: SSL_shutdown(tls_conn); tls_conn = NULL; errno = ECONNRESET; break; } } while (err == SSL_ERROR_WANT_READ); xsignal (SIGALRM, SIG_DFL); } else #endif /* HAVE_OPENSSL */ do { n = read(STDIN_FILENO, p, len); } while (n == -1 && errno == EINTR); if (n <= 0) break; /* EOF or error. */ #if defined(HAVE_SASL) if (sasl_conn != NULL && sasl_ssf > 0) { /* Security layer in place, decode the data. * The incoming data is always encoded in chunks of length * inferior or equal to NNTP_MAXLEN_COMMAND (the maxbufsize value * of SASL_SEC_PROPS passed as part of the SASL exchange). * So there's enough data to read in the p buffer. */ const char *out; unsigned outlen; int r; if ((r = sasl_decode(sasl_conn, p, n, &out, &outlen)) == SASL_OK) { if (outlen > len) { sysnotice("sasl_decode() returned too much output"); n = -1; } else { if (outlen > 0) { memcpy(p, out, outlen); } n = outlen; } } else { const char *ed = sasl_errdetail(sasl_conn); sysnotice("sasl_decode() failed: %s; %s", sasl_errstring(r, NULL, NULL), ed != NULL ? ed : "no detail"); n = -1; } } #endif /* HAVE_SASL */ #if defined(HAVE_ZLIB) if (compression_layer_on && n > 0) { size_t zconsumed; if (zstream_in->avail_in > 0 && zstream_in->next_in != Z_NULL) { zconsumed = zstream_in->next_in - zbuf_in; } else { zconsumed = 0; zbuf_in_allocated = 0; } /* Transfer the data we have just read to zstream_in, * and loop to actually process it. */ if ((ssize_t) (zbuf_in_size - zbuf_in_allocated) < n) { size_t newsize = zbuf_in_size * 2 + n; /* Don't grow the buffer bigger than the maximum * article size we'll accept. */ if (PERMaccessconf->localmaxartsize > NNTP_MAXLEN_COMMAND) { if (newsize > PERMaccessconf->localmaxartsize) { newsize = PERMaccessconf->localmaxartsize; } } if (newsize == zbuf_in_size) { warn("%s overflowed our zstream_in buffer (%lu)", Client.host, (unsigned long) newsize); n = -1; break; } zbuf_in = xrealloc(zbuf_in, newsize); zbuf_in_size = newsize; } memcpy(zbuf_in + zbuf_in_allocated, p, n); zstream_in->next_in = zbuf_in + zconsumed; zstream_in->avail_in += n; zbuf_in_allocated += n; zstream_inflate_needed = true; /* Loop to actually inflate the compressed data we received. */ n = 0; } #endif /* HAVE_ZLIB */ } while (n == 0); /* Split SASL blob, need to read more data. */ return n; } READTYPE line_read(struct line *line, int timeout, const char **p, size_t *len, size_t *stripped) { char *where; char *lf = NULL; READTYPE r = RTok; assert(line != NULL); assert(line->start != NULL); /* Shuffle any trailing portion not yet processed to the start of * the buffer. */ if (line->remaining != 0) { if (line->start != line->where) { memmove(line->start, line->where, line->remaining); } lf = memchr(line->start, '\n', line->remaining); } where = line->start + line->remaining; /* If we found a line terminator in the data we have, we don't need * to ask for any more. */ if (lf == NULL) { do { fd_set rmask; int i; ssize_t count; /* If we've filled the line buffer, double the size, * reallocate the buffer and try again. */ if (where == line->start + line->allocated) { size_t newsize = line->allocated * 2; /* Don't grow the buffer bigger than the maximum * article size we'll accept. */ if (PERMaccessconf->localmaxartsize > NNTP_MAXLEN_COMMAND) if (newsize > PERMaccessconf->localmaxartsize) newsize = PERMaccessconf->localmaxartsize; /* If we're trying to grow from the same size, to the * same size, we must have hit the localmaxartsize * buffer for a second (or subsequent) time -- the user * is likely trying to DOS us, so don't double the * size any more, just overwrite characters until they * stop, then discard the whole thing. */ if (newsize == line->allocated) { warn("%s overflowed our line buffer (%lu), " "discarding further input", Client.host, PERMaccessconf->localmaxartsize); where = line->start; r = RTlong; } else { line->start = xrealloc(line->start, newsize); where = line->start + line->allocated; line->allocated = newsize; } } #ifdef HAVE_OPENSSL /* It seems that the SSL_read cannot be mixed with select() * as in the current code. SSL communicates in its own data * blocks and hand shaking. The do_readline using SSL_read * could return, but still with a partial line in the SSL_read * buffer. Then the server SSL routine would sit there waiting * for completion of that data block while nnrpd sat at the * select() routine waiting for more data from the server. * * Here, we decide to just bypass the select() wait. Unlike * innd with multiple threads, the select on nnrpd is just * waiting on a single file descriptor, so it is not really * essential with blocked read like SSL_read. Using an alarm * signal around SSL_read for non active timeout, SSL works * without dead locks. However, without the select() wait, * the IDLE timer stat won't be collected... */ if (tls_conn == NULL) { #endif /* Wait for activity on stdin, updating timer stats as we * go. */ do { struct timeval t; FD_ZERO(&rmask); FD_SET(STDIN_FILENO, &rmask); t.tv_sec = timeout; t.tv_usec = 0; TMRstart(TMR_IDLE); i = select(STDIN_FILENO + 1, &rmask, NULL, NULL, &t); TMRstop(TMR_IDLE); if (i == -1 && errno != EINTR) { syswarn("%s can't select", Client.host); return RTtimeout; } } while (i == -1); /* If stdin didn't select, we must have timed out. */ if (i == 0 || !FD_ISSET(STDIN_FILENO, &rmask)) return RTtimeout; #ifdef HAVE_OPENSSL } #endif count = line_doread(where, line->allocated - (where - line->start), timeout); /* Give timeout for read errors. */ if (count < 0) { sysnotice("%s can't read", Client.host); return RTtimeout; } /* If we hit EOF, terminate the string and send it back. */ if (count == 0) { assert((where + count) < (line->start + line->allocated)); where[count] = '\0'; return RTeof; } /* Search for `\n' in what we just read. If we find it we'll * drop out and return the line for processing */ lf = memchr(where, '\n', count); where += count; } while (lf == NULL); } /* Remember where we've processed up to, so we can start off there * next time. */ line->where = lf + 1; line->remaining = where - line->where; if (r == RTok) { /* If we see a full CRLF pair, strip them both off before * returning the line to our caller. If we just get an LF * we'll accept that too (debugging INN can then be less annoying). */ if (lf > line->start && lf[-1] == '\r') { --lf; if (stripped != NULL) (*stripped)++; } *lf = '\0'; if (stripped != NULL) (*stripped)++; *len = lf - line->start; *p = line->start; } return r; } inn-2.6.4/nnrpd/list.c0000644000175200017520000002620414002373703014164 0ustar iuliusiulius/* $Id: list.c 9145 2010-10-30 09:44:46Z iulius $ ** ** LIST commands. */ #include "config.h" #include "clibrary.h" #include "nnrpd.h" #include "inn/ov.h" #include "inn/innconf.h" #include "inn/messages.h" typedef struct _LISTINFO { const char *method; const char * File; void (*impl)(struct _LISTINFO *, int ac, char *av[]); bool Required; const char * Items; const char * Format; } LISTINFO; static void cmd_list_schema(LISTINFO *lp, int ac, char *av[]); static void cmd_list_headers(LISTINFO *lp, int ac, char *av[]); static LISTINFO INFOactive = { "ACTIVE", INN_PATH_ACTIVE, NULL, true, "list of active newsgroups", "Newsgroups in form \"group high low status\"" }; static LISTINFO INFOactivetimes = { "ACTIVE.TIMES", INN_PATH_ACTIVETIMES, NULL, false, "list of newsgroup creation times", "Newsgroup creation times in form \"group time who\"" }; static LISTINFO INFOcounts = { "COUNTS", INN_PATH_ACTIVE, NULL, true, "list of active newsgroups with estimated counts", "Newsgroups in form \"group high low count status\"" }; static LISTINFO INFOdistribs = { "DISTRIBUTIONS", INN_PATH_NNRPDIST, NULL, false, "list of newsgroup distributions", "Distributions in form \"distribution description\"" }; static LISTINFO INFOheaders = { "HEADERS", NULL, cmd_list_headers, true, "list of supported headers and metadata items", "Headers and metadata items supported" }; static LISTINFO INFOsubs = { "SUBSCRIPTIONS", INN_PATH_NNRPSUBS, NULL, false, "list of recommended newsgroup subscriptions", "Recommended subscriptions in form \"group\"" }; static LISTINFO INFOdistribpats = { "DISTRIB.PATS", INN_PATH_DISTPATS, NULL, false, "list of distribution patterns", "Default distributions in form \"weight:group-pattern:distribution\"" }; static LISTINFO INFOgroups = { "NEWSGROUPS", INN_PATH_NEWSGROUPS, NULL, true, "list of newsgroup descriptions", "Newsgroup descriptions in form \"group description\"" }; static LISTINFO INFOmoderators = { "MODERATORS", INN_PATH_MODERATORS, NULL, false, "list of submission templates", "Newsgroup moderators in form \"group-pattern:submission-template\"" }; static LISTINFO INFOschema = { "OVERVIEW.FMT", NULL, cmd_list_schema, true, "overview format", "Order of fields in overview database" }; static LISTINFO INFOmotd = { "MOTD", INN_PATH_MOTD_NNRPD, NULL, false, "message of the day", "Message of the day text in UTF-8" }; static LISTINFO *info[] = { &INFOactive, &INFOactivetimes, &INFOcounts, &INFOdistribs, &INFOheaders, &INFOsubs, &INFOdistribpats, &INFOgroups, &INFOmoderators, &INFOschema, &INFOmotd, }; /* ** List the overview schema (standard and extra fields). */ static void cmd_list_schema(LISTINFO *lp, int ac UNUSED, char *av[] UNUSED) { const struct cvector *standard; unsigned int i; Reply("%d %s\r\n", NNTP_OK_LIST, lp->Format); standard = overview_fields(); for (i = 0; i < standard->count; ++i) { Printf("%s:\r\n", standard->strings[i]); } for (i = 0; i < OVextra->count; ++i) { Printf("%s:full\r\n", OVextra->strings[i]); } Printf(".\r\n"); } /* ** List supported headers and metadata information. */ static void cmd_list_headers(LISTINFO *lp, int ac, char *av[]) { bool range; range = (ac > 2 && strcasecmp(av[2], "RANGE") == 0); if (ac > 2 && (strcasecmp(av[2], "MSGID") != 0) && !range) { Reply("%d Syntax error in arguments\r\n", NNTP_ERR_SYNTAX); return; } Reply("%d %s\r\n", NNTP_OK_LIST, lp->Format); Printf(":\r\n"); if (range) { /* These information are only known by the overview system, * and are only accessible with a range. */ Printf(":bytes\r\n"); Printf(":lines\r\n"); } Printf(".\r\n"); } /* ** List a single newsgroup. Called by LIST ACTIVE with a single argument. ** This is quicker than parsing the whole active file, but only works with ** single groups. It also doesn't work for aliased groups, since overview ** doesn't know what group the group is aliased to (yet). Returns whether we ** were able to answer the command. */ static bool CMD_list_single(char *group) { char *grplist[2] = { NULL, NULL }; int lo, hi, count, flag; if (PERMspecified) { grplist[0] = group; if (!PERMmatch(PERMreadlist, grplist)) return false; } if (OVgroupstats(group, &lo, &hi, &count, &flag) && flag != NF_FLAG_ALIAS) { /* When the connected user has the right to locally post, mention it. */ if (PERMaccessconf->locpost && (flag == NF_FLAG_IGNORE || flag == NF_FLAG_JUNK || flag == NF_FLAG_NOLOCAL)) flag = NF_FLAG_OK; /* When a newsgroup is empty, the high water mark should be one less * than the low water mark according to RFC 3977. */ if (count == 0) lo = hi + 1; Reply("%d %s\r\n", NNTP_OK_LIST, INFOactive.Format); Printf("%s %0*u %0*u %c\r\n", group, ARTNUMPRINTSIZE, hi, ARTNUMPRINTSIZE, lo, flag); Printf(".\r\n"); return true; } return false; } /* ** Main LIST function. */ void CMDlist(int ac, char *av[]) { QIOSTATE *qp; char *p; char *save; char *path; char *q; char *grplist[2]; LISTINFO *lp; char *wildarg = NULL; char savec; unsigned int i; int lo, hi, count, flag; p = av[1]; /* LIST ACTIVE is the default LIST command. If a keyword is provided, * we check whether it is defined. */ if (p == NULL) { lp = &INFOactive; } else { lp = NULL; for (i = 0; i < ARRAY_SIZE(info); ++i) { if (strcasecmp(p, info[i]->method) == 0) { lp = info[i]; break; } } } /* If no defined LIST keyword is found, we return. */ if (lp == NULL) { Reply("%d Unknown LIST keyword\r\n", NNTP_ERR_SYNTAX); return; } if (lp == &INFOactive) { if (ac == 3) { wildarg = av[2]; /* No need to parse the active file for a single group. */ if (CMD_list_single(wildarg)) return; } } else if (lp == &INFOgroups || lp == &INFOactivetimes || lp == &INFOcounts || lp == &INFOheaders || lp == &INFOsubs) { if (ac == 3) wildarg = av[2]; } /* Three arguments can be passed only when ACTIVE, ACTIVE.TIMES, COUNTS * HEADERS, NEWSGROUPS or SUBSCRIPTIONS keywords are used. */ if (ac > 2 && !wildarg) { Reply("%d Unexpected wildmat or argument\r\n", NNTP_ERR_SYNTAX); return; } /* If a function is provided for the given keyword, we call it. */ if (lp->impl != NULL) { lp->impl(lp, ac, av); return; } path = innconf->pathetc; /* The active, active.times and newsgroups files are in pathdb. */ if ((strstr(lp->File, "active") != NULL) || (strstr(lp->File, "newsgroups") != NULL)) path = innconf->pathdb; path = concatpath(path, lp->File); qp = QIOopen(path); free(path); if (qp == NULL) { Reply("%d No %s available\r\n", NNTP_ERR_UNAVAILABLE, lp->Items); /* Only the active and newsgroups files are required. */ if (lp->Required || errno != ENOENT) { /* %m outputs strerror(errno). */ syslog(L_ERROR, "%s can't fopen %s %m", Client.host, lp->File); } return; } Reply("%d %s\r\n", NNTP_OK_LIST, lp->Format); if (!PERMspecified && lp != &INFOmotd) { /* Optimize for unlikely case of no permissions and false default. */ QIOclose(qp); Printf(".\r\n"); return; } /* Set up group list terminator. */ grplist[1] = NULL; /* Read lines, ignore long ones. */ while ((p = QIOread(qp)) != NULL) { /* Check that the output does not break the NNTP protocol. */ if (p[0] == '.' && p[1] != '.') { syslog(L_ERROR, "%s bad dot-stuffing in %s", Client.host, lp->File); continue; } if (lp == &INFOmotd) { if (is_valid_utf8(p)) { Printf("%s\r\n", p); } else { syslog(L_ERROR, "%s bad encoding in %s (UTF-8 expected)", Client.host, lp->File); } continue; } /* Matching patterns against patterns is not that * good but it is better than nothing... */ if (lp == &INFOdistribpats) { if (*p == '\0' || *p == '#' || *p == ';' || *p == ' ') continue; if (PERMspecified) { if ((q = strchr(p, ':')) == NULL) continue; q++; if ((save = strchr(q, ':')) == NULL) continue; *save = '\0'; grplist[0] = q; if (!PERMmatch(PERMreadlist, grplist)) continue; *save = ':'; } Printf("%s\r\n", p); continue; } if (lp == &INFOdistribs || lp == &INFOmoderators) { if (*p != '\0' && *p != '#' && *p != ';' && *p != ' ') { if (is_valid_utf8(p)) { Printf("%s\r\n", p); } else if (lp == &INFOdistribs) { syslog(L_ERROR, "%s bad encoding in %s (UTF-8 expected)", Client.host, lp->File); } } continue; } savec = '\0'; for (save = p; *save != '\0'; save++) { if (*save == ' ' || *save == '\t') { savec = *save; *save = '\0'; break; } } /* Check whether the reader has access to the newsgroup. */ if (PERMspecified) { grplist[0] = p; if (!PERMmatch(PERMreadlist, grplist)) continue; } /* Check whether the newsgroup matches the wildmat pattern, * if given. */ if (wildarg && !uwildmat(p, wildarg)) continue; if (lp == &INFOcounts) { if (OVgroupstats(p, &lo, &hi, &count, &flag)) { /* When a newsgroup is empty, the high water mark should be * one less than the low water mark according to RFC 3977. */ if (count == 0) lo = hi + 1; if (flag != NF_FLAG_ALIAS) { Printf("%s %u %u %u %c\r\n", p, hi, lo, count, PERMaccessconf->locpost && (flag == NF_FLAG_IGNORE || flag == NF_FLAG_JUNK || flag == NF_FLAG_NOLOCAL) ? NF_FLAG_OK : flag); } else if (savec != '\0') { *save = savec; if ((q = strrchr(p, NF_FLAG_ALIAS)) != NULL) { *save = '\0'; Printf("%s %u %u %u %s\r\n", p, hi, lo, count, q); } } } continue; } if (savec != '\0') *save = savec; if (lp == &INFOactive) { /* When the connected user has the right to locally post, mention it. */ if (PERMaccessconf->locpost && (q = strrchr(p, ' ')) != NULL) { q++; if (*q == NF_FLAG_IGNORE || *q == NF_FLAG_JUNK || *q == NF_FLAG_NOLOCAL) *q = NF_FLAG_OK; } } Printf("%s\r\n", p); } QIOclose(qp); Printf(".\r\n"); } inn-2.6.4/nnrpd/cache.c0000644000175200017520000000605714002373703014260 0ustar iuliusiulius/* $Id: cache.c 8709 2009-11-06 21:47:11Z iulius $ ** ** Message-ID to storage token cache. ** ** Written by Alex Kiernan (alex.kiernan@thus.net). ** ** Implementation of a message-ID to storage token cache which can be ** built during (X)OVER/(X)HDR/XPAT/NEWNEWS. If we hit in the cache when ** retrieving articles, the (relatively) expensive cost of a trip ** through the history database is saved. */ #include "config.h" #include "clibrary.h" #include "inn/innconf.h" #include "inn/tst.h" #include "inn/list.h" #include "inn/libinn.h" #include "inn/storage.h" #include "cache.h" /* ** Pointer to the message-ID to storage token ternary search tree. */ static struct tst *msgidcache; /* ** Count of message-IDs in the cache so that someone doing GROUP, ** (X)OVER, GROUP, (X)OVER, etc. for example doesn't blow up with ** out of memory. */ static unsigned long msgcachecount; struct cache_entry { struct node node; HASH hash; TOKEN token; }; static struct list unused, used; /* ** Add a translation from HASH, h, to TOKEN, t, to the message-ID ** cache. */ void cache_add(const HASH h, const TOKEN t) { if (innconf->msgidcachesize != 0) { struct cache_entry *entry, *old; const unsigned char *p; void *exist; if (!msgidcache) { msgidcache = tst_init((innconf->msgidcachesize + 9) / 10); list_new(&unused); list_new(&used); } entry = xmalloc(sizeof *entry); entry->hash = h; entry->token = t; p = (unsigned char *) HashToText(h); if (tst_insert(msgidcache, p, entry, 0, &exist) == TST_DUPLICATE_KEY) { free(entry); old = exist; list_remove(&old->node); list_addtail(&unused, &old->node); } else { list_addtail(&unused, &entry->node); ++msgcachecount; } if (msgcachecount >= innconf->msgidcachesize) { /* Need to throw away a node. */ entry = (struct cache_entry *)list_remhead(&used); if (entry == NULL) entry = (struct cache_entry *)list_remhead(&unused); if (entry != NULL) { tst_delete(msgidcache, (unsigned char *) HashToText(entry->hash)); free(entry); } } } } /* ** Lookup (and remove if found) a message-ID to TOKEN mapping. If this ** is a final lookup (ARTICLE, BODY, (X)HDR, XPAT), we remove it if we ** find it since this matches the observed behaviour of most clients, but ** cache it just in case we can reuse it if they issue multiple ** commands against the same message-ID (e.g. HEAD, STAT). */ TOKEN cache_get(const HASH h, bool final) { static HASH last_hash; static TOKEN last_token; static const TOKEN empty_token = { TOKEN_EMPTY, 0, "" }; if (HashCompare(&h, &last_hash) == 0 && !HashEmpty(last_hash)) return last_token; if (msgidcache) { struct cache_entry *entry; entry = tst_search(msgidcache, (unsigned char *) HashToText(h)); if (entry != NULL) { list_remove(&entry->node); if (!final) list_addtail(&unused, &entry->node); else list_addtail(&used, &entry->node); last_hash = entry->hash; last_token = entry->token; return last_token; } } return empty_token; } inn-2.6.4/nnrpd/Makefile0000644000175200017520000004142214002373703014504 0ustar iuliusiulius## $Id: Makefile 10149 2017-06-05 12:24:58Z iulius $ include ../Makefile.global top = .. CFLAGS = $(GCFLAGS) $(SSL_CPPFLAGS) $(SASL_CPPFLAGS) $(ZLIB_CPPFLAGS) ALL = nnrpd SOURCES = article.c auth-ext.c cache.c commands.c group.c line.c \ list.c misc.c newnews.c nnrpd.c perl.c perm.c post.c \ python.c sasl.c tls.c track.c zlib.c INCLUDES = cache.h nnrpd.h post.h tls.h OBJECTS = $(SOURCES:.c=.o) all: $(ALL) warnings: $(MAKE) COPT='$(WARNINGS)' all install: all $(LI_XPUB) nnrpd $D$(PATHBIN)/nnrpd bootstrap: clean clobber distclean maintclean: rm -f *.o $(ALL) nnrpdp profiled rm -rf .libs ## Compilation rules. NNRPDLIBS = $(LIBSTORAGE) $(LIBHIST) $(LIBINN) $(STORAGE_LIBS) \ $(PERL_LIBS) $(PYTHON_LIBS) $(SSL_LDFLAGS) $(SSL_LIBS) \ $(CRYPTO_LIBS) $(SASL_LDFLAGS) $(SASL_LIBS) \ $(ZLIB_LDFLAGS) $(ZLIB_LIBS) $(LIBS) .c.o: $(CC) $(CFLAGS) -c $< perl.o: perl.c ; $(CC) $(CFLAGS) $(PERL_CPPFLAGS) -c perl.c python.o: python.c ; $(CC) $(CFLAGS) $(PYTHON_CPPFLAGS) -c python.c nnrpd: $(OBJECTS) $(LIBHIST) $(LIBSTORAGE) $(LIBINN) $(LIBLD) $(LDFLAGS) -o $@ $(OBJECTS) $(NNRPDLIBS) $(LIBINN): ; (cd ../lib ; $(MAKE)) $(LIBSTORAGE): ; (cd ../storage ; $(MAKE)) $(LIBHIST): ; (cd ../history ; $(MAKE)) ## Profiling. These rules have not been checked for a while and may need ## some work. profiled: nnrpdp nnrpdp: $(SOURCES) rm -f $(OBJECTS) $(MAKEPROFILING) nnrpd mv nnrpd nnrpdp rm -f $(OBJECTS) ## Dependencies. Default list, below, is probably good enough. depend: $(SOURCES) $(MAKEDEPEND) '$(CFLAGS) $(PERL_CPPFLAGS) $(PYTHON_CPPFLAGS)' \ $(SOURCES) # DO NOT DELETE THIS LINE -- make depend depends on it. article.o: article.c ../include/config.h ../include/inn/defines.h \ ../include/inn/system.h ../include/inn/macros.h \ ../include/inn/portable-macros.h ../include/inn/portable-stdbool.h \ ../include/inn/defines.h ../include/inn/options.h ../include/clibrary.h \ ../include/config.h ../include/inn/macros.h \ ../include/portable/stdbool.h ../include/inn/innconf.h \ ../include/inn/messages.h ../include/inn/wire.h nnrpd.h \ ../include/portable/macros.h ../include/portable/socket.h \ ../include/portable/getaddrinfo.h ../include/portable/getnameinfo.h \ ../include/inn/qio.h ../include/inn/libinn.h ../include/inn/concat.h \ ../include/inn/xmalloc.h ../include/inn/xwrite.h ../include/inn/nntp.h \ ../include/inn/paths.h ../include/inn/storage.h ../include/inn/options.h \ ../include/inn/vector.h ../include/inn/timer.h \ ../include/inn/ov.h ../include/inn/history.h ../include/inn/storage.h \ tls.h cache.h auth-ext.o: auth-ext.c ../include/config.h ../include/inn/defines.h \ ../include/inn/system.h ../include/inn/macros.h \ ../include/inn/portable-macros.h ../include/inn/portable-stdbool.h \ ../include/inn/defines.h ../include/inn/options.h ../include/clibrary.h \ ../include/config.h ../include/inn/macros.h \ ../include/portable/stdbool.h ../include/inn/buffer.h \ ../include/inn/messages.h ../include/inn/vector.h nnrpd.h \ ../include/portable/macros.h ../include/portable/socket.h \ ../include/portable/getaddrinfo.h ../include/portable/getnameinfo.h \ ../include/inn/qio.h ../include/inn/libinn.h ../include/inn/concat.h \ ../include/inn/xmalloc.h ../include/inn/xwrite.h ../include/inn/nntp.h \ ../include/inn/paths.h ../include/inn/storage.h ../include/inn/options.h \ ../include/inn/timer.h cache.o: cache.c ../include/config.h ../include/inn/defines.h \ ../include/inn/system.h ../include/inn/macros.h \ ../include/inn/portable-macros.h ../include/inn/portable-stdbool.h \ ../include/inn/defines.h ../include/inn/options.h ../include/clibrary.h \ ../include/config.h ../include/inn/macros.h \ ../include/portable/stdbool.h ../include/inn/innconf.h \ ../include/inn/tst.h ../include/inn/list.h ../include/inn/libinn.h \ ../include/inn/concat.h ../include/inn/xmalloc.h ../include/inn/xwrite.h \ ../include/inn/storage.h ../include/inn/options.h cache.h commands.o: commands.c ../include/config.h ../include/inn/defines.h \ ../include/inn/system.h ../include/inn/macros.h \ ../include/inn/portable-macros.h ../include/inn/portable-stdbool.h \ ../include/inn/defines.h ../include/inn/options.h ../include/clibrary.h \ ../include/config.h ../include/inn/macros.h \ ../include/portable/stdbool.h nnrpd.h ../include/portable/macros.h \ ../include/portable/socket.h ../include/portable/getaddrinfo.h \ ../include/portable/getnameinfo.h ../include/inn/qio.h \ ../include/inn/libinn.h ../include/inn/concat.h ../include/inn/xmalloc.h \ ../include/inn/xwrite.h ../include/inn/nntp.h ../include/inn/paths.h \ ../include/inn/storage.h ../include/inn/options.h \ ../include/inn/vector.h ../include/inn/timer.h \ ../include/inn/fdflag.h ../include/inn/portable-socket.h \ ../include/inn/ov.h ../include/inn/history.h ../include/inn/storage.h \ ../include/inn/innconf.h ../include/inn/messages.h \ ../include/inn/version.h tls.h group.o: group.c ../include/config.h ../include/inn/defines.h \ ../include/inn/system.h ../include/inn/macros.h \ ../include/inn/portable-macros.h ../include/inn/portable-stdbool.h \ ../include/inn/defines.h ../include/inn/options.h ../include/clibrary.h \ ../include/config.h ../include/inn/macros.h \ ../include/portable/stdbool.h ../include/inn/innconf.h nnrpd.h \ ../include/portable/macros.h ../include/portable/socket.h \ ../include/portable/getaddrinfo.h ../include/portable/getnameinfo.h \ ../include/inn/qio.h ../include/inn/libinn.h ../include/inn/concat.h \ ../include/inn/xmalloc.h ../include/inn/xwrite.h ../include/inn/nntp.h \ ../include/inn/paths.h ../include/inn/storage.h ../include/inn/options.h \ ../include/inn/vector.h ../include/inn/timer.h \ ../include/inn/ov.h ../include/inn/history.h ../include/inn/storage.h line.o: line.c ../include/config.h ../include/inn/defines.h \ ../include/inn/system.h ../include/inn/macros.h \ ../include/inn/portable-macros.h ../include/inn/portable-stdbool.h \ ../include/inn/defines.h ../include/inn/options.h ../include/clibrary.h \ ../include/config.h ../include/inn/macros.h \ ../include/portable/stdbool.h ../include/inn/messages.h nnrpd.h \ ../include/portable/macros.h ../include/portable/socket.h \ ../include/portable/getaddrinfo.h ../include/portable/getnameinfo.h \ ../include/inn/qio.h ../include/inn/libinn.h ../include/inn/concat.h \ ../include/inn/xmalloc.h ../include/inn/xwrite.h ../include/inn/nntp.h \ ../include/inn/paths.h ../include/inn/storage.h ../include/inn/options.h \ ../include/inn/vector.h ../include/inn/timer.h \ tls.h list.o: list.c ../include/config.h ../include/inn/defines.h \ ../include/inn/system.h ../include/inn/macros.h \ ../include/inn/portable-macros.h ../include/inn/portable-stdbool.h \ ../include/inn/defines.h ../include/inn/options.h ../include/clibrary.h \ ../include/config.h ../include/inn/macros.h \ ../include/portable/stdbool.h nnrpd.h ../include/portable/macros.h \ ../include/portable/socket.h ../include/portable/getaddrinfo.h \ ../include/portable/getnameinfo.h ../include/inn/qio.h \ ../include/inn/libinn.h ../include/inn/concat.h ../include/inn/xmalloc.h \ ../include/inn/xwrite.h ../include/inn/nntp.h ../include/inn/paths.h \ ../include/inn/storage.h ../include/inn/options.h \ ../include/inn/vector.h ../include/inn/timer.h \ ../include/inn/ov.h ../include/inn/history.h ../include/inn/storage.h \ ../include/inn/innconf.h ../include/inn/messages.h misc.o: misc.c ../include/config.h ../include/inn/defines.h \ ../include/inn/system.h ../include/inn/macros.h \ ../include/inn/portable-macros.h ../include/inn/portable-stdbool.h \ ../include/inn/defines.h ../include/inn/options.h ../include/clibrary.h \ ../include/config.h ../include/inn/macros.h \ ../include/portable/stdbool.h ../include/inn/innconf.h nnrpd.h \ ../include/portable/macros.h ../include/portable/socket.h \ ../include/portable/getaddrinfo.h ../include/portable/getnameinfo.h \ ../include/inn/qio.h ../include/inn/libinn.h ../include/inn/concat.h \ ../include/inn/xmalloc.h ../include/inn/xwrite.h ../include/inn/nntp.h \ ../include/inn/paths.h ../include/inn/storage.h ../include/inn/options.h \ ../include/inn/vector.h ../include/inn/timer.h \ tls.h \ ../include/inn/ov.h ../include/inn/history.h ../include/inn/storage.h newnews.o: newnews.c ../include/config.h ../include/inn/defines.h \ ../include/inn/system.h ../include/inn/macros.h \ ../include/inn/portable-macros.h ../include/inn/portable-stdbool.h \ ../include/inn/defines.h ../include/inn/options.h ../include/clibrary.h \ ../include/config.h ../include/inn/macros.h \ ../include/portable/stdbool.h ../include/inn/innconf.h \ ../include/inn/messages.h ../include/inn/wire.h nnrpd.h \ ../include/portable/macros.h ../include/portable/socket.h \ ../include/portable/getaddrinfo.h ../include/portable/getnameinfo.h \ ../include/inn/qio.h ../include/inn/libinn.h ../include/inn/concat.h \ ../include/inn/xmalloc.h ../include/inn/xwrite.h ../include/inn/nntp.h \ ../include/inn/paths.h ../include/inn/storage.h ../include/inn/options.h \ ../include/inn/vector.h ../include/inn/timer.h \ ../include/inn/ov.h ../include/inn/history.h ../include/inn/storage.h \ cache.h nnrpd.o: nnrpd.c ../include/config.h ../include/inn/defines.h \ ../include/inn/system.h ../include/inn/macros.h \ ../include/inn/portable-macros.h ../include/inn/portable-stdbool.h \ ../include/inn/defines.h ../include/inn/options.h \ ../include/portable/alloca.h ../include/clibrary.h ../include/config.h \ ../include/inn/macros.h ../include/portable/stdbool.h \ ../include/portable/setproctitle.h ../include/portable/macros.h \ ../include/portable/socket.h ../include/portable/getaddrinfo.h \ ../include/portable/getnameinfo.h ../include/inn/innconf.h \ ../include/inn/libinn.h ../include/inn/concat.h ../include/inn/xmalloc.h \ ../include/inn/xwrite.h ../include/inn/messages.h \ ../include/inn/network.h ../include/inn/portable-socket.h \ ../include/inn/network-innbind.h ../include/inn/newsuser.h \ ../include/inn/ov.h ../include/inn/history.h ../include/inn/storage.h \ ../include/inn/options.h ../include/inn/version.h nnrpd.h \ ../include/inn/qio.h ../include/inn/nntp.h ../include/inn/paths.h \ ../include/inn/storage.h ../include/inn/vector.h ../include/inn/timer.h \ tls.h perl.o: perl.c ../include/config.h ../include/inn/defines.h \ ../include/inn/system.h ../include/inn/macros.h \ ../include/inn/portable-macros.h ../include/inn/portable-stdbool.h \ ../include/inn/defines.h ../include/inn/options.h ../include/clibrary.h \ ../include/config.h ../include/inn/macros.h \ ../include/portable/stdbool.h ../include/inn/innconf.h nnrpd.h \ ../include/portable/macros.h ../include/portable/socket.h \ ../include/portable/getaddrinfo.h ../include/portable/getnameinfo.h \ ../include/inn/qio.h ../include/inn/libinn.h ../include/inn/concat.h \ ../include/inn/xmalloc.h ../include/inn/xwrite.h ../include/inn/nntp.h \ ../include/inn/paths.h ../include/inn/storage.h ../include/inn/options.h \ ../include/inn/vector.h ../include/inn/timer.h \ post.h \ ../include/ppport.h \ ../include/innperl.h perm.o: perm.c ../include/config.h ../include/inn/defines.h \ ../include/inn/system.h ../include/inn/macros.h \ ../include/inn/portable-macros.h ../include/inn/portable-stdbool.h \ ../include/inn/defines.h ../include/inn/options.h ../include/clibrary.h \ ../include/config.h ../include/inn/macros.h \ ../include/portable/stdbool.h ../include/conffile.h \ ../include/portable/macros.h ../include/inn/network.h \ ../include/inn/portable-socket.h ../include/inn/portable-getaddrinfo.h \ ../include/inn/portable-getnameinfo.h ../include/inn/innconf.h \ ../include/innperl.h nnrpd.h ../include/portable/macros.h \ ../include/portable/socket.h ../include/inn/qio.h \ ../include/inn/libinn.h ../include/inn/concat.h ../include/inn/xmalloc.h \ ../include/inn/xwrite.h ../include/inn/nntp.h ../include/inn/paths.h \ ../include/inn/storage.h ../include/inn/options.h \ ../include/inn/vector.h ../include/inn/timer.h \ tls.h post.o: post.c ../include/config.h ../include/inn/defines.h \ ../include/inn/system.h ../include/inn/macros.h \ ../include/inn/portable-macros.h ../include/inn/portable-stdbool.h \ ../include/inn/defines.h ../include/inn/options.h ../include/clibrary.h \ ../include/config.h ../include/inn/macros.h \ ../include/portable/stdbool.h ../include/inn/innconf.h nnrpd.h \ ../include/portable/macros.h ../include/portable/socket.h \ ../include/portable/getaddrinfo.h ../include/portable/getnameinfo.h \ ../include/inn/qio.h ../include/inn/libinn.h ../include/inn/concat.h \ ../include/inn/xmalloc.h ../include/inn/xwrite.h ../include/inn/nntp.h \ ../include/inn/paths.h ../include/inn/storage.h ../include/inn/options.h \ ../include/inn/vector.h ../include/inn/timer.h \ ../include/inn/ov.h ../include/inn/history.h ../include/inn/storage.h \ post.h python.o: python.c ../include/config.h ../include/inn/defines.h \ ../include/inn/system.h ../include/inn/macros.h \ ../include/inn/portable-macros.h ../include/inn/portable-stdbool.h \ ../include/inn/defines.h ../include/inn/options.h \ ../include/clibrary.h ../include/config.h ../include/inn/macros.h \ ../include/portable/stdbool.h ../include/inn/innconf.h nnrpd.h \ ../include/portable/macros.h ../include/portable/socket.h \ ../include/portable/getaddrinfo.h ../include/portable/getnameinfo.h \ ../include/inn/qio.h ../include/inn/libinn.h ../include/inn/concat.h \ ../include/inn/xmalloc.h ../include/inn/xwrite.h ../include/inn/nntp.h \ ../include/inn/paths.h ../include/inn/storage.h ../include/inn/options.h \ ../include/inn/vector.h ../include/inn/timer.h \ ../include/inn/hashtab.h sasl.o: sasl.c ../include/config.h ../include/inn/defines.h \ ../include/inn/system.h ../include/inn/macros.h \ ../include/inn/portable-macros.h ../include/inn/portable-stdbool.h \ ../include/inn/defines.h ../include/inn/options.h ../include/clibrary.h \ ../include/config.h ../include/inn/macros.h \ ../include/portable/stdbool.h ../include/inn/messages.h nnrpd.h \ ../include/portable/macros.h ../include/portable/socket.h \ ../include/portable/getaddrinfo.h ../include/portable/getnameinfo.h \ ../include/inn/qio.h ../include/inn/libinn.h ../include/inn/concat.h \ ../include/inn/xmalloc.h ../include/inn/xwrite.h ../include/inn/nntp.h \ ../include/inn/paths.h ../include/inn/storage.h ../include/inn/options.h \ ../include/inn/vector.h ../include/inn/timer.h \ ../include/inn/ov.h ../include/inn/history.h ../include/inn/storage.h \ tls.h tls.o: tls.c ../include/config.h ../include/inn/defines.h \ ../include/inn/system.h ../include/inn/macros.h \ ../include/inn/portable-macros.h ../include/inn/portable-stdbool.h \ ../include/inn/defines.h ../include/inn/options.h ../include/clibrary.h \ ../include/config.h ../include/inn/macros.h \ ../include/portable/stdbool.h nnrpd.h ../include/portable/macros.h \ ../include/portable/socket.h ../include/portable/getaddrinfo.h \ ../include/portable/getnameinfo.h ../include/inn/qio.h \ ../include/inn/libinn.h ../include/inn/concat.h ../include/inn/xmalloc.h \ ../include/inn/xwrite.h ../include/inn/nntp.h ../include/inn/paths.h \ ../include/inn/storage.h ../include/inn/options.h \ ../include/inn/vector.h ../include/inn/timer.h \ ../include/inn/innconf.h tls.h track.o: track.c ../include/config.h ../include/inn/defines.h \ ../include/inn/system.h ../include/inn/macros.h \ ../include/inn/portable-macros.h ../include/inn/portable-stdbool.h \ ../include/inn/defines.h ../include/inn/options.h ../include/clibrary.h \ ../include/config.h ../include/inn/macros.h \ ../include/portable/stdbool.h ../include/inn/innconf.h nnrpd.h \ ../include/portable/macros.h ../include/portable/socket.h \ ../include/portable/getaddrinfo.h ../include/portable/getnameinfo.h \ ../include/inn/qio.h ../include/inn/libinn.h ../include/inn/concat.h \ ../include/inn/xmalloc.h ../include/inn/xwrite.h ../include/inn/nntp.h \ ../include/inn/paths.h ../include/inn/storage.h ../include/inn/options.h \ ../include/inn/vector.h ../include/inn/timer.h zlib.o: zlib.c ../include/config.h ../include/inn/defines.h \ ../include/inn/system.h ../include/inn/macros.h \ ../include/inn/portable-macros.h ../include/inn/portable-stdbool.h \ ../include/inn/defines.h ../include/inn/options.h ../include/clibrary.h \ ../include/config.h ../include/inn/macros.h \ ../include/portable/stdbool.h ../include/inn/messages.h nnrpd.h \ ../include/portable/macros.h ../include/portable/socket.h \ ../include/portable/getaddrinfo.h ../include/portable/getnameinfo.h \ ../include/inn/qio.h ../include/inn/libinn.h ../include/inn/concat.h \ ../include/inn/xmalloc.h ../include/inn/xwrite.h ../include/inn/nntp.h \ ../include/inn/paths.h ../include/inn/storage.h ../include/inn/options.h \ ../include/inn/vector.h ../include/inn/timer.h inn-2.6.4/nnrpd/article.c0000644000175200017520000011507014002373703014634 0ustar iuliusiulius/* $Id: article.c 10149 2017-06-05 12:24:58Z iulius $ ** ** Article-related routines. */ #include "config.h" #include "clibrary.h" #include #if HAVE_LIMITS_H # include #endif #include #include #include "inn/innconf.h" #include "inn/messages.h" #include "inn/wire.h" #include "nnrpd.h" #include "inn/ov.h" #include "tls.h" #include "cache.h" extern bool laxmid; #ifdef HAVE_OPENSSL extern SSL *tls_conn; #endif /* ** 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; const char *Item; } SENDDATA; static ARTHANDLE *ARThandle = NULL; static SENDDATA SENDbody = { STbody, NNTP_OK_BODY, "body" }; static SENDDATA SENDarticle = { STarticle, NNTP_OK_ARTICLE, "article" }; static SENDDATA SENDstat = { STstat, NNTP_OK_STAT, "status" }; static SENDDATA SENDhead = { SThead, NNTP_OK_HEAD, "head" }; static struct iovec iov[IOV_MAX > 1024 ? 1024 : IOV_MAX]; static int queued_iov = 0; static void PushIOvHelper(struct iovec* vec, int* countp) { int result = 0; TMRstart(TMR_NNTPWRITE); #if defined(HAVE_ZLIB) if (compression_layer_on) { int i; for (i = 0; i < *countp; i++) { if (i+1 == *countp) { /* Time to flush the compressed output stream. */ zstream_flush_needed = true; } write_buffer(vec[i].iov_base, vec[i].iov_len); } *countp = 0; return; } #endif /* HAVE_ZLIB */ #ifdef HAVE_SASL if (sasl_conn && sasl_ssf) { int i; for (i = 0; i < *countp; i++) { write_buffer(vec[i].iov_base, vec[i].iov_len); } } else { #endif /* HAVE_SASL */ #ifdef HAVE_OPENSSL if (tls_conn) { Again: result = SSL_writev(tls_conn, vec, *countp); switch (SSL_get_error(tls_conn, result)) { case SSL_ERROR_NONE: case SSL_ERROR_SYSCALL: break; case SSL_ERROR_WANT_WRITE: goto Again; break; case SSL_ERROR_SSL: SSL_shutdown(tls_conn); tls_conn = NULL; errno = ECONNRESET; break; case SSL_ERROR_ZERO_RETURN: break; } } else #endif /* HAVE_OPENSSL */ result = xwritev(STDOUT_FILENO, vec, *countp); #ifdef HAVE_SASL } #endif TMRstop(TMR_NNTPWRITE); if (result == -1) { /* We can't recover, since we can't resynchronise with our * peer. */ ExitWithStats(1, true); } *countp = 0; } static void PushIOvRateLimited(void) { double start, end, elapsed, target; struct iovec newiov[IOV_MAX > 1024 ? 1024 : IOV_MAX]; int newiov_len; int sentiov; int i; int bytesfound; int chunkbittenoff; struct timeval waittime; while (queued_iov) { bytesfound = newiov_len = 0; sentiov = 0; for (i = 0; (i < queued_iov) && (bytesfound < MaxBytesPerSecond); i++) { if ((signed)iov[i].iov_len + bytesfound > MaxBytesPerSecond) { chunkbittenoff = MaxBytesPerSecond - bytesfound; newiov[newiov_len].iov_base = iov[i].iov_base; newiov[newiov_len++].iov_len = chunkbittenoff; iov[i].iov_base = (char *)iov[i].iov_base + chunkbittenoff; iov[i].iov_len -= chunkbittenoff; bytesfound += chunkbittenoff; } else { newiov[newiov_len++] = iov[i]; sentiov++; bytesfound += iov[i].iov_len; } } assert(sentiov <= queued_iov); start = TMRnow_double(); PushIOvHelper(newiov, &newiov_len); end = TMRnow_double(); target = (double) bytesfound / MaxBytesPerSecond; elapsed = end - start; if (elapsed < 1 && elapsed < target) { waittime.tv_sec = 0; waittime.tv_usec = (target - elapsed) * 1e6; start = TMRnow_double(); if (select(0, NULL, NULL, NULL, &waittime) != 0) syswarn("%s: select in PushIOvRateLimit failed", Client.host); end = TMRnow_double(); IDLEtime += end - start; } memmove(iov, &iov[sentiov], (queued_iov - sentiov) * sizeof(struct iovec)); queued_iov -= sentiov; } } static void PushIOv(void) { TMRstart(TMR_NNTPWRITE); fflush(stdout); TMRstop(TMR_NNTPWRITE); if (MaxBytesPerSecond != 0) PushIOvRateLimited(); else PushIOvHelper(iov, &queued_iov); } static void SendIOv(const char *p, int len) { char *q; if (queued_iov) { q = (char *)iov[queued_iov - 1].iov_base + iov[queued_iov - 1].iov_len; if (p == q) { iov[queued_iov - 1].iov_len += len; return; } } iov[queued_iov].iov_base = (char*)p; iov[queued_iov++].iov_len = len; if (queued_iov == IOV_MAX) PushIOv(); } static char *_IO_buffer_ = NULL; static int highwater = 0; static void PushIOb(void) { #if defined(HAVE_ZLIB) /* Last line of a multi-line data block response. * Time to flush the compressed output stream. */ zstream_flush_needed = true; #endif /* HAVE_ZLIB */ write_buffer(_IO_buffer_, highwater); highwater = 0; } static void SendIOb(const char *p, int len) { int tocopy; if (_IO_buffer_ == NULL) _IO_buffer_ = xmalloc(BIG_BUFFER); while (len > 0) { tocopy = (len > (BIG_BUFFER - highwater)) ? (BIG_BUFFER - highwater) : len; memcpy(&_IO_buffer_[highwater], p, tocopy); p += tocopy; highwater += tocopy; len -= tocopy; if (highwater == BIG_BUFFER) PushIOb(); } } /* ** If we have an article open, close it. */ void ARTclose(void) { if (ARThandle) { SMfreearticle(ARThandle); ARThandle = NULL; } } bool ARTinstorebytoken(TOKEN token) { ARTHANDLE *art; struct timeval stv, etv; if (PERMaccessconf->nnrpdoverstats) { gettimeofday(&stv, NULL); } art = SMretrieve(token, RETR_STAT); /* XXX This isn't really overstats, is it? */ if (PERMaccessconf->nnrpdoverstats) { gettimeofday(&etv, NULL); OVERartcheck+=(etv.tv_sec - stv.tv_sec) * 1000; OVERartcheck+=(etv.tv_usec - stv.tv_usec) / 1000; } if (art) { SMfreearticle(art); return true; } return false; } /* ** If the article name is valid, open it and stuff in the ID. */ static bool ARTopen(ARTNUM artnum) { static ARTNUM save_artnum; TOKEN token; /* Re-use article if it's the same one. */ if (save_artnum == artnum) { if (ARThandle) return true; } ARTclose(); if (!OVgetartinfo(GRPcur, artnum, &token)) return false; TMRstart(TMR_READART); ARThandle = SMretrieve(token, RETR_ALL); TMRstop(TMR_READART); if (ARThandle == NULL) { return false; } save_artnum = artnum; return true; } /* ** Open the article for a given message-ID. */ static bool ARTopenbyid(char *msg_id, ARTNUM *ap, bool final) { TOKEN token; *ap = 0; token = cache_get(HashMessageID(msg_id), final); if (token.type == TOKEN_EMPTY) { if (History == NULL) { time_t statinterval; /* Do lazy opens of the history file: lots of clients * will never ask for anything by message-ID, so put off * doing the work until we have to. */ History = HISopen(HISTORY, innconf->hismethod, HIS_RDONLY); if (!History) { syslog(L_NOTICE, "can't initialize history"); Reply("%d NNTP server unavailable; try later\r\n", NNTP_FAIL_TERMINATING); ExitWithStats(1, true); } statinterval = 30; HISctl(History, HISCTLS_STATINTERVAL, &statinterval); } if (!HISlookup(History, msg_id, NULL, NULL, NULL, &token)) return false; } if (token.type == TOKEN_EMPTY) return false; TMRstart(TMR_READART); ARThandle = SMretrieve(token, RETR_ALL); TMRstop(TMR_READART); if (ARThandle == NULL) { return false; } return true; } /* ** Send a (part of) a file to stdout, doing newline and dot conversion. */ static void ARTsendmmap(SENDTYPE what) { const char *p, *q, *r; const char *s, *path, *xref, *endofpath; char lastchar; ARTcount++; GRParticles++; lastchar = -1; /* Get the headers and detect if wire format. */ if (what == STarticle) { q = ARThandle->data; p = ARThandle->data + ARThandle->len; } else { for (q = p = ARThandle->data; p < (ARThandle->data + ARThandle->len); p++) { if (*p == '\r') continue; if (*p == '\n') { if (lastchar == '\n') { if (what == SThead) { if (*(p-1) == '\r') p--; break; } else { q = p + 1; p = ARThandle->data + ARThandle->len; break; } } } lastchar = *p; } } /* q points to the start of the article buffer, p to the end of it. */ if (VirtualPathlen > 0 && (what != STbody)) { path = wire_findheader(ARThandle->data, ARThandle->len, "Path", true); if (path == NULL) { SendIOv(".\r\n", 3); ARTgetsize += 3; PushIOv(); ARTget++; return; } else { xref = wire_findheader(ARThandle->data, ARThandle->len, "Xref", true); if (xref == NULL) { SendIOv(".\r\n", 3); ARTgetsize += 3; PushIOv(); ARTget++; return; } } endofpath = wire_endheader(path, ARThandle->data + ARThandle->len - 1); if (endofpath == NULL) { SendIOv(".\r\n", 3); ARTgetsize += 3; PushIOv(); ARTget++; return; } if ((r = memchr(xref, ' ', p - xref)) == NULL || r == p) { SendIOv(".\r\n", 3); ARTgetsize += 3; PushIOv(); ARTget++; return; } /* r points to the first space in the Xref: header. */ for (s = path, lastchar = '\0'; s + VirtualPathlen + 1 < endofpath; lastchar = *s++) { if ((lastchar != '\0' && lastchar != '!') || *s != *VirtualPath || strncasecmp(s, VirtualPath, VirtualPathlen - 1) != 0) continue; if (*(s + VirtualPathlen - 1) != '\0' && *(s + VirtualPathlen - 1) != '!') continue; break; } if (s + VirtualPathlen + 1 < endofpath) { if (xref > path) { SendIOv(q, path - q); SendIOv(s, xref - s); SendIOv(VirtualPath, VirtualPathlen - 1); SendIOv(r, p - r); } else { SendIOv(q, xref - q); SendIOv(VirtualPath, VirtualPathlen - 1); SendIOv(r, path - r); SendIOv(s, p - s); } } else { /* Double the '!' (thus, adding one '!') in Path: header. */ if (xref > path) { SendIOv(q, path - q); SendIOv(VirtualPath, VirtualPathlen); SendIOv("!", 1); SendIOv(path, xref - path); SendIOv(VirtualPath, VirtualPathlen - 1); SendIOv(r, p - r); } else { SendIOv(q, xref - q); SendIOv(VirtualPath, VirtualPathlen - 1); SendIOv(r, path - r); SendIOv(VirtualPath, VirtualPathlen); SendIOv("!", 1); SendIOv(path, p - path); } } } else SendIOv(q, p - q); ARTgetsize += p - q; if (what == SThead) { SendIOv(".\r\n", 3); ARTgetsize += 3; } else if (memcmp((ARThandle->data + ARThandle->len - 5), "\r\n.\r\n", 5)) { if (memcmp((ARThandle->data + ARThandle->len - 2), "\r\n", 2)) { SendIOv("\r\n.\r\n", 5); ARTgetsize += 5; } else { SendIOv(".\r\n", 3); ARTgetsize += 3; } } PushIOv(); ARTget++; } /* ** Return the header from the specified file, or NULL if not found. */ char * GetHeader(const char *header, bool stripspaces) { const char *p, *q, *r, *s, *t; char *w, *wnew, prevchar; /* Bogus value here to make sure that it isn't initialized to \n. */ char lastchar = ' '; const char *limit; const char *cmplimit; static char *retval = NULL; static int retlen = 0; int headerlen; bool pathheader = false; bool xrefheader = false; limit = ARThandle->data + ARThandle->len; cmplimit = ARThandle->data + ARThandle->len - strlen(header) - 1; for (p = ARThandle->data; p < cmplimit; p++) { if (*p == '\r') continue; if ((lastchar == '\n') && (*p == '\n')) { return NULL; } if ((lastchar == '\n') || (p == ARThandle->data)) { headerlen = strlen(header); if (strncasecmp(p, header, headerlen) == 0 && p[headerlen] == ':' && ISWHITE(p[headerlen+1])) { p += headerlen + 2; if (stripspaces) { for (; (p < limit) && ISWHITE(*p) ; p++); } for (q = p; q < limit; q++) if ((*q == '\r') || (*q == '\n')) { /* Check for continuation header lines. */ t = q + 1; if (t < limit) { if ((*q == '\r' && *t == '\n')) { t++; if (t == limit) break; } if ((*t == '\t' || *t == ' ')) { for (; (t < limit) && ISWHITE(*t) ; t++); q = t; } else { break; } } else { break; } } if (q == limit) return NULL; if (strncasecmp("Path", header, headerlen) == 0) pathheader = true; else if (strncasecmp("Xref", header, headerlen) == 0) xrefheader = true; if (retval == NULL) { /* Possibly add '!' (a second one) at the end of the virtual path. * So it is +2 because of '\0'. */ retlen = q - p + VirtualPathlen + 2; retval = xmalloc(retlen); } else { if ((q - p + VirtualPathlen + 2) > retlen) { retlen = q - p + VirtualPathlen + 2; retval = xrealloc(retval, retlen); } } if (pathheader && (VirtualPathlen > 0)) { const char *endofpath; const char *endofarticle; endofarticle = ARThandle->data + ARThandle->len - 1; endofpath = wire_endheader(p, endofarticle); if (endofpath == NULL) return NULL; for (s = p, prevchar = '\0'; s + VirtualPathlen + 1 < endofpath; prevchar = *s++) { if ((prevchar != '\0' && prevchar != '!') || *s != *VirtualPath || strncasecmp(s, VirtualPath, VirtualPathlen - 1) != 0) continue; if (*(s + VirtualPathlen - 1) != '\0' && *(s + VirtualPathlen - 1) != '!') continue; break; } if (s + VirtualPathlen + 1 < endofpath) { memcpy(retval, s, q - s); *(retval + (int)(q - s)) = '\0'; } else { memcpy(retval, VirtualPath, VirtualPathlen); *(retval + VirtualPathlen) = '!'; memcpy(retval + VirtualPathlen + 1, p, q - p); *(retval + (int)(q - p) + VirtualPathlen + 1) = '\0'; } } else if (xrefheader && (VirtualPathlen > 0)) { if ((r = memchr(p, ' ', q - p)) == NULL) return NULL; for (; (r < q) && isspace((unsigned char) *r) ; r++); if (r == q) return NULL; /* Copy the virtual path without its final '!'. */ memcpy(retval, VirtualPath, VirtualPathlen - 1); memcpy(retval + VirtualPathlen - 1, r - 1, q - r + 1); *(retval + (int)(q - r) + VirtualPathlen) = '\0'; } else { memcpy(retval, p, q - p); *(retval + (int)(q - p)) = '\0'; } for (w = retval, wnew = retval; *w; w++) { if (*w == '\r' && w[1] == '\n') { w++; continue; } if (*w == '\0' || *w == '\t' || *w == '\r' || *w == '\n') { *wnew = ' '; } else { *wnew = *w; } wnew++; } *wnew = '\0'; return retval; } } lastchar = *p; } return NULL; } /* ** Fetch part or all of an article and send it to the client. */ void CMDfetch(int ac, char *av[]) { char buff[SMBUF]; SENDDATA *what; bool mid, ok; ARTNUM art; char *msgid; ARTNUM tart; bool final = false; mid = (ac > 1 && IsValidMessageID(av[1], true, laxmid)); /* Check the syntax of the arguments first. */ if (ac > 1 && !IsValidArticleNumber(av[1])) { /* It is better to check for a number before a message-ID because * '<' could have been forgotten and the error message should then * report a syntax error in the message-ID. */ if (isdigit((unsigned char) av[1][0])) { Reply("%d Syntax error in article number\r\n", NNTP_ERR_SYNTAX); return; } else if (!mid) { Reply("%d Syntax error in message-ID\r\n", NNTP_ERR_SYNTAX); return; } } /* Find what to send; get permissions. */ ok = PERMcanread; switch (*av[0]) { default: what = &SENDbody; final = true; break; case 'a': case 'A': what = &SENDarticle; final = true; 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; } /* Trying to read. */ if (GRPcount == 0 && !mid) { Reply("%d Not in a newsgroup\r\n", NNTP_FAIL_NO_GROUP); return; } /* Check authorizations. If an article number is requested * (not a message-ID), we check whether the group is still readable. */ if (!ok || (!mid && PERMgroupmadeinvalid)) { Reply("%d Read access denied\r\n", PERMcanauthenticate ? NNTP_FAIL_AUTH_NEEDED : NNTP_ERR_ACCESS); return; } /* Requesting by message-ID? */ if (mid) { if (!ARTopenbyid(av[1], &art, final)) { Reply("%d No such article\r\n", NNTP_FAIL_MSGID_NOTFOUND); return; } if (!PERMartok()) { ARTclose(); Reply("%d Read access denied for this article\r\n", PERMcanauthenticate ? NNTP_FAIL_AUTH_NEEDED : NNTP_ERR_ACCESS); return; } Reply("%d %lu %s %s\r\n", what->ReplyCode, art, av[1], what->Item); if (what->Type != STstat) { ARTsendmmap(what->Type); } ARTclose(); return; } /* Default is to get current article, or specified article. */ if (ac == 1) { if (ARTnumber < ARTlow || ARTnumber > ARThigh) { Reply("%d Current article number %lu is invalid\r\n", NNTP_FAIL_ARTNUM_INVALID, ARTnumber); return; } snprintf(buff, sizeof(buff), "%lu", ARTnumber); tart = ARTnumber; } else { /* We have already checked that the article number is valid. */ strlcpy(buff, av[1], sizeof(buff)); tart = (ARTNUM)atol(buff); } /* Open the article and send the reply. */ if (!ARTopen(tart)) { Reply("%d No such article number %lu\r\n", NNTP_FAIL_ARTNUM_NOTFOUND, tart); return; } if ((msgid = GetHeader("Message-ID", true)) == NULL) { ARTclose(); Reply("%d No such article number %lu\r\n", NNTP_FAIL_ARTNUM_NOTFOUND, tart); return; } if (ac > 1) ARTnumber = tart; /* A message-ID does not have more than 250 octets. */ Reply("%d %s %.250s %s\r\n", what->ReplyCode, buff, msgid, what->Item); if (what->Type != STstat) ARTsendmmap(what->Type); ARTclose(); } /* ** Go to the next or last (really previous) article in the group. */ void CMDnextlast(int ac UNUSED, char *av[]) { char *msgid; int save, delta, errcode; bool next; const char *message; /* Trying to read. */ if (GRPcount == 0) { Reply("%d Not in a newsgroup\r\n", NNTP_FAIL_NO_GROUP); return; } /* No syntax to check. Only check authorizations. */ if (!PERMcanread || PERMgroupmadeinvalid) { Reply("%d Read access denied\r\n", PERMcanauthenticate ? NNTP_FAIL_AUTH_NEEDED : NNTP_ERR_ACCESS); return; } if (ARTnumber < ARTlow || ARTnumber > ARThigh) { Reply("%d Current article number %lu is invalid\r\n", NNTP_FAIL_ARTNUM_INVALID, ARTnumber); return; } /* NEXT? */ next = (av[0][0] == 'n' || av[0][0] == 'N'); if (next) { delta = 1; errcode = NNTP_FAIL_NEXT; message = "next"; } else { delta = -1; errcode = NNTP_FAIL_PREV; message = "previous"; } save = ARTnumber; msgid = NULL; do { ARTnumber += delta; if (ARTnumber < ARTlow || ARTnumber > ARThigh) { Reply("%d No %s article to retrieve\r\n", errcode, message); ARTnumber = save; return; } if (!ARTopen(ARTnumber)) continue; msgid = GetHeader("Message-ID", true); ARTclose(); } while (msgid == NULL); Reply("%d %lu %s Article retrieved; request text separately\r\n", NNTP_OK_STAT, ARTnumber, msgid); } /* ** Parse a range (in av[1]) which may be any of the following: ** - An article number. ** - An article number followed by a dash to indicate all following. ** - An article number followed by a dash followed by another article ** number. ** ** In the last case, if the second number is less than the first number, ** then the range contains no articles. ** ** In addition to RFC 3977, we also accept: ** - A dash followed by an article number to indicate all previous. ** - A dash for everything. ** ** ac is the number of arguments in the command: ** LISTGROUP news.software.nntp 12-42 ** gives ac=3 and av[1] should match "12-42" (whence the "av+1" call ** of CMDgetrange). ** ** rp->Low and rp->High will contain the values of the range. ** *DidReply will be true if this function sends an answer. */ bool CMDgetrange(int ac, char *av[], ARTRANGE *rp, bool *DidReply) { char *p; *DidReply = false; if (ac == 1) { /* No arguments, do only current article. */ if (ARTnumber < ARTlow || ARTnumber > ARThigh) { Reply("%d Current article number %lu is invalid\r\n", NNTP_FAIL_ARTNUM_INVALID, ARTnumber); *DidReply = true; return false; } rp->High = rp->Low = ARTnumber; return true; } /* Check the syntax. */ if (!IsValidRange(av[1])) { Reply("%d Syntax error in range\r\n", NNTP_ERR_SYNTAX); *DidReply = true; return false; } /* Got just a single number? */ if ((p = strchr(av[1], '-')) == NULL) { rp->Low = rp->High = atol(av[1]); return true; } /* "-" becomes "\0" and we parse the low water mark. * Note that atol() returns 0 if no valid number * is found at the beginning of *p. */ *p++ = '\0'; rp->Low = atol(av[1]); /* Adjust the low water mark. */ if (rp->Low < ARTlow) rp->Low = ARTlow; /* Parse and adjust the high water mark. * "12-" gives everything from 12 to the end. * We do not bother about "42-12" or "42-0" in this function. */ if ((*p == '\0') || ((rp->High = atol(p)) > ARThigh)) rp->High = ARThigh; p--; *p = '-'; return true; } /* ** Apply virtual hosting to an Xref: field. */ static char * vhost_xref(char *p) { char *space; size_t offset; char *field = NULL; space = strchr(p, ' '); if (space == NULL) { warn("malformed Xref: `%s'", p); goto fail; } offset = space - p; space = strchr(p + offset, ' '); if (space == NULL) { warn("malformed Xref: `%s'", p); goto fail; } field = concat(PERMaccessconf->domain, space, NULL); fail: free(p); return field; } /* ** Dump parts of the overview database with the OVER command. ** The legacy XOVER is also kept, with its specific behaviour. */ void CMDover(int ac, char *av[]) { bool DidReply, HasNotReplied; ARTRANGE range; struct timeval stv, etv; ARTNUM artnum; void *handle; char *data, *r; const char *p, *q; int len, useIOb = 0; TOKEN token; struct cvector *vector = NULL; bool xover, mid; xover = (strcasecmp(av[0], "XOVER") == 0); mid = (ac > 1 && IsValidMessageID(av[1], true, laxmid)); if (mid && !xover) { /* FIXME: We still do not support OVER MSGID, sorry! */ Reply("%d Overview by message-ID unsupported\r\n", NNTP_ERR_UNAVAILABLE); return; } /* Check the syntax of the arguments first. * We do not accept a message-ID for XOVER, contrary to OVER. A range * is accepted for both of them. */ if (ac > 1 && !IsValidRange(av[1])) { /* It is better to check for a range before a message-ID because * '<' could have been forgotten and the error message should then * report a syntax error in the message-ID. */ if (xover || isdigit((unsigned char) av[1][0]) || av[1][0] == '-') { Reply("%d Syntax error in range\r\n", NNTP_ERR_SYNTAX); return; } else if (!mid) { Reply("%d Syntax error in message-ID\r\n", NNTP_ERR_SYNTAX); return; } } /* Trying to read. */ if (GRPcount == 0) { Reply("%d Not in a newsgroup\r\n", NNTP_FAIL_NO_GROUP); return; } /* Check authorizations. If a range is requested (not a message-ID), * we check whether the group is still readable. */ if (!PERMcanread || (!mid && PERMgroupmadeinvalid)) { Reply("%d Read access denied\r\n", PERMcanauthenticate ? NNTP_FAIL_AUTH_NEEDED : NNTP_ERR_ACCESS); return; } /* Parse range. CMDgetrange() correctly sets the range when * there is no arguments. */ if (!CMDgetrange(ac, av, &range, &DidReply)) if (DidReply) return; if (PERMaccessconf->nnrpdoverstats) { OVERcount++; gettimeofday(&stv, NULL); } if ((handle = (void *)OVopensearch(GRPcur, range.Low, range.High)) == NULL) { /* The response code for OVER is different if a range is provided. * Note that XOVER answers OK. */ if (ac > 1) Reply("%d No articles in %s\r\n", xover ? NNTP_OK_OVER : NNTP_FAIL_ARTNUM_NOTFOUND, av[1]); else Reply("%d No such article number %lu\r\n", xover ? NNTP_OK_OVER : NNTP_FAIL_ARTNUM_NOTFOUND, ARTnumber); if (xover) Printf(".\r\n"); return; } if (PERMaccessconf->nnrpdoverstats) { gettimeofday(&etv, NULL); OVERtime+=(etv.tv_sec - stv.tv_sec) * 1000; OVERtime+=(etv.tv_usec - stv.tv_usec) / 1000; } if (PERMaccessconf->nnrpdoverstats) gettimeofday(&stv, NULL); /* If OVSTATICSEARCH is true, then the data returned by OVsearch is only valid until the next call to OVsearch. In this case, we must use SendIOb because it copies the data. */ OVctl(OVSTATICSEARCH, &useIOb); HasNotReplied = true; while (OVsearch(handle, &artnum, &data, &len, &token, NULL)) { if (PERMaccessconf->nnrpdoverstats) { gettimeofday(&etv, NULL); OVERtime+=(etv.tv_sec - stv.tv_sec) * 1000; OVERtime+=(etv.tv_usec - stv.tv_usec) / 1000; } if (len == 0 || (PERMaccessconf->nnrpdcheckart && !ARTinstorebytoken(token))) { if (PERMaccessconf->nnrpdoverstats) { OVERmiss++; gettimeofday(&stv, NULL); } continue; } if (PERMaccessconf->nnrpdoverstats) { OVERhit++; OVERsize += len; } if (HasNotReplied) { if (ac > 1) Reply("%d Overview information for %s follows\r\n", NNTP_OK_OVER, av[1]); else Reply("%d Overview information for %lu follows\r\n", NNTP_OK_OVER, ARTnumber); fflush(stdout); HasNotReplied = false; } vector = overview_split(data, len, NULL, vector); r = overview_get_standard_header(vector, OVERVIEW_MESSAGE_ID); if (r == NULL) { if (PERMaccessconf->nnrpdoverstats) { gettimeofday(&stv, NULL); } continue; } cache_add(HashMessageID(r), token); free(r); if (VirtualPathlen > 0 && overhdr_xref != -1) { if ((size_t)(overhdr_xref + 1) >= vector->count) { if (PERMaccessconf->nnrpdoverstats) { gettimeofday(&stv, NULL); } continue; } p = vector->strings[overhdr_xref] + sizeof("Xref: ") - 1; while ((p < data + len) && *p == ' ') ++p; q = memchr(p, ' ', data + len - p); if (q == NULL) { if (PERMaccessconf->nnrpdoverstats) { gettimeofday(&stv, NULL); } continue; } /* Copy the virtual path without its final '!'. */ if(useIOb) { SendIOb(data, p - data); SendIOb(VirtualPath, VirtualPathlen - 1); SendIOb(q, len - (q - data)); } else { SendIOv(data, p - data); SendIOv(VirtualPath, VirtualPathlen - 1); SendIOv(q, len - (q - data)); } } else { if(useIOb) SendIOb(data, len); else SendIOv(data, len); } if (PERMaccessconf->nnrpdoverstats) gettimeofday(&stv, NULL); } if (PERMaccessconf->nnrpdoverstats) { gettimeofday(&etv, NULL); OVERtime+=(etv.tv_sec - stv.tv_sec) * 1000; OVERtime+=(etv.tv_usec - stv.tv_usec) / 1000; } if (vector) cvector_free(vector); if (HasNotReplied) { /* The response code for OVER is different if a range is provided. * Note that XOVER answers OK. */ if (ac > 1) Reply("%d No articles in %s\r\n", xover ? NNTP_OK_OVER : NNTP_FAIL_ARTNUM_NOTFOUND, av[1]); else Reply("%d No such article number %lu\r\n", xover ? NNTP_OK_OVER : NNTP_FAIL_ARTNUM_NOTFOUND, ARTnumber); if (xover) Printf(".\r\n"); } else { if(useIOb) { SendIOb(".\r\n", 3); PushIOb(); } else { SendIOv(".\r\n", 3); PushIOv(); } } if (PERMaccessconf->nnrpdoverstats) gettimeofday(&stv, NULL); OVclosesearch(handle); if (PERMaccessconf->nnrpdoverstats) { gettimeofday(&etv, NULL); OVERtime+=(etv.tv_sec - stv.tv_sec) * 1000; OVERtime+=(etv.tv_usec - stv.tv_usec) / 1000; } } /* ** Access specific fields from an article with HDR. ** The legacy XHDR and XPAT are also kept, with their specific behaviours. */ void CMDpat(int ac, char *av[]) { char *p; unsigned long i; ARTRANGE range; bool IsBytes, IsLines; bool IsMetaBytes, IsMetaLines; bool DidReply, HasNotReplied; const char *header; char *pattern; char *text; int Overview; ARTNUM artnum; char buff[SPOOLNAMEBUFF]; void *handle; char *data; int len; TOKEN token; struct cvector *vector = NULL; bool hdr, mid; hdr = (strcasecmp(av[0], "HDR") == 0); mid = (ac > 2 && IsValidMessageID(av[2], true, laxmid)); /* Check the syntax of the arguments first. */ if (ac > 2 && !IsValidRange(av[2])) { /* It is better to check for a range before a message-ID because * '<' could have been forgotten and the error message should then * report a syntax error in the message-ID. */ if (isdigit((unsigned char) av[2][0]) || av[2][0] == '-') { Reply("%d Syntax error in range\r\n", NNTP_ERR_SYNTAX); return; } else if (!mid) { Reply("%d Syntax error in message-ID\r\n", NNTP_ERR_SYNTAX); return; } } header = av[1]; /* If metadata is asked for, convert it to headers that * the overview database knows. */ IsBytes = (strcasecmp(header, "Bytes") == 0); IsLines = (strcasecmp(header, "Lines") == 0); IsMetaBytes = (strcasecmp(header, ":bytes") == 0); IsMetaLines = (strcasecmp(header, ":lines") == 0); /* Make these changes because our overview database does * not currently know metadata names. */ if (IsMetaBytes) header = "Bytes"; if (IsMetaLines) header = "Lines"; /* We only allow :bytes and :lines for metadata. */ if (!IsMetaLines && !IsMetaBytes) { p = av[1]; p++; if (strncasecmp(header, ":", 1) == 0 && IsValidHeaderName(p)) { Reply("%d Unsupported metadata request\r\n", NNTP_ERR_UNAVAILABLE); return; } else if (!IsValidHeaderName(header)) { Reply("%d Syntax error in header name\r\n", NNTP_ERR_SYNTAX); return; } } /* Trying to read. */ if (GRPcount == 0 && !mid) { Reply("%d Not in a newsgroup\r\n", NNTP_FAIL_NO_GROUP); return; } /* Check authorizations. If a range is requested (not a message-ID), * we check whether the group is still readable. */ if (!PERMcanread || (!mid && PERMgroupmadeinvalid)) { Reply("%d Read access denied\r\n", PERMcanauthenticate ? NNTP_FAIL_AUTH_NEEDED : NNTP_ERR_ACCESS); return; } if (ac > 3) /* Necessarily XPAT. */ pattern = Glom(&av[3]); else pattern = NULL; /* We will only do the loop once. It is just in order to easily break. */ do { /* Message-ID specified? */ if (mid) { /* FIXME: We do not handle metadata requests by message-ID. */ if (hdr && (IsMetaBytes || IsMetaLines)) { Reply("%d Metadata requests by message-ID unsupported\r\n", NNTP_ERR_UNAVAILABLE); break; } p = av[2]; if (!ARTopenbyid(p, &artnum, false)) { Reply("%d No such article\r\n", NNTP_FAIL_MSGID_NOTFOUND); break; } if (!PERMartok()) { ARTclose(); Reply("%d Read access denied for this article\r\n", PERMcanauthenticate ? NNTP_FAIL_AUTH_NEEDED : NNTP_ERR_ACCESS); break; } Reply("%d Header information for %s follows (from the article)\r\n", hdr ? NNTP_OK_HDR : NNTP_OK_HEAD, av[1]); if ((text = GetHeader(av[1], false)) != NULL && (!pattern || uwildmat_simple(text, pattern))) Printf("%s %s\r\n", hdr ? "0" : p, text); else if (hdr) { /* We always have to answer something with HDR. */ Printf("0 \r\n"); } ARTclose(); Printf(".\r\n"); break; } /* Parse range. CMDgetrange() correctly sets the range when * there is no arguments. */ if (!CMDgetrange(ac - 1, av + 1, &range, &DidReply)) if (DidReply) break; /* In overview? */ Overview = overview_index(header, OVextra); HasNotReplied = true; /* Not in overview, we have to fish headers out from the articles. */ if (Overview < 0 || IsBytes || IsLines) { for (i = range.Low; i <= range.High && range.High > 0; i++) { if (!ARTopen(i)) continue; if (HasNotReplied) { Reply("%d Header information for %s follows (from articles)\r\n", hdr ? NNTP_OK_HDR : NNTP_OK_HEAD, av[1]); HasNotReplied = false; } p = GetHeader(header, false); if (p && (!pattern || uwildmat_simple(p, pattern))) { snprintf(buff, sizeof(buff), "%lu ", i); SendIOb(buff, strlen(buff)); SendIOb(p, strlen(p)); SendIOb("\r\n", 2); } else if (hdr) { /* We always have to answer something with HDR. */ snprintf(buff, sizeof(buff), "%lu \r\n", i); SendIOb(buff, strlen(buff)); } ARTclose(); } if (HasNotReplied) { if (hdr) { if (ac > 2) Reply("%d No articles in %s\r\n", NNTP_FAIL_ARTNUM_NOTFOUND, av[2]); else Reply("%d No such article number %lu\r\n", NNTP_FAIL_ARTNUM_NOTFOUND, ARTnumber); } else { Reply("%d No header information for %s follows (from articles)\r\n", NNTP_OK_HEAD, av[1]); Printf(".\r\n"); } break; } else { SendIOb(".\r\n", 3); } PushIOb(); break; } /* Okay then, we can grab values from the overview database. */ handle = (void *)OVopensearch(GRPcur, range.Low, range.High); if (handle == NULL) { if (hdr) { if (ac > 2) Reply("%d No articles in %s\r\n", NNTP_FAIL_ARTNUM_NOTFOUND, av[2]); else Reply("%d No such article number %lu\r\n", NNTP_FAIL_ARTNUM_NOTFOUND, ARTnumber); } else { Reply("%d No header information for %s follows (from overview)\r\n", NNTP_OK_HEAD, av[1]); Printf(".\r\n"); } break; } while (OVsearch(handle, &artnum, &data, &len, &token, NULL)) { if (len == 0 || (PERMaccessconf->nnrpdcheckart && !ARTinstorebytoken(token))) continue; if (HasNotReplied) { Reply("%d Header or metadata information for %s follows (from overview)\r\n", hdr ? NNTP_OK_HDR : NNTP_OK_HEAD, av[1]); HasNotReplied = false; } vector = overview_split(data, len, NULL, vector); if (Overview < OVERVIEW_MAX) { p = overview_get_standard_header(vector, Overview); } else { p = overview_get_extra_header(vector, header); } if (p != NULL) { if (PERMaccessconf->virtualhost && Overview == overhdr_xref) { p = vhost_xref(p); if (p == NULL) { if (hdr) { snprintf(buff, sizeof(buff), "%lu \r\n", artnum); SendIOb(buff, strlen(buff)); } continue; } } if (!pattern || uwildmat_simple(p, pattern)) { snprintf(buff, sizeof(buff), "%lu ", artnum); SendIOb(buff, strlen(buff)); SendIOb(p, strlen(p)); SendIOb("\r\n", 2); } /* No need to have another condition for HDR because * pattern is NULL for it, and p is not NULL here. */ free(p); } else if (hdr) { snprintf(buff, sizeof(buff), "%lu \r\n", artnum); SendIOb(buff, strlen(buff)); } } if (HasNotReplied) { if (hdr) { if (ac > 2) Reply("%d No articles in %s\r\n", NNTP_FAIL_ARTNUM_NOTFOUND, av[2]); else Reply("%d Current article number %lu is invalid\r\n", NNTP_FAIL_ARTNUM_INVALID, ARTnumber); } else { Reply("%d No header or metadata information for %s follows (from overview)\r\n", NNTP_OK_HEAD, av[1]); Printf(".\r\n"); } break; } else { SendIOb(".\r\n", 3); } PushIOb(); OVclosesearch(handle); } while (0); if (vector) cvector_free(vector); if (pattern) free(pattern); } inn-2.6.4/nnrpd/nnrpd.h0000644000175200017520000002425414002373703014342 0ustar iuliusiulius/* $Id: nnrpd.h 10306 2018-12-02 14:26:13Z iulius $ ** ** NetNews Reading Protocol server. */ #include "config.h" #include "portable/macros.h" #include "portable/socket.h" #include #include #include #include #include #ifdef HAVE_SYS_TIME_H # include #endif #include #include "inn/qio.h" #include "inn/libinn.h" #include "inn/nntp.h" #include "inn/paths.h" #include "inn/storage.h" #include "inn/vector.h" #include "inn/timer.h" #ifdef HAVE_SASL #include #include #endif #if defined(HAVE_ZLIB) # include #endif /* ** A range of article numbers. */ typedef struct _ARTRANGE { ARTNUM Low; ARTNUM High; } ARTRANGE; /* ** Access configuration for each reader. */ typedef struct _ACCESSGROUP { char *name; char *key; char *read; char *post; char *users; char *rejectwith; int allownewnews; bool allowihave; int locpost; int allowapproved; int used; int localtime; int strippath; int nnrpdperlfilter; int nnrpdpythonfilter; char *fromhost; char *pathhost; char *organization; char *moderatormailer; char *domain; char *complaints; int spoolfirst; int checkincludedtext; int clienttimeout; unsigned long localmaxartsize; int readertrack; int strippostcc; int addinjectiondate; int addinjectionpostingaccount; int addinjectionpostinghost; char *nnrpdposthost; unsigned long nnrpdpostport; int nnrpdoverstats; int backoff_auth; char *backoff_db; unsigned long backoff_k; unsigned long backoff_postfast; unsigned long backoff_postslow; unsigned long backoff_trigger; int nnrpdcheckart; int nnrpdauthsender; int virtualhost; char *newsmaster; long maxbytespersecond; } ACCESSGROUP; /* ** What line_read returns. */ typedef enum _READTYPE { RTeof, RTok, RTlong, RTtimeout } READTYPE; /* ** Structure used by line_read to keep track of what has been read. */ struct line { char *start; char *where; size_t remaining; size_t allocated; }; /* ** Information about the currently connected client. Eventually, this struct ** may become the repository for all nnrpd global state, or at least the ** state that relates to a particular client connection. */ struct client { char host[SMBUF]; char ip[INET6_ADDRSTRLEN]; unsigned short port; char serverhost[SMBUF]; char serverip[INET6_ADDRSTRLEN]; unsigned short serverport; }; /* ** Information about the schema of the news overview files. */ typedef struct _ARTOVERFIELD { char *Header; int Length; bool NeedsHeader; } ARTOVERFIELD; /* ** Supported timers. If you add new timers to this list, also add them to ** the list of tags in nnrpd.c. */ enum timer { TMR_IDLE = TMR_APPLICATION, /* Server is completely idle. */ TMR_NEWNEWS, /* Executing NEWNEWS command. */ TMR_READART, /* Reading an article (SMretrieve). */ TMR_CHECKART, /* Checking an article (ARTinstorebytoken). */ TMR_NNTPREAD, /* Reading from the peer. */ TMR_NNTPWRITE, /* Writing to the peer. */ TMR_MAX }; #if defined(MAINLINE) #define EXTERN /* NULL */ #else #define EXTERN extern #endif /* defined(MAINLINE) */ EXTERN bool PERMauthorized; EXTERN bool PERMcanauthenticate; #if defined(HAVE_OPENSSL) || defined(HAVE_SASL) EXTERN bool PERMcanauthenticatewithoutSSL; #endif EXTERN bool PERMcanpost; EXTERN bool PERMcanpostgreeting; EXTERN bool PERMcanread; EXTERN bool PERMneedauth; EXTERN bool PERMspecified; EXTERN bool PERMgroupmadeinvalid; EXTERN ACCESSGROUP *PERMaccessconf; EXTERN bool Tracing; EXTERN bool Offlinepost; EXTERN bool initialSSL; EXTERN char **PERMreadlist; EXTERN char **PERMpostlist; EXTERN struct client Client; EXTERN char Username[SMBUF]; extern char *ACTIVETIMES; extern char *HISTORY; extern char *ACTIVE; extern char *NEWSGROUPS; extern char *NNRPACCESS; EXTERN char PERMuser[SMBUF]; EXTERN FILE *locallog; EXTERN ARTNUM ARTnumber; /* Current article number. */ EXTERN ARTNUM ARThigh; /* Current high number for group. */ EXTERN ARTNUM ARTlow; /* Current low number for group. */ EXTERN unsigned long ARTcount; /* Number of articles in group. */ EXTERN long MaxBytesPerSecond; /* Maximum bytes per sec a client can use, defaults to 0. */ EXTERN long ARTget; EXTERN long ARTgettime; EXTERN long ARTgetsize; EXTERN long OVERcount; /* Number of (X)OVER commands. */ EXTERN long OVERhit; /* Number of (X)OVER records found in overview. */ EXTERN long OVERmiss; /* Number of (X)OVER records found in articles. */ EXTERN long OVERtime; /* Number of ms spent sending (X)OVER data. */ EXTERN long OVERsize; /* Number of bytes of (X)OVER data sent. */ EXTERN long OVERdbz; /* Number of ms spent reading dbz data. */ EXTERN long OVERseek; /* Number of ms spent seeking history. */ EXTERN long OVERget; /* Number of ms spent reading history. */ EXTERN long OVERartcheck; /* Number of ms spent article check. */ EXTERN double IDLEtime; EXTERN unsigned long GRParticles; EXTERN long GRPcount; EXTERN char *GRPcur; EXTERN long POSTreceived; EXTERN long POSTrejected; EXTERN bool BACKOFFenabled; EXTERN char *VirtualPath; EXTERN int VirtualPathlen; EXTERN struct history *History; EXTERN struct line NNTPline; EXTERN struct vector *OVextra; EXTERN int overhdr_xref; EXTERN bool LLOGenable; extern const char *ARTpost(char *article, char *idbuff, bool *permanent); extern void ARTclose(void); extern int TrimSpaces(char *line); extern void InitBackoffConstants(void); extern char *PostRecFilename(char *ip, char *user); extern int LockPostRec(char *path); extern void UnlockPostRec(char *path); extern int RateLimit(long *sleeptime, char *path); extern void ExitWithStats(int x, bool readconf) __attribute__ ((__noreturn__)); extern char *GetHeader(const char *header, bool stripspaces); extern void GRPreport(void); extern bool NGgetlist(char ***argvp, char *list); extern bool PERMartok(void); extern void PERMgetinitialaccess(char *readersconf); extern void PERMgetaccess(bool initialconnection); extern void PERMgetpermissions(void); extern void PERMlogin(char *uname, char *pass, int* code, char *errorstr); extern bool PERMmatch(char **Pats, char **list); extern bool ParseDistlist(char ***argvp, char *list); extern void SetDefaultAccess(ACCESSGROUP*); extern void Reply(const char *fmt, ...) __attribute__((__format__(printf, 1, 2))); extern void Printf(const char *fmt, ...) __attribute__((__format__(printf, 1, 2))); extern void CMDauthinfo (int ac, char** av); extern void CMDcapabilities (int ac, char** av); #if defined(HAVE_ZLIB) extern void CMDcompress (int ac, char** av); #endif extern void CMDdate (int ac, char** av); extern void CMDfetch (int ac, char** av); extern void CMDgroup (int ac, char** av); extern void CMDhelp (int ac, char** av); extern void CMDlist (int ac, char** av); extern void CMDmode (int ac, char** av); extern void CMDnewgroups (int ac, char** av); extern void CMDnewnews (int ac, char** av); extern void CMDnextlast (int ac, char** av); extern void CMDover (int ac, char** av); extern void CMDpost (int ac, char** av); extern void CMDquit (int ac, char** av) __attribute__ ((__noreturn__)); extern void CMDxgtitle (int ac, char** av); extern void CMDpat (int ac, char** av); extern void CMD_unimp (int ac, char** av); #ifdef HAVE_OPENSSL extern void CMDstarttls (int ac, char** av); #endif extern bool CMDgetrange(int ac, char *av[], ARTRANGE *rp, bool *DidReply); /* ** Run a resolver or authenticator. The directory is where to look for the ** command if not fully qualified. username and password may be NULL to run ** resolvers. */ char *auth_external(struct client *, const char *command, const char *directory, const char *username, const char *password); void write_buffer(const char *buff, ssize_t len); extern char *HandleHeaders(char *article); extern bool ARTinstorebytoken(TOKEN token); extern int TrackClient(char *client, char* user, size_t len); #ifdef DO_PERL extern void loadPerl(void); extern void perlAccess(char *user, struct vector *access_vec); extern void perlAuthenticate(char *user, char *passwd, int *code, char *errorstring, char*newUser); extern void perlAuthInit(void); #endif /* DO_PERL */ #ifdef DO_PYTHON extern bool PY_use_dynamic; void PY_authenticate(char *path, char *Username, char *Password, int *code, char *errorstring, char *newUser); void PY_access(char* path, struct vector *access_vec, char *Username); void PY_close_python(void); int PY_dynamic(char *Username, char *NewsGroup, int PostFlag, char **reply_message); void PY_dynamic_init (char* file); # if PY_MAJOR_VERSION >= 3 extern PyMODINIT_FUNC PyInit_nnrpd(void); # else extern void PyInit_nnrpd(void); # endif #endif /* DO_PYTHON */ void line_free(struct line *); void line_init(struct line *); void line_reset(struct line *); READTYPE line_read(struct line *, int, const char **, size_t *, size_t *); #ifdef HAVE_SASL extern sasl_conn_t *sasl_conn; extern int sasl_ssf, sasl_maxout; extern sasl_callback_t sasl_callbacks[]; void SASLauth(int ac, char *av[]); void SASLnewserver(void); #endif /* HAVE_SASL */ #if defined(HAVE_SASL) || defined(HAVE_ZLIB) bool IsValidAlgorithm(const char *); #endif /* HAVE_SASL || HAVE_ZLIB */ #if defined(HAVE_ZLIB) extern bool compression_layer_on; extern bool tls_compression_on; /* (De)compress streams and related variables. */ extern z_stream *zstream_in; extern z_stream *zstream_out; extern bool zstream_inflate_needed; extern bool zstream_flush_needed; /* (De)compress buffers and related variables. */ extern unsigned char *zbuf_in; extern size_t zbuf_in_allocated; extern size_t zbuf_in_size; extern unsigned char *zbuf_out; extern size_t zbuf_out_size; bool zlib_init(void); #endif /* HAVE_ZLIB */ inn-2.6.4/nnrpd/auth-ext.c0000644000175200017520000002543514002373703014755 0ustar iuliusiulius/* $Id: auth-ext.c 10467 2020-12-24 22:33:03Z eagle $ ** ** External authenticator support. ** ** Run an external resolver or authenticator to determine the username of the ** client and return that information to INN. For more information about the ** protocol used, see doc/external-auth. */ #include "config.h" #include "clibrary.h" #include #include #include #include "inn/buffer.h" #include "inn/messages.h" #include "inn/vector.h" #include "nnrpd.h" /* Holds the details about a running child process. */ struct process { pid_t pid; int read_fd; /* Read from child. */ int write_fd; /* Write to child. */ int error_fd; }; /* ** Given the client information struct, a string indicating the program to ** run (possibly including arguments) and the directory in which to look for ** the command if it's not fully qualified, start that program and return a ** struct process providing the PID and file descriptors. */ static struct process * start_process(struct client *client, const char *command, const char *dir) { struct process *process; int rd[2], wr[2], er[2]; pid_t pid; char *path; struct vector *args; /* Parse the command and find the path to the binary. */ args = vector_split_space(command, NULL); path = args->strings[0]; if (path[0] != '/') { path = concatpath(dir, path); } /* Set up the pipes and run the program. */ if (pipe(rd) < 0 || pipe(wr) < 0 || pipe(er) < 0) { syswarn("%s auth: cannot create pipe", client->host); return NULL; } pid = fork(); switch (pid) { case -1: close(rd[0]); close(rd[1]); close(wr[0]); close(wr[1]); close(er[0]); close(er[1]); syswarn("%s auth: cannot fork", client->host); return NULL; case 0: if (dup2(wr[0], 0) < 0 || dup2(rd[1], 1) < 0 || dup2(er[1], 2) < 0) { syswarn("%s auth: cannot set up file descriptors", client->host); _exit(1); } close(rd[0]); close(rd[1]); close(wr[0]); close(wr[1]); close(er[0]); close(er[1]); if (vector_exec(path, args) < 0) { syswarn("%s auth: cannot exec %s", client->host, path); _exit(1); } } /* In the parent. Close excess file descriptors and build return. */ close(rd[1]); close(wr[0]); close(er[1]); process = xmalloc(sizeof(struct process)); process->pid = pid; process->read_fd = rd[0]; process->write_fd = wr[1]; process->error_fd = er[0]; return process; } /* ** Handle a result line from the program which has already been ** nul-terminated at the end of the line. If User: is seen, point ** the second argument at newly allocated space for it. */ static void handle_result(struct client *client UNUSED, const char *line, char **user) { if (strncasecmp(line, "User:", strlen("User:")) == 0) { if (*user != NULL) free(*user); *user = xstrdup(line + strlen("User:")); } } /* ** Handle an error line from the program by logging it. */ static void handle_error(struct client *client, const char *line, char **user UNUSED) { notice("%s auth: program error: %s", client->host, line); } /* ** Read a line of data from the given file descriptor. Return the number of ** bytes read or -1 on buffer overflow. Takes the file descriptor, the ** buffer used for that file descriptor, and the handler function to call for ** each line. Points the fourth argument to a username, if one was found. */ static ssize_t output(struct client *client, int fd, struct buffer *buffer, void (*handler)(struct client *, const char *, char **), char **user) { char *line; char *start; ssize_t count; /* Read the data. */ buffer_compact(buffer); count = buffer_read(buffer, fd); if (buffer->left >= buffer->size - 1) return -1; if (count < 0) { syswarn("%s auth: read error", client->host); return count; } /* If reached end of file, process anything left as a line. */ if (count == 0) { if (buffer->left > 0) { buffer->data[buffer->used + buffer->left] = '\0'; handler(client, buffer->data + buffer->used, user); buffer->used += buffer->left; buffer->left = 0; } return count; } /* Otherwise, break what we got up into lines and process each one. */ start = buffer->data + buffer->used; line = memchr(start, '\n', buffer->left); while (line != NULL) { *line = '\0'; if (line > start && line[-1] == '\r') line[-1] = '\0'; handler(client, start, user); buffer->used += line - start + 1; buffer->left -= line - start + 1; start = buffer->data + buffer->used; line = memchr(start, '\n', buffer->left); } return count; } /* ** Wait for the program to produce output. For each bit of output, call ** handle_output with the appropriate handler function. After end of file or ** an error, check and report on the exit status. Returns the username in ** newly allocated memory, or NULL if none was found. ** ** Currently, use a hard-coded five-second timeout for all programs. This ** might need to be configurable later. */ static char * handle_output(struct client *client, struct process *process) { fd_set fds, rfds; struct timeval tv; int maxfd, status, fd; ssize_t count; pid_t result; struct buffer *readbuf; struct buffer *errorbuf; double start, end; bool done; bool error_done = false; bool killed = false; bool errored = false; char *user = NULL; FD_ZERO(&fds); FD_SET(process->read_fd, &fds); FD_SET(process->error_fd, &fds); maxfd = process->read_fd > process->error_fd ? process->read_fd : process->error_fd; readbuf = buffer_new(); buffer_resize(readbuf, 1024); errorbuf = buffer_new(); buffer_resize(errorbuf, 1024); /* Loop until we get an error or end of file. */ while (1) { tv.tv_sec = 5; tv.tv_usec = 0; rfds = fds; start = TMRnow_double(); status = select(maxfd + 1, &rfds, NULL, NULL, &tv); end = TMRnow_double(); IDLEtime += end - start; /* Check for select timeout or errors. */ if (status <= 0) { if (status == 0) syswarn("%s auth: program timeout", client->host); else { if (errno == EINTR) continue; syswarn("%s auth: select failed", client->host); } killed = true; kill(process->pid, SIGTERM); break; } /* Read from the read and error file descriptors. If we see EOF or an * error from the read file descriptor, we're done. If we see EOF or * an error from the error file descriptor, remove it from the set but * continue waiting for output from the read file descriptor .*/ done = false; count = 0; if (FD_ISSET(process->read_fd, &rfds)) { fd = process->read_fd; count = output(client, fd, readbuf, handle_result, &user); if (count <= 0) done = true; } if (!error_done && FD_ISSET(process->error_fd, &rfds)) { fd = process->error_fd; count = output(client, fd, errorbuf, handle_error, &user); if (count <= 0) { error_done = true; FD_CLR(fd, &fds); maxfd = process->read_fd; } if (count > 0) errored = true; } if (done) { close(process->read_fd); close(process->error_fd); if (count < 0) { warn("%s auth: output too long from program", client->host); killed = true; kill(process->pid, SIGTERM); } break; } } buffer_free(readbuf); buffer_free(errorbuf); /* Wait for the program to exit. */ do { result = waitpid(process->pid, &status, 0); } while (result == -1 && errno == EINTR); if (result != process->pid) { syswarn("%s auth: cannot wait for program", client->host); goto fail; } /* Check the exit status and fall through to fail if the external * authentication program didn't exit successfully. */ if (WIFEXITED(status) && WEXITSTATUS(status) == 0) return user; else { if (WIFSIGNALED(status) && (!killed || WTERMSIG(status) != SIGTERM)) notice("%s auth: program caught signal %d", client->host, WTERMSIG(status)); else if (WIFEXITED(status) && !errored) notice("%s auth: program exited with status %d", client->host, WEXITSTATUS(status)); } fail: if (user != NULL) free(user); return NULL; } /* ** Append the standard connection information to the provided buffer. */ static void append_client_info(struct client *client, struct buffer *data) { if (*client->host) buffer_append_sprintf(data, "ClientHost: %s\r\n", client->host); if (*client->ip) buffer_append_sprintf(data, "ClientIP: %s\r\n", client->ip); if (client->port != 0) buffer_append_sprintf(data, "ClientPort: %hu\r\n", client->port); if (*client->serverip) buffer_append_sprintf(data, "LocalIP: %s\r\n", client->serverip); if (client->serverport != 0) buffer_append_sprintf(data, "LocalPort: %hu\r\n", client->serverport); } /* ** Execute a program to get the remote username. Takes the client info, the ** command to run, the subdirectory in which to look for programs, and ** optional username and password information to pass to the program. ** Returns the username in newly allocated memory if successful, NULL ** otherwise. */ char * auth_external(struct client *client, const char *command, const char *directory, const char *username, const char *password) { char *user; struct process *process; struct buffer *input; /* Start the program. */ process = start_process(client, command, directory); if (process == NULL) return NULL; /* Feed it data. */ input = buffer_new(); append_client_info(client, input); if (username != NULL) buffer_append_sprintf(input, "ClientAuthname: %s\r\n", username); if (password != NULL) buffer_append_sprintf(input, "ClientPassword: %s\r\n", password); buffer_append_sprintf(input, ".\r\n"); xwrite(process->write_fd, input->data, input->left); close(process->write_fd); buffer_free(input); /* Get the results. */ user = handle_output(client, process); close(process->read_fd); close(process->error_fd); free(process); return user; } inn-2.6.4/nnrpd/commands.c0000644000175200017520000006045314002373703015016 0ustar iuliusiulius/* $Id: commands.c 10342 2019-05-30 14:18:48Z iulius $ ** ** Miscellaneous commands. */ #include "config.h" #include "clibrary.h" #include #include "nnrpd.h" #include "inn/fdflag.h" #include "inn/ov.h" #include "inn/innconf.h" #include "inn/messages.h" #include "inn/version.h" #include "tls.h" extern bool laxmid; #if defined(HAVE_OPENSSL) extern bool encryption_layer_on; #endif /* HAVE_OPENSSL */ typedef struct { char *name; ARTNUM high; ARTNUM low; unsigned long count; } GROUPDATA; extern const char *NNRPinstance; /* ** Check after a successful authentication if the currently selected ** newsgroup is still readable. AUTHINFO SASL and STARTTLS do not need ** it because the NNTP protocol is reset after it. ** ** Return true if the group must be made invalid. */ static bool makeGroupInvalid(void) { bool hookpresent = false; char *grplist[2]; /* If no group has been selected yet, it is considered as valid. */ if (GRPcur == NULL) { return false; } #ifdef DO_PYTHON hookpresent = PY_use_dynamic; if (hookpresent) { char *reply; /* Authorize user using Python module method dynamic. */ if (PY_dynamic(PERMuser, GRPcur, false, &reply) < 0) { syslog(L_NOTICE, "PY_dynamic(): authorization skipped due to no Python dynamic method defined"); } else { if (reply != NULL) { syslog(L_TRACE, "PY_dynamic() returned a refuse string for user %s at %s who wants to read %s: %s", PERMuser, Client.host, GRPcur, reply); free(reply); return true; } } } #endif /* DO_PYTHON */ if (!hookpresent) { if (PERMspecified) { grplist[0] = GRPcur; grplist[1] = NULL; if (!PERMmatch(PERMreadlist, grplist)) { return true; } } else { return true; } } if (!hookpresent && !PERMcanread) { return true; } return false; } /* Returns: ** -1 for problem (such as no such authenticator, etc.). ** 1 for authentication succeeded. ** 0 for authentication failed. */ static char *PERMauthstring; static int PERMgeneric(char *av[], char *accesslist, size_t size) { char path[BIG_BUFFER], *fields[6], *p; size_t j; int i, pan[2], status; pid_t pid; struct stat stb; av += 2; PERMcanread = false; PERMcanpost = false; PERMaccessconf->locpost = false; PERMaccessconf->allowapproved = false; PERMaccessconf->allowihave = false; PERMaccessconf->allownewnews = false; if (!*av) { Reply("%d No authenticator provided\r\n", NNTP_ERR_SYNTAX); return -1; } /* Check for ".." (not "../"). Path must not be changed! */ if (strstr(av[0], "..") != NULL) { Reply("%d .. in authenticator %s\r\n", NNTP_ERR_SYNTAX, av[0]); return -1; } /* 502 if authentication will fail. */ if (!PERMcanauthenticate) { if (PERMauthorized && !PERMneedauth) Reply("%d Already authenticated\r\n", NNTP_ERR_ACCESS); else Reply("%d Authentication will fail\r\n", NNTP_ERR_ACCESS); return -1; } if (strchr(INN_PATH_AUTHDIR,'/') == NULL) snprintf(path, sizeof(path), "%s/%s/%s/%s", innconf->pathbin, INN_PATH_AUTHDIR, INN_PATH_AUTHDIR_GENERIC, av[0]); else snprintf(path, sizeof(path), "%s/%s/%s", INN_PATH_AUTHDIR, INN_PATH_AUTHDIR_GENERIC, 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_ERR_UNAVAILABLE, av[0]); return -1; } /* Create a pipe. */ if (pipe(pan) < 0) { Reply("%d Can't pipe %s\r\n", NNTP_FAIL_ACTION, strerror(errno)); syslog(L_FATAL, "can't pipe for %s %m", av[0]); return -1; } for (i = 0; (pid = fork()) < 0; i++) { if (i == (long) innconf->maxforks) { Reply("%d Can't fork %s\r\n", NNTP_FAIL_ACTION, strerror(errno)); syslog(L_FATAL, "can't fork %s %m", av[0]); return -1; } syslog(L_NOTICE, "can't fork %s -- waiting", av[0]); sleep(5); } /* Run the child, with redirection. */ if (pid == 0) { close(STDERR_FILENO); /* Close existing stderr. */ close(pan[PIPE_READ]); /* stderr goes down the pipe. */ if (pan[PIPE_WRITE] != STDERR_FILENO) { if ((i = dup2(pan[PIPE_WRITE], STDERR_FILENO)) != STDERR_FILENO) { syslog(L_FATAL, "can't dup2 %d to %d got %d %m", pan[PIPE_WRITE], STDERR_FILENO, i); _exit(1); } close(pan[PIPE_WRITE]); } fdflag_close_exec(STDIN_FILENO, false); fdflag_close_exec(STDOUT_FILENO, false); fdflag_close_exec(STDERR_FILENO, false); execv(path, av); /* RFC 2980 requires 500 if there are unspecified errors during * the execution of the provided program. */ Reply("%d Program error occurred\r\n", NNTP_ERR_COMMAND); syslog(L_FATAL, "can't execv %s %m", path); _exit(1); } close(pan[PIPE_WRITE]); read(pan[PIPE_READ], path, sizeof(path)); waitpid(pid, &status, 0); if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) return 0; if ((p = strchr(path, '\n')) != NULL) *p = '\0'; if (PERMauthstring) free(PERMauthstring); PERMauthstring = xstrdup(path); //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, j = 0, p = path; *p; p++) if (*p == ':') { *p = '\0'; ++j; if (j < ARRAY_SIZE(fields)) { fields[j] = p + 1; } else { Reply("%d Program error occurred\r\n", NNTP_FAIL_ACTION); syslog(L_FATAL, "over-long response from %s", av[0]); return -1; } } if (j < 4) { Reply("%d Program error occurred\r\n", NNTP_FAIL_ACTION); syslog(L_FATAL, "short response from %s", av[0]); return -1; } PERMcanread = strchr(fields[1], 'R') != NULL; PERMcanpost = strchr(fields[1], 'P') != NULL; PERMaccessconf->allowapproved = strchr(fields[1], 'A') != NULL; PERMaccessconf->locpost = strchr(fields[1], 'L') != NULL; PERMaccessconf->allowihave = strchr(fields[1], 'I') != NULL; PERMaccessconf->allownewnews = strchr(fields[1], 'N') != NULL; strlcpy(PERMuser, fields[2], sizeof(PERMuser)); strlcat(PERMuser, "@", sizeof(PERMuser)); strlcat(PERMuser, fields[0], sizeof(PERMuser)); //strlcpy(PERMpass, fields[3], sizeof(PERMpass)); strlcpy(accesslist, fields[4], size); //for (i = 0; fields[i] && i < 5; i++) // syslog(L_NOTICE, "fields[%d] = %s\n", i, fields[i]); return 1; } /* ** The AUTHINFO command. */ void CMDauthinfo(int ac, char *av[]) { static char User[SMBUF]; static char Password[SMBUF]; /* XXX BIG_BUFFER, if changed, should also be changed in perl.c and python.c. */ char accesslist[BIG_BUFFER]; char errorstr[BIG_BUFFER]; int code; #if defined(HAVE_ZLIB) /* If a compression layer is active, AUTHINFO is not possible. */ if (compression_layer_on && !tls_compression_on) { Reply("%d Already using a compression layer\r\n", NNTP_ERR_ACCESS); return; } #endif if (strcasecmp(av[1], "GENERIC") == 0) { char *logrec = Glom(av); /* Go on parsing the command line. */ ac--; (void) reArgify(av[ac], &av[ac], -1, true); strlcpy(PERMuser, "", sizeof(PERMuser)); /* Arguments are checked by PERMgeneric(). */ switch (PERMgeneric(av, accesslist, sizeof(accesslist))) { case 1: PERMspecified = NGgetlist(&PERMreadlist, accesslist); PERMpostlist = PERMreadlist; syslog(L_NOTICE, "%s auth %s (%s -> %s)", Client.host, PERMuser, logrec, PERMauthstring? PERMauthstring: "" ); Reply("%d Authentication succeeded\r\n", NNTP_OK_AUTHINFO); PERMneedauth = false; PERMauthorized = true; PERMcanauthenticate = false; PERMgroupmadeinvalid = makeGroupInvalid(); free(logrec); return; case 0: syslog(L_NOTICE, "%s bad_auth %s (%s)", Client.host, PERMuser, logrec); /* We keep the right 481 code here instead of the wrong 502 * answer suggested in RFC 2080. */ Reply("%d Authentication failed\r\n", NNTP_FAIL_AUTHINFO_BAD); free(logrec); return; default: /* Lower level (-1) has already issued a reply. */ return; } } else if (strcasecmp(av[1], "SASL") == 0) { #ifdef HAVE_SASL /* Go on parsing the command line. */ ac--; ac += reArgify(av[ac], &av[ac], -1, true); /* Arguments are checked by SASLauth(). */ SASLauth(ac, av); #else Reply("%d SASL authentication unsupported\r\n", NNTP_ERR_SYNTAX); return; #endif /* HAVE_SASL */ } else { /* Each time AUTHINFO USER is used, the new username is cached. */ if (strcasecmp(av[1], "USER") == 0) { /* 502 if authentication will fail. */ if (!PERMcanauthenticate) { if (PERMauthorized && !PERMneedauth) Reply("%d Already authenticated\r\n", NNTP_ERR_ACCESS); else Reply("%d Authentication will fail\r\n", NNTP_ERR_ACCESS); return; } #ifdef HAVE_OPENSSL /* Check whether STARTTLS must be used before trying to authenticate. */ if (PERMcanauthenticate && !PERMcanauthenticatewithoutSSL && !encryption_layer_on) { Reply("%d Encryption required\r\n", NNTP_FAIL_PRIVACY_NEEDED); return; } #endif strlcpy(User, av[2], sizeof(User)); Reply("%d Enter password\r\n", NNTP_CONT_AUTHINFO); return; } /* If it is not AUTHINFO PASS, we do not support the provided subcommand. */ if (strcasecmp(av[1], "PASS") != 0) { Reply("%d Bad AUTHINFO param\r\n", NNTP_ERR_SYNTAX); return; } /* 502 if authentication will fail. */ if (!PERMcanauthenticate) { if (PERMauthorized && !PERMneedauth) Reply("%d Already authenticated\r\n", NNTP_ERR_ACCESS); else Reply("%d Authentication will fail\r\n", NNTP_ERR_ACCESS); return; } #ifdef HAVE_OPENSSL /* Check whether STARTTLS must be used before trying to authenticate. */ if (PERMcanauthenticate && !PERMcanauthenticatewithoutSSL && !encryption_layer_on) { Reply("%d Encryption required\r\n", NNTP_FAIL_PRIVACY_NEEDED); return; } #endif /* AUTHINFO PASS cannot be sent before AUTHINFO USER. */ if (User[0] == '\0') { Reply("%d Authentication commands issued out of sequence\r\n", NNTP_FAIL_AUTHINFO_REJECT); return; } /* There is a cached username and a password is provided. */ strlcpy(Password, av[2], sizeof(Password)); errorstr[0] = '\0'; code = NNTP_FAIL_AUTHINFO_BAD; PERMlogin(User, Password, &code, errorstr); PERMgetpermissions(); /* If authentication is successful. */ if (!PERMneedauth) { syslog(L_NOTICE, "%s user %s", Client.host, PERMuser); if (LLOGenable) { fprintf(locallog, "%s user (%s):%s\n", Client.host, Username, PERMuser); fflush(locallog); } Reply("%d Authentication succeeded\r\n", NNTP_OK_AUTHINFO); PERMneedauth = false; PERMauthorized = true; PERMcanauthenticate = false; PERMgroupmadeinvalid = makeGroupInvalid(); return; } /* For backwards compatibility, we return 481 instead of 502 (which had * the same meaning as 481 in RFC 2980). */ if (code == NNTP_ERR_ACCESS) { code = NNTP_FAIL_AUTHINFO_BAD; } syslog(L_NOTICE, "%s bad_auth", Client.host); /* Return 403 in case the return code is not 481. */ if (errorstr[0] != '\0') { syslog(L_NOTICE, "%s script error str: %s", Client.host, errorstr); Reply("%d %s\r\n", code != NNTP_FAIL_AUTHINFO_BAD ? NNTP_FAIL_ACTION : code, errorstr); } else { Reply("%d Authentication failed\r\n", code != NNTP_FAIL_AUTHINFO_BAD ? NNTP_FAIL_ACTION : code); } } } /* ** The DATE command. Useful mainly in conjunction with NEWNEWS. */ void CMDdate(int ac UNUSED, char *av[] UNUSED) { time_t now; struct tm *gmt; now = time(NULL); gmt = gmtime(&now); if (now == (time_t) -1 || gmt == NULL) { Reply("%d Can't get time, %s\r\n", NNTP_FAIL_ACTION, strerror(errno)); return; } Reply("%d %04d%02d%02d%02d%02d%02d\r\n", NNTP_INFO_DATE, gmt->tm_year + 1900, gmt->tm_mon + 1, gmt->tm_mday, gmt->tm_hour, gmt->tm_min, gmt->tm_sec); } /* ** Handle the MODE command. ** Note that MODE STREAM must return 501 as an unknown MODE variant ** because nnrpd does not implement STREAMING. */ void CMDmode(int ac UNUSED, char *av[]) { if (strcasecmp(av[1], "READER") == 0) /* In the case AUTHINFO has already been successfully used, * nnrpd must answer as a no-op (it still advertises the READER * capability but not MODE-READER). */ Reply("%d %s InterNetNews NNRP server %s ready (%s)\r\n", (PERMcanpost || (PERMcanauthenticate && PERMcanpostgreeting)) ? NNTP_OK_BANNER_POST : NNTP_OK_BANNER_NOPOST, PERMaccessconf->pathhost, INN_VERSION_STRING, (!PERMneedauth && PERMcanpost) ? "posting ok" : "no posting"); else Reply("%d Unknown MODE variant\r\n", NNTP_ERR_SYNTAX); } static int GroupCompare(const void *a1, const void* b1) { const GROUPDATA *a = a1; const GROUPDATA *b = b1; return strcmp(a->name, b->name); } /* ** Display new newsgroups since a given date and time. */ void CMDnewgroups(int ac, char *av[]) { char *p; char *q; QIOSTATE *qp; time_t date; char *grplist[2]; int hi, lo, count, flag; GROUPDATA *grouplist = NULL; GROUPDATA key; GROUPDATA *gd; int listsize = 0; int numgroups = 0; int numfound = 0; int i; bool local = true; /* Check the arguments and parse the date. */ if (ac > 3) { if (strcasecmp(av[3], "GMT") == 0) local = false; else { Reply("%d Syntax error for \"GMT\"\r\n", NNTP_ERR_SYNTAX); return; } } date = parsedate_nntp(av[1], av[2], local); if (date == (time_t) -1) { Reply("%d Bad date\r\n", NNTP_ERR_SYNTAX); return; } /* Log an error if active.times doesn't exist, but don't return an error to the client. The most likely cause of this is a new server installation that's yet to have any new groups created, and returning an error was causing needless confusion. Just return the empty list of groups. */ if ((qp = QIOopen(ACTIVETIMES)) == NULL) { syslog(L_ERROR, "%s can't fopen %s %m", Client.host, ACTIVETIMES); Reply("%d No new newsgroups\r\n", NNTP_OK_NEWGROUPS); Printf(".\r\n"); return; } /* Read the file, ignoring long lines. */ while ((p = QIOread(qp)) != NULL) { if ((q = strchr(p, ' ')) == NULL) continue; *q++ = '\0'; if ((time_t) atol(q) < date) continue; if (!OVgroupstats(p, &lo, &hi, &count, &flag)) continue; if (PERMspecified) { grplist[0] = p; grplist[1] = NULL; if (!PERMmatch(PERMreadlist, grplist)) continue; } else continue; if (grouplist == NULL) { grouplist = xmalloc(1000 * sizeof(GROUPDATA)); listsize = 1000; } if (listsize <= numgroups) { listsize += 1000; grouplist = xrealloc(grouplist, listsize * sizeof(GROUPDATA)); } grouplist[numgroups].high = hi; grouplist[numgroups].low = lo; grouplist[numgroups].count = count; grouplist[numgroups].name = xstrdup(p); numgroups++; } QIOclose(qp); if ((qp = QIOopen(ACTIVE)) == NULL) { syslog(L_ERROR, "%s can't fopen %s %m", Client.host, ACTIVE); Reply("%d Can't open active file\r\n", NNTP_FAIL_ACTION); for (i = 0; i < numgroups; i++) { free(grouplist[i].name); } free(grouplist); return; } qsort(grouplist, numgroups, sizeof(GROUPDATA), GroupCompare); Reply("%d New newsgroups follow\r\n", NNTP_OK_NEWGROUPS); for (numfound = numgroups; (p = QIOread(qp)) && numfound;) { /* p will contain the name of the newsgroup. * When the syntax of the line is not correct, we continue * with the following line. */ if ((q = strchr(p, ' ')) == NULL) continue; *q++ = '\0'; /* Find out the end of the high water mark. */ if ((q = strchr(q, ' ')) == NULL) continue; q++; /* Find out the end of the low water mark. * q will contain the flag of the newsgroup. */ if ((q = strchr(q, ' ')) == NULL) continue; q++; key.name = p; if ((gd = bsearch(&key, grouplist, numgroups, sizeof(GROUPDATA), GroupCompare)) == NULL) continue; Printf("%s %lu %lu %s\r\n", p, gd->high, gd->low, q); numfound--; } for (i = 0; i < numgroups; i++) { free(grouplist[i].name); } free(grouplist); QIOclose(qp); Printf(".\r\n"); } /* ** Handle the POST and IHAVE commands. */ void CMDpost(int ac, char *av[]) { static char *article; static int size; char *p, *q; char *end; int longline; READTYPE r; int i; long l; long sleeptime; char *path; const char *response; char idbuff[SMBUF]; static int backoff_inited = false; bool ihave, permanent; ihave = (strcasecmp(av[0], "IHAVE") == 0); /* Check whether the message-ID is valid for IHAVE. */ if (ihave && ac == 2 && !IsValidMessageID(av[1], true, laxmid)) { Reply("%d Syntax error in message-ID\r\n", NNTP_ERR_SYNTAX); return; } /* Check authorizations. */ if (ihave && (!PERMaccessconf->allowihave || !PERMcanpost)) { syslog(L_NOTICE, "%s noperm ihave without permission", Client.host); Reply("%d IHAVE command disabled by administrator\r\n", PERMcanauthenticate ? NNTP_FAIL_AUTH_NEEDED : NNTP_ERR_ACCESS); return; } if (!ihave && !PERMcanpost) { syslog(L_NOTICE, "%s noperm post without permission", Client.host); Reply("%d Posting not allowed\r\n", PERMcanauthenticate && PERMcanpostgreeting ? NNTP_FAIL_AUTH_NEEDED : NNTP_FAIL_POST_AUTH); return; } if (!backoff_inited) { /* Exponential posting backoff. */ InitBackoffConstants(); backoff_inited = true; } /* Dave's posting limiter. Limit postings to a certain rate. * And now we support multiprocess rate limits. Questions? * E-mail . */ if (BACKOFFenabled) { /* Acquire lock (this could be in RateLimit but that would * invoke the spaghetti factor). */ if ((path = (char *) PostRecFilename(Client.ip, PERMuser)) == NULL) { Reply("%d Retry later\r\n", ihave ? NNTP_FAIL_IHAVE_DEFER : NNTP_FAIL_POST_AUTH); return; } if (LockPostRec(path) == 0) { syslog(L_ERROR, "%s error write locking '%s'", Client.host, path); Reply("%d Retry later\r\n", ihave ? NNTP_FAIL_IHAVE_DEFER : NNTP_FAIL_POST_AUTH); return; } if (!RateLimit(&sleeptime,path)) { syslog(L_ERROR, "%s can't check rate limit info", Client.host); Reply("%d Retry later\r\n", ihave ? NNTP_FAIL_IHAVE_DEFER : NNTP_FAIL_POST_AUTH); UnlockPostRec(path); return; } else if (sleeptime != 0L) { syslog(L_NOTICE,"%s post sleep time is now %ld", Client.host, sleeptime); sleep(sleeptime); } /* Remove the lock here so that only one nnrpd process does the * backoff sleep at once. Other procs are sleeping for the lock. */ UnlockPostRec(path); } /* End backoff code. */ /* Start at beginning of buffer. */ if (article == NULL) { size = 4096; article = xmalloc(size); } idbuff[0] = 0; if (ihave) { /* Check whether it is a duplicate. */ if (History == NULL) { time_t statinterval = 30; History = HISopen(HISTORY, innconf->hismethod, HIS_RDONLY); if (!History) { syslog(L_NOTICE, "can't initialize history"); Reply("%d NNTP server unavailable; try later\r\n", NNTP_FAIL_TERMINATING); ExitWithStats(1, true); } HISctl(History, HISCTLS_STATINTERVAL, &statinterval); } if (HIScheck(History, av[1])) { Reply("%d Duplicate\r\n", NNTP_FAIL_IHAVE_REFUSE); return; } else { Reply("%d Send it; end with .\r\n", NNTP_CONT_IHAVE); } } else { if ((p = GenerateMessageID(PERMaccessconf->domain)) != NULL) { if (VirtualPathlen > 0) { q = p; if ((p = strchr(p, '@')) != NULL) { *p = '\0'; snprintf(idbuff, sizeof(idbuff), "%s%s@%s>", q, NNRPinstance, PERMaccessconf->domain); } } else { strlcpy(idbuff, p, sizeof(idbuff)); } } Reply("%d Ok, recommended message-ID %s\r\n", NNTP_CONT_POST, idbuff); } fflush(stdout); p = article; end = &article[size]; longline = 0; for (l = 1; ; l++) { size_t len; const char *line; r = line_read(&NNTPline, PERMaccessconf->clienttimeout, &line, &len, NULL); switch (r) { default: warn("%s internal %d in post", Client.host, r); /* FALLTHROUGH */ case RTtimeout: warn("%s timeout in post", Client.host); ExitWithStats(1, false); /* NOTREACHED */ case RTeof: warn("%s EOF in post", Client.host); ExitWithStats(1, false); /* NOTREACHED */ case RTlong: if (longline == 0) longline = l; continue; case RTok: break; } /* If it is the terminator, break out. */ if (strcmp(line, ".") == 0) { break; } /* If they broke our line length limit, there's little point * in processing any more of their input. */ if (longline != 0) { continue; } /* +2 because of the \n\0 we append; note we don't add the 2 * when increasing the size of the buffer as ART_LINE_MALLOC * will always be larger than 2 bytes. */ if ((len + 2) > (size_t)(end - p)) { i = p - article; size += len + 4096; article = xrealloc(article, size); end = &article[size]; p = i + article; } /* Reverse any byte-stuffing. */ if (*line == '.') { ++line; --len; } memcpy(p, line, len); p += len; *p++ = '\n'; *p = '\0'; } if (longline) { warn("%s too long in post", Client.host); Reply("%d Line %d too long\r\n", ihave ? NNTP_FAIL_IHAVE_REJECT : NNTP_FAIL_POST_REJECT, longline); POSTrejected++; return; } /* Send the article to the server. */ response = ARTpost(article, idbuff, &permanent); if (response == NULL) { notice("%s %s ok %s", Client.host, ihave ? "ihave" : "post", idbuff); Reply("%d Article received %s\r\n", ihave ? NNTP_OK_IHAVE : NNTP_OK_POST, idbuff); POSTreceived++; } else { if ((p = strchr(response, '\r')) != NULL) *p = '\0'; if ((p = strchr(response, '\n')) != NULL) *p = '\0'; notice("%s %s failed %s", Client.host, ihave ? "ihave" : "post", response); if (!ihave || permanent) { /* For permanent errors, reject the message. */ Reply("%d %s\r\n", ihave ? NNTP_FAIL_IHAVE_REJECT : NNTP_FAIL_POST_REJECT, response); } else { /* Non-permanent errors only have relevance to IHAVE, for * these we have the error status from the upstream * server to report. It includes the answer code. */ Reply("%s\r\n", response); } POSTrejected++; } } inn-2.6.4/nnrpd/python.c0000644000175200017520000006610514002373703014536 0ustar iuliusiulius/* $Id: python.c 10447 2020-12-09 21:19:29Z iulius $ ** ** python.c: Embed Python in the style of nnrpd's Perl stuff ** (authentication, authorization and dynamic hooks ** only at this point). ** ** Written by Ilya Etingof , 1999. ** ** This code bases on Python work for innd filtering done by ** G.J. Andruk . Also it borrows some ideas from ** TCL/Perl work done by Bob Heiney and Christophe Wolfhugel. ** ** A quick note regarding Python exceptions: functions like ** PyObject_GetAttrString(PyObject *o, const char *attr_name) ** raise an exception when they fail, even though they return NULL. ** And as exceptions accumulate from caller to caller and so on, ** it generates weird issues with Python scripts afterwards. So such ** uses should be checked before. For instance with: ** PyObject_HasAttrString(PyObject *o, const char *attr_name). */ #include "config.h" #ifdef DO_PYTHON /* Python redefines _POSIX_C_SOURCE, so undef it to suppress warnings. */ #undef _POSIX_C_SOURCE /* Make "s#" use Py_ssize_t rather than int. */ #define PY_SSIZE_T_CLEAN /* Python.h must be included after having defined PY_SSIZE_T_CLEAN, * and before any standard headers are included (because Python may * define some pre-processor definitions which affect the standard * headers on some systems). */ #pragma GCC diagnostic ignored "-Wredundant-decls" #include "Python.h" #pragma GCC diagnostic warning "-Wredundant-decls" /* Define Py_ssize_t when it does not exist (Python < 2.5.0). */ #if PY_VERSION_HEX < 0x02050000 typedef int Py_ssize_t; #endif #if PY_MAJOR_VERSION >= 3 # define PyInt_AS_LONG PyLong_AS_LONG # define PyInt_Check PyLong_Check # define PyInt_FromLong PyLong_FromLong # define PyString_AS_STRING PyUnicode_AsUTF8 # define PyString_AsString PyUnicode_AsUTF8 # define PyString_Check PyUnicode_Check # define PYBUFF_FROMMEMORY(str, len) \ PyMemoryView_FromMemory((str), (len), PyBUF_WRITE) #else # define PYBUFF_FROMMEMORY(str, len) \ PyBuffer_FromMemory((str), (len)) #endif #include "clibrary.h" #include "inn/innconf.h" #include "nnrpd.h" #include "inn/hashtab.h" /* Values relate name of hook to array index. */ #define PYTHONauthen 1 #define PYTHONaccess 2 #define PYTHONdynamic 3 #define PYTHONtypes_max 4 /* Values relate type of method to array index. */ #define PYTHONmain 1 #define PYTHONinit 2 #define PYTHONclose 3 #define PYTHONmethods_max 4 /* Key names for attributes dictionary. */ #define PYTHONhostname "hostname" #define PYTHONipaddress "ipaddress" #define PYTHONport "port" #define PYTHONinterface "interface" #define PYTHONintipaddr "intipaddr" #define PYTHONintport "intport" #define PYTHONuser "user" #define PYTHONpass "pass" #define PYTHONtype "type" #define PYTHONnewsgroup "newsgroup" /* Max number of items in dictionary to pass to auth methods. */ #define _PY_MAX_AUTH_ITEM 10 /* Pointers to external Python objects. */ PyObject *PYAuthObject = NULL; /* Dictionary of params to pass to authentication methods. */ PyObject *PYauthinfo = NULL; PyObject **PYauthitem = NULL; /* Forward declaration. */ static PyObject *PY_set_auth_hook(PyObject *dummy, PyObject *args); void PY_load_python(void); PyObject* PY_setup(int type, int method, char *file); static const void *file_key(const void *p); static bool file_equal(const void *k, const void *p); static void file_free(void *p); static void file_trav(void *data, void* null); bool PythonLoaded = false; /* Structure for storage of attributes for a module file. */ typedef struct PyFile { char *file; bool loaded[PYTHONtypes_max]; PyObject *procs[PYTHONtypes_max][PYTHONmethods_max]; } PyFile; /* Hash for storing files. */ struct hash *files; /* For passing the dynamic module filename from perm.c. */ char* dynamic_file; /* ** Authenticate connecting host by username&password. ** ** code contains the NNTP reply code as returned by Python method ** or -1 if method is not defined. */ void PY_authenticate(char* file, char *User, char *Password, int *code, char *errorstring, char *newUser) { PyObject *result, *item, *proc; int authnum; int i; const char *temp; PY_load_python(); proc = PY_setup(PYTHONauthen, PYTHONmain, file); /* Return if authentication method is not defined. */ if (proc == NULL) *code = -1; /* Initialize PythonAuthObject with connect method specific items. */ authnum = 0; /* Client hostname. */ PYauthitem[authnum] = PYBUFF_FROMMEMORY(Client.host, strlen(Client.host)); PyDict_SetItemString(PYauthinfo, PYTHONhostname, PYauthitem[authnum++]); /* Client IP number. */ PYauthitem[authnum] =PYBUFF_FROMMEMORY(Client.ip, strlen(Client.ip)); PyDict_SetItemString(PYauthinfo, PYTHONipaddress, PYauthitem[authnum++]); /* Client port number. */ PYauthitem[authnum] = PyInt_FromLong(Client.port); PyDict_SetItemString(PYauthinfo, PYTHONport, PYauthitem[authnum++]); /* Server interface the connection comes to. */ PYauthitem[authnum] = PYBUFF_FROMMEMORY(Client.serverhost, strlen(Client.serverhost)); PyDict_SetItemString(PYauthinfo, PYTHONinterface, PYauthitem[authnum++]); /* Server IP number. */ PYauthitem[authnum] = PYBUFF_FROMMEMORY(Client.serverip, strlen(Client.serverip)); PyDict_SetItemString(PYauthinfo, PYTHONintipaddr, PYauthitem[authnum++]); /* Server port number. */ PYauthitem[authnum] = PyInt_FromLong(Client.serverport); PyDict_SetItemString(PYauthinfo, PYTHONintport, PYauthitem[authnum++]); /* Username if known. */ if (User == NULL) { PYauthitem[authnum] = Py_None; } else { PYauthitem[authnum] = PYBUFF_FROMMEMORY(User, strlen(User)); } PyDict_SetItemString(PYauthinfo, PYTHONuser, PYauthitem[authnum++]); /* Password if known. */ if (Password == NULL) { PYauthitem[authnum] = Py_None; } else { PYauthitem[authnum] = PYBUFF_FROMMEMORY(Password, strlen(Password)); } PyDict_SetItemString(PYauthinfo, PYTHONpass, PYauthitem[authnum++]); /* ** Now invoke authenticate method and see if it likes this user. */ result = PyObject_CallFunction(proc, (char *) "O", PYauthinfo); /* Check the response. */ if (result == NULL || !PyTuple_Check(result) || ((PyTuple_Size(result) != 2) && (PyTuple_Size(result) != 3))) { syslog(L_ERROR, "python authenticate method returned wrong result"); Reply("%d Internal error (2). Goodbye!\r\n", NNTP_FAIL_TERMINATING); ExitWithStats(1, true); } /* Get the NNTP response code. */ item = PyTuple_GetItem(result, 0); /* Check the item. */ if (!PyInt_Check(item)) { syslog(L_ERROR, "python authenticate method returned bad NNTP response code"); Reply("%d Internal error (2). Goodbye!\r\n", NNTP_FAIL_TERMINATING); ExitWithStats(1, true); } /* Store the code. */ *code = PyInt_AS_LONG(item); /* Get the error string. */ item = PyTuple_GetItem(result, 1); /* Check the item. */ if (!PyString_Check(item)) { syslog(L_ERROR, "python authenticate method returned bad error string"); Reply("%d Internal error (2). Goodbye!\r\n", NNTP_FAIL_TERMINATING); ExitWithStats(1, true); } /* Store error string. */ temp = PyString_AS_STRING(item); strlcpy(errorstring, temp, BIG_BUFFER); if (PyTuple_Size(result) == 3) { /* Get the username string. */ item = PyTuple_GetItem(result, 2); /* Check the item. */ if (!PyString_Check(item)) { syslog(L_ERROR, "python authenticate method returned bad username string"); Reply("%d Internal error (2). Goodbye!\r\n", NNTP_FAIL_TERMINATING); ExitWithStats(1, true); } /* Store user string. */ temp = PyString_AS_STRING(item); strlcpy(newUser, temp, BIG_BUFFER); } /* Clean up the dictionary object. */ PyDict_Clear(PYauthinfo); /* Clean up dictionary items. */ for (i = 0; i < authnum; i++) { if (PYauthitem[i] != Py_None) { Py_DECREF(PYauthitem[i]); } } /* Log auth result. */ syslog(L_NOTICE, "python authenticate method succeeded, return code %d, error string %s", *code, errorstring); } /* ** Create an access group based on the values returned by the script in file. ** ** The access_vec vector is set. ** If the access group cannot be generated, the connection is closed. */ void PY_access(char* file, struct vector *access_vec, char *User) { PyObject *result, *key, *value, *proc; char *buffer; int authnum; int i; Py_ssize_t pos; PY_load_python(); proc = PY_setup(PYTHONaccess, PYTHONmain, file); /* Exit if access method is not defined. */ if (proc == NULL) { syslog(L_ERROR, "python access method not defined"); Reply("%d Internal error (3). Goodbye!\r\n", NNTP_FAIL_TERMINATING); ExitWithStats(1, true); } /* Initialize PythonAuthObject with group method specific items. */ authnum = 0; /* Client hostname. */ PYauthitem[authnum] = PYBUFF_FROMMEMORY(Client.host, strlen(Client.host)); PyDict_SetItemString(PYauthinfo, PYTHONhostname, PYauthitem[authnum++]); /* Client IP number. */ PYauthitem[authnum] = PYBUFF_FROMMEMORY(Client.ip, strlen(Client.ip)); PyDict_SetItemString(PYauthinfo, PYTHONipaddress, PYauthitem[authnum++]); /* Client port number. */ PYauthitem[authnum] = PyInt_FromLong(Client.port); PyDict_SetItemString(PYauthinfo, PYTHONport, PYauthitem[authnum++]); /* Server interface the connection comes to. */ PYauthitem[authnum] = PYBUFF_FROMMEMORY(Client.serverhost, strlen(Client.serverhost)); PyDict_SetItemString(PYauthinfo, PYTHONinterface, PYauthitem[authnum++]); /* Server IP number. */ PYauthitem[authnum] = PYBUFF_FROMMEMORY(Client.serverip, strlen(Client.serverip)); PyDict_SetItemString(PYauthinfo, PYTHONintipaddr, PYauthitem[authnum++]); /* Server port number. */ PYauthitem[authnum] = PyInt_FromLong(Client.serverport); PyDict_SetItemString(PYauthinfo, PYTHONintport, PYauthitem[authnum++]); /* Username. */ PYauthitem[authnum] = PYBUFF_FROMMEMORY(User, strlen(User)); PyDict_SetItemString(PYauthinfo, PYTHONuser, PYauthitem[authnum++]); /* Password is not known. */ PYauthitem[authnum] = Py_None; PyDict_SetItemString(PYauthinfo, PYTHONpass, PYauthitem[authnum++]); /* ** Now invoke newsgroup access method. */ result = PyObject_CallFunction(proc, (char *) "O", PYauthinfo); /* Check the response. */ if (result == NULL || result == Py_None || !PyDict_Check(result)) { syslog(L_ERROR, "python access method returned wrong result -- expected a dictionary"); Reply("%d Internal error (2). Goodbye!\r\n", NNTP_FAIL_TERMINATING); ExitWithStats(1, true); } /* Resize vector to dictionary length. */ vector_resize(access_vec, PyDict_Size(result) - 1); /* Store dict values in proper format in access vector. */ pos = 0; buffer = xmalloc(BIG_BUFFER); while(PyDict_Next(result, &pos, &key, &value)) { if (!PyString_Check(key)) { syslog(L_ERROR, "python access method return dictionary key %ld not a string", (long int) pos); Reply("%d Internal error (2). Goodbye!\r\n", NNTP_FAIL_TERMINATING); ExitWithStats(1, false); } if (!PyString_Check(value)) { syslog(L_ERROR, "python access method return dictionary value %ld not a string", (long int) pos); Reply("%d Internal error (2). Goodbye!\r\n", NNTP_FAIL_TERMINATING); ExitWithStats(1, false); } strlcpy(buffer, PyString_AsString(key), BIG_BUFFER); strlcat(buffer, ": \"", BIG_BUFFER); strlcat(buffer, PyString_AsString(value), BIG_BUFFER); strlcat(buffer, "\"\n", BIG_BUFFER); vector_add(access_vec, buffer); } free(buffer); /* Clean up the dictionary object. */ PyDict_Clear(PYauthinfo); /* Clean up dictionary items. */ for (i = 0; i < authnum; i++) { if (PYauthitem[i] != Py_None) { Py_DECREF(PYauthitem[i]); } } /* Log auth result. */ syslog(L_NOTICE, "python access method succeeded"); } /* ** Initialize dynamic access control code. */ void PY_dynamic_init (char* file) { if (!access(file, R_OK)) { syslog(L_NOTICE, "pyfilter %s not installed", file); return; } dynamic_file = xstrdup(file); PY_use_dynamic = true; } /* ** Determine dynamic user access rights to a given newsgroup. ** ** Return 0 if the requested privilege is granted or a positive value ** and a reply_message pointer initialized with reply message. ** Return negative value if dynamic method is not defined. */ int PY_dynamic(char *User, char *NewsGroup, int PostFlag, char **reply_message) { PyObject *result, *proc; char *string; const char *temp; int authnum; int i; PY_load_python(); proc = PY_setup(PYTHONdynamic, PYTHONmain, dynamic_file); /* Return if dynamic method is not defined. */ if (proc == NULL) return -1; /* Initialize PythonAuthObject with group method specific items. */ authnum = 0; /* Client hostname. */ PYauthitem[authnum] = PYBUFF_FROMMEMORY(Client.host, strlen(Client.host)); PyDict_SetItemString(PYauthinfo, PYTHONhostname, PYauthitem[authnum++]); /* Client IP number. */ PYauthitem[authnum] = PYBUFF_FROMMEMORY(Client.ip, strlen(Client.ip)); PyDict_SetItemString(PYauthinfo, PYTHONipaddress, PYauthitem[authnum++]); /* Client port number. */ PYauthitem[authnum] = PyInt_FromLong(Client.port); PyDict_SetItemString(PYauthinfo, PYTHONport, PYauthitem[authnum++]); /* Server interface the connection comes to. */ PYauthitem[authnum] = PYBUFF_FROMMEMORY(Client.serverhost, strlen(Client.serverhost)); PyDict_SetItemString(PYauthinfo, PYTHONinterface, PYauthitem[authnum++]); /* Server IP number. */ PYauthitem[authnum] = PYBUFF_FROMMEMORY(Client.serverip, strlen(Client.serverip)); PyDict_SetItemString(PYauthinfo, PYTHONintipaddr, PYauthitem[authnum++]); /* Server port number. */ PYauthitem[authnum] = PyInt_FromLong(Client.serverport); PyDict_SetItemString(PYauthinfo, PYTHONintport, PYauthitem[authnum++]); /* Username. */ PYauthitem[authnum] = PYBUFF_FROMMEMORY(User, strlen(User)); PyDict_SetItemString(PYauthinfo, PYTHONuser, PYauthitem[authnum++]); /* Password is not known. */ PYauthitem[authnum] = Py_None; PyDict_SetItemString(PYauthinfo, PYTHONpass, PYauthitem[authnum++]); /* Assign authentication type. */ PYauthitem[authnum] = PYBUFF_FROMMEMORY((char *)(PostFlag ? "post" : "read"), 4); PyDict_SetItemString(PYauthinfo, PYTHONtype, PYauthitem[authnum++]); /* Newsgroup user tries to access. */ PYauthitem[authnum] = PYBUFF_FROMMEMORY(NewsGroup, strlen(NewsGroup)); PyDict_SetItemString(PYauthinfo, PYTHONnewsgroup, PYauthitem[authnum++]); /* ** Now invoke newsgroup dynamic access method and see if ** it likes this user to access this newsgroup. */ result = PyObject_CallFunction(proc, (char *) "O", PYauthinfo); /* Check the response. */ if (result == NULL || (result != Py_None && !PyString_Check(result))) { syslog(L_ERROR, "python dynamic method (%s access) returned wrong result", PostFlag ? "post" : "read"); Reply("%d Internal error (2). Goodbye!\r\n", NNTP_FAIL_TERMINATING); ExitWithStats(1, false); } /* Get the response string. */ if (result == Py_None) { string = NULL; } else { temp = PyString_AS_STRING(result); string = xstrdup(temp); } /* Clean up the dictionary object. */ PyDict_Clear(PYauthinfo); /* Clean up dictionary items. */ for (i = 0; i < authnum; i++) { if (PYauthitem[i] != Py_None) { Py_DECREF(PYauthitem[i]); } } /* Log auth result. */ syslog(L_NOTICE, "python dynamic method (%s access) succeeded, refuse string: %s", PostFlag ? "post" : "read", string == NULL ? "" : string); /* Initialize reply string. */ if (reply_message != NULL) *reply_message = string; /* Return result. */ return string == NULL ? 0 : 1; } /* ** This runs when nnrpd shuts down. If Python is closed and reopened ** in the same process, files and dynamic_file are reused so they ** must point to NULL. */ void PY_close_python(void) { if (files != NULL) { hash_traverse(files, file_trav, NULL); hash_free(files); files = NULL; } if (dynamic_file != NULL) { free(dynamic_file); dynamic_file = NULL; } } /* ** Traversal function for PY_close_python. */ void file_trav(void *data, void* null UNUSED) { PyFile *fp = data; int j; PyObject *result, *func; for (j = 1; j < PYTHONtypes_max; j++) { if (fp->loaded[j] != false) { func = fp->procs[j][PYTHONclose]; if (func != NULL) { result = PyObject_CallFunction(func, NULL); Py_XDECREF(result); } } } } /* ** Python's syslog module isn't compiled in by default. It's easier ** to do it this way, and the switch block looks pretty in a color ** editor). */ static PyObject * PY_syslog(PyObject *self UNUSED, PyObject *args) { char *loglevel; Py_ssize_t levellen; char *logmsg; Py_ssize_t msglen; int priority; /* Get loglevel and message. */ if (!PyArg_ParseTuple(args, (char *) "s#s#", &loglevel, &levellen, &logmsg, &msglen)) return NULL; /* Assign syslog priority by abbreviated names. */ switch (*loglevel) { case 'd': case 'D': priority = LOG_DEBUG ; break; case 'i': case 'I': priority = LOG_INFO ; break; case 'n': case 'N': priority = LOG_NOTICE ; break; case 'w': case 'W': priority = LOG_WARNING ; break; case 'e': case 'E': priority = LOG_ERR ; break; case 'c': case 'C': priority = LOG_CRIT ; break; case 'a': case 'A': priority = LOG_ALERT ; break; default: priority = LOG_NOTICE ; } /* Log the message. */ syslog(priority, "python: %s", logmsg); /* Return None. */ Py_INCREF(Py_None); return Py_None; } /* ** Make the internal nnrpd module's functions visible to Python. Python ** annoyingly doesn't use const where appropriate in its structure ** definitions, so we have to add casts for all of the string parameters that ** we're initializing with constant strings. */ #define METHOD(name, func, flags, help) \ { (char *)(name), (func), (flags), (char *)(help) } static PyMethodDef nnrpdPyMethods[] = { METHOD("set_auth_hook", PY_set_auth_hook, METH_VARARGS, ""), METHOD("syslog", PY_syslog, METH_VARARGS, ""), METHOD(NULL, NULL, 0, "") }; #if PY_MAJOR_VERSION >= 3 static struct PyModuleDef nnrpdPyModule = { PyModuleDef_HEAD_INIT, /* m_base */ (char *) "nnrpd", /* m_name */ (char *) "nnrpd Python filter hook", /* m_doc */ -1, /* m_size */ nnrpdPyMethods, /* m_methods */ NULL, /* m_slots */ NULL, /* m_traverse */ NULL, /* m_clear */ NULL, /* m_free */ }; PyMODINIT_FUNC PyInit_nnrpd(void) { PyObject *module = PyModule_Create(&nnrpdPyModule); if (module == NULL) syslog(L_ERROR, "failed to create nnrpd python module"); return module; } #else void PyInit_nnrpd(void) { if (Py_InitModule3((char *) "nnrpd", nnrpdPyMethods, (char *) "nnrpd Python filter hook") == NULL) syslog(L_ERROR, "failed to initialize nnrpd python module"); } #endif /* ** Called by the external module so it can register itself with nnrpd. */ static PyObject * PY_set_auth_hook(PyObject *dummy UNUSED, PyObject *args) { PyObject *result = NULL; PyObject *temp; /* set_auth_hook method should return a pointer to nnrpd auth object. */ if (PyArg_ParseTuple(args, (char *) "O:set_auth_hook", &temp)) { Py_XINCREF(temp); Py_XDECREF(PYAuthObject); PYAuthObject = temp; Py_INCREF(Py_None); result = Py_None; } /* Return a pointer to nnrpd auth method. */ return result; } /* ** Load the Python interpreter. */ void PY_load_python(void) { if (!PythonLoaded) { /* ** Add path for nnrpd module. The environment variable PYTHONPATH ** does it; one can also append innconf->pathfilter to sys.path once ** Python has been initialized. */ setenv("PYTHONPATH", innconf->pathfilter, 1); /* Build a module interface to certain nnrpd functions. */ PyImport_AppendInittab("nnrpd", &PyInit_nnrpd); /* Load up the interpreter ;-O */ Py_Initialize(); /* It makes Python sad when its stdout or stderr are closed. */ if ((fileno(stdout) == -1) || (fileno(stderr) == -1)) PyRun_SimpleString("import sys; sys.stdout=sys.stderr=open('/dev/null', 'a')"); /* See if Python initialized OK. */ if (!Py_IsInitialized()) { syslog(L_ERROR, "python interpreter NOT initialized"); return; } /* ** Grab space for authinfo dictionary so we aren't forever ** recreating them. */ PYauthinfo = PyDict_New(); PYauthitem = xcalloc(_PY_MAX_AUTH_ITEM, sizeof(PyObject *)); /* Create hash to store file attributes. */ files = hash_create(4, hash_string, file_key, file_equal, file_free); PythonLoaded = true; syslog(L_NOTICE, "python interpreter initialized OK"); } } /* ** Check that a method exists and is callable. Set up a pointer to ** the corresponding PyObject, or NULL if not found. */ static void PYdefonemethod(PyFile *fp, int type, int method, const char *methname, int realtype) { PyObject **methptr; methptr = &fp->procs[type][method]; /* There is no need to check the existence of methods useless for our realtype. */ if (type == realtype) { /* ** We check with HasAttrString() the existence of the method because ** otherwise, in case it does not exist, an exception is raised by Python, ** although the result of the function is NULL. */ if (PyObject_HasAttrString(PYAuthObject, (char *) methname) == 1) { /* Get a pointer to given method. */ *methptr = PyObject_GetAttrString(PYAuthObject, (char *) methname); } else { *methptr = NULL; } /* See if such method is defined. */ if (*methptr == NULL) syslog(L_NOTICE, "python method %s not found", methname); else { /* See if it is callable. */ if (PyCallable_Check(*methptr) == 0) { syslog(L_ERROR, "python object %s found but not a function", methname); Py_DECREF(*methptr); *methptr = NULL; } } } else { *methptr = NULL; } } /* ** Look up all the known python methods and set up ** pointers to them so that we could call them from nnrpd. */ static void PYdefmethods(PyFile *fp, int realtype) { /* Get a reference to authenticate() method. */ PYdefonemethod(fp, PYTHONauthen, PYTHONmain, "authenticate", realtype); /* Get a reference to authen_init() method. */ PYdefonemethod(fp, PYTHONauthen, PYTHONinit, "authen_init", realtype); /* Get a reference to authen_close() method. */ PYdefonemethod(fp, PYTHONauthen, PYTHONclose, "authen_close", realtype); /* Get a reference to access() method. */ PYdefonemethod(fp, PYTHONaccess, PYTHONmain, "access", realtype); /* Get a reference to access_init() method. */ PYdefonemethod(fp, PYTHONaccess, PYTHONinit, "access_init", realtype); /* Get a reference to access_close() method. */ PYdefonemethod(fp, PYTHONaccess, PYTHONclose, "access_close", realtype); /* Get a reference to dynamic() method. */ PYdefonemethod(fp, PYTHONdynamic, PYTHONmain, "dynamic", realtype); /* Get a reference to dynamic_init() method. */ PYdefonemethod(fp, PYTHONdynamic, PYTHONinit, "dynamic_init", realtype); /* Get a reference to dynamic_close() method. */ PYdefonemethod(fp, PYTHONdynamic, PYTHONclose, "dynamic_close", realtype); } /* ** Called when a python hook is needed -- this gets the scripts hooked in. */ PyObject* PY_setup(int type, int method, char *file) { int i; PyFile *fp; PyObject *result; /* Check to see if this file is in files. */ if ((fp = hash_lookup(files, file)) == NULL) { fp = xmalloc(sizeof(PyFile)); fp->file = xstrdup(file); for (i = 1; i < PYTHONtypes_max; i++) { fp->loaded[i] = false; } /* Load up external module. */ (void) PyImport_ImportModule(file); /* See if nnrpd auth object is defined in auth module. */ if (PYAuthObject == NULL) { syslog(L_ERROR, "python auth object is not defined"); Reply("%d Internal error (3). Goodbye!\r\n", NNTP_FAIL_TERMINATING); PY_close_python(); ExitWithStats(1, false); } else { /* Set up pointers to known Python methods. */ PYdefmethods(fp, type); } hash_insert(files, file, fp); if ((!fp->loaded[type]) && (fp->procs[type][PYTHONinit] != NULL)) { result = PyObject_CallFunction(fp->procs[type][PYTHONinit], NULL); if (result != NULL) { Py_XDECREF(result); } fp->loaded[type] = true; } } return fp->procs[type][method]; } /* ** Return the key (filename) from a file struct, used by the hash table. */ static const void * file_key(const void *p) { const struct PyFile *f = p; return f->file; } /* ** Check to see if a provided key matches the key of a PyFile struct, ** used by the hash table. */ static bool file_equal(const void *k, const void *p) { const char *key = k; const struct PyFile *f = p; return strcmp(key, f->file) == 0; } /* ** Free a file, used by the hash table. */ static void file_free(void *p) { struct PyFile *fp = p; int i, j; free(fp->file); for (i = 1; i < PYTHONtypes_max; i++) { for (j = 1; j < PYTHONmethods_max; j++) { if (fp->procs[i][j] != NULL) { Py_DECREF(fp->procs[i][j]); } } } free(fp); } #endif /* defined(DO_PYTHON) */ inn-2.6.4/nnrpd/misc.c0000644000175200017520000004225314002373703014146 0ustar iuliusiulius/* $Id: misc.c 10305 2018-12-02 14:21:56Z iulius $ ** ** Miscellaneous support routines. */ #include "config.h" #include "clibrary.h" /* Needed on AIX 4.1 to get fd_set and friends. */ #ifdef HAVE_SYS_SELECT_H # include #endif #include "inn/innconf.h" #include "nnrpd.h" #include "tls.h" /* Outside the ifdef so that make depend works even ifndef HAVE_OPENSSL. */ #include "inn/ov.h" #if defined(HAVE_OPENSSL) extern SSL *tls_conn; extern int tls_cipher_usebits; extern char *tls_peer_CN; extern bool encryption_layer_on; #endif /* HAVE_OPENSSL */ /* ** Match a list of newsgroup specifiers against a list of newsgroups. ** func is called to see if there is a match. */ bool PERMmatch(char **Pats, char **list) { int i; char *p; int match = false; if (Pats == NULL || Pats[0] == NULL) return true; for ( ; *list; list++) { for (i = 0; (p = Pats[i]) != NULL; i++) { if (p[0] == '!') { if (uwildmat(*list, ++p)) match = false; } else if (uwildmat(*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 ** Xref: (or Newsgroups:) line. */ bool PERMartok(void) { static char **grplist; char *p, **grp; if (!PERMspecified) return false; if ((p = GetHeader("Xref", true)) == NULL) { /* In case article does not include Xref:. */ if ((p = GetHeader("Newsgroups", true)) != NULL) { if (!NGgetlist(&grplist, p)) /* No newgroups or null entry. */ return true; } else { return true; } } else { /* Skip path element. */ if ((p = strchr(p, ' ')) == NULL) return true; for (p++ ; *p == ' ' ; p++); if (*p == '\0') return true; if (!NGgetlist(&grplist, p)) /* No newgroups or null entry. */ return true; /* Chop ':' and article number. */ for (grp = grplist ; *grp != NULL ; grp++) { if ((p = strchr(*grp, ':')) == NULL) return true; *p = '\0'; } } #ifdef DO_PYTHON if (PY_use_dynamic) { char *reply; /* Authorize user at a Python authorization module. */ if (PY_dynamic(PERMuser, p, false, &reply) < 0) { syslog(L_NOTICE, "PY_dynamic(): authorization skipped due to no Python dynamic method defined"); } else { if (reply != NULL) { syslog(L_TRACE, "PY_dynamic() returned a refuse string for user %s at %s who wants to read %s: %s", PERMuser, Client.host, p, reply); free(reply); return false; } return true; } } #endif /* DO_PYTHON */ return PERMmatch(PERMreadlist, grplist); } /* ** Parse a newsgroups line, return true if there were any. */ bool NGgetlist(char ***argvp, char *list) { char *p; for (p = list; *p; p++) if (*p == ',') *p = ' '; return Argify(list, argvp) != 0; } /********************************************************************* * POSTING RATE LIMITS -- The following code implements posting rate * limits. News clients are indexed by IP number (or PERMuser, see * config file). After a relatively configurable number of posts, the nnrpd * process will sleep for a period of time before posting anything. * * Each time that IP number posts a message, the time of * posting and the previous sleep time is stored. The new sleep time * is computed based on these values. * * To compute the new sleep time, the previous sleep time is, for most * cases multiplied by a factor (backoff_k). * * See inn.conf(5) for how this code works. * *********************************************************************/ /* Defaults are pass through, i.e. not enabled . * NEW for INN 1.8 -- Use the inn.conf file to specify the following: * * backoffk: * backoffpostfast: * backoffpostslow: * backofftrigger: * backoffdb: * backoffauth: * * You may also specify posting backoffs on a per user basis. To do this, * turn on backoffauth. * * Now these are runtime constants. */ static char postrec_dir[SMBUF]; /* Where is the post record directory? */ void InitBackoffConstants(void) { struct stat st; /* Default is not to enable this code. */ BACKOFFenabled = false; /* Read the runtime config file to get parameters. */ if ((PERMaccessconf->backoff_db == NULL) || !(PERMaccessconf->backoff_postslow >= 1L)) return; /* Need this database for backing off. */ strlcpy(postrec_dir, PERMaccessconf->backoff_db, sizeof(postrec_dir)); if (stat(postrec_dir, &st) < 0) { if (ENOENT == errno) { if (!MakeDirectory(postrec_dir, true)) { syslog(L_ERROR, "%s cannot create backoff_db '%s': %s",Client.host,postrec_dir,strerror(errno)); return; } } else { syslog(L_ERROR, "%s cannot stat backoff_db '%s': %s",Client.host,postrec_dir,strerror(errno)); return; } } if (!S_ISDIR(st.st_mode)) { syslog(L_ERROR, "%s backoff_db '%s' is not a directory",Client.host,postrec_dir); return; } BACKOFFenabled = true; return; } /* ** PostRecs are stored in individual files. I didn't have a better ** way offhand, don't want to touch DBZ, and the number of posters is ** small compared to the number of readers. This is the filename corresponding ** to an IP number. */ char * PostRecFilename(char *ip, char *user) { static char buff[SPOOLNAMEBUFF]; char dirbuff[SMBUF+2+3*3]; struct in_addr inaddr; unsigned long int addr; unsigned char quads[4]; unsigned int i; if (PERMaccessconf->backoff_auth) { snprintf(buff, sizeof(buff), "%s/%s", postrec_dir, user); return(buff); } if (inet_aton(ip, &inaddr) < 1) { /* If inet_aton() fails, we'll assume it's an IPv6 address. We'll * also assume for now that we're dealing with a limited number of * IPv6 clients so we'll place their files all in the same * directory for simplicity. Someday we'll need to change this to * something more scalable such as DBZ when IPv6 clients become * more popular. */ snprintf(buff, sizeof(buff), "%s/%s", postrec_dir, ip); return(buff); } /* If it's an IPv4 address just fall through. */ addr = ntohl(inaddr.s_addr); for (i=0; i<4; i++) quads[i] = (unsigned char) (0xff & (addr>>(i*8))); snprintf(dirbuff, sizeof(dirbuff), "%s/%03u%03u/%03u", postrec_dir, quads[3], quads[2], quads[1]); if (!MakeDirectory(dirbuff,true)) { syslog(L_ERROR, "%s Unable to create postrec directories '%s': %s", Client.host, dirbuff, strerror(errno)); return NULL; } snprintf(buff, sizeof(buff), "%s/%03u", dirbuff, quads[0]); return(buff); } /* ** Lock the post rec file. Return 1 on lock, 0 on error. */ int LockPostRec(char *path) { char lockname[SPOOLNAMEBUFF]; char temp[SPOOLNAMEBUFF]; int statfailed = 0; snprintf(lockname, sizeof(lockname), "%s.lock", path); for (;; sleep(5)) { int fd; struct stat st; time_t now; fd = open(lockname, O_WRONLY|O_EXCL|O_CREAT, 0600); if (fd >= 0) { /* We got the lock! */ snprintf(temp, sizeof(temp), "pid:%lu\n", (unsigned long) getpid()); write(fd, temp, strlen(temp)); close(fd); return(1); } /* No lock. See if the file is there. */ if (stat(lockname, &st) < 0) { syslog(L_ERROR, "%s cannot stat lock file %s", Client.host, strerror(errno)); if (statfailed++ > 5) return(0); continue; } /* If lockfile is older than the value of * PERMaccessconf->backoff_postslow, remove it. */ statfailed = 0; time(&now); if (now < (time_t) (st.st_ctime + PERMaccessconf->backoff_postslow)) continue; syslog(L_ERROR, "%s removing stale lock file %s", Client.host, lockname); unlink(lockname); } } void UnlockPostRec(char *path) { char lockname[SPOOLNAMEBUFF]; snprintf(lockname, sizeof(lockname), "%s.lock", path); if (unlink(lockname) < 0) { syslog(L_ERROR, "%s can't unlink lock file: %s", Client.host,strerror(errno)) ; } return; } /* ** Get the stored postrecord for that IP. */ static int GetPostRecord(char *path, long *lastpost, long *lastsleep, long *lastn) { static char buff[SMBUF]; FILE *fp; char *s; fp = fopen(path,"r"); if (fp == NULL) { if (errno == ENOENT) { return 1; } syslog(L_ERROR, "%s Error opening '%s': %s", Client.host, path, strerror(errno)); return 0; } if (fgets(buff,SMBUF,fp) == NULL) { syslog(L_ERROR, "%s Error reading '%s': %s", Client.host, path, strerror(errno)); fclose(fp); return 0; } *lastpost = atol(buff); if ((s = strchr(buff,',')) == NULL) { syslog(L_ERROR, "%s bad data in postrec file: '%s'", Client.host, buff); fclose(fp); return 0; } s++; *lastsleep = atol(s); if ((s = strchr(s,',')) == NULL) { syslog(L_ERROR, "%s bad data in postrec file: '%s'", Client.host, buff); fclose(fp); return 0; } s++; *lastn = atol(s); fclose(fp); return 1; } /* ** Store the postrecord for that IP. */ static int StorePostRecord(char *path, time_t lastpost, long lastsleep, long lastn) { FILE *fp; fp = fopen(path,"w"); if (fp == NULL) { syslog(L_ERROR, "%s Error opening '%s': %s", Client.host, path, strerror(errno)); return 0; } fprintf(fp,"%ld,%ld,%ld\n",(long) lastpost,lastsleep,lastn); fclose(fp); return 1; } /* ** Return the proper sleeptime. Return false on error. */ int RateLimit(long *sleeptime, char *path) { time_t now; long prevpost, prevsleep, prevn, n; now = time(NULL); prevpost = 0L; prevsleep = 0L; prevn = 0L; n = 0L; if (!GetPostRecord(path, &prevpost, &prevsleep, &prevn)) { syslog(L_ERROR, "%s can't get post record: %s", Client.host, strerror(errno)); return 0; } /* Just because yer paranoid doesn't mean they ain't out ta get ya. * This is called paranoid clipping. */ if (prevn < 0L) prevn = 0L; if (prevsleep < 0L) prevsleep = 0L; if ((unsigned long) prevsleep > PERMaccessconf->backoff_postfast) prevsleep = PERMaccessconf->backoff_postfast; /* Compute the new sleep time. */ *sleeptime = 0L; if (prevpost <= 0L) { prevpost = 0L; prevn = 1L; } else { n = now - prevpost; if (n < 0L) { syslog(L_NOTICE,"%s previous post was in the future (%ld sec)", Client.host,n); n = 0L; } if ((unsigned long) n < PERMaccessconf->backoff_postfast) { if ((unsigned long) prevn >= PERMaccessconf->backoff_trigger) { *sleeptime = 1 + (prevsleep * PERMaccessconf->backoff_k); } } else if ((unsigned long) n < PERMaccessconf->backoff_postslow) { if ((unsigned long) prevn >= PERMaccessconf->backoff_trigger) { *sleeptime = prevsleep; } } else { prevn = 0L; } prevn++; } *sleeptime = ((*sleeptime) > (long) PERMaccessconf->backoff_postfast) ? (long) PERMaccessconf->backoff_postfast : (*sleeptime); /* This ought to trap this bogon. */ if ((*sleeptime) < 0L) { syslog(L_ERROR,"%s Negative sleeptime detected: %ld, prevsleep: %ld, N: %ld", Client.host, *sleeptime, prevsleep, n); *sleeptime = 0L; } /* Store the postrecord. */ if (!StorePostRecord(path, now, *sleeptime, prevn)) { syslog(L_ERROR, "%s can't store post record: %s", Client.host, strerror(errno)); return 0; } return 1; } #if defined(HAVE_SASL) || defined(HAVE_ZLIB) /* ** Check if the argument has a valid syntax. ** ** Currently used for both SASL mechanisms (RFC 4643) and compression ** algorithms. ** ** algorithm = 1*20alg-char ** alg-char = UPPER / DIGIT / "-" / "_" */ bool IsValidAlgorithm(const char *string) { size_t len = 0; const unsigned char *p; /* Not NULL. */ if (string == NULL) { return false; } p = (const unsigned char *) string; for (; *p != '\0'; p++) { len++; if (!isupper((unsigned char) *p) && !isdigit((unsigned char) *p) && *p != '-' && *p != '_') { return false; } } if (len > 0 && len < 21) { return true; } else { return false; } } #endif /* HAVE_SASL || HAVE_ZLIB */ #if defined(HAVE_ZLIB) /* ** The COMPRESS command. RFC 8054. */ void CMDcompress(int ac, char *av[]) { bool result; /* Check the argument. */ if (ac > 1) { if (!IsValidAlgorithm(av[1])) { Reply("%d Syntax error in compression algorithm name\r\n", NNTP_ERR_SYNTAX); return; } if (strcasecmp(av[1], "DEFLATE") != 0) { Reply("%d Only the DEFLATE compression algorithm is supported\r\n", NNTP_ERR_UNAVAILABLE); return; } } if (compression_layer_on) { Reply("%d Already using a compression layer\r\n", NNTP_ERR_ACCESS); return; } result = zlib_init(); if (!result) { Reply("%d Impossible to activate compression\r\n", NNTP_FAIL_ACTION); return; } Reply("%d Compression now active; enjoy the speed!\r\n", NNTP_OK_COMPRESS); /* Flush any pending output, before enabling compression. */ fflush(stdout); compression_layer_on = true; } #endif /* HAVE_ZLIB */ #if defined(HAVE_OPENSSL) /* ** The STARTTLS command. RFC 4642. */ void CMDstarttls(int ac UNUSED, char *av[] UNUSED) { int result; bool boolval; if (encryption_layer_on) { Reply("%d Already using a security layer\r\n", NNTP_ERR_ACCESS); return; } # if defined(HAVE_ZLIB) /* If a compression layer is active, STARTTLS is not possible. */ if (compression_layer_on) { Reply("%d Already using a compression layer\r\n", NNTP_ERR_ACCESS); return; } # endif /* HAVE_ZLIB */ /* If the client is already authenticated, STARTTLS is not possible. */ if (PERMauthorized && !PERMneedauth && !PERMcanauthenticate) { Reply("%d Already authenticated without the use of a security layer\r\n", NNTP_ERR_ACCESS); return; } result = tls_init(); if (result == -1) { /* No reply because tls_init() has already sent one. */ return; } /* Close out any existing article, report group stats. * RFC 4642 requires the reset of any knowledge about the client. */ if (GRPcur) { ARTclose(); GRPreport(); OVctl(OVCACHEFREE, &boolval); free(GRPcur); GRPcur = NULL; if (ARTcount) { syslog(L_NOTICE, "%s exit for STARTTLS articles %ld groups %ld", Client.host, ARTcount, GRPcount); } GRPcount = 0; PERMgroupmadeinvalid = false; } /* We can now assume a secure connection will be negotiated because * nnrpd will exit if STARTTLS fails. * Check the permissions the client will have after having successfully * negotiated a TLS layer. (There may be auth blocks requiring the * negotiation of a security layer in readers.conf that match the * connection.) * In case the client would no longer have access to the server, or an * authentication error happens, the connection aborts after a fatal 400 * response code sent by PERMgetpermissions(). */ encryption_layer_on = true; PERMgetaccess(false); PERMgetpermissions(); Reply("%d Begin TLS negotiation now\r\n", NNTP_CONT_STARTTLS); fflush(stdout); /* Must flush our buffers before starting TLS. */ result = tls_start_servertls(0, /* Read. */ 1); /* Write. */ if (result == -1) { /* No reply because we have already sent NNTP_CONT_STARTTLS. * We close the connection. */ ExitWithStats(1, false); } # if defined(HAVE_SASL) /* Tell SASL about the negotiated layer. */ result = sasl_setprop(sasl_conn, SASL_SSF_EXTERNAL, (sasl_ssf_t *) &tls_cipher_usebits); if (result != SASL_OK) { syslog(L_NOTICE, "sasl_setprop() failed: CMDstarttls()"); } result = sasl_setprop(sasl_conn, SASL_AUTH_EXTERNAL, tls_peer_CN); if (result != SASL_OK) { syslog(L_NOTICE, "sasl_setprop() failed: CMDstarttls()"); } # endif /* HAVE_SASL */ # if defined(HAVE_ZLIB) && OPENSSL_VERSION_NUMBER >= 0x00090800fL /* Check whether a compression layer has just been added. * SSL_get_current_compression() is defined in OpenSSL versions >= 0.9.8 * final release. */ tls_compression_on = (SSL_get_current_compression(tls_conn) != NULL); compression_layer_on = tls_compression_on; # endif /* HAVE_ZLIB && OPENSSL >= v0.9.8 */ /* Reset our read buffer so as to prevent plaintext command injection. */ line_reset(&NNTPline); } #endif /* HAVE_OPENSSL */ inn-2.6.4/nnrpd/post.c0000644000175200017520000013061614002373703014201 0ustar iuliusiulius/* $Id: post.c 10477 2020-12-31 22:46:07Z eagle $ ** ** Check article, send it to the local server. */ #include "config.h" #include "clibrary.h" #include "inn/innconf.h" #include "nnrpd.h" #include "inn/ov.h" #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; char **OtherHeaders; int OtherCount; bool HeadersModified; static int OtherSize; static const char * const BadDistribs[] = { BAD_DISTRIBS }; extern bool laxmid; /* ** Do not modify the table without also looking at post.h for potential ** changes in the order of the fields. ** ** The table should reflect the status of the fields in the "Permanent ** Message Header Field Names" registry: ** http://www.iana.org/assignments/message-headers/ */ HEADER Table[] = { /* Name CanSet Type Size Value Body Len */ { "Path", true, HTstd, 0, NULL, NULL, 0 }, { "From", true, HTreq, 0, NULL, NULL, 0 }, { "Newsgroups", true, HTreq, 0, NULL, NULL, 0 }, { "Subject", true, HTreq, 0, NULL, NULL, 0 }, { "Control", true, HTstd, 0, NULL, NULL, 0 }, { "Supersedes", true, HTstd, 0, NULL, NULL, 0 }, { "Followup-To", true, HTstd, 0, NULL, NULL, 0 }, { "Date", true, HTstd, 0, NULL, NULL, 0 }, { "Organization", true, HTstd, 0, NULL, NULL, 0 }, { "Lines", true, HTstd, 0, NULL, NULL, 0 }, { "Sender", true, HTstd, 0, NULL, NULL, 0 }, { "Approved", true, HTstd, 0, NULL, NULL, 0 }, { "Archive", true, HTstd, 0, NULL, NULL, 0 }, { "Distribution", true, HTstd, 0, NULL, NULL, 0 }, { "Expires", true, HTstd, 0, NULL, NULL, 0 }, { "Message-ID", true, HTstd, 0, NULL, NULL, 0 }, { "References", true, HTstd, 0, NULL, NULL, 0 }, { "Reply-To", true, HTstd, 0, NULL, NULL, 0 }, { "NNTP-Posting-Host", false, HTobs, 0, NULL, NULL, 0 }, { "Mime-Version", true, HTstd, 0, NULL, NULL, 0 }, { "Content-Type", true, HTstd, 0, NULL, NULL, 0 }, { "Content-Transfer-Encoding", true, HTstd, 0, NULL, NULL, 0 }, { "X-Trace", false, HTobs, 0, NULL, NULL, 0 }, { "X-Complaints-To", false, HTobs, 0, NULL, NULL, 0 }, { "NNTP-Posting-Date", false, HTobs, 0, NULL, NULL, 0 }, { "Xref", false, HTstd, 0, NULL, NULL, 0 }, { "Injection-Date", true, HTstd, 0, NULL, NULL, 0 }, { "Injection-Info", false, HTstd, 0, NULL, NULL, 0 }, { "Summary", true, HTstd, 0, NULL, NULL, 0 }, { "Keywords", true, HTstd, 0, NULL, NULL, 0 }, { "User-Agent", true, HTstd, 0, NULL, NULL, 0 }, { "Date-Received", false, HTobs, 0, NULL, NULL, 0 }, { "Posting-Version", false, HTobs, 0, NULL, NULL, 0 }, { "Relay-Version", false, HTobs, 0, NULL, NULL, 0 }, { "Cc", true, HTstd, 0, NULL, NULL, 0 }, { "Bcc", true, HTstd, 0, NULL, NULL, 0 }, { "To", true, HTstd, 0, NULL, NULL, 0 }, { "Archived-At", true, HTstd, 0, NULL, NULL, 0 }, { "Also-Control", false, HTobs, 0, NULL, NULL, 0 }, { "Article-Names", false, HTobs, 0, NULL, NULL, 0 }, { "Article-Updates", false, HTobs, 0, NULL, NULL, 0 }, { "See-Also", false, HTobs, 0, NULL, NULL, 0 }, { "Cancel-Key", true, HTstd, 0, NULL, NULL, 0 }, { "Cancel-Lock", true, HTstd, 0, NULL, NULL, 0 }, /* The Comments: and Original-Sender: header fields can appear more than once * in the headers of an article. Consequently, we MUST NOT put them here. */ }; HEADER *EndOfTable = ARRAY_END(Table); /* ** Turn any \r or \n in text into spaces. Used to splice back multi-line ** headers into a single line. ** Taken from innd.c. */ static char * Join(char *text) { char *p; for (p = text; *p; p++) if (*p == '\n' || *p == '\r') *p = ' '; return text; } /* ** Return a short name that won't overrun our buffer or syslog's buffer. ** q should either be p, or point into p where the "interesting" part is. ** Taken from innd.c. */ static char * MaxLength(char *p, char *q) { static char buff[80]; unsigned int i; /* Return an empty string when p is NULL. */ if (p == NULL) { *buff = '\0'; return buff; } /* Already short enough? */ i = strlen(p); if (i < sizeof buff - 1) return Join(p); /* Don't want casts to unsigned to go horribly wrong. */ if (q < p || q > p + i) q = p; /* Simple case of just want the beginning? */ if (q == NULL || (size_t)(q - p) < sizeof(buff) - 4) { strlcpy(buff, p, sizeof(buff) - 3); strlcat(buff, "...", sizeof(buff)); } else if ((p + i) - q < 10) { /* Is getting last 10 characters good enough? */ strlcpy(buff, p, sizeof(buff) - 13); strlcat(buff, "...", sizeof(buff) - 10); strlcat(buff, &p[i - 10], sizeof(buff)); } else { /* Not in last 10 bytes, so use double ellipses. */ strlcpy(buff, p, sizeof(buff) - 16); strlcat(buff, "...", sizeof(buff) - 13); strlcat(buff, &q[-5], sizeof(buff) - 3); strlcat(buff, "...", sizeof(buff)); } return Join(buff); } /* ** Trim leading and trailing spaces, return the length of the result. */ int TrimSpaces(char *p) { char *start; for (start = p; ISWHITE(*start) || *start == '\n'; start++) continue; for (p = start + strlen(start); p > start && isspace((unsigned char) p[-1]); p--) continue; return (int)(p - 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(char *p) { char *q; for (q = p; (p = strchr(p, '\n')) != NULL; p++) { /* Note that '\r\n' has temporarily been internally replaced by '\n'. * Therefore, the count takes it into account (+1, besides the * length (p-q+1) of the string). */ if (p - q + 2 > MAXARTLINELENGTH) { strlcpy(Error, "Header line too long", sizeof(Error)); return NULL; } /* Check if there is a continuation line for the header. */ if (ISWHITE(p[1])) { q = p + 1; continue; } *p = '\0'; return p + 1; } strlcpy(Error, "Article has no body -- just headers", sizeof(Error)); 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(char *article) { char *p; char *q; HEADER *hp; char c; /* Scan through buffer, a header at a time. */ for (p = article; ; ) { /* See if it's a known header. */ c = islower((unsigned char) *p) ? toupper((unsigned char) *p) : *p; for (hp = Table; hp < ARRAY_END(Table); hp++) { if (c == hp->Name[0] && p[hp->Size] == ':' && strncasecmp(p, hp->Name, hp->Size) == 0) { if (hp->Type == HTobs) { snprintf(Error, sizeof(Error), "Obsolete %s: header", hp->Name); return NULL; } if (hp->Value) { snprintf(Error, sizeof(Error), "Duplicate %s: header", hp->Name); return NULL; } hp->Value = &p[hp->Size + 1]; /* '\r\n' is replaced with '\n', and unnecessary to consider * '\r'. */ for (q = &p[hp->Size + 1]; ISWHITE(*q) || (*q == '\n' && ISWHITE(q[1])); q++) { continue; } hp->Body = q; break; } } /* No; add it to the set of other headers. */ if (hp == ARRAY_END(Table)) { if (OtherCount >= OtherSize - 1) { OtherSize += HEADER_DELTA; OtherHeaders = xrealloc(OtherHeaders, OtherSize * sizeof(char *)); } OtherHeaders[OtherCount++] = p; } /* Get start of next header; if it's a blank line, we hit the end. */ if ((p = NextHeader(p)) == NULL) { /* Error set in NextHeader(). */ 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 const char * CheckControl(char *ctrl) { char *p; 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 (strcasecmp(ctrl, "cancel") == 0) { for (q = p + 1; ISWHITE(*q); q++) continue; if (*q == '\0') return "Message-ID missing in cancel"; } else if (strcasecmp(ctrl, "checkgroups") == 0 || strcasecmp(ctrl, "ihave") == 0 || strcasecmp(ctrl, "sendme") == 0 || strcasecmp(ctrl, "newgroup") == 0 || strcasecmp(ctrl, "rmgroup") == 0) ; else { snprintf(Error, sizeof(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 const char * CheckDistribution(char *p) { static char SEPS[] = " \t,"; const char * const *dp; if ((p = strtok(p, SEPS)) == NULL) return "Can't parse Distribution: header"; do { for (dp = BadDistribs; *dp; dp++) if (uwildmat(p, *dp)) { snprintf(Error, sizeof(Error), "Illegal distribution \"%s\"", MaxLength(p,p)); return Error; } } while ((p = strtok((char *)NULL, SEPS)) != NULL); return NULL; } /* ** Process all the headers. ** Return NULL if okay, or an error message. */ static const char * ProcessHeaders(char *idbuff, bool needmoderation) { static char datebuff[40]; static char localdatebuff[40]; static char orgbuff[SMBUF]; static char pathidentitybuff[SMBUF]; static char complaintsbuff[SMBUF]; static char postingaccountbuff[SMBUF*2]; /* Allocate enough room. */ static char postinghostbuff[SMBUF*2]; static char sendbuff[SMBUF*2]; static char injectioninfobuff[SMBUF*7]; static char *newpath = NULL; HEADER *hp; char *p; char *bad_header; char *fqdn = NULL; time_t t, now; const char *error; pid_t pid; bool addvirtual = false; int i; /* Get the current time, used for creating and checking dates. */ now = time(NULL); /* datebuff is used for both Injection-Date: and Date: header fields * so we have to set it now, and it has to be the UTC date (unless * for the Date: header field if localtime is set to true * in readers.conf). */ if (!makedate(-1, false, datebuff, sizeof(datebuff))) return "Can't generate Date: header"; /* Do some preliminary fix-ups. */ for (hp = Table; hp < ARRAY_END(Table); hp++) { if (!hp->CanSet && hp->Value) { snprintf(Error, sizeof(Error), "Can't set system %s: header", hp->Name); return Error; } if (hp->Value) { hp->Len = TrimSpaces(hp->Value); /* If the header is empty, we just remove it. We do not reject * the article, contrary to what an injecting agent is supposed * to do per Section 3.5 of RFC 5537. (A revision to RFC 5537 * may someday allow again that existing and useful feature.) */ if (hp->Len == 0) { hp->Value = hp->Body = NULL; } else if (!IsValidHeaderBody(hp->Value)) { snprintf(Error, sizeof(Error), "Invalid syntax encountered in %s: header field " "body (unexpected byte or empty content line)", hp->Name); return Error; } } } /* Set the Injection-Date: header field. */ /* Start with this header field because it MUST NOT be added in case * the article already contains both Message-ID: and Date: * header fields (possibility of multiple injection, see Sections 3.4.2 * and 3.5 of RFC 5537). */ if (HDR(HDR__INJECTION_DATE) == NULL) { /* If moderation is needed, do not add an Injection-Date: header field. */ if (!needmoderation && PERMaccessconf->addinjectiondate) { if ((HDR(HDR__MESSAGEID) == NULL) || (HDR(HDR__DATE) == NULL)) { HDR_SET(HDR__INJECTION_DATE, datebuff); } } } else { t = parsedate_rfc5322_lax(HDR(HDR__INJECTION_DATE)); if (t == (time_t) -1) return "Can't parse Injection-Date: header"; if (t > now + DATE_FUZZ) return "Article injected in the future"; } /* If authorized, add the header based on our info. If not authorized, * zap the Sender: header so we don't put out unauthenticated data. */ if (PERMaccessconf->nnrpdauthsender) { if (PERMauthorized && PERMuser[0] != '\0') { p = strchr(PERMuser, '@'); if (p == NULL) { snprintf(sendbuff, sizeof(sendbuff), "%s@%s", PERMuser, Client.host); } else { snprintf(sendbuff, sizeof(sendbuff), "%s", PERMuser); } HDR_SET(HDR__SENDER, sendbuff); } else { HDR_CLEAR(HDR__SENDER); } } /* Set the Date: header. */ if (HDR(HDR__DATE) == NULL) { if (PERMaccessconf->localtime) { if (!makedate(-1, true, localdatebuff, sizeof(localdatebuff))) return "Can't generate local date header"; HDR_SET(HDR__DATE, localdatebuff); } else { HDR_SET(HDR__DATE, datebuff); } } else { t = parsedate_rfc5322_lax(HDR(HDR__DATE)); if (t == (time_t) -1) return "Can't parse Date: header"; if (t > now + DATE_FUZZ) return "Article posted in the future"; /* This check is done for Date: by nnrpd. * innd, as a relaying agent, does not check it when an Injection-Date: * header is present. */ if (innconf->artcutoff != 0) { long cutoff = innconf->artcutoff * 24 * 60 * 60; if (t < now - cutoff) return "Article posted too far in the past (check still " "done for legacy reasons on the Date: header)"; } } /* Newsgroups: is checked later. */ if (HDR(HDR__CONTROL) != NULL) { if ((error = CheckControl(HDR(HDR__CONTROL))) != NULL) return error; } /* Set the Message-ID: header. */ if (HDR(HDR__MESSAGEID) == NULL) { HDR_SET(HDR__MESSAGEID, idbuff); } if (!IsValidMessageID(HDR(HDR__MESSAGEID), true, laxmid)) { return "Can't parse Message-ID: header"; } /* Set the Path: header. */ if (HDR(HDR__PATH) == NULL || PERMaccessconf->strippath) { /* Note that innd will put host name here for us. */ /* If moderation is needed, do not update the Path: header field. */ if (!needmoderation) HDR_SET(HDR__PATH, (char *) PATHMASTER); else if (PERMaccessconf->strippath) HDR_CLEAR(HDR__PATH); if (VirtualPathlen > 0) addvirtual = true; } else { /* Check that the article has not been injected yet. */ for (p = HDR(HDR__PATH); *p != '\0'; p++) { if (*p == '.' && strncasecmp(p, ".POSTED", 7) == 0 && (p[7] == '.' || p[7] == '!' || p[7] == ' ' || p[7] == '\t' || p[7] == '\r' || p[7] == '\n') && (p == HDR(HDR__PATH) || p[-1] == '!')) { return "Path: header shows a previous injection of the article"; } } /* Check whether the virtual host name is required. */ if ((VirtualPathlen > 0) && (p = strchr(HDR(HDR__PATH), '!')) != NULL) { *p = '\0'; if (strcasecmp(HDR(HDR__PATH), PERMaccessconf->pathhost) != 0) addvirtual = true; *p = '!'; } else if (VirtualPathlen > 0) addvirtual = true; } if (newpath != NULL) free(newpath); if (PERMaccessconf->addinjectionpostinghost) { if (addvirtual) { newpath = concat(VirtualPath, ".POSTED.", Client.host, "!", HDR(HDR__PATH), (char *) 0); } else { newpath = concat(".POSTED.", Client.host, "!", HDR(HDR__PATH), (char *) 0); } } else { if (addvirtual) { newpath = concat(VirtualPath, ".POSTED!", HDR(HDR__PATH), (char *) 0); } else { newpath = concat(".POSTED!", HDR(HDR__PATH), (char *) 0); } } /* If moderation is needed, do not update the Path: header field. */ if (!needmoderation) HDR_SET(HDR__PATH, newpath); /* Reply-To: is left alone. */ /* Sender: is set above. */ /* Check the Expires: header. */ if (HDR(HDR__EXPIRES) && parsedate_rfc5322_lax(HDR(HDR__EXPIRES)) == -1) return "Can't parse Expires: header"; /* References: is left alone. */ /* Control: is checked above. */ /* Check the Distribution: header. */ if ((p = HDR(HDR__DISTRIBUTION)) != NULL) { p = xstrdup(p); error = CheckDistribution(p); free(p); if (error != NULL) return error; } /* Set the Organization: header. */ if (HDR(HDR__ORGANIZATION) == NULL && (p = PERMaccessconf->organization) != NULL) { strlcpy(orgbuff, p, sizeof(orgbuff)); HDR_SET(HDR__ORGANIZATION, orgbuff); } /* Keywords: is left alone. */ /* Summary: is left alone. */ /* Approved: is left alone. */ /* Lines: should not be generated. */ /* Supersedes: is left alone. */ /* Set the Injection-Info: header. */ /* Set the path identity. */ if (VirtualPathlen > 0) { p = PERMaccessconf->domain; } else { fqdn = inn_getfqdn(PERMaccessconf->domain); if (fqdn == NULL) p = (char *) "unknown"; else p = fqdn; } snprintf(pathidentitybuff, sizeof(pathidentitybuff), "%s", p); free(fqdn); p = NULL; /* Set the posting-account value. */ if (PERMaccessconf->addinjectionpostingaccount && PERMuser[0] != '\0') { snprintf(postingaccountbuff, sizeof(postingaccountbuff), "; posting-account=\"%s\"", PERMuser); } /* Set the posting-host identity. * Check a proper definition of Client.host and Client.ip * (we already saw the case of "localhost:" without IP), * when getpeername fails. */ if ((strlen(Client.host) > 0) || (strlen(Client.ip) > 0)) { if ((strcmp(Client.host, Client.ip) == 0) || (strlen(Client.host) == 0)) { snprintf(postinghostbuff, sizeof(postinghostbuff), "; posting-host=\"%s\"", Client.ip); } else if (strlen(Client.ip) == 0) { snprintf(postinghostbuff, sizeof(postinghostbuff), "; posting-host=\"%s\"", Client.host); } else { snprintf(postinghostbuff, sizeof(postinghostbuff), "; posting-host=\"%s:%s\"", Client.host, Client.ip); } } /* Set the logging-data attribute. */ pid = getpid(); /* Set the mail-complaints-to attribute. */ if ((p = PERMaccessconf->complaints) != NULL) { snprintf(complaintsbuff, sizeof(complaintsbuff), "%s", p); } else { static const char newsmaster[] = NEWSMASTER; if ((p = PERMaccessconf->fromhost) != NULL && strchr(newsmaster, '@') == NULL) { snprintf(complaintsbuff, sizeof(complaintsbuff), "%s@%s", newsmaster, p); } else { snprintf(complaintsbuff, sizeof(complaintsbuff), "%s", newsmaster); } } /* ARTpost() will convert bare LF to CRLF. Do not use CRLF here.*/ snprintf(injectioninfobuff, sizeof(injectioninfobuff), "%s%s%s;\n\tlogging-data=\"%ld\"; mail-complaints-to=\"%s\"", pathidentitybuff, PERMaccessconf->addinjectionpostingaccount && PERMuser[0] != '\0' ? postingaccountbuff : "", PERMaccessconf->addinjectionpostinghost ? postinghostbuff : "", (long) pid, complaintsbuff); /* If moderation is needed, do not add an Injection-Info: header field. */ if (!needmoderation) HDR_SET(HDR__INJECTION_INFO, injectioninfobuff); /* Clear out some headers that should not be here. */ if (PERMaccessconf->strippostcc) { HDR_CLEAR(HDR__CC); HDR_CLEAR(HDR__BCC); HDR_CLEAR(HDR__TO); } /* Now make sure everything is there. */ for (hp = Table; hp < ARRAY_END(Table); hp++) if (hp->Type == HTreq && hp->Value == NULL) { snprintf(Error, sizeof(Error), "Missing required %s: header", hp->Name); return Error; } /* Check that all other header fields are valid. */ for (i = 0; i < OtherCount; i++) { if (!IsValidHeaderField(OtherHeaders[i])) { p = strchr(OtherHeaders[i], ':'); if (p == NULL || p == OtherHeaders[i]) bad_header = xstrdup(OtherHeaders[i]); else bad_header = xstrndup(OtherHeaders[i], p - OtherHeaders[i]); snprintf(Error, sizeof(Error), "Invalid syntax encountered in header (unexpected " "byte, no colon-space, or empty content line): %s", bad_header); free(bad_header); return Error; } } return NULL; } /* ** See if the user has more included text than new text. Simple-minded, ** but reasonably effective for catching neophyte's mistakes. Son-of-1036 ** says: ** ** NOTE: While encouraging trimming is desirable, the 50% rule imposed ** by some old posting agents is both inadequate and counterproductive. ** Posters do not respond to it by being more selective about quoting; ** they respond by padding short responses, or by using different ** quoting styles to defeat automatic analysis. The former adds ** unnecessary noise and volume, while the latter also defeats more ** useful forms of automatic analysis that reading agents might wish to ** do. ** ** NOTE: At the very least, if a minimum-unquoted quota is being set, ** article bodies shorter than (say) 20 lines, or perhaps articles ** which exceed the quota by only a few lines, should be exempt. This ** avoids the ridiculous situation of complaining about a 5-line ** response to a 6-line quote. ** ** Accordingly, bodies shorter than 20 lines are exempt. A line starting ** with >, |, or : is included text. Decrement the count on lines starting ** with < so that we don't reject diff(1) output. */ static const char * CheckIncludedText(const char *p, int lines) { int i; if (lines < 20) return NULL; for (i = 0; ; p++) { switch (*p) { case '>': i++; break; case '|': i++; break; case ':': i++; break; case '<': i--; break; default: break; } p = strchr(p, '\n'); if (p == NULL) break; } if (i * 2 > lines) return "Article not posted -- more included text than new text"; return NULL; } /* ** Try to mail an article to the moderator of the group. */ static const char * MailArticle(char *group, char *article) { static char CANTSEND[] = "Can't send text to mailer"; FILE *F; HEADER *hp; int i; char *address; char buff[SMBUF]; /* Try to get the address first. */ if ((address = GetModeratorAddress(NULL, NULL, group, PERMaccessconf->moderatormailer)) == NULL) { snprintf(Error, sizeof(Error), "No mailing address for \"%s\" -- %s", group, "ask your news administrator to fix this"); free(group); return Error; } free(group); /* Now build up the command (ignore format/argument mismatch errors, * in case %s isn't in inconf->mta) and send the headers. */ if (innconf->mta == NULL) return "Can't start mailer -- mta not set"; snprintf(buff, sizeof(buff), innconf->mta, address); if ((F = popen(buff, "w")) == NULL) return "Can't start mailer"; fprintf(F, "To: %s\n", address); if (FLUSH_ERROR(F)) { pclose(F); return CANTSEND; } /* Write the headers, a blank line, then the article. */ for (hp = Table; hp < ARRAY_END(Table); hp++) if (hp->Value) { if (*hp->Value == ' ' || *hp->Value == '\t') fprintf(F, "%s:%s\n", hp->Name, hp->Value); else fprintf(F, "%s: %s\n", hp->Name, hp->Value); if (FLUSH_ERROR(F)) { pclose(F); return CANTSEND; } } for (i = 0; i < OtherCount; i++) { fprintf(F, "%s\n", OtherHeaders[i]); if (FLUSH_ERROR(F)) { pclose(F); return CANTSEND; } } fprintf(F, "\n"); i = strlen(article); if (fwrite(article, 1, i, F) != (size_t)i) return "Can't send article"; if (FLUSH_ERROR(F)) { pclose(F); return CANTSEND; } i = pclose(F); if (i) { snprintf(Error, sizeof(Error), "Mailer exited with status %d -- %s", i, "Article might not have been mailed"); return Error; } return NULL; } /* ** Check the newsgroups and make sure they're all valid, that none are ** moderated, etc. */ static const char * ValidNewsgroups(char *hdr, char **modgroup) { static char distbuff[SMBUF]; char *groups; char *p; bool approved; struct _DDHANDLE *h; char *grplist[2]; bool IsNewgroup; bool FoundOne; int flag; bool hookpresent = false; #ifdef DO_PYTHON hookpresent = PY_use_dynamic; #endif /* DO_PYTHON */ p = HDR(HDR__CONTROL); IsNewgroup = (p && strncasecmp(p, "newgroup", 8) == 0); groups = xstrdup(hdr); if ((p = strtok(groups, NGSEPS)) == NULL) { free(groups); return "Can't parse Newsgroups: header"; } Error[0] = '\0'; /* Reject all articles with Approved: headers unless the user is allowed to * add them, even to unmoderated or local groups. We want to reject them * to unmoderated groups in case there's a disagreement of opinion * between various sites as to the moderation status. */ approved = HDR(HDR__APPROVED) != NULL; if (approved && !PERMaccessconf->allowapproved) { snprintf(Error, sizeof(Error), "You are not allowed to approve postings"); } FoundOne = false; h = DDstart((FILE *)NULL, (FILE *)NULL); do { if (innconf->mergetogroups && strncmp(p, "to.", 3) == 0) p = (char *) "to"; if (!hookpresent && PERMspecified) { grplist[0] = p; grplist[1] = NULL; if (!PERMmatch(PERMpostlist, grplist)) { snprintf(Error, sizeof(Error), "You are not allowed to post to %s\r\n", p); } } if (!OVgroupstats(p, NULL, NULL, NULL, &flag)) continue; FoundOne = true; DDcheck(h, p); switch (flag) { case NF_FLAG_OK: #ifdef DO_PYTHON if (PY_use_dynamic) { char *reply; /* Authorize user using Python module method dynamic. */ if (PY_dynamic(PERMuser, p, true, &reply) < 0) { syslog(L_NOTICE, "PY_dynamic(): authorization skipped due to no Python dynamic method defined"); } else { if (reply != NULL) { syslog(L_TRACE, "PY_dynamic() returned a refuse string for user %s at %s who wants to post to %s: %s", PERMuser, Client.host, p, reply); snprintf(Error, sizeof(Error), "%s\r\n", reply); free(reply); break; } } } #endif /* DO_PYTHON */ break; case NF_FLAG_MODERATED: if (!approved && modgroup != NULL && !*modgroup) *modgroup = xstrdup(p); break; case NF_FLAG_IGNORE: case NF_FLAG_JUNK: case NF_FLAG_NOLOCAL: if (!PERMaccessconf->locpost) snprintf(Error, sizeof(Error), "Postings to \"%s\" are not allowed here", p); break; case NF_FLAG_ALIAS: snprintf(Error, sizeof(Error), "The newsgroup \"%s\" has been renamed\n", p); break; } } while ((p = strtok((char *)NULL, NGSEPS)) != NULL); free(groups); if (!FoundOne && !IsNewgroup) snprintf(Error, sizeof(Error), "No valid newsgroups in \"%s\"", MaxLength(hdr,hdr)); if (Error[0]) { tmpPtr = DDend(h); free(tmpPtr); if (modgroup != NULL && *modgroup != NULL) { free(*modgroup); *modgroup = NULL; } return Error; } p = DDend(h); if (HDR(HDR__DISTRIBUTION) == NULL && *p) { strlcpy(distbuff, p, sizeof(distbuff)); HDR_SET(HDR__DISTRIBUTION, distbuff); } free(p); return NULL; } /* ** Send a QUIT message to the server, eat its reply. */ static void SendQuit(FILE *FromServer, FILE *ToServer) { char buff[NNTP_MAXLEN_COMMAND]; fprintf(ToServer, "QUIT\r\n"); fflush(ToServer); fclose(ToServer); fgets(buff, sizeof buff, FromServer); fclose(FromServer); } /* ** Offer the article to the server, return its reply. */ static int OfferArticle(char *buff, int buffsize, FILE *FromServer, FILE *ToServer) { /* We have a valid message-ID here (checked beforehand). */ fprintf(ToServer, "IHAVE %s\r\n", HDR(HDR__MESSAGEID)); if (FLUSH_ERROR(ToServer) || fgets(buff, buffsize, FromServer) == NULL) { snprintf(buff, buffsize, "Can't send %s to server, %s", "IHAVE", strerror(errno)); return -1; } return atoi(buff); } /* ** Spool article to temp file. */ static const char * SpoolitTo(char *article, char *err, char *SpoolDir) { static char CANTSPOOL[NNTP_MAXLEN_COMMAND+2]; HEADER *hp; FILE *F = NULL; int i, fd; char *tmpspool = NULL; char *spoolfile = NULL; char *q; /* Initialize the returned error message. */ snprintf(CANTSPOOL, sizeof(CANTSPOOL), "%s and can't write text to local spool file", err); /* Try to write it to the spool dir. */ tmpspool = concatpath(SpoolDir, ".XXXXXX"); fd = mkstemp(tmpspool); if (fd < 0) { syslog(L_FATAL, "can't create temporary spool file %s %m", tmpspool); goto fail; } F = fdopen(fd, "w"); if (F == NULL) { syslog(L_FATAL, "can't open %s %m", tmpspool); goto fail; } fchmod(fileno(F), BATCHFILE_MODE); /* Write the headers and a blank line. */ for (hp = Table; hp < ARRAY_END(Table); hp++) if (hp->Value) { q = xstrndup(hp->Value, hp->Body - hp->Value + hp->Len); if (*hp->Value == ' ' || *hp->Value == '\t') fprintf(F, "%s:%s\n", hp->Name, q); else fprintf(F, "%s: %s\n", hp->Name, q); if (FLUSH_ERROR(F)) { fclose(F); free(q); goto fail; } free(q); } for (i = 0; i < OtherCount; i++) { fprintf(F, "%s\n", OtherHeaders[i]); if (FLUSH_ERROR(F)) { fclose(F); goto fail; } } fprintf(F, "\n"); /* Write the article body. */ i = strlen(article); if (fwrite(article, 1, i, F) != (size_t)i) { fclose(F); goto fail; } /* Flush and catch any errors. */ if (fclose(F)) goto fail; /* Rename the spool file to something rnews will pick up. */ spoolfile = concatpath(SpoolDir, "XXXXXX"); fd = mkstemp(spoolfile); if (fd < 0) { syslog(L_FATAL, "can't create spool file %s %m", spoolfile); goto fail; } close(fd); if (rename(tmpspool, spoolfile) < 0) { syslog(L_FATAL, "can't rename %s %s %m", tmpspool, spoolfile); goto fail; } /* Article has been spooled. */ free(tmpspool); free(spoolfile); return NULL; fail: if (tmpspool != NULL) free(tmpspool); if (spoolfile != NULL) free(spoolfile); return CANTSPOOL; } /* ** Spool article to temp file. */ static const char * Spoolit(char *article, char *err) { return SpoolitTo(article, err, innconf->pathincoming); } static char * Towire(char *p) { char *q, *r, *s; int curlen, len = BIG_BUFFER; for (r = p, q = s = xmalloc(len); *r != '\0' ;) { curlen = q - s; if (curlen + 3 > len) { len += BIG_BUFFER; s = xrealloc(s, len); q = s + curlen; } if (*r == '\n') { if (r > p) { if (*(r - 1) != '\r') *q++ = '\r'; } else { /* This should not happen. */ free(s); return NULL; } } *q++ = *r++; } curlen = q - s; if (curlen + 1 > len) { len++; s = xrealloc(s, len); q = s + curlen; } *q = '\0'; return s; } /* ** The main function which handles POST and IHAVE. */ const char * ARTpost(char *article, char *idbuff, bool *permanent) { int i; char *p, *q; char *next; HEADER *hp; FILE *ToServer; FILE *FromServer; char buff[NNTP_MAXLEN_COMMAND + 2], frombuf[SMBUF]; char *modgroup = NULL; const char *error; char *TrackID; char *DirTrackID; FILE *ftd; /* Assume errors are permanent, until we discover otherwise. */ *permanent = true; /* Set up the other headers list. */ if (OtherHeaders == NULL) { OtherSize = HEADER_DELTA; OtherHeaders = xmalloc(OtherSize * sizeof(char *)); } /* Basic processing. */ OtherCount = 0; for (hp = Table; hp < ARRAY_END(Table); hp++) { hp->Size = strlen(hp->Name); hp->Value = hp->Body = 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 (PERMaccessconf->checkincludedtext) { if ((error = CheckIncludedText(article, i)) != NULL) return error; } /* modgroup is set when moderated newsgroups are found in the * Newsgroups: header field, and the article does not contain * an Approved: header field. * Therefore, moderation will be needed. * * Be sure to check that a Newsgroups: header field exists * because ProcessHeaders() still has not been called. It would * have rejected the message. */ if (HDR(HDR__NEWSGROUPS) != NULL) { if ((error = ValidNewsgroups(HDR(HDR__NEWSGROUPS), &modgroup)) != NULL) return error; } if ((error = ProcessHeaders(idbuff, modgroup != NULL)) != NULL) { if (modgroup != NULL) free(modgroup); return error; } if (i == 0 && HDR(HDR__CONTROL) == NULL) { if (modgroup != NULL) free(modgroup); return "Article is empty"; } strlcpy(frombuf, HDR(HDR__FROM), sizeof(frombuf)); /* Unfold the From: header field. */ for (p = frombuf; p < frombuf + sizeof(frombuf); ) if ((p = strchr(p, '\n')) == NULL) break; else *p++ = ' '; /* Try to rewrite the From: header field in a cleaner format. */ HeaderCleanFrom(frombuf); /* Now perform basic checks of the From: header field. * Pass leading '@' chars because they are not part of an address. */ p = frombuf; while (*p == '@') { p++; } p = strchr(p, '@'); if (p != NULL) { p = strrchr(p+1, '.'); if (p == NULL) { if (modgroup) free(modgroup); return "From: address not in Internet syntax"; } } else { if (modgroup) free(modgroup); return "From: address not in Internet syntax"; } if ((p = HDR(HDR__FOLLOWUPTO)) != NULL && strcmp(p, "poster") != 0 && (error = ValidNewsgroups(p, (char **)NULL)) != NULL) { if (modgroup) free(modgroup); return error; } if ((PERMaccessconf->localmaxartsize != 0) && (strlen(article) > PERMaccessconf->localmaxartsize)) { snprintf(Error, sizeof(Error), "Article is bigger than local limit of %lu bytes\n", PERMaccessconf->localmaxartsize); if (modgroup) free(modgroup); return Error; } #if defined(DO_PERL) /* Calls the Perl subroutine for headers management. * The article may be modified, and its syntax may become invalid * but well... that's the news admin choice! */ p = PERMaccessconf->nnrpdperlfilter ? HandleHeaders(article) : NULL; if (p != NULL) { char SDir[255]; if (idbuff) { if (modgroup) snprintf(idbuff, SMBUF, "(mailed to moderator for %s)", modgroup); else if (HDR(HDR__MESSAGEID) != idbuff) { strlcpy(idbuff, HDR(HDR__MESSAGEID), SMBUF); } } if (strncmp(p, "DROP", 4) == 0) { syslog(L_NOTICE, "%s post failed %s", Client.host, p); if (modgroup) free(modgroup); return NULL; } else if (strncmp(p, "SPOOL", 5) == 0) { syslog(L_NOTICE, "%s post failed %s", Client.host, p); strlcpy(SDir, innconf->pathincoming, sizeof(SDir)); if (modgroup) { free(modgroup); strlcat(SDir, "/spam/mod", sizeof(SDir)); return SpoolitTo(article, p, SDir); } else { strlcat(SDir, "/spam", sizeof(SDir)); return SpoolitTo(article, p, SDir); } } else if (strncmp(p, "CLOSE", 5) == 0) { syslog(L_NOTICE, "%s post failed %s", Client.host, p); Reply("%d NNTP server unavailable; no posting\r\n", NNTP_FAIL_TERMINATING); POSTrejected++; ExitWithStats(1, true); } else { if (modgroup) free(modgroup); return p; } } #endif /* defined(DO_PERL) */ /* Handle mailing to moderated groups. */ if (modgroup) { if (idbuff != NULL) { const char *retstr; retstr = MailArticle(modgroup, article); /* MailArticle frees modgroup. */ strlcpy (idbuff, "(mailed to moderator)", SMBUF); return retstr; } return MailArticle(modgroup, article); } if (idbuff != NULL && HDR(HDR__MESSAGEID) != idbuff) { strlcpy(idbuff, HDR(HDR__MESSAGEID), SMBUF); } if (PERMaccessconf->spoolfirst) return Spoolit(article, Error); if (Offlinepost) return Spoolit(article,Error); /* Open a local connection to the server. */ if (PERMaccessconf->nnrpdposthost != NULL) i = NNTPconnect(PERMaccessconf->nnrpdposthost, PERMaccessconf->nnrpdpostport, &FromServer, &ToServer, buff, sizeof(buff)); else { #if defined(HAVE_UNIX_DOMAIN_SOCKETS) i = NNTPlocalopen(&FromServer, &ToServer, buff, sizeof(buff)); #else i = NNTPremoteopen(innconf->port, &FromServer, &ToServer, buff, sizeof(buff)); #endif /* defined(HAVE_UNIX_DOMAIN_SOCKETS) */ } /* 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]) strlcpy(Error, buff, sizeof(Error)); else { snprintf(Error, sizeof(Error), "Can't send connect request to server, %s", strerror(errno)); } return Spoolit(article,Error); } if (Tracing) syslog(L_TRACE, "%s post_connect %s", Client.host, PERMaccessconf->nnrpdposthost ? PERMaccessconf->nnrpdposthost : "localhost"); /* The code below ignores too many return values 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, (int)sizeof buff, FromServer, ToServer); if (i == NNTP_FAIL_AUTH_NEEDED) { /* Send authorization. */ if (NNTPsendpassword(PERMaccessconf->nnrpdposthost, FromServer, ToServer) < 0) { snprintf(Error, sizeof(Error), "Can't authorize with %s", PERMaccessconf->nnrpdposthost ? PERMaccessconf->nnrpdposthost : "innd"); return Spoolit(article,Error); } i = OfferArticle(buff, (int)sizeof buff, FromServer, ToServer); } if (i != NNTP_CONT_IHAVE) { strlcpy(Error, buff, sizeof(Error)); SendQuit(FromServer, ToServer); if (i == NNTP_FAIL_IHAVE_REJECT || i == NNTP_FAIL_IHAVE_DEFER) { *permanent = false; } /* As the syntax of the IHAVE command sent by nnrpd is valid, * the only valid case of response is a refusal. */ if (i != NNTP_FAIL_IHAVE_REFUSE) return Spoolit(article, Error); return Error; } if (Tracing) syslog(L_TRACE, "%s post starting", Client.host); /* Write the headers and a blank line. */ for (hp = Table; hp < ARRAY_END(Table); hp++) if (hp->Value) { q = xstrndup(hp->Value, hp->Body - hp->Value + hp->Len); if (strchr(q, '\n') != NULL) { if ((p = Towire(q)) != NULL) { /* There is no white space, if hp->Value and hp->Body are the same. */ if (*hp->Value == ' ' || *hp->Value == '\t') fprintf(ToServer, "%s:%s\r\n", hp->Name, p); else fprintf(ToServer, "%s: %s\r\n", hp->Name, p); free(p); } } else { /* There is no white space, if hp->Value and hp->Body are the same. */ if (*hp->Value == ' ' || *hp->Value == '\t') fprintf(ToServer, "%s:%s\r\n", hp->Name, q); else fprintf(ToServer, "%s: %s\r\n", hp->Name, q); } free(q); } for (i = 0; i < OtherCount; i++) { if (strchr(OtherHeaders[i], '\n') != NULL) { if ((p = Towire(OtherHeaders[i])) != NULL) { fprintf(ToServer, "%s\r\n", p); free(p); } } else { fprintf(ToServer, "%s\r\n", OtherHeaders[i]); } } fprintf(ToServer, "\r\n"); if (FLUSH_ERROR(ToServer)) { snprintf(Error, sizeof(Error), "Can't send headers to server, %s", strerror(errno)); fclose(FromServer); 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) { snprintf(Error, sizeof(Error), "Can't send article to server, %s", strerror(errno)); fclose(FromServer); fclose(ToServer); return Spoolit(article, Error); } /* Did the server want the article? */ if ((i = atoi(buff)) != NNTP_OK_IHAVE) { strlcpy(Error, buff, sizeof(Error)); SendQuit(FromServer, ToServer); syslog(L_TRACE, "%s server rejects %s from %s", Client.host, HDR(HDR__MESSAGEID), HDR(HDR__PATH)); if (i != NNTP_FAIL_IHAVE_REJECT && i != NNTP_FAIL_IHAVE_REFUSE) return Spoolit(article, Error); if (i == NNTP_FAIL_IHAVE_REJECT || i == NNTP_FAIL_IHAVE_DEFER) { *permanent = false; } return Error; } /* Send a quit and close down. */ SendQuit(FromServer, ToServer); /* Tracking. */ if (PERMaccessconf->readertrack) { TrackID = concat(innconf->pathlog, "/trackposts/track.", HDR(HDR__MESSAGEID), (char *) 0); if ((ftd = fopen(TrackID,"w")) == NULL) { DirTrackID = concatpath(innconf->pathlog, "trackposts"); MakeDirectory(DirTrackID, false); free(DirTrackID); } if (ftd == NULL && (ftd = fopen(TrackID,"w")) == NULL) { syslog(L_ERROR, "%s (%s) open %s: %m", Client.host, Username, TrackID); free(TrackID); return NULL; } for (hp = Table; hp < ARRAY_END(Table); hp++) if (hp->Value) { q = xstrndup(hp->Value, hp->Body - hp->Value + hp->Len); if (strchr(q, '\n') != NULL) { if ((p = Towire(q)) != NULL) { /* There is no white space, if hp->Value and hp->Body are the same. */ if (*hp->Value == ' ' || *hp->Value == '\t') fprintf(ftd, "%s:%s\r\n", hp->Name, p); else fprintf(ftd, "%s: %s\r\n", hp->Name, p); free(p); } } else { /* There is no white space, if hp->Value and hp->Body are the same. */ if (*hp->Value == ' ' || *hp->Value == '\t') fprintf(ftd, "%s:%s\r\n", hp->Name, q); else fprintf(ftd, "%s: %s\r\n", hp->Name, q); } free(q); } for (i = 0 ; i < OtherCount ; i++) { if (strchr(OtherHeaders[i], '\n') != NULL) { if ((p = Towire(OtherHeaders[i])) != NULL) { fprintf(ftd, "%s\r\n", p); free(p); } } else { fprintf(ftd, "%s\r\n", OtherHeaders[i]); } } fprintf(ftd,"\r\n"); NNTPsendarticle(article, ftd, true); if (fclose(ftd) != EOF) { syslog(L_NOTICE, "%s (%s) posttrack ok %s", Client.host, Username, TrackID); if (LLOGenable) fprintf(locallog, "%s (%s) posttrack ok %s\n", Client.host, Username, TrackID); } else { syslog(L_ERROR, "%s (%s) posttrack error 2 %s", Client.host, Username, TrackID); } free(TrackID); } return NULL; } inn-2.6.4/nnrpd/group.c0000644000175200017520000002111714002373703014343 0ustar iuliusiulius/* $Id: group.c 8904 2010-01-17 19:45:19Z iulius $ ** ** Newsgroups and the active file. */ #include "config.h" #include "clibrary.h" #include "inn/innconf.h" #include "nnrpd.h" #include "inn/ov.h" /* ** Change to or list the specified newsgroup. If invalid, stay in the old ** group. ** Do not forget to free(group) before any return after "group" has been set. */ void CMDgroup(int ac, char *av[]) { ARTNUM i; int low, high; char *grplist[2]; char *group; void *handle; TOKEN token; int count; bool boolval; bool hookpresent = false; #ifdef DO_PYTHON hookpresent = PY_use_dynamic; #endif /* DO_PYTHON */ /* Parse arguments. */ if (ac == 1) { if (GRPcur == NULL) { Reply("%d No group specified\r\n", NNTP_FAIL_NO_GROUP); return; } else { group = xstrdup(GRPcur); } } else { group = xstrdup(av[1]); } /* Check whether the second argument is valid (for LISTGROUP). */ if (ac == 3 && !IsValidRange(av[2])) { Reply("%d Syntax error in range\r\n", NNTP_ERR_SYNTAX); free(group); return; } /* Check authorizations. */ if (!hookpresent && !PERMcanread) { Reply("%d Read access denied\r\n", PERMcanauthenticate ? NNTP_FAIL_AUTH_NEEDED : NNTP_ERR_ACCESS); free(group); return; } /* FIXME: Temporarily work around broken API. */ if (!OVgroupstats(group, &low, &high, &count, NULL)) { Reply("%d No such group %s\r\n", NNTP_FAIL_BAD_GROUP, group); free(group); return; } #ifdef DO_PYTHON if (PY_use_dynamic) { char *reply; /* Authorize user using Python module method dynamic. */ if (PY_dynamic(PERMuser, group, false, &reply) < 0) { syslog(L_NOTICE, "PY_dynamic(): authorization skipped due to no Python dynamic method defined"); } else { if (reply != NULL) { syslog(L_TRACE, "PY_dynamic() returned a refuse string for user %s at %s who wants to read %s: %s", PERMuser, Client.host, group, reply); Reply("%d %s\r\n", PERMcanauthenticate ? NNTP_FAIL_AUTH_NEEDED : NNTP_ERR_ACCESS, reply); free(group); free(reply); return; } } } #endif /* DO_PYTHON */ if (!hookpresent) { if (PERMspecified) { grplist[0] = group; grplist[1] = NULL; if (!PERMmatch(PERMreadlist, grplist)) { Reply("%d Read access denied\r\n", PERMcanauthenticate ? NNTP_FAIL_AUTH_NEEDED : NNTP_ERR_ACCESS); free(group); return; } } else { Reply("%d Read access denied\r\n", PERMcanauthenticate ? NNTP_FAIL_AUTH_NEEDED : NNTP_ERR_ACCESS); free(group); return; } } /* Close out any existing article, report group stats. */ ARTclose(); GRPreport(); /* These values must be changed after the Python dynamic hook and everything * that can lead to a failure of authorization. */ ARTlow = low; ARThigh = high; /* Doing a GROUP command? */ if (strcasecmp(av[0], "GROUP") == 0) { if (count == 0) { Reply("%d 0 %lu %lu %s\r\n", NNTP_OK_GROUP, ARThigh+1, ARThigh, group); } else { /* If we are an NFS reader, check the last nfsreaderdelay * articles in the group to see if they arrived in the * last nfsreaderdelay (default 60) seconds. If they did, * don't report them as we don't want them to appear too * soon. */ if (innconf->nfsreader != 0) { ARTNUM low, prev; time_t now, arrived; time(&now); /* We assume that during the last nfsreaderdelay seconds, * we did not receive more than 1 article per second. */ if (ARTlow + innconf->nfsreaderdelay > ARThigh) low = ARTlow; else low = ARThigh - innconf->nfsreaderdelay; handle = OVopensearch(group, low, ARThigh); if (!handle) { Reply("%d group disappeared\r\n", NNTP_FAIL_ACTION); free(group); return; } prev = low; while (OVsearch(handle, &i, NULL, NULL, NULL, &arrived)) { if ((time_t) (arrived + innconf->nfsreaderdelay) > now) { ARThigh = prev; /* No need to update the count since it is only * an estimate but make sure it is not too high. */ if ((unsigned int)count > ARThigh - ARTlow) count = ARThigh - ARTlow + 1; break; } prev = i; } OVclosesearch(handle); } Reply("%d %d %lu %lu %s\r\n", NNTP_OK_GROUP, count, ARTlow, ARThigh, group); } GRPcount++; ARTnumber = (count == 0 ? 0 : ARTlow); if (GRPcur) { if (strcmp(GRPcur, group) != 0) { OVctl(OVCACHEFREE, &boolval); free(GRPcur); GRPcur = xstrdup(group); } } else GRPcur = xstrdup(group); PERMgroupmadeinvalid = false; } else { /* Must be doing a LISTGROUP command. We used to just return something bland here ("Article list follows"), but reference NNTP returns the same data as GROUP does and since we have it all available it shouldn't hurt to return the same thing. */ ARTRANGE range; bool DidReply; /* Parse the range. */ if (ac == 3) { /* CMDgetrange() expects av[1] to contain the range. * It is av[2] for LISTGROUP. * We already know that GRPcur exists. */ if (!CMDgetrange(ac, av + 1, &range, &DidReply)) { if (DidReply) { free(group); return; } } } else { range.Low = ARTlow; range.High = ARThigh; } if (count == 0) { Reply("%d 0 %lu %lu %s\r\n", NNTP_OK_GROUP, ARThigh+1, ARThigh, group); Printf(".\r\n"); } else { Reply("%d %d %lu %lu %s\r\n", NNTP_OK_GROUP, count, ARTlow, ARThigh, group); /* If OVopensearch() is restricted to the range, it returns NULL * in case there isn't any article within the range. We already * know that the group exists. */ if ((handle = OVopensearch(group, range.Low, range.High)) != NULL) { while (OVsearch(handle, &i, NULL, NULL, &token, NULL)) { if (PERMaccessconf->nnrpdcheckart && !ARTinstorebytoken(token)) continue; Printf("%lu\r\n", i); } OVclosesearch(handle); } Printf(".\r\n"); } GRPcount++; ARTnumber = (count == 0 ? 0 : ARTlow); if (GRPcur) { if (strcmp(GRPcur, group) != 0) { OVctl(OVCACHEFREE, &boolval); free(GRPcur); GRPcur = xstrdup(group); } } else GRPcur = xstrdup(group); PERMgroupmadeinvalid = false; } free(group); } /* ** Report on the number of articles read in the group, and clear the count. */ void GRPreport(void) { char buff[SPOOLNAMEBUFF]; if (GRPcur) { strlcpy(buff, GRPcur, sizeof(buff)); syslog(L_NOTICE, "%s group %s %lu", Client.host, buff, GRParticles); GRParticles = 0; } } /* ** Used by ANU-News clients. */ void CMDxgtitle(int ac, char *av[]) { QIOSTATE *qp; char *line; char *p; char *q; char *grplist[2]; char save; /* Parse the arguments. */ if (ac == 1) { if (GRPcount == 0) { /* Keep the legacy response code 481 instead of 412. */ Reply("%d No group specified\r\n", NNTP_FAIL_XGTITLE); return; } p = GRPcur; } else p = av[1]; if (!PERMspecified) { Reply("%d No descriptions follow\r\n", NNTP_OK_XGTITLE); Printf(".\r\n"); return; } /* Open the file, get ready to scan. */ if ((qp = QIOopen(NEWSGROUPS)) == NULL) { syslog(L_ERROR, "%s can't open %s %m", Client.host, NEWSGROUPS); Reply("%d Can't open %s\r\n", NNTP_FAIL_XGTITLE, NEWSGROUPS); return; } Reply("%d Descriptions in form \"group description\"\r\n", NNTP_OK_XGTITLE); /* 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 (uwildmat(line, p)) { if (PERMspecified) { grplist[0] = line; grplist[1] = NULL; if (!PERMmatch(PERMreadlist, grplist)) continue; } *q = save; Printf("%s\r\n", line); } } /* Done. */ QIOclose(qp); Printf(".\r\n"); } inn-2.6.4/nnrpd/sasl.c0000644000175200017520000002576514002373703014166 0ustar iuliusiulius/* ** AUTHINFO SASL functionality. ** ** $Id: sasl.c 10117 2016-11-06 14:23:27Z iulius $ */ #include "config.h" #include "clibrary.h" #include "inn/messages.h" #include "nnrpd.h" /* Outside the ifdef so that make depend works even ifndef HAVE_OPENSSL. */ #include "inn/ov.h" #include "tls.h" #if defined(HAVE_OPENSSL) extern int tls_cipher_usebits; extern char *tls_peer_CN; #endif /* HAVE_OPENSSL */ #if defined(HAVE_OPENSSL) || defined(HAVE_SASL) extern bool encryption_layer_on; #endif /* HAVE_OPENSSL || HAVE_SASL */ #ifdef HAVE_SASL sasl_conn_t *sasl_conn = NULL; int sasl_ssf = 0; int sasl_maxout = NNTP_MAXLEN_COMMAND; sasl_callback_t sasl_callbacks[] = { /* XXX Do we want a proxy callback? */ /* XXX Add a getopt callback? */ { SASL_CB_LIST_END, NULL, NULL } }; #define BASE64_BUF_SIZE 21848 /* Per RFC 4422: (floor(n/3) + 1) * 4 where n = 16 kB = 16384 bytes. */ /* ** Create a new SASL server authentication object. */ void SASLnewserver(void) { if (sasl_conn != NULL) { sasl_dispose(&sasl_conn); sasl_conn = NULL; sasl_ssf = 0; sasl_maxout = NNTP_MAXLEN_COMMAND; } if (sasl_server_new("nntp", NULL, NULL, NULL, NULL, NULL, SASL_SUCCESS_DATA, &sasl_conn) != SASL_OK) { syslog(L_FATAL, "sasl_server_new() failed"); Reply("%d SASL server unavailable. Try later!\r\n", NNTP_FAIL_TERMINATING); ExitWithStats(1, true); } else { /* XXX Fill in SASL_IPLOCALPORT and SASL_IPREMOTEPORT. */ sasl_security_properties_t secprops; memset(&secprops, 0, sizeof(secprops)); secprops.security_flags = SASL_SEC_NOANONYMOUS; secprops.max_ssf = 256; secprops.maxbufsize = NNTP_MAXLEN_COMMAND; sasl_setprop(sasl_conn, SASL_SEC_PROPS, &secprops); #ifdef HAVE_OPENSSL /* Tell SASL about the negotiated TLS layer. */ if (encryption_layer_on) { if (sasl_setprop(sasl_conn, SASL_SSF_EXTERNAL, (sasl_ssf_t *) &tls_cipher_usebits) != SASL_OK) { syslog(L_NOTICE, "sasl_setprop() failed: TLS layer for SASL"); } if (sasl_setprop(sasl_conn, SASL_AUTH_EXTERNAL, tls_peer_CN) != SASL_OK) { syslog(L_NOTICE, "sasl_setprop() failed: TLS layer for SASL"); } } #endif } } void SASLauth(int ac, char *av[]) { const char *mech; const char *clientin = NULL; unsigned int clientinlen = 0; size_t tclientinlen = 0; const char *serverout = NULL; unsigned int serveroutlen; char base64[BASE64_BUF_SIZE+1]; const char *canon_user = NULL; const int *ssfp = NULL; const int *maxoutp; const void *property; int r = SASL_OK; int r1; bool base64error = false; if (ac < 3 || ac > 4) { /* In fact, ac > 4 here. */ Reply("%d Too many arguments\r\n", NNTP_ERR_SYNTAX); return; } mech = av[2]; if (!IsValidAlgorithm(mech)) { Reply("%d Syntax error in mechanism name\r\n", NNTP_ERR_SYNTAX); return; } /* 502 if authentication will fail. */ if (!PERMcanauthenticate) { if (PERMauthorized && !PERMneedauth) Reply("%d Already authenticated\r\n", NNTP_ERR_ACCESS); else Reply("%d Authentication will fail\r\n", NNTP_ERR_ACCESS); return; } #ifdef HAVE_OPENSSL /* Check whether STARTTLS must be used before trying to authenticate * with AUTHINFO SASL PLAIN, LOGIN or EXTERNAL. */ if (PERMcanauthenticate && !PERMcanauthenticatewithoutSSL && !encryption_layer_on && ((strcasecmp(mech, "PLAIN") == 0 || strcasecmp(mech, "LOGIN") == 0 || strcasecmp(mech, "EXTERNAL") == 0))) { Reply("%d Encryption layer required\r\n", NNTP_FAIL_PRIVACY_NEEDED); return; } #endif if (ac == 4) { /* Initial response. */ clientin = av[3]; if (strcmp(clientin, "=") == 0) { /* Zero-length initial response. */ clientin = ""; clientinlen = 0; } else { /* Decode the response. On error, SASL_CONTINUE should not be * given because we know for sure that we have already received * the whole challenge/response. Use SASL_BADPROT instead, * in order to indicate a base64-encoding error. */ r1 = sasl_decode64(clientin, strlen(clientin), base64, BASE64_BUF_SIZE, &clientinlen); clientin = base64; r = (r1 == SASL_CONTINUE ? SASL_BADPROT : r1); base64error = (r == SASL_BADPROT); } } if (r == SASL_OK) { /* Start the exchange. */ r = sasl_server_start(sasl_conn, mech, clientin, clientinlen, &serverout, &serveroutlen); } while (r == SASL_CONTINUE || (r == SASL_OK && serveroutlen != 0)) { if (serveroutlen != 0) { /* Encode the server challenge. * In sasl_encode64() calls, the fourth argument is the length * of the third including the null terminator. */ r1 = sasl_encode64(serverout, serveroutlen, base64, BASE64_BUF_SIZE+1, NULL); if (r1 != SASL_OK) r = r1; } /* Check for failure or success. */ if (r != SASL_CONTINUE) break; /* Send the challenge to the client. */ Reply("%d %s\r\n", NNTP_CONT_SASL, serveroutlen != 0 ? base64 : "="); fflush(stdout); /* Get the response from the client. */ r1 = line_read(&NNTPline, PERMaccessconf->clienttimeout, &clientin, &tclientinlen, NULL); clientinlen = tclientinlen; switch (r1) { case RTok: if (clientinlen <= BASE64_BUF_SIZE) break; /* FALLTHROUGH */ case RTlong: warn("%s response too long in AUTHINFO SASL", Client.host); Reply("%d Too long response\r\n", NNTP_FAIL_TERMINATING); ExitWithStats(1, false); break; case RTtimeout: warn("%s timeout in AUTHINFO SASL", Client.host); /* No answer. */ ExitWithStats(1, false); break; case RTeof: warn("%s EOF in AUTHINFO SASL", Client.host); Reply("%d EOF\r\n", NNTP_FAIL_TERMINATING); ExitWithStats(1, false); break; default: warn("%s internal %d in AUTHINFO SASL", Client.host, r); Reply("%d Internal error\r\n", NNTP_FAIL_TERMINATING); ExitWithStats(1, false); break; } /* Check if client cancelled. */ if (strcmp(clientin, "*") == 0) { /* Restart the SASL server in order to be able to reauthenticate. * Call that function before the reply because in case of failure, * 400 is sent. */ SASLnewserver(); Reply("%d Client cancelled authentication\r\n", NNTP_FAIL_AUTHINFO_BAD); return; } if (strcmp(clientin, "=") == 0) { /* Zero-length answer. */ clientin = ""; clientinlen = 0; } else { /* Decode the response. On error, SASL_CONTINUE should not be * given because we know for sure that we have already received * the whole challenge/response. Use SASL_BADPROT instead, * in order to indicate a base64-encoding error. */ r1 = sasl_decode64(clientin, clientinlen, base64, BASE64_BUF_SIZE, &clientinlen); clientin = base64; r = (r1 == SASL_CONTINUE ? SASL_BADPROT : r1); base64error = (r == SASL_BADPROT); } /* Do the next step. */ if (r == SASL_OK) { r = sasl_server_step(sasl_conn, clientin, clientinlen, &serverout, &serveroutlen); } } /* Fetch the username (authorization ID). */ if (r == SASL_OK) { r = sasl_getprop(sasl_conn, SASL_USERNAME, &property); canon_user = property; } /* Grab info about the negotiated layer. */ if (r == SASL_OK) { r = sasl_getprop(sasl_conn, SASL_SSF, &property); ssfp = property; } if (r == SASL_OK) { r = sasl_getprop(sasl_conn, SASL_MAXOUTBUF, &property); maxoutp = property; } if (r == SASL_OK) { /* Success! * First, save info about the negotiated security layer * for I/O functions. */ sasl_ssf = *ssfp; sasl_maxout = (*maxoutp == 0 || *maxoutp > NNTP_MAXLEN_COMMAND) ? NNTP_MAXLEN_COMMAND : *maxoutp; if (sasl_ssf > 1) { /* For the forthcoming check of the permissions the client now * has, tell the connection is encrypted, so that auth blocks * requiring the negotiation of a security layer in readers.conf * are properly taken into account. * When sasl_ssf equals 1, only data integrity is provided, without * any security. */ encryption_layer_on = true; /* Close out any existing article, report group stats. * RFC 4643 requires the reset of any knowledge about the client. */ if (GRPcur) { bool boolval; ARTclose(); GRPreport(); OVctl(OVCACHEFREE, &boolval); free(GRPcur); GRPcur = NULL; if (ARTcount) { syslog(L_NOTICE, "%s exit for AUTHINFO SASL articles %ld groups %ld", Client.host, ARTcount, GRPcount); } GRPcount = 0; PERMgroupmadeinvalid = false; /* Reset our read buffer so as to prevent plaintext * command injection. */ line_reset(&NNTPline); } } PERMgetaccess(false); strlcpy(PERMuser, canon_user, sizeof(PERMuser)); PERMgetpermissions(); PERMneedauth = false; PERMauthorized = true; PERMcanauthenticate = false; syslog(L_NOTICE, "%s user %s", Client.host, PERMuser); if (serveroutlen) { Reply("%d %s\r\n", NNTP_OK_SASL, base64); } else { Reply("%d Authentication succeeded\r\n", NNTP_OK_AUTHINFO); } } else { /* Failure. */ int resp_code; const char *errstring = sasl_errstring(r, NULL, NULL); syslog(L_NOTICE, "%s bad_auth", Client.host); switch (r) { case SASL_BADPROT: resp_code = (base64error ? NNTP_ERR_BASE64 : NNTP_FAIL_AUTHINFO_REJECT); break; case SASL_BADPARAM: case SASL_NOTDONE: resp_code = NNTP_FAIL_AUTHINFO_REJECT; break; case SASL_NOMECH: resp_code = NNTP_ERR_UNAVAILABLE; break; case SASL_ENCRYPT: resp_code = NNTP_FAIL_PRIVACY_NEEDED; break; default: resp_code = NNTP_FAIL_AUTHINFO_BAD; break; } /* Restart the SASL server in order to be able to reauthenticate. * Call that function before the reply because in case of failure, * 400 is sent. */ SASLnewserver(); Reply("%d %s\r\n", resp_code, errstring ? errstring : "Authentication failed"); } } #endif /* HAVE_SASL */ inn-2.6.4/nnrpd/track.c0000644000175200017520000000277014002373703014317 0ustar iuliusiulius/* $Id: track.c 8034 2008-09-20 07:13:18Z iulius $ ** ** User and post tracking database. */ #include "config.h" #include "clibrary.h" #include "inn/innconf.h" #include "nnrpd.h" #define MAX_LEN 180 /* ** TrackClient determines whether or not ** we are interested in tracking the activities ** of the currently connected host. We have to ** rely on an external process to set up the ** entries in the database though, which makes ** this only as reliable as the process that ** sets this up... */ /* ** Format of the input line is the following one. ** : */ int TrackClient(char *client, char *user, size_t len) { int RARTon; FILE *fd; char line[MAX_LEN],*p,*pp,*lp; char *dbfile; dbfile = concatpath(innconf->pathetc, "nnrpd.track"); RARTon=false; strlcpy(user, "unknown", len); if ((fd=fopen(dbfile,"r"))!=NULL) { while((fgets(line,(MAX_LEN - 1),fd))!=NULL) { if (line[0] == '#' || line[0] == '\n') continue; if ((p=strchr(line,' ')) != NULL) *p='\0'; if ((p=strchr(line,'\n')) != NULL) *p='\0'; if ((p=strchr(line,':')) != NULL) { *p++='\0'; } else { p=NULL; } pp=line; if ((lp=strchr(pp,'*')) != NULL) { pp=++lp; } if (strstr(client,pp)!=NULL) { RARTon=true; if (p != NULL) strlcpy(user,p,len); break; } } fclose(fd); } else { RARTon=false; syslog(L_NOTICE, "%s No logging -- can't read %s", Client.host, dbfile); } free(dbfile); return RARTon; } inn-2.6.4/authprogs/0000755000175200017520000000000014002373674013743 5ustar iuliusiuliusinn-2.6.4/authprogs/libauth.h0000644000175200017520000000257214002373703015543 0ustar iuliusiulius/* $Id: libauth.h 7183 2005-04-10 22:46:50Z rra $ ** ** Some utility functions for writing authenticators and resolvers. */ #ifndef LIBAUTH_H #define LIBAUTH_H 1 #include "config.h" #include "portable/socket.h" #include #include /* Holds the resolver information from nnrpd. */ struct res_info { char *clienthostname; char *clientip; char *clientport; char *localip; char *localport; }; /* Holds the authentication information from nnrpd. */ struct auth_info { char *username; char *password; }; BEGIN_DECLS /* Reads connection information from a file descriptor (normally stdin, when talking to nnrpd) and returns a new res_info or auth_info struct, or returns NULL on failure. Note that the fields will never be NULL; if the corresponding information is missing, it is an error (which will be logged and NULL will be returned). The client is responsible for freeing the struct and its fields; this can be done by calling the appropriate destruction function below. */ extern struct auth_info *get_auth_info(FILE *); extern struct res_info *get_res_info (FILE *); /* Free a res_info or auth_info struct. */ extern void free_auth_info(struct auth_info *); extern void free_res_info (struct res_info *); /* Return the user string to nnrpd. */ extern void print_user(const char *); END_DECLS #endif /* !LIBAUTH_H */ inn-2.6.4/authprogs/ident.c0000644000175200017520000000743414002373703015213 0ustar iuliusiulius/* $Id: ident.c 9893 2015-06-14 10:05:50Z iulius $ ** ** Ident authenticator. */ #include "config.h" #include "clibrary.h" #include #include #include #include #include "inn/messages.h" #include "inn/network.h" #include "inn/libinn.h" #include "libauth.h" #define IDENT_PORT 113 /* ** The signal handler for a timeout. Just exit with a non-zero status. */ static void timeout(int sig UNUSED) { exit(1); } int main(int argc, char *argv[]) { struct servent *s; char buf[2048]; struct res_info *res; int sock; int opt; int truncate_domain = 0; char *iter; char *p; unsigned int got; int identport; char *endstr; message_program_name = "ident"; xsignal_norestart(SIGALRM, timeout); alarm(15); s = getservbyname("ident", "tcp"); if (s == NULL) identport = IDENT_PORT; else identport = ntohs(s->s_port); while ((opt = getopt(argc, argv, "p:t")) != -1) { switch (opt) { case 'p': for (iter = optarg; *iter; iter++) if (*iter < '0' || *iter > '9') break; if (*iter) { /* not entirely numeric */ s = getservbyname(optarg, "tcp"); if (s == NULL) die("cannot getsrvbyname(%s, tcp)", optarg); identport = s->s_port; } else identport = atoi(optarg); break; case 't': truncate_domain = 1; break; } } /* Read the connection info from stdin. */ res = get_res_info(stdin); if (res == NULL) die("did not get client information from nnrpd"); /* Connect back to the client system. */ sock = network_connect_host(res->clientip, identport, res->localip, DEFAULT_TIMEOUT); if (sock < 0) { if (errno != ECONNREFUSED) sysdie("cannot connect to ident server"); else sysdie("client host does not accept ident connections"); } /* send the request out */ snprintf(buf, sizeof(buf), "%s , %s\r\n", res->clientport, res->localport); opt = xwrite(sock, buf, strlen(buf)); if (opt < 0) sysdie("cannot write to ident server"); free_res_info(res); /* get the answer back */ got = 0; do { opt = read(sock, buf+got, sizeof(buf)-got); if (opt < 0) sysdie("cannot read from ident server"); else if (!opt) die("end of file from ident server before response"); while (opt--) if (buf[got] != '\n') got++; } while (buf[got] != '\n'); buf[got] = '\0'; if (got > 0 && buf[got-1] == '\r') buf[got-1] = '\0'; /* buf now contains the entire ident response. */ if (!(iter = strchr(buf, ':'))) /* malformed response */ die("malformed response \"%s\" from ident server", buf); iter++; while (*iter && ISWHITE(*iter)) iter++; endstr = iter; while (*endstr && *endstr != ':' && !ISWHITE(*endstr)) endstr++; if (!*endstr) /* malformed response */ die("malformed response \"%s\" from ident server", buf); if (*endstr != ':') { *endstr++ = '\0'; while (*endstr != ':') endstr++; } *endstr = '\0'; if (strcmp(iter, "ERROR") == 0) die("ident server reported an error"); else if (strcmp(iter, "USERID") != 0) die("ident server returned \"%s\", not USERID", iter); /* skip the operating system */ if (!(iter = strchr(endstr+1, ':'))) exit(1); /* everything else is username */ iter++; while (*iter && ISWHITE(*iter)) iter++; if (*iter == '\0' || *iter == '[') /* null, or encrypted response */ die("ident response is null or encrypted"); for (p = iter; *p != '\0' && !ISWHITE(*p); p++) ; *p = '\0'; if (truncate_domain) { p = strchr(iter, '@'); if (p != NULL) *p = '\0'; } print_user(iter); exit(0); } inn-2.6.4/authprogs/auth_krb5.c0000644000175200017520000001607114002373703015771 0ustar iuliusiulius/* $Id: auth_krb5.c 10266 2018-03-10 14:59:27Z iulius $ ** ** Check an username and password against Kerberos. ** ** Based on nnrpkrb5auth by Christopher P. Lindsey ** See ** ** This program takes a username and password pair from nnrpd and checks ** their validity against a Kerberos KDC by attempting to obtain a TGT. ** With the -i command line option, appends / to ** the username prior to authentication. ** ** Special thanks to Von Welch for giving me the initial ** code on which the Kerberos V authentication is based many years ago, and ** for introducing me to Kerberos back in '96. ** ** Also, thanks to Graeme Mathieson for his inspiration ** through the pamckpasswd program. */ #include "config.h" #include "clibrary.h" #include "libauth.h" #if defined(HAVE_KRB5_H) # include #elif defined(HAVE_KERBEROSV5_KRB5_H) # include #else # include #endif /* Figure out what header files to include for error reporting. */ #if !defined(HAVE_KRB5_GET_ERROR_MESSAGE) && !defined(HAVE_KRB5_GET_ERR_TEXT) # if !defined(HAVE_KRB5_GET_ERROR_STRING) # if defined(HAVE_IBM_SVC_KRB5_SVC_H) # include # elif defined(HAVE_ET_COM_ERR_H) # include # elif defined(HAVE_KERBEROSV5_COM_ERR_H) # include # else # include # endif # endif #endif #include "inn/messages.h" #include "inn/libinn.h" #include "inn/xmalloc.h" /* * This string is returned for unknown error messages. We use a static * variable so that we can be sure not to free it. */ #if !defined(HAVE_KRB5_GET_ERROR_MESSAGE) \ || !defined(HAVE_KRB5_FREE_ERROR_MESSAGE) static const char error_unknown[] = "unknown error"; #endif #ifndef HAVE_KRB5_GET_ERROR_MESSAGE /* * Given a Kerberos error code, return the corresponding error. Prefer the * Kerberos interface if available since it will provide context-specific * error information, whereas the error_message() call will only provide a * fixed message. */ const char * krb5_get_error_message(krb5_context ctx UNUSED, krb5_error_code code UNUSED) { const char *msg; # if defined(HAVE_KRB5_GET_ERROR_STRING) msg = krb5_get_error_string(ctx); # elif defined(HAVE_KRB5_GET_ERR_TEXT) msg = krb5_get_err_text(ctx, code); # elif defined(HAVE_KRB5_SVC_GET_MSG) krb5_svc_get_msg(code, (char **) &msg); # else msg = error_message(code); # endif if (msg == NULL) return error_unknown; else return msg; } #endif /* !HAVE_KRB5_GET_ERROR_MESSAGE */ #ifndef HAVE_KRB5_FREE_ERROR_MESSAGE /* * Free an error string if necessary. If we returned a static string, make * sure we don't free it. * * This code assumes that the set of implementations that have * krb5_free_error_message is a subset of those with krb5_get_error_message. * If this assumption ever breaks, we may call the wrong free function. */ void krb5_free_error_message(krb5_context ctx UNUSED, const char *msg) { if (msg == error_unknown) return; # if defined(HAVE_KRB5_GET_ERROR_STRING) krb5_free_error_string(ctx, (char *) msg); # elif defined(HAVE_KRB5_SVC_GET_MSG) krb5_free_string(ctx, (char *) msg); # endif } #endif /* !HAVE_KRB5_FREE_ERROR_MESSAGE */ /* ** Report a Kerberos error to standard error. */ static void __attribute__((__format__(printf, 3, 4))) warn_krb5(krb5_context ctx, krb5_error_code code, const char *format, ...) { const char *k5_msg; char *message; va_list args; k5_msg = krb5_get_error_message(ctx, code); va_start(args, format); xvasprintf(&message, format, args); va_end(args); if (k5_msg == NULL) warn("%s", message); else warn("%s: %s", message, k5_msg); free(message); if (k5_msg != NULL) krb5_free_error_message(ctx, k5_msg); } /* ** Check the username and password by attempting to get a TGT. Returns 1 on ** success and 0 on failure. */ static int krb5_check_password(const char *principal, const char *password) { krb5_error_code code; krb5_context ctx; krb5_creds creds; krb5_principal princ = NULL; krb5_get_init_creds_opt opts; bool creds_valid = false; int result = 0; code = krb5_init_context(&ctx); if (code != 0) { warn_krb5(NULL, code, "cannot initialize Kerberos"); return 0; } code = krb5_parse_name(ctx, principal, &princ); if (code != 0) { warn_krb5(ctx, code, "cannot parse principal %.100s", principal); goto cleanup; } memset(&opts, 0, sizeof(opts)); krb5_get_init_creds_opt_init(&opts); krb5_get_init_creds_opt_set_forwardable(&opts, 0); krb5_get_init_creds_opt_set_proxiable(&opts, 0); code = krb5_get_init_creds_password(ctx, &creds, princ, (char *) password, NULL, NULL, 0, NULL, &opts); if (code == 0) { krb5_verify_init_creds_opt vopts; creds_valid = true; memset(&opts, 0, sizeof(vopts)); krb5_verify_init_creds_opt_init(&vopts); code = krb5_verify_init_creds(ctx, &creds, princ, NULL, NULL, &vopts); } if (code == 0) result = 1; else { switch (code) { case KRB5KRB_AP_ERR_BAD_INTEGRITY: warn("bad password for %.100s", principal); break; case KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN: warn("unknown user %.100s", principal); break; default: warn_krb5(ctx, code, "Kerberos authentication for %.100s failed", principal); break; } } cleanup: if (creds_valid) krb5_free_cred_contents(ctx, &creds); if (princ != NULL) krb5_free_principal(ctx, princ); krb5_free_context(ctx); return result; } int main (int argc, char *argv[]) { struct auth_info *authinfo; char *new_user; message_program_name = "auth_krb5"; /* Retrieve the username and passwd from nnrpd. */ authinfo = get_auth_info(stdin); /* Must have a username/password, and no '@' in the address. @ checking is there to prevent authentication against another Kerberos realm; there should be a -r command line option to make this check unnecessary in the future. */ if (authinfo == NULL) die("no authentication information from nnrpd"); if (authinfo->username[0] == '\0') die("null username"); if (strchr(authinfo->username, '@') != NULL) die("username contains @, not allowed"); /* May need to prepend instance name if -i option was given. */ if (argc > 1) { if (argc == 3 && strcmp(argv[1], "-i") == 0) { xasprintf(&new_user, "%s/%s", authinfo->username, argv[2]); free(authinfo->username); authinfo->username = new_user; } else { die("error parsing command-line options"); } } if (krb5_check_password(authinfo->username, authinfo->password)) { print_user(authinfo->username); exit(0); } else { die("failure validating password"); } } inn-2.6.4/authprogs/domain.c0000644000175200017520000000264514002373703015356 0ustar iuliusiulius/* $Id: domain.c 7585 2006-11-21 09:37:51Z eagle $ ** ** Domain authenticator. ** ** Compares the domain of the client connection to the first argument given ** on the command line, and returns the host portion of the connecting host ** as the user if it matches. */ #include "config.h" #include "clibrary.h" #include "inn/messages.h" #include "inn/libinn.h" #include "libauth.h" int main(int argc, char *argv[]) { char *p, *host; struct res_info *res; if (argc != 2) die("Usage: domain "); message_program_name = "domain"; /* Read the connection information from stdin. */ res = get_res_info(stdin); if (res == NULL) die("did not get ClientHost data from nnrpd"); host = res->clienthostname; /* Check the host against the provided domain. Allow the domain to be specified both with and without a leading period; if without, make sure that there is a period right before where it matches in the host. */ p = strstr(host, argv[1]); if (p == host) die("host %s matches the domain exactly", host); if (p == NULL || (argv[1][0] != '.' && p != host && *(p - 1) != '.')) die("host %s didn't match domain %s", host, argv[1]); /* Peel off the portion of the host before where the provided domain matches and return it as the user. */ if (argv[1][0] != '.') p--; *p = '\0'; print_user(host); return 0; } inn-2.6.4/authprogs/Makefile0000644000175200017520000001314614002373703015401 0ustar iuliusiulius## $Id: Makefile 10100 2016-11-04 22:24:26Z iulius $ include ../Makefile.global top = .. CFLAGS = $(GCFLAGS) ALL = ckpasswd domain ident radius $(KRB5_AUTH) LIBAUTH = libauth.o SOURCES = auth_krb5.c ckpasswd.c domain.c ident.c libauth.c radius.c all: $(ALL) warnings: $(MAKE) COPT='$(WARNINGS)' all install: all if [ x"$(KRB5_AUTH)" != x ] ; then \ $(LI_XPUB) auth_krb5 $(D)$(PATHAUTHPASSWD)/auth_krb5 ; \ fi for F in ckpasswd radius ; do \ $(LI_XPUB) $$F $D$(PATHAUTHPASSWD)/$$F ; \ done for F in domain ident ; do \ $(LI_XPUB) $$F $D$(PATHAUTHRESOLV)/$$F ; \ done bootstrap: clean clobber distclean maintclean: rm -f *.o $(ALL) rm -rf .libs profiled: $(MAKEPROFILING) all ## Compilation rules. LINK = $(LIBLD) $(LDFLAGS) -o $@ AUTH_LIBS = $(LIBAUTH) $(LIBINN) $(LIBS) CK_LIBS = $(CRYPT_LIBS) $(SHADOW_LIBS) $(PAM_LIBS) $(DBM_LIBS) auth_krb5: auth_krb5.o $(LIBAUTH) $(LIBINN) $(LINK) auth_krb5.o $(KRB5_LDFLAGS) $(KRB5_LIBS) $(AUTH_LIBS) ckpasswd: ckpasswd.o $(LIBAUTH) $(LIBINN) $(LINK) ckpasswd.o $(CK_LIBS) $(AUTH_LIBS) domain: domain.o $(LIBAUTH) $(LIBINN) $(LINK) domain.o $(AUTH_LIBS) ident: ident.o $(LIBAUTH) $(LIBINN) $(LINK) ident.o $(AUTH_LIBS) radius: radius.o $(LIBAUTH) $(LIBINN) $(LINK) radius.o $(AUTH_LIBS) auth_krb5.o: auth_krb5.c $(CC) $(CFLAGS) $(KRB5_CPPFLAGS) -c auth_krb5.c ckpasswd.o: ckpasswd.c $(CC) $(CFLAGS) $(DBM_CPPFLAGS) -c ckpasswd.c $(LIBINN): ; (cd ../lib ; $(MAKE)) $(LIBSTORAGE): ; (cd ../storage ; $(MAKE)) $(LIBAUTH): libauth.h libauth.c ## Dependencies. Default list, below, is probably good enough. depend: Makefile $(SOURCES) $(MAKEDEPEND) '$(CFLAGS)' $(SOURCES) # DO NOT DELETE THIS LINE -- make depend depends on it. auth_krb5.o: auth_krb5.c ../include/config.h ../include/inn/defines.h \ ../include/inn/system.h ../include/inn/macros.h \ ../include/inn/portable-macros.h ../include/inn/portable-stdbool.h \ ../include/inn/defines.h ../include/inn/options.h ../include/clibrary.h \ ../include/config.h ../include/inn/macros.h \ ../include/portable/stdbool.h libauth.h ../include/portable/socket.h \ ../include/portable/macros.h ../include/portable/getaddrinfo.h \ ../include/portable/getnameinfo.h ../include/inn/messages.h \ ../include/inn/libinn.h ../include/inn/concat.h ../include/inn/xmalloc.h \ ../include/inn/xwrite.h ckpasswd.o: ckpasswd.c ../include/config.h ../include/inn/defines.h \ ../include/inn/system.h ../include/inn/macros.h \ ../include/inn/portable-macros.h ../include/inn/portable-stdbool.h \ ../include/inn/defines.h ../include/inn/options.h ../include/clibrary.h \ ../include/config.h ../include/inn/macros.h \ ../include/portable/stdbool.h ../include/inn/messages.h \ ../include/inn/qio.h ../include/inn/vector.h ../include/inn/libinn.h \ ../include/inn/concat.h ../include/inn/xmalloc.h ../include/inn/xwrite.h \ libauth.h ../include/portable/socket.h ../include/portable/macros.h \ ../include/portable/getaddrinfo.h ../include/portable/getnameinfo.h domain.o: domain.c ../include/config.h ../include/inn/defines.h \ ../include/inn/system.h ../include/inn/macros.h \ ../include/inn/portable-macros.h ../include/inn/portable-stdbool.h \ ../include/inn/defines.h ../include/inn/options.h ../include/clibrary.h \ ../include/config.h ../include/inn/macros.h \ ../include/portable/stdbool.h ../include/inn/messages.h \ ../include/inn/libinn.h ../include/inn/concat.h ../include/inn/xmalloc.h \ ../include/inn/xwrite.h libauth.h ../include/portable/socket.h \ ../include/portable/macros.h ../include/portable/getaddrinfo.h \ ../include/portable/getnameinfo.h ident.o: ident.c ../include/config.h ../include/inn/defines.h \ ../include/inn/system.h ../include/inn/macros.h \ ../include/inn/portable-macros.h ../include/inn/portable-stdbool.h \ ../include/inn/defines.h ../include/inn/options.h ../include/clibrary.h \ ../include/config.h ../include/inn/macros.h \ ../include/portable/stdbool.h ../include/inn/messages.h \ ../include/inn/network.h ../include/inn/portable-socket.h \ ../include/inn/portable-getaddrinfo.h \ ../include/inn/portable-getnameinfo.h ../include/inn/libinn.h \ ../include/inn/concat.h ../include/inn/xmalloc.h ../include/inn/xwrite.h \ libauth.h ../include/portable/socket.h libauth.o: libauth.c ../include/config.h ../include/inn/defines.h \ ../include/inn/system.h ../include/inn/macros.h \ ../include/inn/portable-macros.h ../include/inn/portable-stdbool.h \ ../include/inn/defines.h ../include/inn/options.h ../include/clibrary.h \ ../include/config.h ../include/inn/macros.h \ ../include/portable/stdbool.h ../include/portable/socket.h \ ../include/portable/macros.h ../include/portable/getaddrinfo.h \ ../include/portable/getnameinfo.h ../include/inn/messages.h libauth.h \ ../include/inn/libinn.h ../include/inn/concat.h ../include/inn/xmalloc.h \ ../include/inn/xwrite.h radius.o: radius.c ../include/config.h ../include/inn/defines.h \ ../include/inn/system.h ../include/inn/macros.h \ ../include/inn/portable-macros.h ../include/inn/portable-stdbool.h \ ../include/inn/defines.h ../include/inn/options.h ../include/clibrary.h \ ../include/config.h ../include/inn/macros.h \ ../include/portable/stdbool.h ../include/inn/innconf.h \ ../include/inn/md5.h ../include/inn/messages.h ../include/inn/libinn.h \ ../include/inn/concat.h ../include/inn/xmalloc.h ../include/inn/xwrite.h \ ../include/inn/nntp.h ../include/inn/paths.h ../include/conffile.h \ ../include/portable/macros.h libauth.h ../include/portable/socket.h \ ../include/portable/macros.h ../include/portable/getaddrinfo.h \ ../include/portable/getnameinfo.h inn-2.6.4/authprogs/libauth.c0000644000175200017520000001200514002373703015526 0ustar iuliusiulius/* $Id: libauth.c 7585 2006-11-21 09:37:51Z eagle $ ** ** Common code for authenticators and resolvers. ** ** Collects common code to read information from nnrpd that should be done ** the same for all authenticators, and common code to get information about ** the incoming connection. */ #include "config.h" #include "clibrary.h" #include "portable/socket.h" #include "inn/messages.h" #include "libauth.h" #include "inn/libinn.h" #define NAMESTR "ClientAuthname: " #define PASSSTR "ClientPassword: " #define CLIHOST "ClientHost: " #define CLIIP "ClientIP: " #define CLIPORT "ClientPort: " #define LOCIP "LocalIP: " #define LOCPORT "LocalPort: " /* ** Main loop. If res != NULL, expects to get resolver info from nnrpd, and ** writes it into the struct. If auth != NULL, expects to get authentication ** info from nnrpd, and writes it into the struct. */ static bool get_connection_info(FILE *stream, struct res_info *res, struct auth_info *auth) { char buff[SMBUF]; size_t length; /* Zero fields first (anything remaining NULL after is missing data). */ if (res != NULL) { res->clienthostname = NULL; res->clientip = NULL; res->clientport = NULL; res->localip = NULL; res->localport = NULL; } if (auth != NULL) { auth->username = NULL; auth->password = NULL; } /* Read input from nnrpd a line at a time, stripping \r\n. */ while (fgets(buff, sizeof(buff), stream) != NULL) { length = strlen(buff); if (length == 0 || buff[length - 1] != '\n') return false; buff[length - 1] = '\0'; if (length > 1 && buff[length - 2] == '\r') buff[length - 2] = '\0'; /* Parse */ if (strncmp(buff, ".", 2) == 0) break; else if (auth != NULL && strncmp(buff, NAMESTR, strlen(NAMESTR)) == 0) auth->username = xstrdup(buff + strlen(NAMESTR)); else if (auth != NULL && strncmp(buff, PASSSTR, strlen(PASSSTR)) == 0) auth->password = xstrdup(buff + strlen(PASSSTR)); else if (res != NULL && strncmp(buff, CLIHOST, strlen(CLIHOST)) == 0) res->clienthostname = xstrdup(buff + strlen(CLIHOST)); else if (res != NULL && strncmp(buff, CLIIP, strlen(CLIIP)) == 0) res->clientip = xstrdup(buff + strlen(CLIIP)); else if (res != NULL && strncmp(buff, CLIPORT, strlen(CLIPORT)) == 0) res->clientport = xstrdup(buff + strlen(CLIPORT)); else if (res != NULL && strncmp(buff, LOCIP, strlen(LOCIP)) == 0) res->localip = xstrdup(buff + strlen(LOCIP)); else if (res != NULL && strncmp(buff, LOCPORT, strlen(LOCPORT)) == 0) res->localport = xstrdup(buff + strlen(LOCPORT)); else { debug("libauth: unexpected data from nnrpd: \"%s\"", buff); } } /* If some field is missing, free the rest and error out. */ if (auth != NULL && (auth->username == NULL || auth->password == NULL)) { warn("libauth: requested authenticator data not sent by nnrpd"); return false; } if (res != NULL && (res->clienthostname == NULL || res->clientip == NULL || res->clientport == NULL || res->localip == NULL || res->localport == NULL)) { warn("libauth: requested resolver data not sent by nnrpd"); return false; } return true; } /* ** Free a struct res_info, including all of its members. */ void free_res_info(struct res_info *res) { if (res == NULL) return; if (res->clientip != NULL) free(res->clientip); if (res->clientport != NULL) free(res->clientport); if (res->localip != NULL) free(res->localip); if (res->localport != NULL) free(res->localport); if (res->clienthostname != NULL) free(res->clienthostname); free(res); } /* ** Free a struct auth_info, including all of its members. */ void free_auth_info(struct auth_info *auth) { if (auth == NULL) return; if (auth->username != NULL) free(auth->username); if (auth->password != NULL) free(auth->password); free(auth); } /* ** Read resolver information from nnrpd, returning an allocated struct on ** success. */ struct res_info * get_res_info(FILE *stream) { struct res_info *res = xmalloc(sizeof(struct res_info)); if (get_connection_info(stream, res, NULL)) return res; free_res_info(res); return NULL; } /* ** Read authenticator information from nnrpd, returning an allocated struct ** on success. */ struct auth_info * get_auth_info(FILE *stream) { struct auth_info *auth = xmalloc(sizeof(struct auth_info)); if (get_connection_info(stream, NULL, auth)) return auth; free_auth_info(auth); return NULL; } /* ** Print the User: result on standard output in the format expected by ** nnrpd. The string passed in should be exactly the user, with no ** extraneous leading or trailing whitespace. */ void print_user(const char *user) { printf("User:%s\r\n", user); } inn-2.6.4/authprogs/radius.c0000644000175200017520000004044014002373703015371 0ustar iuliusiulius/* $Id: radius.c 10001 2016-04-03 13:34:28Z iulius $ ** ** Authenticate a user against a remote radius server. */ #include "config.h" #include "clibrary.h" #include #include #include #include #include #ifdef HAVE_SYS_TIME_H # include #endif #include /* Needed on AIX 4.1 to get fd_set and friends. */ #if HAVE_SYS_SELECT_H # include #endif #include "inn/innconf.h" #include "inn/md5.h" #include "inn/messages.h" #include "inn/libinn.h" #include "inn/nntp.h" #include "inn/paths.h" #include "conffile.h" #include "libauth.h" #define RADIUS_LOCAL_PORT NNTP_PORT #define AUTH_VECTOR_LEN 16 typedef struct _auth_req { unsigned char code; unsigned char id; unsigned short length; unsigned char vector[AUTH_VECTOR_LEN]; unsigned char data[NNTP_MAXLEN_COMMAND*2]; int datalen; } auth_req; typedef struct _rad_config_t { char *secret; /* pseudo encryption thingy secret that radius uses */ char *radhost; /* parameters for talking to the remote radius sever */ int radport; char *lochost; int locport; char *prefix, *suffix; /* futz with the username, if necessary */ int ignore_source; struct _rad_config_t *next; /* point to any additional servers */ } rad_config_t; typedef struct _sending_t { auth_req req; int reqlen; struct sockaddr_in sinr; struct _sending_t *next; } sending_t; #define RADlbrace 1 #define RADrbrace 2 #define RADserver 10 #define RADhost 11 #define RADsecret 12 #define RADport 13 #define RADlochost 14 #define RADlocport 15 #define RADprefix 16 #define RADsuffix 17 #define RADsource 18 static CONFTOKEN radtoks[] = { { RADlbrace, (char *) "{" }, { RADrbrace, (char *) "}" }, { RADserver, (char *) "server" }, { RADhost, (char *) "radhost:" }, { RADsecret, (char *) "secret:" }, { RADport, (char *) "radport:" }, { RADlochost, (char *) "lochost:" }, { RADlocport, (char *) "locport:" }, { RADprefix, (char *) "prefix:" }, { RADsuffix, (char *) "suffix:" }, { RADsource, (char *) "ignore-source:" }, { 0, NULL } }; static rad_config_t *get_radconf(void) { rad_config_t *new; new = xcalloc(1, sizeof(rad_config_t)); new->next = NULL; return new; } static int read_config(char *authfile, rad_config_t *radconf) { int inbrace; rad_config_t *radconfig=NULL; CONFFILE *file; CONFTOKEN *token; int type; char *iter; if ((file = CONFfopen(authfile)) == NULL) sysdie("cannot open config file %s", authfile); inbrace = 0; while ((token = CONFgettoken(radtoks, file)) != NULL) { if (!inbrace) { if (token->type != RADserver) die("expected server keyword on line %d", file->lineno); if ((token = CONFgettoken(0, file)) == NULL) die("expected server name on line %d", file->lineno); if ((token = CONFgettoken(radtoks, file)) == NULL || token->type != RADlbrace) die("expected { on line %d", file->lineno); inbrace = 1; if (radconfig == NULL) radconfig = radconf; else { radconfig->next = get_radconf(); radconfig = radconfig->next; } } else { type = token->type; if (type == RADrbrace) inbrace = 0; else { if ((token = CONFgettoken(0, file)) == NULL) die("keyword with no value on line %d", file->lineno); iter = token->name; /* what are we setting? */ switch(type) { case RADsecret: if (radconfig->secret) continue; radconfig->secret = xstrdup(iter); break; case RADhost: if (radconfig->radhost) continue; radconfig->radhost = xstrdup(iter); break; case RADport: if (radconfig->radport) continue; radconfig->radport = atoi(iter); break; case RADlochost: if (radconfig->lochost) continue; radconfig->lochost = xstrdup(iter); break; case RADlocport: if (radconfig->locport) continue; radconfig->locport = atoi(iter); break; case RADprefix: if (radconfig->prefix) continue; radconfig->prefix = xstrdup(iter); break; case RADsuffix: if (radconfig->suffix) continue; radconfig->suffix = xstrdup(iter); break; case RADsource: if (!strcasecmp(iter, "true")) radconfig->ignore_source = 1; else if (!strcasecmp(iter, "false")) radconfig->ignore_source = 0; else die("expected true or false after ignore-source on line %d", file->lineno); break; default: die("unknown keyword on line %d", file->lineno); } } } } CONFfclose(file); if (!radconf->radhost) die("no radius host specified"); else if (!radconf->secret) die("no shared secret with radius host specified"); return(0); } #define PW_AUTH_UDP_PORT 1645 #define PW_AUTHENTICATION_REQUEST 1 #define PW_AUTHENTICATION_ACK 2 #define PW_AUTHENTICATION_REJECT 3 #define PW_USER_NAME 1 #define PW_PASSWORD 2 #define PW_SERVICE_TYPE 6 #define PW_SERVICE_AUTH_ONLY 8 #define RAD_NAS_IP_ADDRESS 4 /* IP address */ #define RAD_NAS_PORT 5 /* Integer */ static void req_copyto (auth_req *to, sending_t *from) { *to = from->req; } static void req_copyfrom (sending_t *to, auth_req *from) { to->req = *from; } static int rad_auth(rad_config_t *radconfig, char *uname, char *pass) { auth_req req; int i, j, jlen, passstart; unsigned char secbuf[128]; char hostname[SMBUF]; unsigned char digest[MD5_DIGESTSIZE]; struct timeval seed; struct sockaddr_in sinl; int sock; struct hostent *hent; int passlen; time_t now, end; struct timeval tmout; int got; fd_set rdfds; uint32_t nvalue; socklen_t slen; int authtries= 3; /* number of times to try reaching the radius server */ rad_config_t *config; sending_t *reqtop, *sreq, *new; int done; /* set up the linked list */ config = radconfig; if (config == NULL) { warn("no configuration file"); return(-2); } else { /* setting sreq to NULL guarantees reqtop will be properly set later */ sreq = NULL; reqtop = NULL; } while (config != NULL){ new = xmalloc(sizeof(sending_t)); new->next = NULL; if (sreq == NULL){ reqtop = new; sreq = new; } else { sreq->next = new; sreq = sreq->next; } req_copyto(&req, sreq); /* first, build the sockaddrs */ memset(&sinl, '\0', sizeof(sinl)); memset(&sreq->sinr, '\0', sizeof(sreq->sinr)); sinl.sin_family = AF_INET; sreq->sinr.sin_family = AF_INET; if (config->lochost == NULL) { if (gethostname(hostname, sizeof(hostname)) != 0) { syswarn("cannot get local hostname"); return(-2); } config->lochost = xstrdup(hostname); } if (config->lochost) { if (inet_aton(config->lochost, &sinl.sin_addr) != 1) { if ((hent = gethostbyname(config->lochost)) == NULL) { warn("cannot gethostbyname lochost %s", config->lochost); return(-2); } memcpy(&sinl.sin_addr.s_addr, hent->h_addr, sizeof(struct in_addr)); } } if (inet_aton(config->radhost, &sreq->sinr.sin_addr) != 1) { if ((hent = gethostbyname(config->radhost)) == NULL) { warn("cannot gethostbyname radhost %s", config->radhost); return(-2); } memcpy(&sreq->sinr.sin_addr.s_addr, hent->h_addr_list[0], sizeof(struct in_addr)); } if (config->radport) sreq->sinr.sin_port = htons(config->radport); else sreq->sinr.sin_port = htons(PW_AUTH_UDP_PORT); /* seed the random number generator for the auth vector */ gettimeofday(&seed, 0); srandom((unsigned) seed.tv_sec+seed.tv_usec); /* build the visible part of the auth vector randomly */ for (i = 0; i < AUTH_VECTOR_LEN; i++) req.vector[i] = random() % 256; strlcpy((char *) secbuf, config->secret, sizeof(secbuf)); memcpy(secbuf+strlen(config->secret), req.vector, AUTH_VECTOR_LEN); md5_hash(secbuf, strlen(config->secret)+AUTH_VECTOR_LEN, digest); /* fill in the auth_req data */ req.code = PW_AUTHENTICATION_REQUEST; req.id = 0; /* bracket the username in the configured prefix/suffix */ req.data[0] = PW_USER_NAME; req.data[1] = 2; req.data[2] = '\0'; if (config->prefix) { req.data[1] += strlen(config->prefix); strlcat((char *) &req.data[2], config->prefix, sizeof(req.data) - 2); } req.data[1] += strlen(uname); strlcat((char *)&req.data[2], uname, sizeof(req.data) - 2); if (!strchr(uname, '@') && config->suffix) { req.data[1] += strlen(config->suffix); strlcat((char *)&req.data[2], config->suffix, sizeof(req.data) - 2); } req.datalen = req.data[1]; /* set the password */ passstart = req.datalen; req.data[req.datalen] = PW_PASSWORD; /* Null pad the password */ passlen = (strlen(pass) + 15) / 16; passlen *= 16; req.data[req.datalen+1] = passlen+2; strlcpy((char *)&req.data[req.datalen+2], pass, sizeof(req.data) - req.datalen - 2); passlen -= strlen(pass); while (passlen--) req.data[req.datalen+passlen+2+strlen(pass)] = '\0'; req.datalen += req.data[req.datalen+1]; /* Add NAS_PORT and NAS_IP_ADDRESS into request */ if ((nvalue = config->locport) == 0) nvalue = RADIUS_LOCAL_PORT; req.data[req.datalen++] = RAD_NAS_PORT; req.data[req.datalen++] = sizeof(nvalue) + 2; nvalue = htonl(nvalue); memcpy(req.data + req.datalen, &nvalue, sizeof(nvalue)); req.datalen += sizeof(nvalue); req.data[req.datalen++] = RAD_NAS_IP_ADDRESS; req.data[req.datalen++] = sizeof(struct in_addr) + 2; memcpy(req.data + req.datalen, &sinl.sin_addr.s_addr, sizeof(struct in_addr)); req.datalen += sizeof(struct in_addr); /* we're only doing authentication */ req.data[req.datalen] = PW_SERVICE_TYPE; req.data[req.datalen+1] = 6; req.data[req.datalen+2] = (PW_SERVICE_AUTH_ONLY >> 24) & 0x000000ff; req.data[req.datalen+3] = (PW_SERVICE_AUTH_ONLY >> 16) & 0x000000ff; req.data[req.datalen+4] = (PW_SERVICE_AUTH_ONLY >> 8) & 0x000000ff; req.data[req.datalen+5] = PW_SERVICE_AUTH_ONLY & 0x000000ff; req.datalen += req.data[req.datalen+1]; /* filled in the data, now we know what the actual length is. */ req.length = 4+AUTH_VECTOR_LEN+req.datalen; /* "encrypt" the password */ for (i = 0; i < req.data[passstart+1]-2; i += sizeof(HASH)) { jlen = sizeof(HASH); if (req.data[passstart+1]-(unsigned)i-2 < sizeof(HASH)) jlen = req.data[passstart+1]-i-2; for (j = 0; j < jlen; j++) req.data[passstart+2+i+j] ^= digest[j]; if (jlen == sizeof(HASH)) { /* Recalculate the digest from the HASHed previous */ strlcpy((char *) secbuf, config->secret, sizeof(secbuf)); memcpy(secbuf+strlen(config->secret), &req.data[passstart+2+i], sizeof(HASH)); md5_hash(secbuf, strlen(config->secret)+sizeof(HASH), digest); } } sreq->reqlen = req.length; req.length = htons(req.length); req_copyfrom(sreq, &req); /* Go to the next record in the list */ config = config->next; } /* YAYY! The auth_req is ready to go! Build the reply socket and send out * the message. */ /* now, build the sockets */ if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { syswarn("cannot build reply socket"); return(-1); } if (bind(sock, (struct sockaddr*) &sinl, sizeof(sinl)) < 0) { syswarn("cannot bind reply socket"); close(sock); return(-1); } for(done = 0; authtries > 0 && !done; authtries--) { for (config = radconfig, sreq = reqtop; sreq != NULL && !done; config = config->next, sreq = sreq->next){ req_copyto(&req, sreq); /* send out the packet and wait for reply. */ if (sendto(sock, (char *)&req, sreq->reqlen, 0, (struct sockaddr*) &sreq->sinr, sizeof (struct sockaddr_in)) < 0) { syswarn("cannot send auth_reg"); close(sock); return(-1); } /* wait 5 seconds maximum for a radius reply. */ now = time(0); end = now+5; tmout.tv_sec = 6; tmout.tv_usec = 0; FD_ZERO(&rdfds); /* store the old vector to verify next checksum */ memcpy(secbuf+sizeof(req.vector), req.vector, sizeof(req.vector)); FD_SET(sock, &rdfds); got = select(sock+1, &rdfds, 0, 0, &tmout); if (got < 0) { syswarn("cannot not select"); break; } else if (got == 0) { /* timer ran out */ now = time(0); tmout.tv_sec = end - now + 1; tmout.tv_usec = 0; warn("timeout talking to remote radius server %s:%d", inet_ntoa(sreq->sinr.sin_addr), ntohs(sreq->sinr.sin_port)); continue; } slen = sizeof(sinl); if ((jlen = recvfrom(sock, (char *)&req, sizeof(req)-sizeof(int), 0, (struct sockaddr*) &sinl, &slen)) < 0) { syswarn("cannot recvfrom"); break; } if (!config->ignore_source) { if (sinl.sin_addr.s_addr != sreq->sinr.sin_addr.s_addr || (sinl.sin_port != sreq->sinr.sin_port)) { warn("received unexpected UDP packet from %s:%d", inet_ntoa(sinl.sin_addr), ntohs(sinl.sin_port)); continue; } } sreq->reqlen = ntohs(req.length); if (jlen < 4+AUTH_VECTOR_LEN || jlen != sreq->reqlen) { warn("received badly-sized packet"); continue; } /* verify the checksum */ memcpy(((char*)&req)+sreq->reqlen, config->secret, strlen(config->secret)); memcpy(secbuf, req.vector, sizeof(req.vector)); memcpy(req.vector, secbuf+sizeof(req.vector), sizeof(req.vector)); md5_hash((unsigned char *)&req, strlen(config->secret)+sreq->reqlen, digest); if (memcmp(digest, secbuf, sizeof(HASH)) != 0) { warn("checksum didn't match"); continue; } /* FINALLY! Got back a known-good packet. See if we're in. */ close(sock); done = 1; req_copyfrom(sreq, &req); return (req.code == PW_AUTHENTICATION_ACK) ? 0 : -1; } } if (authtries == 0) warn("cannot talk to any remote radius servers"); return(-2); } #define RAD_HAVE_HOST 1 #define RAD_HAVE_PORT 2 #define RAD_HAVE_PREFIX 4 #define RAD_HAVE_SUFFIX 8 #define RAD_HAVE_LOCHOST 16 #define RAD_HAVE_LOCPORT 32 int main(int argc, char *argv[]) { int opt; int havefile, haveother; struct auth_info *authinfo; rad_config_t radconfig; int retval; char *radius_config; message_program_name = "radius"; if (!innconf_read(NULL)) exit(1); memset(&radconfig, '\0', sizeof(rad_config_t)); haveother = havefile = 0; while ((opt = getopt(argc, argv, "f:h")) != -1) { switch (opt) { case 'f': if (haveother) die("-f flag after another flag"); if (!havefile) { /* override the standard config completely if the user * specifies an alternate config file */ memset(&radconfig, '\0', sizeof(rad_config_t)); havefile = 1; } read_config(optarg, &radconfig); break; case 'h': printf("Usage: radius [-f config]\n"); exit(0); } } if (argc != optind) exit(2); if (!havefile) { radius_config = concatpath(innconf->pathetc, INN_PATH_RADIUS_CONFIG); read_config(radius_config, &radconfig); free(radius_config); } authinfo = get_auth_info(stdin); if (authinfo == NULL) die("failed getting auth info"); if (authinfo->username[0] == '\0') die("empty username"); /* got username and password, check that they're valid */ retval = rad_auth(&radconfig, authinfo->username, authinfo->password); if (retval == -1) die("user %s password doesn't match", authinfo->username); else if (retval == -2) /* couldn't talk to the radius server.. output logged above. */ exit(1); else if (retval != 0) die("unexpected return code from authentication function: %d", retval); /* radius password matches! */ print_user(authinfo->username); exit(0); } inn-2.6.4/authprogs/ckpasswd.c0000644000175200017520000002651414002373703015727 0ustar iuliusiulius/* $Id: ckpasswd.c 9586 2013-12-14 20:09:55Z iulius $ ** ** The default username/password authenticator. ** ** This program is intended to be run by nnrpd and handle usernames and ** passwords. It can authenticate against a regular flat file (the type ** managed by htpasswd), a DBM file, the system password file or shadow file, ** or PAM. */ #include "config.h" #include "clibrary.h" #include "inn/messages.h" #include "inn/qio.h" #include "inn/vector.h" #include "inn/libinn.h" #include "libauth.h" #if HAVE_CRYPT_H # include #endif #include #include #include /* ** If compiling with Berkeley DB, use its ndbm compatibility layer ** in preference to other libraries. */ #if defined(HAVE_DBM) || defined(HAVE_BDB_NDBM) # if HAVE_BDB_NDBM # define DB_DBM_HSEARCH 1 # include # elif HAVE_NDBM_H # include # elif HAVE_DB1_NDBM_H # include # elif HAVE_GDBM_SLASH_NDBM_H # include # elif HAVE_GDBM_HYPHEN_NDBM_H # include # endif # define OPT_DBM "d:" #else # define OPT_DBM "" #endif #if HAVE_GETSPNAM # include # define OPT_SHADOW "s" #else # define OPT_SHADOW "" #endif #if HAVE_PAM # if HAVE_SECURITY_PAM_APPL_H # include # else # include # endif #endif /* ** The PAM conversation function. ** ** Since we already have all the information and can't ask the user ** questions, we can't quite follow the real PAM protocol. Instead, we just ** return the password in response to every question that PAM asks. There ** appears to be no generic way to determine whether the message in question ** is indeed asking for the password.... ** ** This function allocates an array of struct pam_response to return to the ** PAM libraries that's never freed. For this program, this isn't much of an ** issue, since it will likely only be called once and then the program will ** exit. This function uses malloc and strdup instead of xmalloc and xstrdup ** intentionally so that the PAM conversation will be closed cleanly if we ** run out of memory rather than simply terminated. ** ** appdata_ptr contains the password we were given. */ #if HAVE_PAM static int pass_conv(int num_msg, PAM_CONST struct pam_message **msgm UNUSED, struct pam_response **response, void *appdata_ptr) { int i; *response = malloc(num_msg * sizeof(struct pam_response)); if (*response == NULL) return PAM_CONV_ERR; for (i = 0; i < num_msg; i++) { (*response)[i].resp = strdup((char *)appdata_ptr); (*response)[i].resp_retcode = 0; } return PAM_SUCCESS; } #endif /* HAVE_PAM */ /* ** Authenticate a user via PAM. ** ** Attempts to authenticate a user with PAM, returning true if the user ** successfully authenticates and false otherwise. Note that this function ** doesn't attempt to handle any remapping of the authenticated user by the ** PAM stack, but just assumes that the authenticated user was the same as ** the username given. ** ** Right now, all failures are handled via die. This may be worth revisiting ** in case we want to try other authentication methods if this fails for a ** reason other than the system not having PAM support. */ #if !HAVE_PAM static bool auth_pam(char *username UNUSED, char *password UNUSED) { return false; } #else static bool auth_pam(const char *username, char *password) { pam_handle_t *pamh; struct pam_conv conv; int status; conv.conv = pass_conv; conv.appdata_ptr = password; status = pam_start("nnrpd", username, &conv, &pamh); if (status != PAM_SUCCESS) die("pam_start failed: %s", pam_strerror(pamh, status)); status = pam_authenticate(pamh, PAM_SILENT); if (status != PAM_SUCCESS) die("pam_authenticate failed: %s", pam_strerror(pamh, status)); status = pam_acct_mgmt(pamh, PAM_SILENT); if (status != PAM_SUCCESS) die("pam_acct_mgmt failed: %s", pam_strerror(pamh, status)); status = pam_end(pamh, status); if (status != PAM_SUCCESS) die("pam_end failed: %s", pam_strerror(pamh, status)); /* If we get to here, the user successfully authenticated. */ return true; } #endif /* HAVE_PAM */ /* ** Try to get a password out of a dbm file. The dbm file should have the ** username for the key and the crypted password as the value. The crypted ** password, if found, is returned as a newly allocated string; otherwise, ** NULL is returned. */ #if !(defined(HAVE_DBM) || defined(HAVE_BDB_NDBM)) static char * password_dbm(char *user UNUSED, const char *file UNUSED) { return NULL; } #else static char * password_dbm(char *name, const char *file) { datum key, value; DBM *database; char *password; database = dbm_open(file, O_RDONLY, 0600); if (database == NULL) return NULL; key.dptr = name; key.dsize = strlen(name); value = dbm_fetch(database, key); if (value.dptr == NULL) { dbm_close(database); return NULL; } password = xmalloc(value.dsize + 1); strlcpy(password, value.dptr, value.dsize + 1); dbm_close(database); return password; } #endif /* HAVE_DBM || HAVE_BDB_NDBM */ /* ** Try to get a password out of the system /etc/shadow file. The crypted ** password, if found, is returned as a newly allocated string; otherwise, ** NULL is returned. */ #if !HAVE_GETSPNAM static char * password_shadow(const char *user UNUSED) { return NULL; } #else static char * password_shadow(const char *user) { struct spwd *spwd; spwd = getspnam(user); if (spwd != NULL) return xstrdup(spwd->sp_pwdp); return NULL; } #endif /* HAVE_GETSPNAM */ /* ** Try to get a password out of a file. The crypted password, if found, is ** returned as a newly allocated string; otherwise, NULL is returned. */ static char * password_file(const char *username, const char *file) { QIOSTATE *qp; char *line, *password; struct cvector *info = NULL; qp = QIOopen(file); if (qp == NULL) return NULL; for (line = QIOread(qp); line != NULL; line = QIOread(qp)) { if (*line == '#' || *line == '\n') continue; info = cvector_split(line, ':', info); if (info->count < 2 || strcmp(info->strings[0], username) != 0) continue; password = xstrdup(info->strings[1]); QIOclose(qp); cvector_free(info); return password; } if (QIOtoolong(qp)) die("line too long in %s", file); if (QIOerror(qp)) sysdie("error reading %s", file); QIOclose(qp); cvector_free(info); return NULL; } /* ** Try to get a password out of the system password file. The crypted ** password, if found, is returned as a newly allocated string; otherwise, ** NULL is returned. */ static char * password_system(const char *username) { struct passwd *pwd; pwd = getpwnam(username); if (pwd != NULL) return xstrdup(pwd->pw_passwd); return NULL; } /* ** Try to get the name of a user's primary group out of the system group ** file. The group, if found, is returned as a newly allocated string; ** otherwise, NULL is returned. If the username is not found, NULL is ** returned. */ static char * group_system(const char *username) { struct passwd *pwd; struct group *gr; pwd = getpwnam(username); if (pwd == NULL) return NULL; gr = getgrgid(pwd->pw_gid); if (gr == NULL) return NULL; return xstrdup(gr->gr_name); } /* ** Output username (and group, if desired) in correct return format. */ static void output_user(const char *username, bool wantgroup) { if (wantgroup) { char *group = group_system(username); if (group == NULL) die("group info for user %s not available", username); printf("User:%s@%s\r\n", username, group); } else print_user(username); } /* ** Main routine. ** ** We handle the variences between systems with #if blocks above, so that ** this code can look fairly clean. */ int main(int argc, char *argv[]) { enum authtype { AUTH_NONE, AUTH_SHADOW, AUTH_FILE, AUTH_DBM }; int opt; enum authtype type = AUTH_NONE; bool wantgroup = false; const char *filename = NULL; struct auth_info *authinfo = NULL; char *password = NULL; message_program_name = "ckpasswd"; while ((opt = getopt(argc, argv, "gf:u:p:" OPT_DBM OPT_SHADOW)) != -1) { switch (opt) { case 'g': if (type == AUTH_DBM || type == AUTH_FILE) die("-g option is incompatible with -d or -f"); wantgroup = true; break; case 'd': if (type != AUTH_NONE) die("only one of -s, -f, or -d allowed"); if (wantgroup) die("-g option is incompatible with -d or -f"); type = AUTH_DBM; filename = optarg; break; case 'f': if (type != AUTH_NONE) die("only one of -s, -f, or -d allowed"); if (wantgroup) die("-g option is incompatible with -d or -f"); type = AUTH_FILE; filename = optarg; break; case 's': if (type != AUTH_NONE) die("only one of -s, -f, or -d allowed"); type = AUTH_SHADOW; break; case 'u': if (authinfo == NULL) { authinfo = xmalloc(sizeof(struct auth_info)); authinfo->password = NULL; } authinfo->username = optarg; break; case 'p': if (authinfo == NULL) { authinfo = xmalloc(sizeof(struct auth_info)); authinfo->username = NULL; } authinfo->password = optarg; break; default: exit(1); } } if (argc != optind) die("extra arguments given"); if (authinfo != NULL && authinfo->username == NULL) die("-u option is required if -p option is given"); if (authinfo != NULL && authinfo->password == NULL) die("-p option is required if -u option is given"); /* Unless a username or password was given on the command line, assume we're being run by nnrpd. */ if (authinfo == NULL) authinfo = get_auth_info(stdin); if (authinfo == NULL) die("no authentication information from nnrpd"); if (authinfo->username[0] == '\0') die("null username"); /* Run the appropriate authentication routines. */ switch (type) { case AUTH_SHADOW: password = password_shadow(authinfo->username); if (password == NULL) password = password_system(authinfo->username); break; case AUTH_FILE: password = password_file(authinfo->username, filename); break; case AUTH_DBM: password = password_dbm(authinfo->username, filename); break; case AUTH_NONE: if (auth_pam(authinfo->username, authinfo->password)) { output_user(authinfo->username, wantgroup); exit(0); } password = password_system(authinfo->username); break; } if (password == NULL) die("user %s unknown", authinfo->username); if (strcmp(password, crypt(authinfo->password, password)) != 0) die("invalid password for user %s", authinfo->username); /* The password matched. */ output_user(authinfo->username, wantgroup); exit(0); } inn-2.6.4/contrib/0000755000175200017520000000000014002373675013370 5ustar iuliusiuliusinn-2.6.4/contrib/stathist.in0000644000175200017520000000344014002373703015554 0ustar iuliusiulius#!/usr/bin/perl -w # Parse log files created by innd history profiler # 2001/01/29 - Fabien Tassin use strict; use FileHandle; my $file = shift || "stathist.log"; if ($file eq '-h' || $file eq '--help') { print "Usage: stathist [logfile]\n"; exit 0; } sub parse { my $file = shift; my $f = new FileHandle $file; unless (defined $f) { print STDERR "Can't open file: $!\n"; return {}; } my $data = {}; my $begin = 1; my @stack = (); while (defined (my $line = <$f>)) { next if $begin && $line !~ / HIS(havearticle|write|setup) begin/; $begin = 0; chomp $line; my @c = split /[\[\]\(\) ]+/, $line; ($c[4] eq 'begin') && do { push @stack, $c[3]; my $d = $data; for my $l (@stack) { unless (defined $$d{$l}) { $$d{$l}{'min'} = 1E10; $$d{$l}{'total'} = $$d{$l}{'count'} = $$d{$l}{'max'} = 0; } $d = $$d{$l} } } || ($c[4] eq 'end') && do { my $d = $data; for my $l (@stack) { $d = $$d{$l}; } $$d{'count'}++; $$d{'total'} += $c[5]; $$d{'min'} = $c[5] if $$d{'min'} > $c[5]; $$d{'max'} = $c[5] if $$d{'max'} < $c[5]; pop @stack; }; } $f->close; $data; } sub report { my $data = shift; my $inc = shift; unless (defined $inc) { printf "%-16s %10s %14s %10s %10s %10s\n\n", "Function", "Invoked", "Total(s)", "Min(ms)", "Avg(ms)", "Max(ms)"; $inc = 0; } for my $key (sort keys %$data) { next unless $key =~ m/^HIS/; printf "%-16s %10d %14.6f %10.3f %10.3f %10.3f\n", (' ' x $inc) . $key, $$data{$key}{'count'}, $$data{$key}{'total'}, $$data{$key}{'min'} * 1000, $$data{$key}{'total'} / $$data{$key}{'count'} * 1000, $$data{$key}{'max'} * 1000; &report($$data{$key}, $inc + 1) } } my $data = &parse($file); &report($data); inn-2.6.4/contrib/authmysql.config0000644000175200017520000000104014002373703016571 0ustar iuliusiulius# Config for authmysql.pl # Format # Label:Column # Needed labels are User, Pass, DB, HOST, usercol, passcol and groupcol # The Column refers to either the detalis needed to connect to the # MySQL database or the column for the table. DB:blah # the database to connect to HOST:localhost # which host it resides on TABLE:passwd # the table to query against User:foo # who to connect as Pass:bar # pass for above usercol:username # column which containts the username passcol:password # column which includes unix crypt style password inn-2.6.4/contrib/mm_ckpasswd0000755000175200017520000000432414002373703015621 0ustar iuliusiulius#!/usr/bin/env python # P@draigBrady.com # # This is a ckpasswd equivalent that verifies user passwords against the # passwords stored in a Mailman list configuration file. It allows users # to access newsgroups with the same password as they use to access their # Mailman configuration. # # To use this program, it needs to run as the Mailman user, and therefore # may have to be run from a wrapper. Other than that, use it like ckpasswd # in a readers.conf file as an auth parameter, passing it the configuration # file for the list as its only parameter. # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the Free # Software Foundation; either version 2 of the License, or (at your option) # any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # # You should have received a copy of the GNU General Public License along # with this program; if not, write to the Free Software Foundation, # Inc., 675 Mass Ave, Cambridge, MA 02139, USA. """Reads username and password from stdin, and database to use as first parameter. and is meant to be used like ckpasswd is. returns: 0 success 1 bad username &/or password 2 other errors""" import sys import marshal import string import os os.setgid(41) try: filename = sys.argv[1] except IndexError: sys.stderr.write("Usage: " + sys.argv[0] + " /path/to/config.db\n") sys.exit(2) fp = open(filename) d = marshal.load(fp) passwords=d['passwords'] fp.close() username="" password="" while 1: line=sys.stdin.readline() if line == '': break try: name, value = map(string.strip,line.split(':')) if name == "ClientAuthname": username=value if name == "ClientPassword": password=value except: pass if not username or not password: sys.exit(2) auth=0 try: if passwords[username] == password: auth=1 except: pass if auth==1: print "User:%s" % username sys.exit(0) else: sys.exit(1) inn-2.6.4/contrib/nnrp.access2readers.conf.in0000644000175200017520000000717014002373703020506 0ustar iuliusiulius#! /usr/bin/perl -w ## $Id: nnrp.access2readers.conf.in 9772 2014-12-16 20:46:02Z iulius $ ## ## Convert an old-style nnrp.access file to readers.conf format. ## (readers.conf replaced nnrp.access, starting with INN 2.3.0.) ## ## Written by Jeffrey M. Vinocur . ## ## This work is hereby placed in the public domain by its author. use strict; my ($src, $passwd, $dst, $debug); if (@ARGV == 1) { $src = shift; $passwd = 'passwd'; $debug = 1; } elsif (@ARGV == 3) { ($src, $passwd, $dst) = @ARGV; $debug = 0; } else { usage(); } my ($address, $access, $user, $pass, $groups); my ($noauth, $shadow); my %passwords; my @badsyntax; my @duplicates; my $OUT; open(SRC, $src) or die "Could not open $src: $!\n"; if ($debug) { $OUT = \*STDOUT; } else { open(DST, ">$dst") or die "Could not open $dst: $!\n"; $OUT = \*DST; } while () { chomp; # Keep comments and blank lines. if (/^\s*$/) { print $OUT "\n"; next; } if (/(\#.*)/) { print $OUT "$1\n"; } s/\s*\#.*//; next if /^$/; # TODO - The following syntax is currently not recognized: # host:/path/to/another/file # %DEFINE0:bar.* # bar.foo.net:RP:::%0 ($address, $access, $user, $pass, $groups) = split /:/; unless (defined $groups) { push (@badsyntax, $.); next; } # If there is whitespace in user/pass, access is disabled. $noauth = ($user =~ /\s/ or $pass =~ /\s/) ? 1 : 0; # If user is '+', then authentication is against /etc/shadow. $shadow = ($user eq '+') ? 1 : 0; $user = '' if ($noauth or $shadow); # Only keep R, P, N, and L for the access rights. $access =~ s/[^RPNL]//g; unless ($user eq '') { push (@duplicates, $.) if defined ($passwords{$user}); $passwords{$user} = $pass; } print $OUT "auth \"$address\" {\n"; print $OUT " hosts: \"$address\"\n"; print $OUT " key: \"line$.\"\n"; print $OUT " auth: \"ckpasswd -f $passwd\"\n" unless $user eq ''; print $OUT " auth: \"ckpasswd -s\"\n" if $shadow; print $OUT " default: \"\"\n" if $user eq '' and not $shadow; print $OUT "}\n"; print $OUT "access \"$address\" {\n"; print $OUT " key: \"line$.\"\n"; print $OUT " newsgroups: \"$groups\"\n"; print $OUT " access: \"$access\"\n"; print $OUT " users: \"$user\"\n" unless $user eq ''; print $OUT " reject_with: \"Access disabled.\"\n" if $noauth; print $OUT "}\n\n"; } close SRC; srand($$^time); if (!$debug) { close $OUT; open(PASSWD, ">$passwd") or die "Could not open $passwd: $!\n"; $OUT = \*PASSWD; } while (my ($user, $pass) = each %passwords) { $pass = crypt($pass, seedchar().seedchar()); print $OUT "$user:$pass\n"; } close PASSWD unless $debug; print STDERR "\nHad trouble with syntax on line", @badsyntax > 1 ? 's ' : ' ', join(", ", @badsyntax), ".\n" if @badsyntax; print STDERR "\nFound username duplication on line", @duplicates > 1 ? 's ' : ' ', join(", ", @duplicates), ".\n" if @duplicates; sub seedchar { # From Randal Schwarz. ('a'..'z','A'..'Z','0'..'9','.','/')[rand(64)]; } sub usage { print STDERR << "__END__"; Usage: $0 [ ] Use $0 to convert an old-style nnrp.access file to readers.conf format. All unique user/password pairs from the nnrp.access file are placed in the passwd file (in format suitable for ckpasswd). If the second and third arguments are missing, everything is printed instead to stdout for examination purposes. __END__ exit 1; } inn-2.6.4/contrib/auth_pass.README0000644000175200017520000000707714002373703016241 0ustar iuliusiuliusThis directory contains sample authorization programs for use with the AUTHINFO GENERIC command in nnrpd. The first program in here is from Doug Needham. I have successfully tested this program when connecting to nnrpd by hand, but I've not taken the time to figure out how to get my newsreader to use AUTHINFO GENERIC. There is no Makefile here and no serious testing of it, so it's not integrated. If you have success using it and care to share what you've done. Please drop me a note (). Thanks. Notes: * AUTHINFO GENERIC is currently deprecated in favour of AUTHINFO USER/PASS and AUTHINFO SASL, as described in RFC 4643. * In case you write to , please CC too. --------------------------------------------------------------------------- Replied: Fri, 26 Jul 1996 19:29:17 +0200 Replied: Douglas Wade Needham Received: by gw.home.vix.com id UAA05867; Thu, 25 Jul 1996 20:45:27 -0700 (PDT) Received: (from dneedham@localhost) by dneedham.inhouse.compuserve.com (8.7.4/8.6.9) id XAA21103; Thu, 25 Jul 1996 23:45:25 -0400 (EDT) From: Douglas Wade Needham Message-Id: <199607260345.XAA21103@dneedham.inhouse.compuserve.com> Subject: A sample program for authinfo generic (for inn 1.5) To: inn-workers@vix.com (INN Gurus/Workers) Date: Thu, 25 Jul 1996 23:45:25 -0400 (EDT) Cc: inn@isc.org, brister@vix.com (James A. Brister) X-Mailer: ELM [version 2.4 PL25] MIME-Version: 1.0 Content-Type: multipart/mixed; boundary=%#%record%#% Status: U --%#%record%#% Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 7bit Content-Length: 1894 Hi folks... Finally started to get some time to clear some things from my todo list...Here is a sample program which can be used by "authinfo generic" to validate a user against the password file on the news host. While not a great example, it does demonstrate how you can write an authentication program. All I ask is that credit be given. A couple of notes that I have found out about these programs for those of you who may be interested in writing your own... 1) These programs have stdin and stdout connected all the way back to the reader, so they can carry on a dialog in whatever fashion they want to with the user's news reader. This can include passing Kerberos tickets, encrypted or hashed passwords, or doing a challenge-response type session for authenticating the user rather than passing the password in clear-text across the network. 2) Regardless of the outcome, the authentication program must send NNRPD a record such as is found in nnrp.access by writing it to stderr. 3) Successful authentication is indicated by a zero exit status, and unsuccessful authentication is indicated by a non-zero exit status. 4) Need I say it (again)...these programs can be a security hole unless care is taken to avoid SUID programs and those that transmit/receive passwords in the clear (especially those that use login passwords). We should give some thought to doing a similiar program for Kerberos authentication (what sort of instance should we use???) and other authentication methods such as Compuserve's Distributed Authentication (guess I should do this one once the standard is finialized with the IETF 8) ). Also, a question for the list as a whole... what readers easily support authinfo generic (including running a program at the reader's end to do things like challenge-response)??? Well...here it is...enjoy 8)... - doug #### See auth_pass.c ##### inn-2.6.4/contrib/README0000644000175200017520000001401214002373703014236 0ustar iuliusiuliusThis directory contains unsupported contributions to INN. Most of these programs are of interest to a limited set of sites, require some manual modifications to make work, and/or are separately maintained independent of INN. Programs in here may or may not have been tested on the latest version of INN, so keep that in mind when trying them out. The INN developers may not be able to answer bug reports for these utilities; it's best to send them to the original author. Volunteers who would like to take particularly useful applications in this directory and make them suitable for inclusion in INN proper are heartily encouraged, but discuss this on . Sometimes there's a reason why this hasn't already been done or something specific that's needed before they can be included. Type "make " to build any of the following programs and then copy the binary to somewhere on your PATH to use it. For details on what each program does, see below, as well as the comments at the beginning of each file (if any). In addition to these files, also see the contrib section of the INN FTP site at for more software designed to work with INN. ------------------------- analyze-traffic.pl Analyzes which newsgroups are receiving the most traffic and which peer is most responsible for each high-traffic group. archivegz A compressing version of archive, writing out .gz files instead of plain text files. May not work with the storage API without some changes to use sm. authmysql An authenticator that checks a username and password against a MySQL database. Could also be easily modified to check against any other type of database that Perl's DBI module can talk to. auth_pass A sample authorization program for use with the (deprecated) AUTHINFO GENERIC command in nnrpd. backlogstat Prints informations about the current state of innfeed's backlog, if any. cleannewsgroups Performs various cleanups on the newsgroups file. count_overview.pl Counts the groups in a bunch of Xref records. delayer Sits in a data stream and delays it by some constant period of time. Mostly useful for delaying innfeed feeds to allow cancels a chance to remove articles before innfeed sends them to your peers. See the beginning of the file for an example of how to use it. expirectl Automatically builds expire.ctl based on current available disk space and a template, adjusting the expiration times of groups based on a weight and the available space. Uses a template expire.ctl.ctl file; see the end of expirectl.c for a sample. findreadgroups Scans the news log files and generates a file giving readership counts by newsgroup. Used by makeexpctl and makestorconf. fixhist Performs various cleanups and sanity checks on the history database. innconfcheck Merges your inn.conf settings with the inn.conf man page to make it easier to be sure that your settings match what you want. Edit this script to add the correct paths to the man page; see the comments at the beginning of this script. innreport-filter.xslt Copies individual sections from innreport's HTML files. makeexpctl Generates an expire.ctl based on what newsgroups are actually read. Uses data generated by findreadgroups. This script will require editing before being usable for your server. makestorconf Generates a storage.conf file putting frequently read newsgroups into timecaf rather than CNFS. Uses data gefnerated by findreadgroups. This script will require editing before being usable for your server. mkbuf Creates a CNFS cycbuff; see the comments at the beginning of this script. mlockfile Locks files given on the command line into memory using mlock (only tested on Solaris). Useful primarily for locking the history files (history.hash and history.index) into memory on a system with sufficient memory to speed history lookups in innd. This seems to help some systems quite a lot and others not at all. mm_ckpasswd A ckpasswd replacement that checks user passwords against a Mailman list configuration database. See the comments at the top of the script for information on how to use it. newsresp Opens an NNTP channel to a server and takes a peek at various response times. Can check the round-trip time and the history lookup time. See the comments at the beginning of the source for more details. nnrp.access2readers.conf Converts an old-style nnrp.access file to readers.conf format. (readers.conf replaced nnrp.access, starting with INN 2.3.0.) pullart Attempts to pull news articles out of CNFS cycbuffs. Useful for emergency recoveries. reset-cnfs Clears a CNFS cycbuff; see the comments at the beginning of this script. respool Takes a list of tokens on stdin and respools them, by retrieving the article, storing it again, and then calling SMcancel on the previous instance of the article. Note that after running this program, you'd need to rebuild the history and overview, since it doesn't update either. sample.init.script Tries to increase the file descriptor limits to the maximum allowed by the system since INN and related programs can be file descriptor hogs. It then starts INN. sample.init.systemd Sample systemd-style init script for INN. stathist Parses and summarizes the log files created by the history profiling code. thdexpire A dynamic expire daemon for timehash and timecaf spools. It should be started along with innd and periodically looks if news spool space is getting tight, and then frees space by removing articles until enough is free. It is an adjunct to (not a replacement for) INN's expire program. tunefeed Given two active files, attempts to produce a good set of wildmat patterns for newsfeeds to minimize the number of rejects. For full documentation, run "perldoc tunefeed". inn-2.6.4/contrib/cleannewsgroups.in0000644000175200017520000000300214002373703017122 0ustar iuliusiulius#! /usr/bin/perl -w # fixscript will replace this line with code to load INN::Config # This script cleans the newsgroups file: # * Groups no longer in the active file are removed. # * Duplicate entries are removed. The last of a set of duplicates # is the one retained. That way, you could simply append the # new/revised entries from a docheckgroups run and then this script # will remove the old ones. # * Groups with no description are removed. # * Groups matching the $remove regexp are removed. $remove=''; # $remove='^alt\.'; open ACT, $INN::Config::active or die "Can't open $INN::Config::active: $!\n"; while() { ($group) = split; $act{$group} = 1 unless($remove ne "" && $group =~ /$remove/o); } close ACT; open NG, $INN::Config::newsgroups or die "Can't open $INN::Config::newsgroups: $!\n"; while() { chomp; ($group, $desc) = split /\s+/,$_,2; next unless(defined $act{$group}); next if(!defined $desc); next if($desc =~ /^[?\s]*$/); next if($desc =~ /^no desc(ription)?(\.)?$/i); $hist{$group} = $desc; } close NG; open NG, ">$INN::Config::newsgroups.new" or die "Can't open $INN::Config::newsgroups.new for write: $!\n"; foreach $group (sort keys %act) { if(defined $hist{$group}) { print NG "$group\t$hist{$group}\n" or die "Can't write: $!\n"; } } close NG or die "Can't close: $!\n"; rename "$INN::Config::newsgroups.new", $INN::Config::newsgroups or die "Can't rename $INN::Config::newsgroups.new to $INN::Config::newsgroups: $!\n"; inn-2.6.4/contrib/count_overview.pl0000755000175200017520000000110314002373703016771 0ustar iuliusiulius#!/usr/local/bin/perl # # count_overview.pl: Count the groups in a bunch of xref records. while (<>) { chop; @xreflist = split(/\t/); # split apart record $_ = $xreflist[$#xreflist]; # xref is last. @xreflist = reverse(split(/ /)); #break part xref line. pop @xreflist; # get rid xref header pop @xreflist; while ($current = pop @xreflist) { ($current) = split(/:/,$current); #get newsgroup name $groups{$current}++; #tally } } # display accumulated groups and counts. foreach $current (sort keys %groups) { printf "%-50s\t%5d\n", $current, $groups{$current}; } inn-2.6.4/contrib/makestorconf.in0000644000175200017520000000222214002373703016401 0ustar iuliusiulius#! /usr/bin/perl -w # fixscript will replace this line with code to load INN::Config # Create storage.conf script based on recently read articles. $readfile="$INN::Config::pathdb/readgroups"; $outfile="$INN::Config::pathdb/storage.conf"; outloop: for ($level=9 ; $level >= 2; --$level) { # clear groups hash. foreach $i (keys %groups) { delete $groups{$i}; } if (open(RDF, "$INN::Config::sort $readfile|")) { while () { chop; next if (/^group/); # bogus @foo=split(/ /); # foo[0] should be group, foo[1] lastreadtime @bar=split(/\./,$foo[0]); if ( $level >= scalar @bar) { $grf = join(".", @bar); } else { $grf=join(".", @bar[0..($level-1)]) . ".*"; } $groups{$grf} = 1; } close(RDF); } $grlist = join(",",keys(%groups)); last outloop if (length($grlist) < 2048); } open(OUT, ">$outfile") || die "cant open $outfile"; #open(OUT, ">/dev/tty"); print OUT <<"EOF" ; method cnfs { newsgroups: control,control.* class: 1 options: MINI } method timecaf { newsgroups: $grlist class: 1 } method cnfs { newsgroups: * options: MONGO class: 0 } EOF close(OUT); exit(0); inn-2.6.4/contrib/respool.c0000644000175200017520000000447514002373703015221 0ustar iuliusiulius/* ** Refile articles into the storage manager under the current storage.conf ** rules, deleting articles from their old place in the spool. ** Written 10-09-99 by rmtodd@servalan.servalan.com ** ** Note that history and overview will have to be rebuilt for the moved ** articles to be visible after they're moved. */ /* include foo needed by libinn/storage manager */ #include "config.h" #include "clibrary.h" #include #include "inn/innconf.h" #include "inn/qio.h" #include "inn/libinn.h" #include "inn/paths.h" #include "inn/storage.h" char *ME; static void ProcessLine(char *line) { char *tokenptr; int len; ARTHANDLE *art; ARTHANDLE newart = ARTHANDLE_INITIALIZER; TOKEN token, newtoken; char *arttmp; tokenptr = line; /* zap newline at end of tokenptr, if present. */ len = strlen(tokenptr); if (tokenptr[len-1] == '\n') { tokenptr[len-1] = '\0'; } if (!IsToken(tokenptr)) { fprintf(stderr, "%s: bad token format %s\n", ME, tokenptr); return; } token = TextToToken(tokenptr); if ((art = SMretrieve(token, RETR_ALL)) == NULL) return; len = art->len; arttmp = xmalloc(len); memcpy(arttmp, art->data, len); SMfreearticle(art); if (!SMcancel(token)) { fprintf(stderr, "%s: cant cancel %s:%s\n", ME, tokenptr, SMerrorstr); return; } newart.data = arttmp; newart.len = len; newart.arrived = (time_t) 0; /* set current time */ newart.token = (TOKEN *)NULL; newtoken = SMstore(newart); if (newtoken.type == TOKEN_EMPTY) { fprintf(stderr, "%s: cant store article:%s\n", ME, SMerrorstr); return; } free(arttmp); printf("refiled %s ",TokenToText(token)); printf("to %s\n", TokenToText(newtoken)); return; } int main(int argc UNUSED, char *argv[]) { bool one = true; char buff[SMBUF]; ME = argv[0]; if (!innconf_read(NULL)) exit(1); if (!SMsetup(SM_PREOPEN, &one) || !SMsetup(SM_RDWR, (void *)&one)) { fprintf(stderr, "can't init storage manager"); exit(1); } if (!SMinit()) { fprintf(stderr, "Can't init storage manager: %s", SMerrorstr); } while (fgets(buff, SMBUF, stdin)) { ProcessLine(buff); } printf("\nYou will now need to rebuild history and overview for the moved" "\narticles to be visible again.\n"); exit(0); } inn-2.6.4/contrib/expirectl.c0000644000175200017520000002072614002373703015532 0ustar iuliusiulius/* * EXPIRECTL.C * * expirectl * * This program uses expire.ctl.ctl as input; please see the end of this * file for an example of such a file. */ /* * Date: Mon, 21 Nov 1994 12:29:52 -0801 * From: Matthew Dillon * Message-Id: <199411212030.MAA21835@apollo.west.oic.com> * To: rsalz@uunet.uu.net * Subject: Re: INN is great, bug fix for BSDI * * [...] * Oh, while I'm at it, I also wrote a cute program that builds the * expire.ctl file dynamically based on available space. Feel free * to include this in the dist (or not) as you please. * * Basically, the expirectl programs determines the amount of disk blocks * and inodes free in the spool and creates a new expire.ctl file based * on an expire.ctl.ctl template. The template specifies expiration times * as a fraction of nominal. expirectl adjusts the nominal expiration * up or down based on available disk space. * * The idea is to make expiration as hands off as possible. I tested * it on a smaller spool and it appeared to work fine. Currently it * only works for single-partition news spools tho. The above spool * will not really exercise the program for another 14 days or so :-). */ #include "config.h" #include "clibrary.h" #include #include /* Following portability code lifted from inndf.c */ #if HAVE_STATVFS # include # define df_stat(p, s) (statvfs((p), (s)) == 0) # define df_declare(s) struct statvfs s # define df_total(s) ((s).f_blocks) # define df_avail(s) ((s).f_bavail) # define df_scale(s) ((s).f_frsize == 0 ? (s).f_bsize : (s).f_frsize) # define df_files(s) ((s).f_files) # define df_favail(s) ((s).f_favail) #elif HAVE_STATFS # if HAVE_SYS_VFS_H # include # endif # if HAVE_SYS_PARAM_H # include # endif # if HAVE_SYS_MOUNT_H # include # endif # ifdef __ultrix__ # define df_stat(p, s) (statfs((p), (s)) >= 1) # define df_declare(s) struct fs_data s # define df_total(s) ((s).fd_btot) # define df_avail(s) ((s).fd_bfreen) # define df_scale(s) 1024 # define df_files(s) ((s).fd_gtot) # define df_favail(s) ((s).fd_gfree) # else # define df_stat(p, s) (statfs((p), (s)) == 0) # define df_declare(s) struct statfs s # define df_total(s) ((s).f_blocks) # define df_avail(s) ((s).f_bavail) # define df_scale(s) ((s).f_bsize) # define df_files(s) ((s).f_files) # define df_favail(s) ((s).f_ffree) # endif #else # error "Platform not supported. Neither statvfs nor statfs available." #endif #define EXPIRE_CTL_DIR "/home/news" #define NEWS_SPOOL "/home/news/spool/news/." #define EXPIRE_DAYS EXPIRE_CTL_DIR "/expire.days" #define EXPIRE_CTL EXPIRE_CTL_DIR "/expire.ctl" #define EXPIRE_CTL_CTL EXPIRE_CTL_DIR "/expire.ctl.ctl" int main(int ac, char **av) { df_declare(sfs); long minFree = 100 * 1024 * 1024; long minIFree = 20 * 1024; long expireDays = 2; time_t expireIncTime = time(NULL) - 24 * 60 * 60; int modified = 0; int verbose = 0; /* * options */ { int i; for (i = 1; i < ac; ++i) { char *ptr = av[i]; if (*ptr == '-') { ptr += 2; switch(ptr[-1]) { case 'v': verbose = 1; break; case 'f': modified = 1; break; case 'n': modified = -1; break; case 'b': minFree = strtol(((*ptr) ? ptr : av[++i]), &ptr, 0); if (*ptr == 'k') minFree *= 1024; if (*ptr == 'm') minFree *= 1024 * 1024; break; case 'i': minIFree = strtol(((*ptr) ? ptr : av[++i]), NULL, 0); if (*ptr == 'k') minIFree *= 1024; if (*ptr == 'm') minIFree *= 1024 * 1024; break; default: fprintf(stderr, "bad option: %s\n", ptr - 2); exit(1); } } else { fprintf(stderr, "bad option: %s\n", ptr); exit(1); } } } if (!df_stat("/home/news/spool/news/.", &sfs)) { fprintf(stderr, "expirectl: couldn't fsstat /home/news/spool/news/.\n"); exit(1); } /* * Load /home/news/expire.days */ { FILE *fi; char buf[256]; if ((fi = fopen(EXPIRE_DAYS, "r")) != NULL) { while (fgets(buf, sizeof(buf), fi) != NULL) { if (strncmp(buf, "time", 4) == 0) { expireIncTime = strtol(buf + 4, NULL, 0); } else if (strncmp(buf, "days", 4) == 0) { expireDays = strtol(buf + 4, NULL, 0); } } fclose(fi); } else { if (modified >= 0) modified = 1; printf("creating %s\n", EXPIRE_DAYS); } } /* * print status */ if (verbose) { printf("spool: %4.2lfM / %3.2lfKinode free\n", (double)df_scale(sfs) * (double)df_avail(sfs) / (1024.0 * 1024.0), (double)df_favail(sfs) / 1024.0 ); printf("decrs: %4.2lfM / %3.2lfKinode\n", (double)(minFree) / (double)(1024*1024), (double)(minIFree) / (double)(1024) ); printf("incrs: %4.2lfM / %3.2lfKinode\n", (double)(minFree * 2) / (double)(1024*1024), (double)(minIFree * 2) / (double)(1024) ); } /* * Check limits, update as appropriate */ { double bytes; long inodes; bytes = (double)df_scale(sfs) * (double)df_avail(sfs); inodes = df_favail(sfs); if (bytes < (double)minFree || inodes < minIFree) { if (--expireDays <= 0) { expireDays = 1; expireIncTime = time(NULL) - 24 * 60 * 60; } if (modified >= 0) modified = 1; printf("decrement expiration to %ld days\n", expireDays); } else if (bytes >= (double)minFree * 2.0 && inodes >= minIFree * 2) { long dt = (long)(time(NULL) - expireIncTime); if (dt >= 60 * 60 * 24 || dt < -60) { ++expireDays; expireIncTime = time(NULL); if (modified >= 0) modified = 1; printf("increment expiration to %ld days\n", expireDays); } else { printf("will increment expiration later\n"); } } else if (verbose) { printf("expiration unchanged: %ld\n", expireDays); } } /* * Write EXPIRE_CTL file from EXPIRE_CTL_CTL template */ if (modified > 0) { FILE *fi; FILE *fo; if ((fi = fopen(EXPIRE_CTL_CTL, "r")) != NULL) { if ((fo = fopen(EXPIRE_CTL ".tmp", "w")) != NULL) { char sbuf[2048]; char dbuf[4096]; while (fgets(sbuf, sizeof(sbuf), fi) != NULL) { char *base = sbuf; char *sptr; char *dptr = dbuf; while ((sptr = strchr(base, '[')) != NULL) { double d; int m = 0; bcopy(base, dptr, sptr - base); dptr += sptr - base; d = strtod(sptr + 1, &sptr); if (*sptr == '/') m = strtol(sptr + 1, &sptr, 0); if (*sptr == ']') { long v = (long)((double)expireDays * d + 0.5); if (v < 1) v = 1; if (v < m) v = m; sprintf(dptr, "%ld", v); dptr += strlen(dptr); ++sptr; } base = sptr; } strcpy(dptr, base); fputs(dbuf, fo); } fclose(fo); if (rename(EXPIRE_CTL ".tmp", EXPIRE_CTL) != 0) { fprintf(stderr, "rename(%s,%s): %s\n", EXPIRE_CTL ".tmp", EXPIRE_CTL, strerror(errno) ); } } fclose(fi); } } /* * Write EXPIRE_DAYS file */ if (modified > 0) { FILE *fo; if ((fo = fopen(EXPIRE_DAYS, "w")) != NULL) { fprintf(fo, "time 0x%08lx\n", (unsigned long) expireIncTime); fprintf(fo, "days %ld\n", expireDays); fclose(fo); } else { fprintf(stderr, "unable to create %s\n", EXPIRE_DAYS); } } exit(0); } /* # Start of sample expire.ctl.ctl file. # EXPIRE.CTL.CTL (EXPIRE.CTL GENERATED FROM EXPIRE.CTL.CTL !!!) # # The expire.ctl file is generated by the expirectl program from the # expire.ctl.ctl file. The expirectl program calculates the proper # expiration based on the number of free inodes and free bytes available. # # This file is exactly expire.ctl but with the multiplier [N] replaced by # a calculated value, where a multiplier of '1' nominally fills the whole # disk. # # Any field [N] is substituted after being multiplied by the expiration # time (in days). A integer minimum can also be specified with a slash, # as in [N/minimum]. # # expirectl is normally run just after expire is run. Note that expirectl # isn't very useful for the case where you are 'catching up' on news after # a long period of downtime UNLESS you use the -p option to expire. /remember/:[1.2/20] ## Keep for 1-10 days, allow Expires headers to work. # *:A:1:[1.0]:[6.0] *.advocacy:A:1:[0.5]:[2.0] alt.binaries.pictures.erotica:A:1:[0.8]:[2.0] # permanent, semi-permanent # best.intro:A:never:never:never best.announce:A:5:60:120 best.general:A:never:never:never best.bugs:A:never:never:never # End of sample expire.ctl.ctl file. */ inn-2.6.4/contrib/backlogstat.in0000644000175200017520000000551114002373703016210 0ustar iuliusiulius#! /usr/bin/perl -w # fixscript will replace this line with code to load INN::Config # backlogstat - display backlog to sites # based on bklog by bill davidsen # breaks if backlog-directory in innfeed.conf is not "innfeed" my $dir = "$INN::Config::pathspool/innfeed"; my $Revision = '1.8'; use strict; use warnings; use Getopt::Std; use vars qw($opt_H $opt_h $opt_n $opt_t $opt_k $opt_S $opt_d); $| = 1; # option processing &getopts('HhntkS:d:') || &Usage; &Usage if $opt_h; # open the directory; $dir = $opt_d if $opt_d; print "$opt_d\n"; chdir($dir) or die "Can't cd to $dir"; opendir(DIR, ".") or die "Can't open dir"; my %nodes; while (my $name = readdir(DIR)) { # must be a file, correct name, non-zero size my $size; next unless -f $name; next unless ($size = -s $name); next unless $name =~ m/.*\.(in|out)put/; my $io = $1; (my $nodename = $name) =~ s/\..*//; # check for only some sites wanted next if ($opt_S && $nodename !~ /^${opt_S}.*/); # here we do the counts if asked if ($opt_n) { # open the file and count lines if (open(IN, "<$name")) { if ($name =~ m/.*\.input/) { my $offset = + 0; seek(IN, $offset, 0); } $size = 0; for ($size = 0; ; ++$size) {}; close IN; } } else { # get the offset on .input files if ($name =~ m/.*\.input/ && open(IN, "<$name")) { my $offset = + 0; $size -= $offset; close IN; } } $nodes{$nodename} = () unless defined $nodes{$nodename}; $nodes{$nodename}->{$io} = ( $opt_k ? $size / 1024 : $size ); } closedir DIR; # output the data for each node if (my $numnodes = keys %nodes) { if ($opt_H) { if ($opt_n) { print " <---------- posts ----------->\n"; } else { print " <---------- bytes ----------->\n"; } } my $ofmt; if ($opt_k) { print " input(k) output(k) total(k) Feed Name\n" if $opt_H; $ofmt = ( $opt_n ? "%10.2f" : "%10.1f" ); } else { print " input output total Feed Name\n" if $opt_H; $ofmt = "%10d"; } for my $node (sort keys %nodes) { my $hash = $nodes{$node}; my $size_in = $hash->{in} || 0; my $size_out = $hash->{out} || 0; my $size_tot = $size_in + $size_out; printf "${ofmt} ${ofmt} ${ofmt} %s\n", $size_in, $size_out, $size_tot, $node; } } else { print "NO backlog!\n"; } exit 0; sub Usage { print "\n" . "bklog - print innfeed backlog info - v$Revision\n" . "\n" . "Format:\n" . " bklog [ options ]\n" . "\n" . "Options:\n" . " -H output a header at the top of the output\n" . " -k scale all numbers in k (1024) units\n" . " -n count number of arts, not bytes of backlog filesize\n" . " Note: this may be SLOW for large files!\n" . " -Sxx Display only site names starting with xx\n" . " -d dir Use \"dir\" instead of \$pathspool/innfeed\n" . "\n" . " -h HELP - this is all, you got it!\n" . "\n"; exit 1; } inn-2.6.4/contrib/sample.init.systemd0000644000175200017520000000247614002373703017226 0ustar iuliusiulius# $Id: sample.init.systemd 10507 2021-01-11 21:55:08Z iulius $ # # This is a simple, bare-bones example of a systemd-style init script for INN. # [Unit] Description=InterNetNews News Server Documentation=https://www.eyrie.org/~eagle/software/inn/ After=network-online.target Wants=network-online.target ConditionPathExists=/etc/news/inn.conf [Service] Type=notify Restart=on-abort ExecStart=/usr/lib/news/bin/rc.news ExecReload=/usr/sbin/ctlinnd -t 20 reload '' 'systemd unit reload' ExecStop=/usr/lib/news/bin/rc.news stop PIDFile=/run/news/innd.pid User=news Group=news AmbientCapabilities=CAP_NET_BIND_SERVICE PrivateTmp=true ProtectControlGroups=true ProtectHome=true ProtectSystem=full RuntimeDirectory=news LimitNOFILE=infinity ReadWritePaths=/var/spool/news/ # Setting NoNewPrivileges will break most local sendmail implementations # because they're setuid or setgid to drop off mail in the mail queue. With # this configuration, one can use mSMTP as the configured mta, set to forward # mail via SMTP to localhost. Nevertheless, one can probably do better than # this by adding some syscall filtering. #NoNewPrivileges=true # # These directives automatically enable NoNewPrivileges, and are therefore # incompatible: #PrivateDevices=true #ProtectKernelModules=true #ProtectKernelTunables=true [Install] WantedBy=multi-user.target inn-2.6.4/contrib/findreadgroups.in0000644000175200017520000000156514002373703016733 0ustar iuliusiulius#! /usr/bin/perl -w # fixscript will replace this line with code to load INN::Config # Keep track of which groups are currently being read. Takes logfile input # on stdin. $readfile="$INN::Config::newsetc/readgroups"; $curtime = time; $oldtime = $curtime - 30 * 86400; # 30 days in the past if (open(RDF, $readfile)) { while () { chop; @foo=split(/ /); # foo[0] should be group, foo[1] lastreadtime if ($foo[1] < $oldtime) { next; # skip entries that are too old. } $groups{$foo[0]} = $foo[1]; } close(RDF); } # read input logs. while (<>) { next unless /nnrpd/; next unless / group /; chop; @foo = split(/ +/); # group name is in the 8th field. $groups{$foo[7]} = $curtime; } open(WRF, ">$readfile") || die "cannot open $readfile for write.\n"; foreach $i (keys %groups) { print WRF $i, " ", $groups{$i}, "\n"; } exit(0); inn-2.6.4/contrib/innreport-filter.xslt0000644000175200017520000000671514002373703017610 0ustar iuliusiulius inn-2.6.4/contrib/thdexpire.in0000644000175200017520000004130714002373703015711 0ustar iuliusiulius#! /usr/bin/perl -w # fixscript will replace this line with code to load INN::Config $ID='$Id: thdexpire.in 9408 2012-05-28 18:42:29Z iulius $$'; use POSIX ":fcntl_h"; use SDBM_File; use Getopt::Std; use INN::Utils::Shlock; # With the -M switch this program installs its own man page. #----------------------------------------------------------------------------- =head1 NAME thdexpire - dynamic expire daemon for timehash and timecaf storage =head1 SYNOPSIS B [ B<-t> I ] [ B<-f> I ] [ B<-i> I ] [ B<-m> I ] [ B<-x> I ] [ B<-N> ] [ B<-v> I ] B =head1 DESCRIPTION This is a daemon, to be started along with B, which periodically looks if news spool space is getting tight, and frees space by removing articles until enough is free. It is an adjunct (not a replacement) to INNs B program. =head2 Setting Up =over 4 =item 1. Configure your storage classes carefully. Let the default go in class 100 and choose the storage classes as relative (percent) retention times. E.g. if you want to give C a fifth of the default time, put them in class 20. Storage classes above 200 are ignored by this program. 0 expires immediately. An example is given in L<"EXAMPLES">. =item 2. Set up your F in a way that it puts only a maximum cap on retention times. Run B from B as usual. However, it should only expire articles which have an Expires line or are in classes above 200. See L<"EXAMPLES">. =item 3. Ensure to start this daemon along with B. =item 4. To get information and statistics, run B (in parallel to a running daemon). This will show you the current actual retention times. =back =head2 How It Works B works directly on the spool. It assumes the layout described in the timehash and timecaf sections of L as of INN-2.x-CURRENT (Dec. 5, 1998). For every storage class associated with timehash/timecaf, B keeps a I which is the modification time of the oldest article/CAF file in this class. This time is chosen so that the difference of the work time of class N to now (i.e. the I for class N) will be N/100 of the retention time of class 100. The work time of all classes is continuously adjusted as time goes by. Articles and CAF files which are older than the work time are deleted. =head1 OPTIONS =over 8 =item B<-t> I Check for free space every I minutes (default 30). =item B<-f> I Leave I kilobytes of free disk space on each spool filesystem (default 50000). =item B<-i> I Leave I inodes free on each spool filesystem (default 5000). =item B<-m> I Set the minimum normal holding time for class 100 to I days (default 7). =item B<-x> I Set the absolute minimum holding time for any article to I seconds (default 86400, i.e. 1 day). =item B<-N> Do not delete any articles, just print what would be done. =item B<-v> I Set the verbosity level. Values from 1 to 3 are meaningful, where higher levels are mostly for debugging. =item B<-r> Do not run as a daemon, instead print a report from the database (see L) on the available storage classes, current expire times and other stuff. =back =head1 EXAMPLES Here is an example F file: # Large postings in binary groups are expired fast: # 20% retention time method timehash { newsgroups: *.binaries.*,*.binaer.*,*.dateien.*,alt.mag.* size: 30000 class: 20 } # Local groups and *.answers groups don't expire at all with # thdexpire. These are handled by Expires lines and a cutoff # in expire.ctl. method timehash { newsgroups: *.answers,news.announce.*,local.* class: 201 } # Expires lines are honored if they dont exceed 90 days. # Exempt those postings from thdexpire handling. method timehash { newsgroups: * expires: 1d,90d class: 202 } # Default: should be class 100 because thdexpire bases its # calculations thereupon. method timecaf { newsgroups: * class: 100 } And here is an F which fits: # Our local groups are held 6 months local.*:A:7:180:180 # Everything else is handled by thdexpire, or Expires lines *:A:7:never:never Note that B does not actually use these files, they just configure other parts of the news system in an appropriate way. =head1 FILES =over 4 =item I/thdexpstat.{dir,pag} Holds state information like classes, expire times, oldest articles. When this file is missing, it will be rebuilt the next time the daemon is started, which basically means scanning the spool directories to find the oldest articles. With the B<-r> option, the contents of this file are printed. =item I/thdexpire.pid Contains the PID of the running daemon. =back =head1 SIGNALS I or I can be sent to the daemon at any time, causing it to gracefully exit immediately. =head1 SEE ALSO L, L, L =head1 NOTES This version needs the B program supplied with newer releases of INN. The filenames for timecaf were wrong in older versions of the INN documentation. This program uses the true filenames, as found by reading the INN source. =head1 DIAGNOSTICS Any error messages are printed on standard error. Normal progress messages, as specified by the B<-v> option, are printed on standard output. =head1 BUGS Storage classes which are in I but not on disk (i.e. which have never been filed into) when the daemon starts are ignored. The code is ugly and uses too many global variables. Should probably rewrite it in C. =head1 RESTRICTIONS Directories which are left empty are not removed. The overview database is not affected by B, it has to be cleaned up by the daily regular B run. This may need a patch to B. =head1 AUTHOR Olaf Titz . Use and distribution of this work is permitted under the same terms as the B package. =head1 HISTORY Inspired by the old B program for the traditional spool. June 1998: wrote the first version for timehash. November 1998: added code for timecaf, works on multiple spool filesystems, PODed documentation. July 1999: bugfixes. =cut #----------------------------------------------------------------------------- my $lockfile = "$INN::Config::innddir/thdexpire.pid"; END { # In case we bail out, while holding a lock. INN::Utils::Shlock::releaselocks(); } chdir $INN::Config::spool || die "chdir $INN::Config::spool: $!"; $opt_r=0; # make a report $opt_t=30; # check interval in minutes $opt_f=50000; # required space in kilobytes $opt_i=5000; # required space in inodes $opt_m=7; # minimum normal (class 100) time in days $opt_x=86400; # absolute minimum hold time in seconds $opt_N=0; # dont actually delete articles $opt_v=0; # verbosity level $opt_M=0; # install man page getopts("rt:f:i:m:x:Nv:M"); $sfile="$INN::Config::pathdb/thdexpstat"; $ID=~/ ([^,]+,v [^ ]+)/; $ID=$1; if ($opt_M) { print "Installing thdexpire(8) man page\n"; $0=~m:^(.*)/([^/]+)$:; chdir $1 || die "chdir $1"; exec "pod2man --section=8 --center='Contributed News Software'" . " --release='$ID' $2 >$INN::Config::pathnews/man/man8/thdexpire.8"; } if ($opt_r) { tie(%S, SDBM_File, $sfile, O_RDONLY, 0664) || die "open $sfile: $!"; &report; untie %S; exit 0; } # Acquire a lock. INN::Utils::Shlock::lock($lockfile, 5) or die ("cannot create lockfile $lockfile"); tie(%S, SDBM_File, $sfile, O_RDWR|O_CREAT, 0664) || die "open $sfile: $!"; $SIG{'TERM'}=$SIG{'INT'}='finish'; $|=1; printf "%s starting at %s\n", $ID, &wtime(time) if ($opt_v>0); undef @c; $NOW=time; $ac=$cc=0; opendir(CD, ".") || &err("opendir $INN::Config::spool: $!"); while ($cd=readdir(CD), defined($cd)) { $cd=~/^time(caf)?-([0-9a-f][0-9a-f])$/i || next; $c{hex($2)}=1 unless hex($2)>200; } closedir CD; @classes=sort {$a<=>$b} keys %c; foreach $c (@classes) { &initclass($c); $S{"work$;$c"}=$S{"oldest$;$c"}&0xFFFFFF00; } $S{"classes"}=join(",", @classes); $S{"inittime"}=time; $S{"ID"}=$ID; printf "Checked %d articles, %d CAFs in %d seconds\n", $ac, $cc, time-$NOW if ($ac+$cc>0 && $opt_v>0); chdir $INN::Config::spool || die "chdir $INN::Config::spool: $!"; while (1) { $S{"lastrun"}=$NOW=time; printf "%s\n", &wtime($NOW) if ($opt_v>0); $nt=0; foreach $c (@classes) { $t=($NOW-$S{"work$;$c"})*100/$c; $nt=$t if ($nt<$t); } printf "Normal time (class 100): %s\n", &xtime($NOW-$nt) if ($opt_v>0); if ($nt<$opt_m*24*60*60) { printf " capped at minimum %d days\n", $opt_m if ($opt_v>0); $nt=$opt_m*24*60*60; } if ($nt>180*24*60*60) { print " capped at maximum 180 days\n" if ($opt_v>0); $nt=180*24*60*60; } $S{"normaltime"}=$nt; $decrement=$opt_t*60; $pass=$need=0; $x="/"; undef %needk; undef %needi; foreach $c (@classes) { $Dart{$c}=$Dcaf{$c}=$Dkb{$c}=$Dino{$c}=0; $y=sprintf("time-%02x", $c); if (-d $y) { @S=stat(_); if ($#S>=0) { $dev{$y}=$S[0]; unless (defined($needk{$S[0]})) { $x.=" $y"; $needk{$S[0]}=$needi{$S[0]}=-1; } } } $y=sprintf("timecaf-%02x", $c); if (-d $y) { @S=stat(_); if ($#S>=0) { $dev{$y}=$S[0]; unless (defined($needk{$S[0]})) { $x.=" $y"; $needk{$S[0]}=$needi{$S[0]}=-1; } } } } if (open(D, "$INN::Config::newsbin/inndf $x |")) { while () { @S=split(/\s+/, $_); $needk{$dev{$S[0]}}=$opt_f-$S[1] unless ($S[0] eq "/"); } close D; } if (open(D, "$INN::Config::newsbin/inndf -i $x |")) { while () { @S=split(/\s+/, $_); $needi{$dev{$S[0]}}=$opt_i-$S[1] unless ($S[0] eq "/"); } close D; } foreach $c (keys %needk) { printf "Device %d needs to free %d kilobytes, %d inodes\n", $c, $needk{$c}<0?0:$needk{$c}, $needi{$c}<0?0:$needi{$c} if ($opt_v>0 && ($needk{$c}>0 || $needi{$c}>0)); if ($needk{$c}>0 || $needi{$c}>0) { ++$need; } } if ($opt_v>0 && $need<=0) { print " (nothing to do)\n"; $tt=0; } else { $error=0; while (!$error && $need>0) { if ($S{"normaltime"}-$decrement<$opt_m*24*60*60) { print " Normal time hit minimum\n" if ($opt_v>0); last; } $S{"normaltime"}-=$decrement; printf " normal time (100) becomes %ld\n", $S{"normaltime"} if ($opt_v>2); ++$pass; $Dart=$Dcaf=$Dkb=$Dino=$need=0; foreach $c (keys %needk) { if ($needk{$c}>0 || $needi{$c}>0) { ++$need; } } if ($need) { foreach $c (@classes) { &worktime($c, $NOW-($S{"normaltime"}*$c/100)); $Dart+=$dart; $Dcaf+=$dcaf; $Dkb+=$dbb>>10; $Dino+=$dino; $Dart{$c}+=$dart; $Dcaf{$c}+=$dcaf; $Dkb{$c}+=$dbb>>10; $Dino{$c}+=$dino; last if ($error); } } if ($Dart+$Dcaf) { printf " pass %d deleted %d arts, %d CAFs, %d kb\n", $pass, $Dart, $Dcaf, $Dkb if ($opt_v>1); $decrement-=$decrement>>2 if ($decrement>10*60); } else { $decrement+=$decrement>>1 if ($decrement<4*60*60); } } $Dkb=$Dart=$Dcaf=$Dino=0; foreach $c (@classes) { printf " class %3d: deleted %6d arts %6d CAFs %10d kb\n", $c, $Dart{$c}, $Dcaf{$c}, $Dkb{$c} if ($opt_v>1); $Dkb+=$Dkb{$c}; $Dart+=$Dart{$c}; $Dcaf+=$Dcaf{$c}; } $tt=time-$NOW; printf " deleted %d articles, %d CAFs, %d kb in %d seconds\n", $Dart, $Dcaf, $Dkb, time-$NOW if ($opt_v>0); if ($tt>$opt_t*60) { printf STDERR "Round needed %d seconds, interval is %d\n", $tt, $opt_t*60; $tt=$opt_t*60; } } sleep $opt_t*60-$tt; } &finish(0); sub initclass { my $C=shift; if (!$S{"blocksize$;$C$;CAF"}) { # Determine filesystem blocksize # unfortunately no way in perl to statfs my $x=sprintf("%s/timecaf-%02x/test%d", $INN::Config::spool, $C, $$); if (open(A, ">$x")) { print A "X" x 4096; close A; @S=stat $x; $#S>=12 || die "stat: $!"; if ($S[12]) { $S{"blocksize$;$C$;CAF"}=$S[7]/$S[12]; } else { $S{"blocksize$;$C$;CAF"}=512; warn "hack around broken stat blocksize"; } unlink $x; } } return if ($S{"oldest$;$C"}); my $oldest=time; $S{"oldest$;$C"}=$oldest; my $base=sprintf("%s/time-%02x", $INN::Config::spool, $C); my $count=0; if (chdir $base) { printf "Finding oldest in class %d (%s)\n", $C, $base if ($opt_v>0); opendir(D0, "."); while ($d1=readdir(D0), defined($d1)) { $d1=~/^[0-9a-f][0-9a-f]$/ || next; chdir $d1; opendir(D1, ".") || next; while ($d2=readdir(D1), defined($d2)) { $d2=~/^[0-9a-f][0-9a-f]$/ || next; chdir $d2; opendir(D2, ".") || next; while ($a=readdir(D2), defined($a)) { $a=~/^\./ && next; @S=stat($a); $oldest=$S[9] if ($S[9]<$oldest); ++$count; } closedir D2; chdir ".."; } closedir D1; chdir ".."; } closedir D0; $ac+=$count; } $base=sprintf("%s/timecaf-%02x", $INN::Config::spool, $C); if (chdir $base) { printf "Finding oldest in class %d (%s)\n", $C, $base if ($opt_v>0); opendir(D0, "."); while ($d1=readdir(D0), defined($d1)) { $d1=~/^[0-9a-f][0-9a-f]$/ || next; chdir $d1; opendir(D1, ".") || next; while ($a=readdir(D1), defined($a)) { $a=~/^\./ && next; @S=stat($a); $oldest=$S[9] if ($S[9]<$oldest); ++$count; } closedir D1; chdir ".."; } closedir D0; $cc+=$count; } $S{"count$;$C"}=$count; $S{"oldest$;$C"}=$oldest; } sub worktime { my $C=shift; my $goal=shift; $goal&=0xFFFFFF00; printf " goal for class %d becomes %s\n", $C, &xtime($goal) if ($opt_v>2); if ($goal>$NOW-$opt_x) { printf " goal for class %d cut off\n", $C if ($opt_v>1); $error=1; return; } $dart=$dcaf=$dbb=$dino=0; $hdir=sprintf("time-%02x", $C); $cdir=sprintf("timecaf-%02x", $C); while (($_=$S{"work$;$C"})<$goal) { printf " running: %08x\n", $_ if ($opt_v>2); ($aa,$bb,$cc) = (($_>>24)&0xFF, ($_>>16)&0xFF, ($_>>8)&0xFF); $dir=sprintf("%s/%02x/%02x", $hdir, $bb, $cc); $pat=sprintf("[0-9a-f]{4}-%02x[0-9a-f]{2}", $aa); if (opendir(D, $dir)) { while ($_=readdir(D), defined($_)) { /^$pat$/ || next; $art="$dir/$_"; @S=stat($art); if ($#S>=7) { if ($opt_N) { print " would delete $art" if ($opt_v>2); } else { print " deleting $art" if ($opt_v>2); unlink $art; } ++$dart; ++$dino; printf " %d kb\n", $S[7]>>10 if ($opt_v>2); $dbb+=$S[7]; $needk{$dev{$hdir}}-=$S[7]>>10; $needi{$dev{$hdir}}--; } } } else { printf " (no dir %s)\n", $dir if ($opt_v>2); } $caf=sprintf("%s/%02x/%02x%02x.CF", $cdir, $bb, $aa, $cc); @S=stat($caf); if ($#S>=12) { if ($opt_N) { print " would delete $caf" if ($opt_v>2); } else { print " deleting $caf" if ($opt_v>2); unlink $caf; } $y=0; if (open(C, $caf)) { # try to find how much there is in the CAF sysread(C, $_, 16); @C=unpack("a4LLL", $_); if ($C[0] eq "CRMT") { $y=$C[3]-$C[1]; $dart+=$y; } close C; } ++$dcaf; ++$dino; if ($S[12]) { $x=$S[12]*$S{"blocksize$;$C$;CAF"}; } else { $x=$S[7]; warn "hack around broken stat blocksize"; } printf " %d arts %d kb\n", $y, $x>>10 if ($opt_v>2); $dbb+=$x; $needk{$dev{$cdir}}-=$x>>10; $needi{$dev{$cdir}}--; } $S{"work$;$C"}+=0x100; $S{"oldest$;$C"}=$S{"work$;$C"} unless ($opt_N); } } sub report { $NOW=time; my $cc=$S{"classes"}; my $nt=$S{"normaltime"}; unless ($cc && $nt) { print "Not initialized.\n"; return; } printf "Version: %s (this: %s)\n", $S{"ID"}, $ID; printf "Started at: %s\n", &xtime($S{"inittime"}) if ($S{"inittime"}); printf "Last run: %s\n", &xtime($S{"lastrun"}) if ($S{"lastrun"}); printf "Classes: %s\n", $cc; foreach $c (split(/,/, $cc)) { printf "Class %d:\n", $c; #printf " Initial count %d articles\n", $S{"count$;$c"}; printf " Oldest article: %s\n", &xtime($S{"oldest$;$c"}); printf " Expiring at: %s\n", &xtime($S{"work$;$c"}); printf " Normal time: %s\n", &xtime($NOW-$nt*$c/100); printf " Filesystem block size (CAF): %d\n", $S{"blocksize$;$c$;CAF"}; } } sub wtime { my $t=shift; my @T=localtime($t); sprintf("%04d-%02d-%02d %02d:%02d", $T[5]+1900, $T[4]+1, $T[3], $T[2], $T[1]); } sub xtime { my $t=shift; if ($NOW-$t<0 || $NOW-$t>350*24*60*60) { return &wtime($t); } my @T=localtime($t); my @D=gmtime($NOW-$t); sprintf("%04d-%02d-%02d %02d:%02d (%dd %dh %dm)", $T[5]+1900, $T[4]+1, $T[3], $T[2], $T[1], $D[7], $D[2], $D[1]); } sub err { printf STDERR "%s\n", shift; &finish(0); } sub finish { untie(%S); # Unlock. INN::Utils::Shlock::unlock($lockfile); exit 0; } #----------------------------------------------------------------------------- inn-2.6.4/contrib/fixhist0000755000175200017520000000413714002373703014771 0ustar iuliusiulius#!/usr/local/bin/perl # # history database sanity checker # David Barr # version 1.4 # w/mods from: hucka@eecs.umich.edu # Katsuhiro Kondou # version 1.1 # Throw away history entries with: # malformed lines (too long, contain nulls or special characters) # # INN Usage: # ctlinnd throttle 'fixing history' # ./fixhist history.n # makedbz -s `wc -l ) { chop; ($msgid,$dates,$arts,$xtra) = split('\t'); if ($xtra) { &tossit(); # too many fields next; } if (!($dates) && (($arts) || ($xtra))) { &tossit(); # if not date field, then the rest next; # should be empty } if (length($msgid) >= $MAXKEYLEN) { &tossit(); # message-id too long next; } if ($msgid !~ /^<[^<> ]*>$/) { if ($msgid =~ /^\[[0-9A-F]{32}\]$/) { if ($arts ne "") { if ($arts =~ /^\@[0-9A-F]{56}\@$/) { $arts =~ s/^\@([0-9A-F]{36})([0-9A-F]{20})\@$/\@${1}\@/; print "$msgid\t$dates\t$arts\n"; next; } if ($arts !~ /^\@[0-9A-F]{36}\@$/) { &tossit(); next; } } } else { &tossit(); # malformed msg-ids next; } } else { if ($arts ne "" && ($arts !~ /[^\/]*\/[0-9]*/)) { &tossit(); # malformed articles list next; } } if (/[\000-\010\012-\037\177-\237]/) { # non-control chars except tab &tossit(); # illegal chars next; } if ($dates) { if ($dates =~ /[^\d~\-]/) { # rudimentary check &tossit(); # full check would be too slow next; } } print "$_\n"; $count++; $0 = "history line $./$count" if $. % 50000 == 0; } print STDERR "Done. Now run:\nmakedbz -s $count -f history.n\n"; sub tossit { print STDERR "$_\n"; } inn-2.6.4/contrib/mlockfile.c0000644000175200017520000001036714002373703015500 0ustar iuliusiulius/* $Id: mlockfile.c 10018 2016-05-05 12:45:13Z iulius $ */ /* Locks the files given on the command line into memory using mlock. This code has only been tested on Solaris and may not work on other platforms. Contributed by Alex Kiernan . */ #include #include #include #include #include #include #include #include #include #include #include struct mlock { const char *path; struct stat st; void *base; off_t offset; size_t length; }; void inn_lock_files(struct mlock *); char *progname; int flush = 0; int interval = 60000; void inn_lock_files(struct mlock *ml) { for (; ml->path != NULL; ++ml) { int fd; fd = open(ml->path, O_RDONLY); if (fd == -1) { fprintf(stderr, "%s: can't open `%s' - %s\n", progname, ml->path, strerror(errno)); } else { struct stat st; /* check if size, inode or device of the path have * changed, if so unlock the previous file & lock the new * one */ if (fstat(fd, &st) != 0) { fprintf(stderr, "%s: can't stat `%s' - %s\n", progname, ml->path, strerror(errno)); } else if (ml->st.st_ino != st.st_ino || ml->st.st_dev != st.st_dev || ml->st.st_size != st.st_size) { if (ml->base != MAP_FAILED) munmap(ml->base, ml->length > 0 ? ml->length : (size_t) ml->st.st_size); /* free everything here, so in case of failure we try * again next time */ ml->st.st_ino = 0; ml->st.st_dev = 0; ml->st.st_size = 0; ml->base = mmap(NULL, ml->length > 0 ? ml->length : (size_t) st.st_size, PROT_READ, MAP_SHARED, fd, ml->offset); if (ml->base == MAP_FAILED) { fprintf(stderr, "%s: can't mmap `%s' - %s\n", progname, ml->path, strerror(errno)); } else { if (mlock(ml->base, ml->length > 0 ? ml->length : (size_t) st.st_size) != 0) { fprintf(stderr, "%s: can't mlock `%s' - %s\n", progname, ml->path, strerror(errno)); } else { ml->st = st; } } } else if (flush) { msync(ml->base, ml->length > 0 ? ml->length : (size_t) st.st_size, MS_SYNC); } } close (fd); } } static void usage(void) { fprintf(stderr, "usage: %s [-f] [-i interval] file[@offset[:length]] ...\n", progname); fprintf(stderr, " -f\tflush locked bitmaps at interval\n"); fprintf(stderr, " -i interval\n\tset interval between checks/flushes\n"); } int main(int argc, char *argv[]) { struct mlock *ml; int i; progname = *argv; while ((i = getopt(argc, argv, "fi:")) != EOF) { switch (i) { case 'i': interval = 1000 * atoi(optarg); break; case 'f': flush = 1; break; default: usage(); return EX_USAGE; } } argc -= optind; argv += optind; /* construct list of pathnames which we're to operate on, zero out * the "cookies" so we lock it in core first time through */ ml = malloc((1 + argc) * sizeof ml); for (i = 0; argc--; ++i, ++argv) { char *at; off_t offset = 0; size_t length = 0; ml[i].path = *argv; ml[i].st.st_ino = 0; ml[i].st.st_dev = 0; ml[i].st.st_size = 0; ml[i].base = MAP_FAILED; /* if we have a filename of the form ...@offset:length, only * map in that portion of the file */ at = strchr(*argv, '@'); if (at != NULL) { char *end; *at++ = '\0'; errno = 0; offset = strtoull(at, &end, 0); if (errno != 0) { fprintf(stderr, "%s: can't parse offset `%s' - %s\n", progname, at, strerror(errno)); free(ml); return EX_USAGE; } if (*end == ':') { at = end + 1; errno = 0; length = strtoul(at, &end, 0); if (errno != 0) { fprintf(stderr, "%s: can't parse length `%s' - %s\n", progname, at, strerror(errno)); free(ml); return EX_USAGE; } } if (*end != '\0') { fprintf(stderr, "%s: unrecognised separator `%c'\n", progname, *end); free(ml); return EX_USAGE; } } ml[i].offset = offset; ml[i].length = length; } ml[i].path = NULL; /* loop over the list of paths, sleeping 60s between iterations */ for (;;) { inn_lock_files(ml); poll(NULL, 0, interval); } free(ml); return EX_OSERR; } inn-2.6.4/contrib/pullart.c0000644000175200017520000001447514002373703015222 0ustar iuliusiulius/* June 14, 1999 Recover text articles from cyclic buffers Articles start with "\0Path:" and end with "\r\n.\r\n" Tested with INND 2.2 under AIX 4.2 rifkin@uconn.edu */ /* (1) Pull 16 bytes at a time (2) Last 7 bytes must be \000\000\000Path (3) When found, print "\nPath"; (4) print subsequent bytes until \r\n.\r\n found */ #include "config.h" #include "clibrary.h" #define INFILE 1 #define FILEPREFIX 2 #define HEADER 3 #define STRING 4 /* String buffer size */ #define NBUFF 512 #define MAX_ART_SIZE 2200000 #define WRITEMSG printf ("File %s line %i\n", __FILE__, __LINE__); \ fflush(stdout); #define WRITEVAR(VAR_NAME,VAR_TYPE) \ { \ printf ("FILE %s LINE %i :", __FILE__, __LINE__); \ printf ("%s = ", #VAR_NAME); \ printf (#VAR_TYPE, (VAR_NAME) ); \ printf ("\n"); \ } #define WRITETXT(TEXT) \ printf ("FILE %s LINE %i \"%s\"\n", __FILE__, __LINE__, TEXT); \ fflush(stdout); #if 0 #define WRITEMSG #define WRITEVAR(X,Y) #endif int WriteArticle (char *, int, char *, char *, char *, int); char ArtHead[7] = {0, 0, 0, 'P', 'a', 't', 'h'}; char ArtTail[5] = {'\r', '\n', '.', '\r', '\n'}; int LenTail = 5; int main (int argc, char *argv[]) { FILE *Infile; int NumTailCharFound; bool ReadingArticle = false; char buffer[32]; char *obuffer = NULL; char *header = NULL; char *string = NULL; int osize = MAX_ART_SIZE; int opos = 0; int i; int nchar; int fileno = 0; int artno = 0; /* Check number of args */ if (argc<3) { printf ("Usage: pullart [
]\n"); printf (" Read cycbuffer and print all articles whose\n"); printf (" article header
contains .\n"); printf (" Articles are written to files name .nnnnnn\n"); printf (" where nnnnnn is numbered sequentially from 0.\n"); printf (" If
and not specified, all articles\n"); printf (" are written.\n"); printf (" Examples:\n"); printf (" pullart /news3/cycbuff.3 alt.rec Newsgroup: alt.rec\n"); printf (" pullart /news3/cycbuff.3 all\n"); printf (" pullart firstbuff article Subject bluejay\n"); return 0; } /* Allocate output buffer */ obuffer = (char *) calloc (osize+1, sizeof(char)); if (obuffer==NULL) { printf ("Cannot allocate obuffer[]\n"); return 1; } /* Open input file */ Infile = fopen (argv[INFILE], "rb"); if (Infile==NULL) { printf ("Cannot open input file.\n"); free(obuffer); return 1; } if (argc>=4) header = argv[HEADER]; if (argc>=5) string = argv[STRING]; if (header != NULL && *header == '\0') { header = NULL; } if (string != NULL && *string == '\0') { string = NULL; } /*test*/ printf ("filename <%s>\n", argv[INFILE]); printf ("fileprefix <%s>\n", argv[FILEPREFIX]); printf ("header <%s>\n", header != NULL ? header : NULL); printf ("string <%s>\n", string != NULL ? string : NULL); /* Skip first 0x38000 16byte buffers */ i = fseek (Infile, 0x38000L, SEEK_SET); /* Read following 16 byte buffers */ ReadingArticle = false; NumTailCharFound = 0; nchar=0; artno=0; while ( 0!=fread(buffer, 16, 1, Infile) ) { nchar+=16; /* Found start of article, start writing to obuffer */ if (0==memcmp(buffer+9, ArtHead, 7)) { ReadingArticle = true; memcpy (obuffer, "Path", 4); opos = 4; continue; } /* Currnetly reading article */ if (ReadingArticle) { for (i=0; i<16; i++) { /* Article too big, drop it and move on */ if (opos>=osize) { printf ("article number %i bigger than buffer size %i.\n", artno+1, osize); artno++; ReadingArticle=false; break; } /* Add current character to output buffer, but remove \r */ if ('\r' != buffer[i]) obuffer[opos++] = buffer[i]; /* Check for article ending sequence */ if (buffer[i]==ArtTail[NumTailCharFound]) { NumTailCharFound++; } else NumTailCharFound=0; /* End found, write article, reset for next */ if (NumTailCharFound==LenTail) { ReadingArticle = false; NumTailCharFound = 0; /* Add trailing \0 to buffer */ obuffer[opos+1] = '\0'; fileno += WriteArticle (obuffer, opos, argv[FILEPREFIX], header, string, fileno); artno++; break; } } } } fclose (Infile); free(obuffer); return 0; } /* Writes article stored in buff[] if it has a "Newsgroups:" header line which contains *newsgroup Write to a file named fileprefix.fileno */ int WriteArticle (char *buff, int n, char *fileprefix, char *headerin, char *string, int fileno) { char *begptr; char *endptr; char *newsptr; char savechar; char header[NBUFF]; char filename[NBUFF]; FILE *outfile; /* Prevent buffer overflow due to fileprefix too long */ if (strlen(fileprefix)>384) { printf ("program error: cannot have file prefix greater then 384 characters\n"); exit(1); } /* Is header here? Search if header string requested, leave if not found */ if (headerin!=NULL) { /* Find \nHEADER */ strlcpy(header, "\n", sizeof(header)); strlcat(header, headerin, sizeof(header)); begptr = strstr (buff, header); /* return if Header name not found */ if (begptr==NULL) { return 0; } /* Header found. What about string? Search if string requested, leave if not found */ if (string!=NULL) { /* Find end of header line */ begptr++; endptr = strchr (begptr, '\n'); /* Something is wrong, end of header not found, do not write * article */ if (endptr==NULL) return 0; /* Temporarily make string end a null char */ savechar = *endptr; *endptr = '\0'; newsptr = strstr (begptr, string); /* Requested newsgroup not found */ if (newsptr==NULL) return 0; /* Restore character at end of header string */ *endptr = savechar; } /* No string specified */ } /* No header specified */ /* Open file, write buffer, close file */ snprintf (filename, sizeof(filename), "%s.%06i", fileprefix, fileno); outfile = fopen (filename, "wt"); if (outfile==NULL) { printf ("Cannot open file name %s\n", filename); exit(1); } while (n--) fprintf (outfile, "%c", *buff++); fclose (outfile); /* Return number of files written */ return 1; } inn-2.6.4/contrib/innconfcheck0000755000175200017520000001304714002373703015743 0ustar iuliusiulius#!/bin/ksh ### INNCONFcheck v1.1 ### Revision history: # v1.0 B. Galliart (designed to work with 2.3 inn.conf man page) # v1.1 B. Galliart (optional support for using inn.conf POD src instead) ### Description: # This script is written to inner-mix the inn.conf settings with the # documentation from the inn.conf man page. The concept was shamelessly # ripped off of a CGI application provided at Mib Software's Usenet Rapid # Knowledge Transfer (http://www.mibsoftware.com/userkt/inn2.0/). # The idea is that a news administrator usually must go through the # task of reading the inn.conf man page in parallel with the inn.conf # inn.conf to confirm that the settings are set as desired. Manually # matching up the two files can become troublesome. This script should # make the task easier and hopefully reduce the chance a misconfiguration # is missed. ### Known bugs: # - Is very dependent on the format of the man page. It is know NOT to # work with the inn.conf man pages written before INN 2.3 and may # require minor rewriting to address future revisions of inn.conf # Note: this known bug is addressed via the "EDITPOD" option below # but is not enabled by default (details explained below). # # - SECURITY! While taken from the concept of a CGI script, it is not # intended to be a CGI script itself. It is *assumed* that the # inn.conf file is provided by a "trusted" source. ### License: this script is provided under the same terms as the majority # of INN 2.3.0 as stated in the file "inn-2.3.0/LICENSE" ### Warrenty/Disclaimer: There is no warrenty provided. For details, please # refer to the file "inn-2.3.0/LICENSE" from the INN 2.3 package ################ ### The User Modifiable Parameters/Settings: # INNCONF should be set to the actual location of the inn.conf file INNCONF=/usr/local/news/etc/inn.conf # INNCONFMAN should be set to the location of the inn.conf man page INNCONFMAN=/usr/local/news/man/man5/inn.conf.5 # INNCONFPOD should be set to the location of the inn.conf POD source # INNCONFPOD=/usr/local/src/inn-2.3.0/doc/pod/inn.conf.pod INNCONFPOD=/usr/local/news/man/man5/inn.conf.pod # NROFF should be set to an approbate program for formatting the man page # this could be the vendor provided nroff, the FSF's groff (which could be # used for producing PostScript output) or Earl Hood's man2html from # http://www.oac.uci.edu/indiv/ehood/man2html.html # NROFF=man2html NROFF="nroff -man" # Pager should be set to an approbate binary for making the output # readable in the user's desired method. Possible settings include # page, more, less, ghostview, lynx, mozilla, lpr, etc. If no pager # application is desire then by setting it to "cat" will cause the output # to continue on to stdout. PAGER=less # By default the script uses the inn.conf man page before being processed # by nroff to edit in the actual inn.conf settings. The problem with this # approach is that if the format of the inn.conf man page ever changes # assumptions about the format that this script makes will probably break. # Presently, the base/orginal format of the inn.conf man page is in perl # POD documentation. The formatting of this file is less likely to change # in the future and is a cleaner format for automated editing. However, # their is some disadvantages to using this file. First disadvantage, # the POD file is not installed by INN 2.3.0 by default (see INNCONFPOD # enviromental variable for setting the script to find the file in the # correct location). Second disadvantage, pod2man does not appear to # support using stdin so the edited POD must be temporarily stored as a # file. Finally, the last disadvantage, the script is slower due to the # added processing time of pod2man. Weighing the advantages and # disadvantages to both approaches are left to the user. If you wish to # have innconfcheck edit the POD file then change the variable below to # a setting of "1", otherwise leave it with the setting of "0" EDITPOD=0 ################ ### The Script: (non-developers should not need to go beyond this point) # All variable settings in inn.conf should not contain a comment # character of "#" and should have a ":" in the line. These variable names # should then be matched up with the man page "items" in the inn.conf file. # In the INN 2.3 man page, these items appear in the following format: # .Ip "\fIvariable name\fR" 4 # Hence, if there exists an entry in the inn.conf of "verifycancels: false" # then the awk script will produce: # s#^.Ip "\fIvarifycancels\f$" 4#.Ip "\verifycancels: false\f$" 4# # once piped to sed, this expression will replace the man page item to # include the setting from the inn.conf file. The nroff and pager # applications then polish the script off to provide a documented formatted # in a way that is easier to find incorrect setting withen. if [ $EDITPOD -eq 0 ] ; then grep -v "#" $INNCONF | grep ":" | \ awk 'BEGIN { FS = ":" } { print "s#^.Ip \042\\\\fI"$1"\\\\fR\042 4#.Ip \042\\\\fI"$0"\\\\fR\042 4#" }' | \ sed -f - $INNCONFMAN | $NROFF | $PAGER else # The next part is similar to above but provides working from the POD source # instead of from the resulting nroff/man page. This section is discussed # in more detail above with the "EDITPOD" setting. grep -v "#" $INNCONF | grep ":" | \ awk 'BEGIN { FS = ":" } { print "s#=item I<"$1">#=item I<"$0">#" }' | \ sed -f - $INNCONFPOD > /tmp/innconfcheck-$$ pod2man /tmp/innconfcheck-$$ | $NROFF | $PAGER rm -f /tmp/innconfcheck-$$ fi # That's all. # EOF inn-2.6.4/contrib/Makefile0000644000175200017520000000405114002373703015020 0ustar iuliusiulius## $Id: Makefile 9770 2014-12-14 20:55:09Z iulius $ ## ## There are no installation rules or other top-level rules for this ## directory as it's not properly part of INN. Installation should be ## done by the user by hand for those files that they're interested in. include ../Makefile.global top = .. CFLAGS = $(GCFLAGS) ALL = archivegz auth_pass backlogstat cleannewsgroups \ delayer expirectl \ findreadgroups makeexpctl makestorconf mlockfile newsresp \ nnrp.access2readers.conf pullart reset-cnfs respool \ stathist thdexpire \ tunefeed all: $(ALL) warnings: $(MAKE) COPT='$(WARNINGS)' all clean clobber distclean maintclean: rm -f *.o $(ALL) rm -rf .libs $(FIXSCRIPT): @echo Run configure before running make. See INSTALL for details. @exit 1 ## Compilation rules. LINK = $(LIBLD) $(LDFLAGS) -o $@ FIX = $(FIXSCRIPT) STORELIBS = $(LIBSTORAGE) $(LIBHIST) $(LIBINN) $(STORAGE_LIBS) $(LIBS) auth_pass: auth_pass.o ; $(LINK) auth_pass.o $(LIBINN) $(CRYPT_LIBS) expirectl: expirectl.o ; $(LINK) expirectl.o mlockfile: mlockfile.o ; $(LINK) mlockfile.o newsresp: newsresp.o ; $(LINK) newsresp.o $(LIBS) pullart: pullart.o ; $(LINK) pullart.o $(LIBINN) reset-cnfs: reset-cnfs.o ; $(LINK) reset-cnfs.o respool: respool.o ; $(LINK) respool.o $(STORELIBS) archivegz: archivegz.in $(FIX) ; $(FIX) -i archivegz.in backlogstat: backlogstat.in $(FIX) ; $(FIX) backlogstat.in cleannewsgroups: cleannewsgroups.in $(FIX) ; $(FIX) cleannewsgroups.in delayer: delayer.in $(FIX) ; $(FIX) -i delayer.in findreadgroups: findreadgroups.in $(FIX) ; $(FIX) findreadgroups.in makeexpctl: makeexpctl.in $(FIX) ; $(FIX) makeexpctl.in makestorconf: makestorconf.in $(FIX) ; $(FIX) makestorconf.in nnrp.access2readers.conf: nnrp.access2readers.conf.in $(FIX) ; $(FIX) -i nnrp.access2readers.conf.in stathist: stathist.in $(FIX) ; $(FIX) -i stathist.in thdexpire: thdexpire.in $(FIX) ; $(FIX) thdexpire.in tunefeed: tunefeed.in $(FIX) ; $(FIX) -i tunefeed.in inn-2.6.4/contrib/authmysql0000755000175200017520000000545414002373703015345 0ustar iuliusiulius#!/usr/bin/perl -w # # Authenticate users for INN against a MySQL database. # Written by Daniel Marsh # Covered under the same license as INN in general. # You really shouldn't need to edit this file. # To test via tcsh: # ( echo 'ClientAuthname: test' ; echo 'ClientPassword: monkey' ) | ./authmysql.pl use DBI; use strict; # get STDIN and retun it as a HASH my %stdin = get_stdin(); # edit this path to wherever you want your config to reside. my %conf = readconf('/usr/local/news/etc/authmysql.config'); # read our config # create our dbi string for the connection $conf{'database'} = "dbi:mysql:database=$conf{'DB'};host=$conf{'HOST'};"; # open the database connection my $dbh = db_open(%conf); # create the query we're going to pass through my $query = "SELECT $conf{'passcol'} FROM $conf{'TABLE'} WHERE $conf{'usercol'}=\'$stdin{'ClientAuthname'}\'"; # get our statement handler... not really a result. my $result = $dbh->prepare($query); $result->execute; my $cryptedpw = $result->fetchrow_array(); # the database needs to store this encrypted $stdin{'ClientPassword'} = crypt($stdin{'ClientPassword'}, $cryptedpw); # encrypt the client password we were given. # this query is to return a count of 1. there should either be one # match of the encrypted password/username or none. $query = "SELECT COUNT(*) FROM $conf{'TABLE'} WHERE" ."$conf{'usercol'}=\'$stdin{'ClientAuthname'}\' and" ."$conf{'passcol'}=\'$stdin{'ClientPassword'}\'"; $result = $dbh->prepare($query); $result->execute; my $query_result = $result->fetchrow_array(); # this should be 1 or 0, 1 on success $result->finish; # need to get the return shit working now so it will reply proper # information to news clients if( $query_result ) { # the user authenticated fine. print "user:$stdin{'ClientAuthname'}\n"; # return based on nnrpd # auth specs. exit(0); # exit with no error } else { exit(502); # exit with error. username/password incorrect } # subs below sub readconf { my ($file) = @_; my %conf; open(CONF, "$file"); while () { chomp; next if $_ =~ /^#.*$/; next if $_ =~ /\s+/; $_ =~ s/#.*$//g; if ( $_ ne "" ) { my ($key, $value) = split(':', $_, 2); $conf{$key} = $_; } } close(CONF); return(%conf); } sub db_open { my (%conf) = @_; my ($err, $dbh); if( $dbh = DBI->connect($conf{'database'}, $conf{'User'}, $conf{'Pass'}) ) { return($dbh); } else { $err = "Failure opening database ".$DBI::errstr; } return(undef, $err); } sub get_stdin { my %stdin; while () { chomp; next if $_ =~ /^#.*$/; next if $_ =~ /\s+/; $_ =~ s/#.*$//g; $_ =~ s/\s+//g; if ( $_ ne "" ) { my $key = $_; my ($key, $value) = split(':', $_, 2); $stdin{$key} = $value; } } return(%stdin); } inn-2.6.4/contrib/reset-cnfs.c0000644000175200017520000000364414002373703015604 0ustar iuliusiulius/* Quick and Dirty Hack to reset a CNFS buffer without having to DD the * Entire Thing from /dev/zero again. */ #include "config.h" #include "clibrary.h" #include #include #include int main(int argc, char *argv[]) { int fd; int i; char buf[512]; #ifdef DO_LARGEFILES struct stat64 st; #else struct stat st; #endif size_t j, numwr; bool status = true; bzero(buf, sizeof(buf)); for (i = 1; i < argc; i++) { #ifdef DO_LARGEFILES if ((fd = open(argv[i], O_LARGEFILE | O_RDWR, 0664)) < 0) { #else if ((fd = open(argv[i], O_RDWR, 0664)) < 0) { #endif fprintf(stderr, "Could not open file %s: %s\n", argv[i], strerror(errno)); status = false; } else { #ifdef DO_LARGEFILES if (fstat64(fd, &st) < 0) { #else if (fstat(fd, &st) < 0) { #endif fprintf(stderr, "Could not stat file %s: %s\n", argv[i], strerror(errno)); status = false; } else { /* Each bit in the bitfield is 512 bytes of data. Each byte * has 8 bits, so calculate as 512 * 8 bytes of data, plus * fuzz. buf has 512 bytes in it, therefore containing data * for (512 * 8) * 512 bytes of data. */ numwr = (st.st_size / (512*8) / sizeof(buf)) + 50; printf("File %s: %lu %lu\n", argv[i], (unsigned long) st.st_size, (unsigned long) numwr); for (j = 0; j < numwr; j++) { if (!(j % 100)) { printf("\t%lu/%lu\n", (unsigned long) j, (unsigned long) numwr); } write(fd, buf, sizeof(buf)); } status = true; } close(fd); } } if (status) { exit(0); } else { exit(1); } } inn-2.6.4/contrib/mkbuf0000755000175200017520000000066414002373703014420 0ustar iuliusiulius#!/usr/bin/perl sub usage { print STDERR "Usage: $0 \n"; exit 1; } usage if(@ARGV != 2); $buf1k = "\0"x1024; $buf1m = "$buf1k"x1024; $kb = $ARGV[0] * 1; &usage if($kb == 0); if($ARGV[1] eq '-') { open(FILE, "|cat") or die; } else { open(FILE, ">$ARGV[1]") or die; } for($i = 0; $i+1024 <= $kb; $i+=1024) { print FILE $buf1m or die; } if($i < $kb) { print FILE "$buf1k"x($kb-$i) or die; } close FILE; inn-2.6.4/contrib/auth_pass.c0000644000175200017520000001117014002373703015513 0ustar iuliusiulius/* * auth_pass.c ( $Revision: 9701 $ ) * * Abstract: * * This module is the complete source for a sample "authinfo generic" * program. This program takes a user's login name and password * (supplied either as arguments or as responses to prompts) and * validates them against the contents of the password database. * * If the user properly authenticates themselves, a nnrp.auth style * record indicating the user's authenticated login and permitting * reading and posting to all groups is output on stderr (for reading by * nnrpd) and the program exits with a 0 status. If the user fails to * authenticate, then a record with the attempted login name and no * access is output on stderr and a non-zero exit status is returned. * * Exit statuses: * 0 Successfully authenticated. * 1 getpeername() failed, returned a bad address family, or * gethostbyaddr() failed. * 2 Entry not found in password file. * 3 No permission to read passwords, or password field is '*'. * 4 Bad password match. * * Environment: * Run by nnrpd with stdin/stdout connected to the reader and stderr * connected back to nnrpd. This program will need to be run as suid * root on systems where passwords are stored in a file readable only by * root. * * Written 1996 July 6 by Douglas Wade Needham (dneedham@oucsace.cs.ohiou.edu). * */ #include "config.h" #include "clibrary.h" #include "portable/socket.h" #include #include #if HAVE_CRYPT_H # include #endif int main(int argc, char** argv) /*+ * Abstract: * Main routine of the program, implementing all prompting, validation, * and status returns. * * Arguments: * argc Argument count. * argv Null terminated argument vector. * * Returns: * Exits according to program status values. * * Variables: * hp Pointer to host entry. * length General integer variable * password Password given by user. * peername Hostname of the peer. * pwd Pointer to entry from passwd file. * sin Socket address structure. * username User's login name. */ { struct hostent * hp; socklen_t length; char password[256]; char peername[1024]; struct passwd * pwd; struct sockaddr_in sin; char username[32]; /* * Get the user name and password if needed. */ if (argc<2) { fprintf(stdout, "Username: "); fflush(stdout); fgets(username, sizeof(username), stdin); } else { strlcpy(username, argv[1], sizeof(username)); } if (argc<3) { fprintf(stdout, "Password: "); fflush(stdout); fgets(password, sizeof(password), stdin); } else { strlcpy(password, argv[2], sizeof(password)); } /* * Strip CR's and NL's from the end. */ length = strlen(username)-1; while (username[length] == '\r' || username[length] == '\n') { username[length--] = '\0'; } length = strlen(password)-1; while (password[length] == '\r' || password[length] == '\n') { password[length--] = '\0'; } /* * Get the hostname of the peer. */ length = sizeof(sin); if (getpeername(0, (struct sockaddr *)&sin, &length) < 0) { if (!isatty(0)) { fprintf(stderr, "cant getpeername()::%s:+:!*\n", username); exit(1); } strlcpy(peername, "localhost", sizeof(peername)); } else if (sin.sin_family != AF_INET) { fprintf(stderr, "Bad address family %ld::%s:+:!*\n", (long)sin.sin_family, username); exit(1); } else if ((hp = gethostbyaddr((char *)&sin.sin_addr, sizeof(sin.sin_addr), AF_INET)) == NULL) { strlcpy(peername, inet_ntoa(sin.sin_addr), sizeof(peername)); } else { strlcpy(peername, hp->h_name, sizeof(peername)); } /* * Get the user name in the passwd file. */ if ((pwd = getpwnam(username)) == NULL) { /* * No entry in the passwd file. */ fprintf(stderr, "%s::%s:+:!*\n", peername, username); exit(2); } /* * Make sure we managed to read in the password. */ if (strcmp(pwd->pw_passwd, "*")==0) { /* * No permission to read passwords. */ fprintf(stderr, "%s::%s:+:!*\n", peername, username); exit(3); } /* * Verify the password. */ if (strcmp(pwd->pw_passwd, crypt(password, pwd->pw_passwd))!=0) { /* * Password was invalid. */ fprintf(stderr, "%s::%s:+:!*\n", peername, username); exit(4); } /* * We managed to authenticate the user. */ fprintf(stderr, "%s:RP:%s:+:*\n", peername, username); exit(0); } inn-2.6.4/contrib/analyze-traffic.pl0000755000175200017520000001545614002373703017012 0ustar iuliusiulius#!/usr/bin/perl -w ######################################################################## # # analyze-traffic.pl # # Written by Jeffrey M. Vinocur # This work is hereby placed in the public domain by its author. # # Script for keeping track of which newsgroups are receiving the most # traffic (by article count or byte usage), and which peer is most # responsible for the traffic in each high-traffic group. # ######################################################################## # # Usage: # # 1. Add an entry in $pathetc/newsfeeds like the one below, and issue # `ctlinnd reload newsfeeds traffic` (you can change the path to # whatever you like). # # analyze!\ # :*\ # :Tf,WgsbmnN:/usr/local/news/log/traffic # # You may find it useful to restrict the articles being logged, # either by modifing the wildmat pattern, or by using the /exclude # notation to indicate articles that have passed through some # servers should not be included. # # Also, if $USE_ALL_GROUPS (see below) is false, you can leave out # the N flag, which may eliminate some parsing errors. # # 2. Wait for some data. # # 3. Run analyze-traffic.pl on the logged data (you can pass the # filename as an argument or feed the data on standard input). # You probably want to pipe it into a file, `less`, or `tail` as the # output is a line for every group that has received an article # according the input data. # # There are some options hardcoded into the script below, under # "Constants" -- check for customization, if you like. # # 4. Be sure to comment out the newsfeeds entry when done, or set # up some sort of log rotation, or INN will eventually fill up your # disk... # ######################################################################## # # Implementation notes and known bugs: # # - We try (if $USE_ALL_GROUPS is set, below) to count crossposted # towards each listed group (even ones not carried on the server!), # but since some articles have funky Newsgroups headers, that can # backfire. So parsing can fail, which usually results in the # relevant line being skipped, but occasionally can cause Perl to # issue warnings (and perhaps produce funny things in the output). # # A workaround would be to repeat e.g. the Message-ID at the end of # the intput format (i.e. WgsbmnNm), and then the script could read as # many lines as necessary until that ad hoc end-of-record marker # appeared. I haven't found a need for this yet, though. # # - The input format is a sequence of lines, each containing a number of # space-separated fields. Check newsfeeds(5) for what the semantics # are, but an example line (wrapped), for reference, looks like: # # rec.aviation.military [space] # news-out.maxwell.syr.edu [space] # 2796 [space] # <3Jvua.104184$My6.1642017@twister.tampabay.rr.com> [space] # @030247454E45524C31000016AD3100000004@ [space] # rec.aviation.military,rec.travel.usa-canada, [no space here] # sci.electronics.design,sci.econ,sci.environment # # - The output format is a sequence of lines, one for each newsgroup, # with three tab-separated fields. They are sorted by either the # second or third field, depending on $SORT_BY_SIZE, below. The first # field is the name of the newsgroup. The second is the total number # of articles appearing in that newsgroup followed by, in parentheses, # the short name of the peer (see about $TLD_REGEX below) responsible # for the most articles and the percentage it made up. The third is # the total number of kilobytes of (accepted) traffic in that # newsgroup, followed similarly by the peer responsible for the most # traffic in that group. It looks something like this: # # news.lists.filters 1057 arts (63% syr) 7105.9 KB (36% cox) # # The short names are made by taking the last component of the # (dot-separated) peer name that doesn't match /$TLD_REGEX/. The idea # is that, for example, "isc.org" would be listed as "isc", and # "demon.co.uk" would be listed as "demon". Adjust $TLD_REGEX as # needed to trim the top-level domains in your part of the world. # # If your peers have very long short names, the output may look # somewhat funny. Similar things can happen with newsgroup names, so # those longer than $FIELD1_WIDTH will be truncated to fit. (You can # set $FIELD1_WIDTH to '' to skip this truncation, in which case the # first column will not be space-padded and the output will look a bit # ragged.) # ######################################################################## # # Constants: my $USE_ALL_GROUPS = 1; # if 0, use only group article is stored under my $SORT_BY_SIZE = 1; # if 0, sort output by number of articles my $FIELD1_WIDTH = 30; # maximum length of newsgroup name, '' for none my $TLD_REGEX = '^(?:com|net|org|edu|gov|mil|ac|co|uk|au|ca|de)$'; # feel free to add any others as needed ######################################################################## use strict; my %stats; while( <> ) { my ($group, $peer, $bytes, $id, $token, @Newsgroups) = split; next unless ($USE_ALL_GROUPS ? @Newsgroups : $token); # bad input line my @groups = map { split /\s*,\s*/ } @Newsgroups; foreach ($USE_ALL_GROUPS && @groups ? @groups : $group) { my $s = $stats{$_} ||= { count => 0, bytes => 0, peers => {}, }; $s->{count}++; $s->{bytes} += $bytes; $s->{peers}->{$peer}->{count}++; $s->{peers}->{$peer}->{bytes} += $bytes; } } my $f = $SORT_BY_SIZE ? 'bytes' : 'count'; foreach (sort { $stats{$a}->{$f} <=> $stats{$b}->{$f} } (keys %stats)) { my %s = %{$stats{$_}}; my ($topcount,$topcountwho) = &max('count', $s{peers}); my ($topbytes,$topbyteswho) = &max('bytes', $s{peers}); $topcountwho = &trim($topcountwho); $topbyteswho = &trim($topbyteswho); my $countf = int(100 * $topcount / $s{count}); my $bytesf = int(100 * $topbytes / $s{bytes}); my $kb = 0.1 * int($s{bytes} * 10 / 1024); my $ng = $FIELD1_WIDTH eq '' ? $_ : substr($_,0,$FIELD1_WIDTH); print +(sprintf("%-${FIELD1_WIDTH}s\t", $ng)), "$s{count} arts ($countf% $topcountwho)\t", "${kb} KB ($bytesf% $topbyteswho)\n"; } 1; sub trim { my @parts = split(/\./, $_[0]); my $part; while( defined($part = pop(@parts)) ) { last unless $part =~ /$TLD_REGEX/o; } return defined($part) ? $part : $_[0]; } sub max { my $x = 0; my $who; my ($field, $listref) = @_; while( my ($peer, $stats) = each %{$listref} ) { if( $stats->{$field} > $x ) { $x = $stats->{$field}; $who = $peer; } } return ($x, $who); } inn-2.6.4/contrib/makeexpctl.in0000644000175200017520000000523114002373703016046 0ustar iuliusiulius#! /usr/bin/perl -w # fixscript will replace this line with code to load INN::Config # Create expire.ctl script based on recently read articles. Argument gives # scale factor to use to adjust expires. $readfile="$INN::Config::pathdb/readgroups"; $expirectl=$INN::Config::expirectl; $curtime = time; $oldtime = $curtime - 30 * 86400; # 30 days in the past if (open(RDF, $readfile)) { while () { chop; @foo=split(/ /); # foo[0] should be group, foo[1] lastreadtime if ($foo[1] < $oldtime) { next; # skip entries that are too old. } $groups{$foo[0]} = $foo[1]; } close(RDF); } $scale = $ARGV[0]; if ($scale <= 0) { die "invalid scale parameter\n"; } rename($expirectl, "$expirectl.OLD") || die "rename $expirectl failed!\n"; open(OUTFILE, ">$expirectl") || die "open $expirectl for write failed!\n"; print OUTFILE <<'EOF' ; ## expire.ctl - expire control file ## Format: ## /remember/: ## :::: ## First line gives history retention; other lines specify expiration ## for newsgroups. Must have a "*:A:..." line which is the default. ## Wildmat-style patterns for the newsgroups ## Pick one of M U A -- modifies pattern to be only ## moderated, unmoderated, or all groups ## Minimum number of days to keep article ## Default number of days to keep the article ## Flush article after this many days ## , , and can be floating-point numbers or the ## word "never". Times are based on the arrival time for expire and expireover ## (unless -p is used; see expire(8) and expireover(8)), and on the posting ## time for history retention. ## ## See the expire.ctl man page for more information. # How long to remember old history entries for. /remember/:11 # EOF # defaults for most groups. printline("*", "A", 1); printline("alt*,misc*,news*,rec*,sci*,soc*,talk*,vmsnet*","U",3); printline("alt*,misc*,news*,rec*,sci*,soc*,talk*,vmsnet*","M",5); printline("comp*,gnu*,info*,ok*,ecn*,uok*", "U", 5); printline("comp*,gnu*,info*,ok*,ecn*,uok*", "M", 7); # and now handle each group that's regularly read, # assinging them 3* normal max expire foreach $i (keys %groups) { printline($i, "A", 21); } # and now put some overrides for groups which are too likely to fill spool if # we let them go to autoexpire. printline("*binaries*,*pictures*", "A", 0.5); printline("control*","A",1); printline("control.cancel","A",0.5); printline("news.lists.filters,alt.nocem.misc","A",1); close(OUTFILE); exit(1); sub printline { local($grpstr, $mflag, $len) = @_; print OUTFILE $grpstr,":",$mflag,":",$len*$scale,":",$len*$scale,":",$len*$scale,"\n"; } inn-2.6.4/contrib/archivegz.in0000644000175200017520000002124614002373703015677 0ustar iuliusiulius#!/usr/bin/perl # Copyright 1999 Stephen M. Benoit, Service Providers of America. # See notice at end of this file. # # Filename: archivegz.pl # Author: Stephen M. Benoit (benoits@servicepro.com) # Created: Wed Apr 14 13:56:01 1999 # Version: $Id: archivegz.in 4329 2001-01-14 13:47:52Z rra $ # $RCSID='$Id: archivegz.in 4329 2001-01-14 13:47:52Z rra $ '; # Specify command line options, and decode the command line. require 'newgetopt.pl'; require 'newusage.pl'; @opts = ( "help|usage;;print this message", "version;;print version", "a=s;;directory to archive in instead of the default", "f;;directory names will be flattened out", "i=s;;append one line to the index file for each article (Destination name, Message ID, Subject)", "m;; Files are copied by making a link. Not applicable, ignored", "r;;Suppress stderr redirection to /var/log/news/errlog", "n=s;;the news spool (source) directory (default=/var/spool/news/)", "t=i;;timeout that separates batches (default 10 seconds)", ";;input", # Examples. # # "OPT;;Option without an argument", # "OPT!;;Negatable option without an argument", # "VAR=T;;Option with mandatory argumet T = s(tring),i(nteger), or f(loat). # "VAR:T;;Option with optional argument. # "OPT|AAA|BBB";;AAA and BBB are aliases for OPT", # "VAR=T@";;Push option argument onto array @opt_VAR" ); $ignorecase = 0; $badopt = !&NGetOpt(&NMkOpts(@opts)); # $badarg = (@ARGV != 0); if ($badarg || $badopt || $opt_help) { &NUsage($0,0,'',@opts); exit ($badopt||$badarg); } if ($opt_version) {print STDERR "$RCSID\n"; exit 0} # -------------------------------------------------------------------- # --- constants and defaults --- $NEWS_ROOT = "/var/spool/news/"; $NEWS_ERR = "/var/log/news/errlog"; $NEWS_ARCHIVE = $NEWS_ROOT . "news.archive/"; $timeout = 10; if ($opt_t) { $timeout = $opt_t;} if ($timeout<1) {$timeout=1;} # -------------------------------------------------------------------- sub regexp_escape { local($data)=@_; $data =~ s+\\+\\\\+gi; # replace \ with \\ $data =~ s+\/+\\\/+gi; # replace / with \/ $data =~ s/([\+\*\?\[\]\(\)\{\}\.\|])/\\$1/gi; # replace +*?[](){}.| return $data; } sub fhbits { local(@fhlist) = split(' ',$_[0]); local($bits); for (@fhlist) { vec($bits,fileno($_),1) = 1; } $bits; } sub timed_getline { my ($fileh,$timeout)=@_; my $filehandle = (ref($fileh) ? (ref($fileh) eq 'GLOB' || UNIVERSAL::isa($fileh, 'GLOB') || UNIVERSAL::isa($fileh, 'IO::Handle')) : (ref(\$fileh) eq 'GLOB')); local(*FILEH) = *$fileh{FILEHANDLE}; local($rin,$win,$ein); local($rout,$wout,$eout); $rin = $win = $ein = ''; $rin = fhbits('FILEH'); $ein = $rin | $win; local($nfound); local($offset)=0; local($accum)=''; local($done)=0; local($result); $nfound = select($rout=$rin, $wout=$win, $eout=$ein, $timeout); if ($nfound>0) { # use sysread() to get characters up to end-of-line (incl.) while (!$done) { $result = sysread(FILEH, $accum, 1, $offset); if ($result<=0) { $done=1; return undef; } if (substr($accum,$offset,1) eq "\n") { $done=1; } else { $offset+=$result; } } } return $accum; } # -------------------------------------------------------------------- # --- source spool directory --- if ($opt_n) { if ($opt_n !~ /^\//) # absolute path? { $opt_n = $NEWS_ROOT . $opt_n; } if ($opt_n !~ /\/$/) # must end with / { $opt_n .= '/'; } $NEWS_ROOT = $opt_n; } # --- archive directory --- if ($opt_a) { if ($opt_a !~ /^\//) # absolute path? { $opt_a = $NEWS_ROOT . $opt_a; } if ($opt_a !~ /\/$/) # must end with / { $opt_a .= '/'; } $NEWS_ARCHIVE = $opt_a; } # --- redirect stderr --- if (!$opt_r) { open(SAVEERR, ">&STDERR"); open(STDERR, ">>$NEWS_ERR") || die "Can't redirect stderr"; } # --- get input file opened --- if ($infilename=shift(@ARGV)) { if ($infilename !~ /^\//) # absolute filename? { $infilename = $NEWS_ROOT . $infilename; } } else { $infilename="-"; } open(INFILE,"<$infilename"); $done=0; while (!$done) { %sourcefile=(); %destfile=(); %destname=(); # --- loop over each line in infile --- # comments start with '#', ignore blank lines, each line is a filename while ($srcfile = &timed_getline(INFILE,$timeout)) { if ($srcfile =~ /\#/) {$srcfile = $`;} if ($srcfile =~ /^\s*/) {$srcfile = $';} if ($srcfile =~ /\s*$/) {$srcfile = $`;} if ($srcfile) # if a filename survived all that... { if ($srcfile !~ /^\//) # absolute filename? { $srcfile = $NEWS_ROOT . $srcfile; } # $srcfile is now a valid, absolute filename # split filename into news directory, newsgroup and article number $artnum=-1; $remaining=$srcfile; if ($remaining =~ /\/(\d*)$/) # remove / and article number { $artnum = $1; $remaining=$`;} $regex = ®exp_escape($NEWS_ROOT); if ($remaining =~ /^$regex/) # split off news dir { $newsdir = $&; $grpdir = $';} else { $newsdir = ''; $grpdir = $remaining; } # ... otherwise, grp = dir $newsgrp = $grpdir; $newsgrp =~ s/\//\./g; # replace slash (/) with dot (.) if ($opt_f) { $grpdir = "$newsgrp.gz"; } else { $grpdir .= "/archive.gz"; } $destfile = $NEWS_ARCHIVE . $grpdir; # print STDERR "$srcfile --> $newsgrp --> $destfile\n"; if ($sourcefile{$newsgrp}) {$sourcefile{$newsgrp} .= " ";} $sourcefile{$newsgrp} .= $srcfile; $destfile{$newsgrp} = $destfile; $destname{$newsgrp} = $grpdir; } } # --- is there anything to do at this time? --- if (%destfile) { # --- open INDEX --- if ($opt_i) { # make sure directory exists if ($opt_i =~ /\/[^\/]*$/) { $dirbase=$`; system("mkdir -p $dirbase"); } open(INDEX,">>$opt_i"); } # --- make sure that archive file can be written (make parent dirs) --- if ($destfile{$group} =~ /\/[^\/]*$/) { $dirbase=$`; system("mkdir -p $dirbase"); } # --- process each article --- foreach $group (keys(%destfile)) { # --- gzip the concatenated document, appending archive file --- open(GZIP, "|gzip -c >> $destfile{$group}") || die "Can't open gzip"; # --- concatenate the articles, keeping header info if needed --- @accum_headers=(); foreach $srcfile (split(/\s+/, $sourcefile{$group})) { # print STDERR "reading $srcfile...\n"; $this_doc=''; open(DOC, "<$srcfile"); while ($line=) { $this_doc .= $line; } close(DOC); print GZIP $this_doc; if ($opt_i) { # --- get header information and store it in index $subject=''; $mesageid=''; $destname=''; if ($this_doc =~ /Subject:\s*(.*)/) { $subject = $1; } if ($subject =~ /^\s*/) {$subject = $';} if ($subject =~ /\s*$/) {$subject = $`;} if ($this_doc =~ /Message-ID:\s*(.*)/) {$messageid = $1; } if ($messageid =~ /^\s*/) {$messageid = $';} if ($messageid =~ /\s*$/) {$messageid = $`;} print INDEX "$destname{$group} $messageid $subject\n"; } } close(GZIP); } # --- close index file --- if ($opt_i) { close(INDEX); } } if (!defined($srcfile)) # file was closed { $done=1; last; # "break" } } # --- restore stderr --- if (!$opt_r) { close(STDERR); open(STDERR,">>&SAVEERR"); } # --- close input file --- close(INFILE); __END__ # Local Variables: # mode: perl # End: # Copyright 1999 Stephen M. Benoit, Service Providers of America (SPA). # # Permission to use, copy, modify, and distribute this software and its # documentation for any purpose without fee is hereby granted without fee, # provided that the above copyright notice appear in all copies and that both # that copyright notice and this permission notice appear in supporting # documentation, and that the name of SPA not be used in advertising or # publicity pertaining to distribution of the software without specific, # written prior permission. SPA makes no representations about the # suitability of this software for any purpose. It is provided "as is" # without express or implied warranty. # # SPA DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL # SPA BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY # DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN # AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. inn-2.6.4/contrib/newsresp.c0000644000175200017520000001721614002373703015401 0ustar iuliusiulius/* newsresp.c - EUnet - bilse */ /* * From: Koen De Vleeschauwer * Subject: Re: innfeed-users: innfeed: measuring server response time * To: jeff.garzik@spinne.com (Jeff Garzik) * Date: Tue, 13 May 1997 16:33:27 +0200 (MET DST) * Cc: innfeed-users@vix.com * * > Is there an easy way to measure server response time, and print it out * > on the innfeed status page? Cyclone's nntpTime measures login banner * > response time and an article add and lookup operation. * > * > It seems to me that innfeed could do something very similar. It could * > very easily sample gettimeofday() or Time.Now to determine a remote * > server's average response time for lookups, lookup failures, article * > send throughput, whatever. * > * > These statistics might be invaluable to developers creating advanced * > connection and article delivery algorithms. If I knew, for example, * > that a site's article send/save throughput was really fast, but history * > lookups were really slow, my algorithm could reserve a channel or two * > for TAKETHIS-only use. * * We use a stand-alone program which opens up an additional nntp channel * from time to time and takes a peek at the various response times. * It's also interesting to tune one's own box. * I've included the source code; please consider this supplied 'as is'; * bugs and features alike. SunOS, Solaris and Irix ought to be ok; * eg. gcc -traditional -o newsresp ./newsresp.c -lnsl -lsocket on S0laris. * If a host has an uncommonly long banner you may have to change a constant * somewhere; forget. Please note one has to interpret the output; * eg. whether one is measuring rtt or history lookup time. * * Basic usage is: * news 1 % newsresp -n 5 news.eu.net * --------------------------------- * news.eu.net is 134.222.90.2 port 119 * elap diff * 0.0 0.0 Connecting ... * 0.0 0.0 OK, waiting for prompt * 0.0 0.0 <<< 200 EU.net InterNetNews server INN 1.5.1 17-Dec-1996 re [...] * 0.0 0.0 >>> ihave <244796399@a> * 0.0 0.0 <<< 335 * 0.0 0.0 >>> . * 0.0 0.0 <<< 437 Empty article * 0.0 0.0 >>> ihave <244796398@a> * 0.0 0.0 <<< 335 * 0.0 0.0 >>> . * 0.0 0.0 <<< 437 Empty article * 0.0 0.0 >>> ihave <244796397@a> * 0.0 0.0 <<< 335 * 0.0 0.0 >>> . * 0.0 0.0 <<< 437 Empty article * 0.0 0.0 >>> ihave <244796396@a> * 0.1 0.0 <<< 335 * 0.1 0.0 >>> . * 0.1 0.0 <<< 437 Empty article * 0.1 0.0 >>> ihave <244796395@a> * 0.1 0.0 <<< 335 * 0.1 0.0 >>> . * 0.1 0.0 <<< 437 Empty article * 0.1 0.0 >>> quit * 0.1 0.0 <<< 205 . */ #include "clibrary.h" #include "portable/socket.h" #include #ifdef HAVE_SYS_TIME_H # include #endif #include #define NNTPPORT 119 void error(const char *); void fatal(const char *); void ierror(const char *, const char *); void ifatal(const char *, const char *); unsigned int do_time(unsigned int); void ptime(void); void massagebuff(int, char *); bool punt(int); struct sockaddr_in sock_in; int sock; char buf[1024]; int main(int argc, char *argv[]) { int errflg = 0, c; bool status = true; struct hostent *host; unsigned long temp; unsigned numart = 1; struct protoent *tcp_proto; char **whoP; while ( (c = getopt(argc,argv,"n:")) != -1 ) switch ( c ) { case 'n': sscanf(optarg,"%u",&numart); break; default : errflg++; } if ( numart == 0 || optind == argc ) errflg++; if ( errflg ) { fprintf(stderr,"Usage: %s [-n articles] host ...\n",argv[0]); exit(1); } if ( (tcp_proto = getprotobyname("tcp")) == 0 ) fatal("getprotobyname"); for ( whoP = argv+optind; *whoP != 0; whoP++ ) { if ( (sock = socket(PF_INET,SOCK_STREAM,tcp_proto->p_proto)) < 0 ) fatal("socket"); temp = inet_addr(*whoP); if ( temp != (unsigned long) -1 ) { sock_in.sin_addr.s_addr = temp; sock_in.sin_family = AF_INET; } else { host = gethostbyname(*whoP); if ( host ) { sock_in.sin_family = host->h_addrtype; memcpy(&sock_in.sin_addr,host->h_addr,host->h_length); } else { fprintf(stderr,"gethostbyname can't find %s\n",*whoP); exit(1); } } sock_in.sin_port = htons(NNTPPORT); printf("---------------------------------\n%s is %s port %d\n", *whoP,inet_ntoa(sock_in.sin_addr),ntohs(sock_in.sin_port)); status = punt(numart); close(sock); } if (status) { exit(0); } else { exit(1); } } void error(const char *what) { ptime(); fflush(stdout); perror(what); } void fatal(const char *what) { error(what); exit(2); } void ierror(const char *how, const char *what) { printf("Expected %s, received %s; bailing out.\n", how, what); } void ifatal(const char *how, const char *what) { ierror(how, what); exit(1); } unsigned int do_time(unsigned int start) { struct timeval now; gettimeofday(&now,(struct timezone *)0); return ( now.tv_sec*1000 + now.tv_usec/1000 - start ); } unsigned int start, elapsed, diff; void ptime(void) { diff = elapsed; elapsed = do_time(start); diff = elapsed - diff; printf("%5.1f %5.1f ", ((double)elapsed)/1000.0, ((double)diff)/1000.0); } void massagebuff(int bread, char *buffer) { char *p; if ( bread > 55 ) strcpy(buffer+55," [...]\n"); else buffer[bread] = '\0'; for ( p = buffer; *p != '\0'; ) if ( *p != '\r' ) /* We like to do it RISC style. */ p++; else { *p = ' '; p++; } } bool punt(int numart) { static char ihave[32], dot[] = ".\r\n", quit[] = "quit\r\n"; struct timeval start_tv; int bread; printf(" elap diff\n"); diff = elapsed = 0; gettimeofday(&start_tv,(struct timezone *)0); start = start_tv.tv_sec*1000 + start_tv.tv_usec/1000; ptime(); printf("Connecting ...\n"); if ( connect(sock,(struct sockaddr*)&sock_in,sizeof(sock_in)) < 0 ) { error("connect"); return false; } ptime(); printf("OK, waiting for prompt\n"); if ( (bread=read(sock,buf,sizeof(buf))) < 0 ) { error("read socket"); return false; } massagebuff(bread,buf); ptime(); printf("<<< %s",buf); if ( strncmp(buf,"200",3) != 0 && strncmp(buf,"201",3) != 0 ) { ierror("200 or 201",buf); return false; } do { snprintf(ihave,sizeof(ihave),"ihave <%u@a>\r\n",start+numart); ptime(); printf(">>> %s",ihave); if ( write(sock,ihave,strlen(ihave)) != (int) strlen(ihave) ) { error("write socket"); return false; } if ( (bread=read(sock,buf,sizeof(buf))) < 0 ) { error("read socket"); return false; } massagebuff(bread,buf); ptime(); printf("<<< %s",buf); if ( strncmp(buf,"335",3) != 0 && strncmp(buf,"435",3) != 0 ) { ierror("335 or 435",buf); return false; } if ( strncmp(buf,"335",3) == 0 ) { ptime(); printf(">>> %s",dot); if ( write(sock,dot,sizeof(dot)-1) != sizeof(dot)-1 ) { error("write socket"); return false; } if ( (bread=read(sock,buf,sizeof(buf))) < 0 ) { error("read socket"); return false; } massagebuff(bread,buf); ptime(); printf("<<< %s",buf); if ( strncmp(buf,"437",3) != 0 && strncmp(buf,"235",3) != 0 ) { ierror("437 or 235",buf); return false; } } } while ( --numart != 0 ); ptime(); printf(">>> %s",quit); if ( write(sock,quit,sizeof(quit)-1) != sizeof(quit)-1 ) { error("write socket"); return false; } if ( (bread=read(sock,buf,sizeof(buf))) < 0 ) { error("read socket"); return false; } massagebuff(bread,buf); ptime(); printf("<<< %s",buf); if ( strncmp(buf,"205",3) != 0 ) { ierror("205",buf); return false; } return true; } inn-2.6.4/contrib/sample.init.script0000644000175200017520000000266214002373703017037 0ustar iuliusiulius#! /bin/sh # $Id: sample.init.script 10148 2017-06-05 12:24:07Z iulius $ # # This is a simple, bare-bones example of a SysV-style init.d script for INN. # It tries to increase the file descriptor limits to the maximum allowed by # the system since INN and related programs can be file descriptor hogs. test -f '/rc.news' || exit 0 start () { ulimit -n unlimited # Start INN. su news -s /bin/sh -c '/rc.news' >> /rc.news 2>&1 # Start another nnrpd daemon, handling initial TLS connections, on port 563. #su news -s /bin/sh -c '/nnrpd -D -p 563 -S' >> /rc.news 2>&1 } case "$1" in start) start ;; stop) # Stop INN. su news -s /bin/sh -c '/rc.news stop' >> /rc.news 2>&1 # Stop possible other nnrpd daemons. One of the two following commands is enough. #start-stop-daemon --stop --name nnrpd --quiet --oknodo #su news -s /bin/sh -c 'killall nnrpd' >> /rc.news 2>&1 ;; reload|force-reload) # Reload INN. /ctlinnd -t 20 reload '' 'reload asked' ;; restart) # Restart INN. if [ -f '/innd.pid' ]; then /ctlinnd -t 20 throttle 'restart asked' > /dev/null || true /ctlinnd -t 20 xexec innd > /dev/null || start else start fi ;; *) echo "Recognized arguments: start|stop|reload|force-reload|restart" >&2 exit 1 ;; esac exit 0 inn-2.6.4/contrib/tunefeed.in0000644000175200017520000004225214002373703015514 0ustar iuliusiulius#!/usr/bin/perl $version = q$Id: tunefeed.in 9767 2014-12-07 21:13:43Z iulius $; # # tunefeed -- Compare active files with a remote site to tune a feed. # Copyright 1998 by Russ Allbery # # This program is free software; you can redistribute it and/or modify it # under the same terms as Perl itself. ############################################################################ # Site configuration ############################################################################ # A list of hierarchies in the Big Eight. %big8 = map { $_ => 1 } qw(comp humanities misc news rec sci soc talk); # A list of hierarchies that are considered global and not language # hierarchies. %global = map { $_ => 1 } qw(bionet bit biz borland ddn gnu gov ieee info linux k12 microsoft netscape tnn vmsnet); # The pattern matching local-only hierarchies (that we should disregard when # doing feed matching). %ignore = map { $_ => 1 } qw(clari control junk); ############################################################################ # Modules and declarations ############################################################################ require 5.003; use Getopt::Long qw(GetOptions); use strict; use vars qw(%big8 $days %global %ignore $threshold %traffic $version); ############################################################################ # Active file hashing and analysis ############################################################################ # Read in an active file, putting those groups into a hash where the key is # the name of the group and the value is always 1. If the optional third # argument is true, exclude any groups in the hierarchies listed in %local # and use this active file to store traffic information (in a rather # simple-minded fashion). sub hash { my ($file, $hash, $local) = @_; open (ACTIVE, $file) or die "$0: cannot open $file: $!\n"; local $_; while () { my ($group, $high, $low, $flags) = split; next if ($flags =~ /^=|^x/); my $hierarchy = (split (/\./, $group, 2))[0]; next if ($local && $ignore{$hierarchy}); $$hash{$group} = 1; $traffic{$group} = ($high - $low) / $days if $local; } close ACTIVE; } # Read in a file that gives traffic statistics. We assume it's in the form # group, whitespace, number of articles per day, and we just read it # directly into the %traffic hash. sub traffic { my ($file) = @_; open (TRAFFIC, $file) or die "$0: cannot open $file: $!\n"; local $_; while () { my ($group, $traffic) = split; $traffic{$group} = $traffic; } close TRAFFIC; } # Pull off the first X nodes of a group name. sub prefix { my ($group, $count) = @_; my @group = split (/\./, $group); splice (@group, $count); join ('.', @group); } # Find the common hierarchical prefix of a list. sub common { my (@list) = @_; my @prefix = split (/\./, shift @list); local $_; while (defined ($_ = shift @list)) { my @group = split /\./; my $i; $i++ while ($prefix[$i] && $prefix[$i] eq $group[$i]); if ($i <= $#prefix) { splice (@prefix, $i) } } join ('.', @prefix); } # Given two lists, a list of groups that the remote site does have and a # list of groups that the remote site doesn't have, in a single hierarchy, # perform a smash. The object is to find the minimal pattern that expresses # just the groups they want. We're also given the common prefix of all the # groups in the have and exclude lists, and a flag indicating whether we're # coming in with a positive assumption (all groups sent unless excluded) or # a negative assumption (no groups sent unless added). sub smash { my ($have, $exclude, $top, $positive) = @_; my (@positive, @negative); my $level = ($top =~ tr/././) + 1; # Start with the positive assumption. We make copies of our @have and # @exclude arrays since we're going to be needing the virgin ones again # later for the negative assumption. If we're coming in with the # negative assumption, we have to add a wildcarded entry to switch # assumptions, and we also have to deal with the cases where there is a # real group at the head of the hierarchy. my @have = @$have; my @exclude = @$exclude; if ($top eq $have[0]) { shift @have; push (@positive, "$top*") unless $positive; } else { if ($top eq $exclude[0]) { if ($positive && $traffic{$top} > $threshold) { push (@positive, "!$top"); } shift @exclude; } push (@positive, "$top.*") unless $positive; } # Now that we've got things started, keep in mind that we're set up so # that every group will be sent *unless* it's excluded. So we step # through the list of exclusions. The idea here is to pull together all # of the exclusions with the same prefix (going one level deeper into # the newsgroup names than we're currently at), and then find all the # groups with the same prefix that the remote site *does* want. If # there aren't any, then we can just exclude that whole prefix provided # that we're saving enough traffic to make it worthwhile (checked # against the threshold). If there are, and if the threshold still # makes it worthwhile to worry about this, we call this sub recursively # to compute the best pattern for that prefix. while (defined ($_ = shift @exclude)) { my ($prefix) = prefix ($_, $level + 1); my @drop = ($_); my @keep; my $traffic = $traffic{$_}; while ($exclude[0] =~ /^\Q$prefix./) { $traffic += $traffic{$exclude[0]}; push (@drop, shift @exclude); } $prefix = common (@drop); my $saved = $traffic; while (@have && $have[0] le $prefix) { shift @have } while ($have[0] =~ /^\Q$prefix./) { $traffic += $traffic{$have[0]}; push (@keep, shift @have); } next unless $saved > $threshold; if (@keep) { $traffic{"$prefix*"} = $traffic; push (@positive, smash (\@keep, \@drop, $prefix, 1)); } elsif (@drop == 1) { push (@positive, "!$_"); } elsif ($prefix eq $_) { push (@positive, "!$prefix*"); } else { push (@positive, "!$prefix.*"); } } # Now we do essentially the same thing, but from the negative # perspective (adding a wildcard pattern as necessary to make sure that # we're not sending all groups and then finding the groups we are # sending and trying to smash them into minimal wildcard patterns). @have = @$have; @exclude = @$exclude; if ($top eq $exclude[0]) { shift @exclude; push (@negative, "!$top*") if $positive; } else { if ($top eq $have[0]) { push (@negative, $top) unless $positive; shift @have; } push (@negative, "!$top.*") if $positive; } # This again looks pretty much the same as what we do for the positive # case; the primary difference is that we have to make sure that we send # them every group that they want, so we still err on the side of # sending too much, rather than too little. while (defined ($_ = shift @have)) { my ($prefix) = prefix ($_, $level + 1); my @keep = ($_); my @drop; my $traffic = $traffic{$_}; while ($have[0] =~ /^\Q$prefix./) { $traffic += $traffic{$have[0]}; push (@keep, shift @have); } $prefix = common (@keep); while (@exclude && $exclude[0] le $prefix) { shift @exclude } my $saved = 0; while ($exclude[0] =~ /^\Q$prefix./) { $saved += $traffic{$exclude[0]}; push (@drop, shift @exclude); } if (@drop && $saved > $threshold) { $traffic{"$prefix*"} = $traffic + $saved; push (@negative, smash (\@keep, \@drop, $prefix, 0)); } elsif (@keep == 1) { push (@negative, $_); } elsif ($prefix eq $_) { push (@negative, "$prefix*"); } else { push (@negative, "$prefix.*"); } } # Now that we've built both the positive and negative case, we decide # which to return. We want the one that's the most succinct, and if # both descriptions are equally succinct, we return the negative case on # the grounds that it's likely to send less of what they don't want. (@positive < @negative) ? @positive : @negative; } ############################################################################ # Output ############################################################################ # We want to sort Big Eight ahead of alt.* ahead of global non-language # hierarchies ahead of regionals and language hierarchies. sub score { my ($hierarchy) = @_; if ($big8{$hierarchy}) { return 1 } elsif ($hierarchy eq 'alt') { return 2 } elsif ($global{$hierarchy}) { return 3 } else { return 4 } } # Our special sort routine for hierarchies. It calls score to get a # hierarchy score and sorts on that first. sub by_hierarchy { (score $a) <=> (score $b) || $a cmp $b; } # Given a reference to a list of patterns, output it in some reasonable # form. Currently, this is lines prefixed by a tab, with continuation lines # like INN likes to have in newsfeeds, 76 column margin, and with a line # break each time the hierarchy score changes. sub output { my ($patterns) = @_; my ($last, $line); for (@$patterns) { my ($hierarchy) = /^!?([^.]+)/; my $score = score $hierarchy; $line += 1 + length $_; if (($last && $score > $last) || $line > 76) { print ",\\\n\t"; $line = 8 + length $_; } elsif ($last) { print ','; } else { print "\t"; $line += 8; } print; $last = $score; } print "\n"; } ############################################################################ # Main routine ############################################################################ # Clean up the name of this program for error messages. my $fullpath = $0; $0 =~ s%.*/%%; # Parse the command line. Our argument is the path to an active file (we # tell the difference by seeing if it contains a /). my ($help, $print_version); Getopt::Long::config ('bundling'); GetOptions ('help|h' => \$help, 'days|d=i' => \$days, 'threshold|t=i' => \$threshold, 'version|v' => \$print_version) or exit 1; # Set a default for the minimum threshold traffic required to retain an # exclusion, and assume that active file differences represent one day of # traffic unless told otherwise. $threshold = (defined $threshold) ? $threshold : 250; $days ||= 1; # If they asked for our version number, abort and just print that. if ($print_version) { my ($program, $ver) = (split (' ', $version))[1,2]; $program =~ s/,v$//; die "$program $ver\n"; } # If they asked for help, give them the documentation. if ($help) { print "Feeding myself to perldoc, please wait....\n"; exec ('perldoc', '-t', $fullpath) or die "$0: can't fork: $!\n"; } # Hash the active files, skipping groups we ignore in the local one. Make # sure we have our two files listed first. unless (@ARGV == 2 || @ARGV == 3) { die "Usage: $0 [-hv] [-t ] []\n"; } my (%local, %remote); hash (shift, \%local, 1); hash (shift, \%remote); traffic (shift) if @ARGV; # Now, we analyze the differences between the two feeds. We're trying to # build a pattern of what *we* should send *them*, so stuff that's in # %remote and not in %local doesn't concern us. Rather, we're looking for # stuff that we carry that they don't, since that's what we'll want to # exclude from a full feed. my (%have, %exclude, %count, $have, $exclude, $positive); for (sort keys %local) { my ($hierarchy) = (split /\./); $count{$hierarchy}++; $traffic{"$hierarchy*"} += $traffic{$_}; if ($remote{$_}) { push (@{$have{$hierarchy}}, $_); $have++ } else { push (@{$exclude{$hierarchy}}, $_); $exclude++ } } my @patterns; if ($have > $exclude * 4) { push (@patterns, "*"); $positive = 1; } for (sort by_hierarchy keys %count) { if ($have{$_} && !$exclude{$_}) { push (@patterns, "$_.*") unless $positive; } elsif ($exclude{$_} && !$have{$_}) { push (@patterns, "!$_.*") if $positive; } else { push (@patterns, smash ($have{$_}, $exclude{$_}, $_, $positive)); } } output (\@patterns); __END__ ############################################################################ # Documentation ############################################################################ =head1 NAME tunefeed - Build a newsgroups pattern for a remote feed =head1 SYNOPSIS B [B<-hv>] [B<-t> I] [B<-d> I] I I [I] =head1 DESCRIPTION Given two active files, B generates an INN newsfeeds pattern for a feed from the first site to the second, that sends the second site everything in its active file carried by the first site but tries to minimize the number of rejected articles. It does this by noting differences between the two active files and then trying to generate wildcard patterns that cover the similarities without including much (or any) unwanted traffic. I and I should be standard active files. You can probably get the active file of a site that you feed (provided they're running INN) by connecting to their NNTP port and typing C. B makes an effort to avoid complex patterns when they're of minimal gain. I is the number of messages per day at which to worry about excluding a group; if a group the remote site doesn't want to receive gets below that number of messages per day, then that group is either sent or not sent depending on which choice results in the simplest (shortest) wildcard pattern. If you want a pattern that exactly matches what the remote site wants, use C<-t 0>. Ideally, B likes to be given the optional third argument, I, which points at a file listing traffic numbers for each group. The format of this file is a group name, whitespace, and then the number of messages per day it receives. Without such a file, B will attempt to guess traffic by taking the difference between the high and low numbers in the active file as the amount of traffic in that group per day. This will almost always not be accurate, but it should at least be a ballpark figure. If you know approximately how many days of traffic the active file numbers represent, you can tell B this information using the B<-d> flag. B's output will look something like: comp.*,humanities.classics,misc.*,news.*,rec.*,sci.*,soc.*,talk.*,\ alt.*,!alt.atheism,!alt.binaries.*,!alt.nocem.misc,!alt.punk*,\ !alt.sex*,!alt.video.dvd,\ bionet.*,biz.*,gnu.*,vmsnet.*,\ ba.*,!ba.jobs.agency,ca.*,sbay.* (with each line prefixed by a tab, and with standard INN newsfeeds continuation syntax). Due to the preferences of the author, it will also be sorted as Big Eight, then alt.*, then global non-language hierarchies, then regional and language hierarchies. =head1 OPTIONS =over 4 =item B<-h>, B<--help> Print out this documentation (which is done simply by feeding the script to C. =item B<-v>, B<--version> Print out the version of B and exit. =item B<-d> I, B<--days>=I Assume that the difference between the high and low numbers in the active file represent I days of traffic. =item B<-t> I, B<--threshold>=I Allow any group with less than I articles per day in traffic to be either sent or not sent depending on which choice makes the wildcard patterns simpler. If a threshold isn't specified, the default value is 250. =back =head1 BUGS This program takes a long time to run, not to mention being a nasty memory hog. The algorithm is thorough, but definitely not very optimized, and isn't all that friendly. Guessing traffic from active file numbers is going to produce very skewed results on sites with expiration policies that vary widely by group. There is no way to optimize for size in avoiding rejections, only quantity of articles. There should be a way to turn off the author's idiosyncratic ordering of hierarchies, or to specify a different ordering, without editing this script. This script should attempt to retrieve the active file from the remote site automatically if so desired. This script should be able to be given some existing wildcard patterns and take them into account when generating new ones. =head1 CAVEATS Please be aware that your neighbor's active file may not accurately represent the groups they wish to receive from you. As with everything, choices made by automated programs like this one should be reviewed by a human and the remote site should be notified, and if they have sent explicit patterns, those should be honored instead. I definitely do *not* recommend running this program on any sort of automated basis. =head1 AUTHOR Russ Allbery Eeagle@eyrie.orgE =cut inn-2.6.4/contrib/delayer.in0000644000175200017520000000254414002373703015342 0ustar iuliusiulius#!/usr/bin/perl # -*- perl -*- # # delay lines for N seconds. # # primarily meant to be used with INN to generate a delayed feed with innfeed. # # put it into your newsfeeds file like # # innfeed-delayed!\ # :!*\ # :Tc,Wnm*,S16384:/usr/local/news/bin/delayer 60 \ # /usr/local/news/bin/innfeed -c innfeed-delayed.conf # # done by christian mock sometime in july 1998, # and put into the public domain. # $delay = shift || die "usage: $0 delay prog-n-args\n"; $timeout = $delay; $eof = 0; open(OUT, "|" . join(" ", @ARGV)) || die "open |prog-n-args: $!\n"; #select(OUT); #$| = 1; #select(STDOUT); $rin = ''; vec($rin,fileno(STDIN),1) = 1; while(!$eof || $#queue >= 0) { if(!$eof) { ($nfound,$timeleft) = select($rout=$rin, undef, undef, $timeout); } else { sleep($timeout); } $now = time(); $exp = $now + $delay; if(!$eof && vec($rout,fileno(STDIN),1)) { $line = ; if(!defined $line) { # exit NOW! foreach(@queue) { s/^[^:]+://g; print OUT; } close(OUT); sleep(1); exit; } push(@queue, "$exp:$line"); } if($#queue < 0) { undef $timeout; next; } ($first, $line) = split(/:/, $queue[0], 2); while($#queue >= 0 && $first <= $now) { print OUT $line; shift(@queue); ($first, $line) = split(/:/, $queue[0], 2); } $timeout = $first - $now; } inn-2.6.4/INSTALL0000644000175200017520000025372214002373703012764 0ustar iuliusiuliusWelcome to INN 2.6! Please read this document thoroughly before trying to install INN. You'll be glad you did. If you are upgrading from a major release of INN prior to 2.3, it is recommended that you make copies of your old configuration files and use them as guides for doing a clean installation and configuration of 2.6. Many config files have changed, some have been added, and some have been removed. You'll find it much easier to start with a fresh install than to try to update your old installation. This is particularly true if you're upgrading from a version of INN prior to 2.0. If you are upgrading from INN 2.3 or later, you may be able to just update the binaries, scripts, and man pages by running: make update after building INN and then comparing the new sample configuration files with your current ones to see if anything has changed. If you take this route, the old binaries and scripts will be saved with an extension of ".OLD" so that you can easily back out. Note that if you do not want to have such backup copies, you can deactivate this behaviour with "make BACKUP_OPTION='' update" instead of a mere "make update". Be sure to configure INN with the same options that you used previously if you take this approach (in particular, INN compiled with --enable-largefiles can't read the data structures written by INN compiled without that flag, and vice versa). If you don't remember what options you used but you have your old build tree, look at the beginning of config.log. If you made ckpasswd setuid root so that you could use system passwords, you'll have to do that again after "make update". (It's much better to use PAM instead if you can.) If you use "make update" to upgrade from a previous major release of INN, also look at the new sample configuration files in samples to see if there are new options of interest to you. For more information about recent changes, see NEWS. Supported Systems As much as possible, INN is written in portable C and should work on any Unix platform. It does, however, make extensive use of mmap(2) and certain other constructs that may be poorly or incompletely implemented, particularly on very old operating systems. INN has been confirmed to work on recent versions of the following operating systems: AIX (including 7.2) FreeBSD (including 12.1) Linux (including 3.16, 4.19 and 5.10 kernels, glibc 2.19, 2.28 and 2.31) macOS (including 11) NetBSD (including 9.0) OpenBSD (including 6.8) Oracle Solaris (including 10 and 11) Current versions of INN may also work on other operating systems like HP-UX, OpenServer, SCO, UnixWare or UX/4800, as well as old versions of the above list of operating systems, but have not been confirmed to. Old versions of INN used to, but current ones have not been tested on such systems or ancient specific versions. If you have gotten INN working on an operating system other than the ones listed above, please let us know at . Before You Begin INN requires several other packages be installed in order to be fully functional (or in some cases, to work at all): * In order to build INN, you will need a C compiler that understands ANSI C. If you are trying to install INN on an operating system that doesn't have an ANSI C compiler (such as SunOS), installing gcc is recommended. You can get it from or its mirrors. INN is tested with gcc more thoroughly than with any other compiler, so even if you have another compiler available, you may wish to use gcc instead. * Currently, in order to build INN, you will need an implementation of yacc. GNU bison (from or its mirrors) will work fine. We hope to remove this requirement in the future. * INN requires at least Perl 5.8.0 to build and to run several subsystems. In order to process control messages, controlchan needs the "MIME::Parser" module available from CPAN ("MIME-tools" in modules/by-module/MIME/, for instance on ). This Perl module has probably already been packaged for your distribution. INN is tested primarily with newer versions of Perl, so it's generally recommended that you install the latest stable distribution of Perl before compiling INN. For instructions on obtaining and installing Perl, see . Note that you may need to use the same compiler and options (particularly large file supporti and shared libraries) for Perl and INN. If you're using a version of Perl prior to 5.6.0, you may need to make sure that the Perl versions of your system header files have been generated in order for "Sys::Syslog" to work properly (used by various utility programs, including controlchan). To do this, run the following two commands: # cd /usr/include # h2ph * sys/* An even better approach is to install Perl 5.6.1 or later, which have a fixed version of "Sys::Syslog" that doesn't require this (as well as many other improvements over earlier versions of Perl). * The INN Makefiles use the syntax "include FILE", rather than the syntax expected by some BSDish systems of ".include ". If your system expects the latter syntax, the recommended solution is to install GNU make from . You may have GNU make already installed as gmake, in which case using gmake rather than make to build INN should be sufficient. * If you want to enable support for authenticated control messages (this is not required, but is highly recommended for systems carrying public Usenet hierarchies) then you will need to install some version of PGP. The recommended version is GnuPG, since it's actively developed, supports OpenPGP, is freely available from and free to use for any purpose (in the US and elsewhere), and (as of version 1.0.4 at least) supports the RSA signatures used by most current control message senders. * If you want to use either the Python embedded hooks, you'll need to have a suitable version of Python installed. See doc/hook-python for more information. * If you want to use systemd notifications and socket activation, you'll need to have pkg-config and libsystemd (along with its libsystemd.pc configuration) installed so that these features are enabled at configure time. * Many of INN's optional features require other packages (primarily libraries) be installed. If you wish to use any of these optional features, you will need to install those packages first. Here is a table of configure options enabling optional features and the software and versions you'll need: --with-perl Perl 5.004_03 or higher, 5.8.0+ recommended --with-python Python 2.3.0 or higher, 2.5.0+ recommended (in the 2.x series); Python 3.3.0 or higher (in the 3.x series) --with-bdb Berkeley DB 4.4 or higher, 4.7+ recommended --with-zlib zlib 1.x or higher --with-openssl OpenSSL 0.9.6 or higher --with-sasl Cyrus SASL 2.x or higher --with-krb5 MIT Kerberos v5 1.2.x or higher If any of these libraries (other than Perl or Python) are built shared and installed in locations where your system doesn't search for shared libraries by default, you may need to encode the paths to those shared libraries in the INN binaries. For more information on shared library paths, see . For most systems, setting the environment variable LD_RUN_PATH to a colon-separated list of additional directories in which to look for shared libraries before building INN will be sufficient. If you build your own libraries, make sure to generate them as either shared libraries or static libraries built with -fPIC amongst the options given to the compiler (to obtain position-independent code). Otherwise, building INN will fail, unless you pass --disable-hardening-flags to configure. Unpacking the Distribution Released versions of INN are available from . New major releases will be announced on (see README) when they're made. If you want a more cutting-edge version, you can obtain current snapshots from . These are snapshots of the INN Subversion tree taken daily; there are two snapshots made each night (one of the current development branch, and one of the stable branch consisting of bug fixes to the previous major release). They are stored in date format; in other words the snapshots from April 6th, 2020, would be named inn-CURRENT-20200406.tar.gz and inn-STABLE-20200406.tar.gz. Choose the newest file of whichever branch you prefer. (Note that the downloading, configuring, and compiling steps can be done while logged in as any user.) The distribution is in gzip compressed tar archive format. To extract it, execute: gunzip -c | tar -xf - Extracting the source distribution will create a directory named inn- or inn-- where the source resides. Installing INN Before beginning installation, you should make sure that there is a user on your system named "news", and that this user's primary group is set to a group called "news". You can change these with the --with-news-user and --with-news-group options to configure (see below). The home directory of this user should be set to the directory under which you wish to install INN (/usr/local/news is the default and is a good choice). This location will be set as *pathnews* in inn.conf. INN will install itself as this user and group. You can change these if you want, but these are the defaults and it's easier to stick with them on a new installation. By default, INN sends reports to the user "usenet". This account is used for instance by controlchan (notifying any changes as for newsgroups) or news.daily (sending Usenet daily reports). You can change it with the --with-news-master option to configure (see below). There is also the *mailto* keyword which can be given to news.daily in order to modify the mail address to which these reports are sent. WARNING: By default, INN installs various configuration files as group-writeable, and in general INN is not hardened from a security standpoint against an attack by someone who is already in the "news" group. In general, you should consider membership in the news group as equivalent to access to the news account. You should not rely on being able to keep anyone with access to the news GID from converting that into access to the news UID. The recommended configuration is to have the only member of the group "news" be the user "news". Installing INN so that all of its files are under a single directory tree, rather than scattering binaries, libraries, and man pages throughout the file system, is strongly recommended. It helps keep everything involved in the operation of INN together as a unit and will make the installation instructions easier to follow. As a side note, whenever doing anything with a running news server, first log in as this user. That way, you can ensure that all files created by any commands you run are created with the right ownership to be readable by the server. Particularly avoid doing anything in the news spool itself as root, and make sure you fix the ownership of any created files if you have to. INN doesn't like files in the news spool owned by a user other than the news user. However, since certain binaries need to be setuid root, indiscriminate use of "chown news" is not the solution. (If you don't like to log in to system accounts, careful use of "chmod g+s" on directories and a umask of 002 or 007 may suffice.) INN uses GNU autoconf and a generated configure script to make configuration rather painless. Unless you have a rather abnormal setup, configure should be able to completely configure INN for your system. If you want to change the defaults, you can invoke the configure script with one or more command line options. Type: ./configure --help for a full list of supported options. Some of the most commonly used options are: --prefix=PATH Sets the installation prefix for INN. The default is /usr/local/news. All of INN's programs and support files will be installed under this directory. This should match the home directory of your news user (it will make installation and maintenance easier). It is not recommended to set this to /usr; if you decide to do that anyway, make sure to point INN's temporary directory at a directory that isn't world-writeable (see --with-tmp-dir below). --with-db-dir=PATH Sets the prefix for INN database files. The default is PREFIX/db, where PREFIX is /usr/local/news unless overridden with the option above. The history and active files will be stored in this directory, and writes to those files are an appreciable percentage of INN's disk activity. The history file can also be quite large (requiring up to 2 GB or more during nightly expire), so this is a common portion of INN to move to a different file system. --with-spool-dir=PATH Sets the prefix for the news spool (when using any storage method other than CNFS) and the overview spool. The default is PREFIX/spool. This is another common portion of INN to move to a different file system (often /news). --with-tmp-dir=PATH Sets the directory in which INN will create temporary files. This should under no circumstances be the same as the system temporary directory or otherwise be set to a world-writeable directory, since INN doesn't take care to avoid symlink attacks and other security problems possible with a world-writeable directory. This directory should be reserved for the exclusive use of INN and only writeable by the news user. Usage is generally light, so this is unlikely to need a separate partition. It's also possible to set the paths for most other sections of the INN installation independently; see "./configure --help" and look for the --with-*-dir=PATH options. --enable-reduced-depends Requests that library probes assume shared libraries are in use and dependencies of libraries should not be probed. It therefore tries to minimize the shared library dependencies of the resulting binaries on platforms with proper shared library dependencies. This is not enabled by default, and is of interest primarily to people building packages for distributions. --enable-largefiles Enables large file support. This is not enabled by default, even on platforms that support it, because it changes the format of INN's on-disk databases (making it difficult to upgrade an earlier INN installation) and can significantly increase the size of some of the history database files. Large file support is not necessary unless your history database is so large that it exceeds 2 GB or you want to use CNFS buffers larger than 2 GB on 32-bit platforms (and some very rare 64-bit platforms that aren't Linux). The history, tradindexed and buffindexed overview, and timecaf databases written by an INN built with this option are incompatible with those written by an INN without this option. (CNFS buffers are compatible.) --enable-tagged-hash Use tagged hash table for the history database. The tagged hash format uses much less memory but is somewhat slower. This option is recommended if you have less than 256 MB of RAM on your news server. If you install INN without tagged hash (the default) and expire takes an excessive amount of time, you should make sure the RAM in your system satisfies the following formula: ram > 10 * tablesize ram: Amount of system RAM (in bytes) tablesize: 3rd field on the 1st line of history.dir (bytes) If you don't have at least that much RAM, try rebuilding INN with tagged hash enabled. NOTE: --enable-largefiles cannot be used with --enable-tagged-hash. --with-perl Enables support for embedded Perl, allowing you to install filter scripts written in Perl. Highly recommended, because many really good spam filters are written in Perl. See doc/hook-perl for all the details. Even if you do not use this option, INN still requires Perl as mentioned above. If the $PERL environment variable is set, it will be used as the path to Perl. --with-python Enables support for Python, allowing you to install filter and authentication scripts written in Python. You will need Python 2.3.0 or later (in the 2.x series), or Python 3.3.0 or later (in the 3.x series) installed on your system to enable this option. See doc/hook-python for all the details. If the $PYTHON environment variable is set, it will be used as the path to Python. --with-innd-port=PORT By default, innbind(8) refuses to bind to any port under 1024 other than 119, 433 and 563 for security reasons (to prevent attacks on rsh(1)-based commands and replacing standard system daemons). If you want to run innd on a different port under 1024, you'll need to tell configure what port you intend to use. (You'll also still need to set the port number in inn.conf or give it to innd on the command line.) --with-syslog-facility=FACILITY Specifies the syslog facility that INN programs should log to. The default is LOG_NEWS unless configure detects that your system doesn't understand that facility, in which case it uses LOG_LOCAL1. This flag overrides the automatic detection. Be sure to specify a facility not used by anything else on your system (one of LOG_LOCAL0 through LOG_LOCAL7, for example). --enable-uucp-rnews If this option is given to configure, rnews will be installed setuid "news", owned by group "uucp", and mode 4550. This will allow the UUCP subsystem to run rnews to process UUCP batches of news articles. Prior to INN 2.3, installing rnews setuid "news" was standard; since most sites no longer use UUCP, it is no longer the default as of INN 2.3 and must be requested at configure time. You probably don't want to use this option unless your server accepts UUCP news batches. --enable-setgid-inews If this option is given to configure, inews will be installed setgid "news" and world-executable so that non-privileged users on the news server machine can use inews to post articles locally (somewhat faster than opening a new network connection). For standalone news servers, by far the most common configuration now, there's no need to use this option; even if you have regular login accounts on your news server, INN's inews can post fine via a network connection to your running news server and doesn't need to use the local socket (which is what setgid enables it to do). Installing inews setgid was the default prior to INN 2.3. --with-bdb=PATH Enables support for Berkeley DB (4.4 or higher), which means that it will then be possible to use the ovdb overview method if you wish. Enabling this configure option doesn't mean you'll be required to use ovdb, but it does require that Berkeley DB be installed on your system (including the header files, not just the runtime libraries). If a path is given, it sets the installed directory of Berkeley DB (configure will search for it in standard locations, but if you have it installed elsewhere, you may need this option). This directory is expected to have subdirectories include and lib (lib32 and lib64 are also checked), containing respectively db.h, and the library itself. In case non-standard paths to the Berkeley DB libraries are used, one or both of the options --with-bdb-include and --with-bdb-lib can be given to configure with a path. If the Berkeley DB library is found at configure time, INN will be built with Berkeley DB support unless the --without-bdb flag is explicitly passed to configure. --with-zlib=PATH Enables support for compression for news reading, which means a compression layer can be negotiated between your server and newsreaders supporting that NNTP extension. Also enables support for compression with the ovdb storage method. This option requires that zlib be installed on your system (including the header files, not just the runtime libraries). If a path is given, it sets the installed directory of zlib. In case non-standard paths to the zlib library are used, one or both of the options --with-zlib-include and --with-zlib-lib can be given to configure with a path. If the zlib library is found at configure time, INN will be built with compression support unless the --without-zlib flag is explicitly passed to configure. --with-openssl=PATH Enables support for TLS/SSL for news reading, which means it will be possible to have TLS encrypted NNTP connections between your server and newsreaders. This option requires OpenSSL be installed on your system (including the header files, not just the runtime libraries). If a path is given, it sets the installed directory of OpenSSL. After compiling and installing INN with this option, you'll still need to make a certificate and private key to use TLS. See below for details on how to do that. In case non-standard paths to the OpenSSL libraries are used, one or both of the options --with-openssl-include and --with-openssl-lib can be given to configure with a path. If the OpenSSL SSL and crypto libraries are found at configure time, INN will be built with TLS/SSL support unless the --without-openssl flag is explicitly passed to configure. For the most common installation, a standalone news server, a suggested set of options is: ./configure --with-perl --with-python provided that you have the necessary versions of Perl and Python installed. (Compiling with embedded Perl and Python interpreters will allow you to use one of the available excellent spam filters if you so choose.) If the configure program runs successfully, then you are ready to build the distribution. From the root of the INN source tree, type: make At this point you can step away from the computer for a little while and have a quick snack while INN compiles. On a decently fast system it should only take five or ten minutes at the most to build. Once the build has completed successfully, you are ready to install INN into its final home. Type: make install Under most circumstances, you will need to run the "make install" command as root, so that INN can create the directories it needs, change ownerships (if you did not compile as the news user) and install a setuid program needed to raise resource limits and allow innd to bind to ports under 1024. This step will install INN under the install directory (/usr/local/news, known as *pathnews* in inn.conf, unless you specified something else to the configure script). Exceptionally, if you are installing INN into a directory writable by the news user, you can run "make install" as the configured news user. The resulting INN installation won't be able to use ports below 1024 (including the default NNTP port of 119) unless you then run "make install-root" as root, which will install only the setuid helper program. If you are building INN on a different system than the one on which it will eventually run, and you therefore want INN to install its files in a virtual root directory and not into the actual filesystem of the build machine, you can pass the virtual root directory to the install step via the DESTDIR variable. You then just need to type: make DESTDIR=/tmp/inn-root install In the above example, all of INN's directories and files would be installed under the /tmp/inn-root directory instead of the normal / (root) directory. Just replace "/tmp/inn-root" with whatever directory you wish to install INN in (the result will be in /tmp/inn-root/usr/local/news if the default value of /usr/local/news for *pathnews* has not been changed). This won't affect any of the paths compiled into INN; it's used primarily in some situations like building a software distribution, where software has to be installed into some file system that will later be mounted as / on the final system. Using DESTDIR permits building INN, installing it into a virtual root directory, and packaging the resulting files in a single step, without manual intervention, by a non-root user. It is possible to build and install INN in this way, but you must set a DESTDIR value for the install step, and additionally, you must tell the installation process that it should omit executing "chown" and "chgrp" commands (which will fail if the installation step is being executed by a non-root user). To do this, type: CHOWNPROG=set CHGRPPROG=set make DESTDIR=/tmp/inn-root install WARNING: if you install INN in this manner, none of the resulting directories and files in the virtual root directory will be owned by the correct users and groups. It is YOUR responsibility to ensure the resulting directories and files are packaged with the users, groups, and modes which INN wanted them to be installed with! Please note that INN's shared library interface is not stable and may change drastically in future major releases. Only INN should use INN's shared libraries, and you should only use the shared libraries corresponding to the version of INN that you're installing. Also, when updating an existing version of INN, INN tries to save backup copies of all files but man pages and shared libraries so that you can revert to the previous installed version. Shared libraries are not backed up because this confuses ldconfig on some systems (such as Linux) and the symbolic links for the libraries may point to the ".OLD" versions. Nonetheless, reverting to a previous version of INN should work fine for official releases (that is to say releases that are not daily STABLE or CURRENT snapshots) because a proper versioning is done, during the release of a new version. If you are configuring TLS/SSL support for newsreaders, you must make a certificate and private key at least once. Type: make cert as root in order to do this. You can also type "make DESTDIR=/tmp/inn-root cert" as either root (preferred) or a non-root user. All of the warnings and caveats mentioned above apply. You are now ready for the really fun part: configuring your copy of INN! Choosing an Article Storage Format The first thing to decide is how INN should store articles on your system. There are four different methods for you to choose from, each of which has its own advantages and disadvantages. INN can support all four at the same time, so you can store certain newsgroups in one method and other newsgroups in another method. The supported storage formats are: tradspool This is the storage method used by all versions of INN previous to 2.0. Articles are stored as individual text files whose names are the same as the article number. The articles are divided up into directories based on the newsgroup name. For example, article 12345 in news.software.nntp would be stored as news/software/nntp/12345 relative to the root of the article spool. Advantages: Widely used and well-understood storage mechanism, can read article spools written by older versions of INN, compatible with all third-party INN add-ons, provides easy and direct access to the articles stored on your server and makes writing programs that fiddle with the news spool very easy, and gives you fine control over article retention times. Disadvantages: Takes a very fast file system and I/O system to keep up with current Usenet traffic volumes due to file system overhead. Groups with heavy traffic tend to create a bottleneck because of inefficiencies in storing large numbers of article files in a single directory. Requires a nightly expire program to delete old articles out of the news spool, a process that can slow down the server for several hours or more. timehash Articles are stored as individual files as in tradspool, but are divided into directories based on the arrival time to ensure that no single directory contains so many files as to cause a bottleneck. Advantages: Heavy traffic groups do not cause bottlenecks, and fine control of article retention time is still possible. Disadvantages: The ability to easily find all articles in a given newsgroup and manually fiddle with the article spool is lost, and INN still suffers from speed degradation due to file system overhead (creating and deleting individual files is a slow operation). timecaf Similar to timehash, articles are stored by arrival time, but instead of writing a separate file for each article, multiple articles are put in the same file. Advantages: Roughly four times faster than timehash for article writes, since much of the file system overhead is bypassed, while still retaining the same fine control over article retention time. Disadvantages: Even worse than timehash, and similar to CNFS (below), using this method means giving up all but the most careful manually fiddling with your article spool. As one of the newer and least widely used storage types, timecaf has not been as thoroughly tested as the other methods. cnfs CNFS stores articles sequentially in pre-configured buffer files. When the end of the buffer is reached, new articles are stored from the beginning of the buffer, overwriting older articles. Advantages: Blazingly fast because no file creations or deletions are necessary to store an article. Unlike all other storage methods, does not require manual article expiration; old articles are deleted to make room for new ones when the buffers get too full. Also, with CNFS your server will never throttle itself due to a full spool disk, and groups are restricted to just the buffer files you give them so that they can never use more than the amount of disk space you allocate to them. Disadvantages: Article retention times are more difficult to control because old articles are overwritten automatically. Attacks on Usenet, such as flooding or massive amounts of spam, can result in wanted articles expiring much faster than you intended (with no warning). Some general recommendations: If you are installing a transit news server (one that just accepts news and sends it out again to other servers and doesn't support any readers), use CNFS exclusively and don't worry about any of the other storage methods. Otherwise, put high-volume groups and groups whose articles you don't need to keep around very long (binaries groups, *.jobs*, news.lists.filters, etc.) in CNFS buffers, and use timehash, timecaf, or tradspool (if you have a fast I/O subsystem or need to be able to go through the spool manually) for everything else. You'll probably find it most convenient to keep special hierarchies like local hierarchies and hierarchies that should never expire in tradspool. Choosing an Overview Storage Mechanism If your news server will be supporting readers, you'll also need to choose an overview storage mechanism (by setting *ovmethod* in inn.conf). There are three overview mechanisms to choose from: buffindexed It stores overview data and index information into preconfigured large files like CNFS. Fast at writing, the "buffindexed" overview storage method can keep up with a large feed more easily and never consumes additional disk space beyond that allocated to these buffers. The downside is that these buffers are hard to recover in case of corruption and somewhat slower for readers and the expiry process. See the buffindexed.conf(5) man page for more details, and notably how to create the buffers. ovdb It stores overview information into a Berkeley DB database, whose development pace has stalled these last years. This method is fast and very robust, but may require more disk space, unless compression is enabled. See the ovdb(5) man page for more details. tradindexed It uses two files per newsgroup, one containing the overview data and one containing the index. Fast for readers, but slow to write to because it has to update two files for each incoming article. Its main advantage is to be the best tested, the most reliable and the method with the best recovery tools. Here are a few elements that can be helpful in choosing the right overview method for your needs and estimating the associated storage size. In 2020, the volume for a full-text Usenet feed is about 18,000 articles per day, with peaks to 1,200 articles per hour. Article storage size is about 65 MB per day. As for overview storage size, if you have 5 million articles, you'll need at least 3.25 GB of disk space for buffindexed, 5.5 GB for ovdb (4.5 GB if compressed), and 3.10 GB for tradindexed. If you store more header fields in overview data than the standard ones, the space needed to store overview data will be superior than these estimates. (This is configured in inn.conf, via the *extraoverviewadvertised* and *extraoverviewhidden* parameters.) Configuring INN All documentation from this point on assumes that you have set up the news user on your system as suggested in "Installing INN" so that the root of your INN installation is ~news (*pathnews* in inn.conf). If you've moved things around by using options with "configure", you'll need to adjust the instructions to account for that. All of INN's configuration files are located in *pathetc* as set in inn.conf. Unless noted otherwise, any files referred to below are in this directory. When you first install INN, a sample of each file (containing lots of comments) is installed in *pathetc*; refer to these for concrete examples of everything discussed in this section. All of INN's configuration files, all of the programs that come with it, and some of its library routines have documentation in the form of man pages. These man pages were installed in *pathnews*/share/man as part of the INN installation process and are the most complete reference to how INN works. You're strongly encouraged to refer to the man pages frequently while configuring INN, and for quick reference afterwards. Any detailed questions about individual configuration files or the behavior of specific programs should be answered in them. You may want to add *pathnews*/share/man to your MANPATH environment variable; otherwise, you may have to use a command like: man -M /share/man inn.conf to see the inn.conf(5) man page (for example). Before we begin, it is worth mentioning the wildmat pattern matching syntax used in many configuration files. These are simple wildcard matches using the asterisk ("*") as the wildcard character, much like the simple wildcard expansion used by Unix shells. In many cases, wildmat patterns can be specified in a comma-separated list to indicate a list of newsgroups. When used in this fashion, each pattern is checked in turn to see if it matches, and the last pattern in the line that matches the group name is used. Patterns beginning with "!" mean to exclude groups matching that pattern. For example: *,!comp.*,comp.os.* In this case, we're saying we match everything ("*"), except that we don't match anything under comp ("!comp.*"), unless it is actually under the comp.os hierarchy ("comp.os.*"). This is because non-comp groups will match only the first pattern (so we want them), comp.os groups will match all three patterns (so we want them too, because the third pattern counts in this case), and all other comp groups will match the first and second patterns and will be excluded by the second pattern. Some uses of wildmat patterns also support "poison" patterns (patterns starting with "@"). These patterns behave just like "!" patterns when checked against a single newsgroup name. Where they become special is for articles crossposted to multiple newsgroups; normally, such an article will be considered to match a pattern if any of the newsgroups it is posted to matches the pattern. If any newsgroup the article is posted to matches an expression beginning with "@", however, that article will not match the pattern even if other newsgroups to which it was posted match other expressions. For instance, if an article is crossposted between misc.foo and misc.bar, the pattern: misc.*,!misc.bar will match that article whereas the pattern: misc.*,@misc.bar will not match that article. An article posted only to misc.bar will fail to match either pattern. See uwildmat(3) for full details on wildmat patterns. In all INN configuration files, blank lines and lines beginning with a "#" symbol are considered comments and are ignored. Be careful, not all files permit comments to begin in the middle of the line. inn.conf The first, and most important file is inn.conf. This file is organized as a series of parameter-value pairs, one per line. The parameter is first, followed by a colon and one or more whitespace characters, and then the value itself. For some parameters the value is a string or a number; for others it is true or false. (True values can be written as "yes", "true", or "on", whichever you prefer. Similarly, false values can be written as "no", "false", or "off".) inn.conf contains dozens of changeable parameters (see inn.conf(5) for full details), but only a few really need to be edited during normal operation: allownewnews If set to true then INN will support the NEWNEWS command for news readers. While this can be an expensive operation, its speed has been improved considerably as of INN 2.3 and it's probably safe to turn on without risking excessive server load. The default is true. (Note that the *access* setting in readers.conf overrides this value; see readers.conf(5) for more details.) complaints Used to set the value of the mail-complaints-to attribute of the Injection-Info: header, which is added to all articles posted locally. The usual value would be something like "abuse@example.com" or "postmaster@example.com". If not specified, the newsmaster e-mail address will be used. hiscachesize The amount of memory (in kilobytes) to allocate for a cache of recently used history file entries. Setting this to 0 disables history caching. History caching can greatly increase the number of articles per second that your server is capable of processing. A value of 256 is a good default choice. logipaddr If set to true (the default), INN will log the IP address (or hostname, if the host is listed in incoming.conf with a hostname) of the remote host from which it received an article. If set to false, the trailing Path: header entry is logged instead. If you are using controlchan (see below) and need to process ihave/sendme control messages (this is very, very unlikely, so if you don't know what this means, don't worry about it), make sure you set this to false, since controlchan needs a site name, not an IP address. organization Set this to the name of your organization as you want it to appear in the Organization: header of all articles posted locally and not already containing that header. This will be overridden by the value of the ORGANIZATION environment variable (if it exists). If neither this parameter nor the environment variable is set, no Organization: header will be added to posts which lack one. pathhost This is the name of your news server as you wish it to appear in the Path: header of all postings which travel through your server (this includes local posts and incoming posts that you forward out to other sites). If this parameter is unspecified, the fully qualified domain name (FQDN) of the machine, as reported by the operating system, will be used instead. Please use the canonical FQDN of your server or an alias unless you have a very good reason not to; a future version of the news RFCs may require this. rlimitnofile If set to a non-negative value (the default is -1), INN (both innd and innfeed) will try to raise the maximum number of open file descriptors to this value when it starts. This may be needed if you have lots of incoming and outgoing feeds. Note that the maximum value for this setting is very operating-system-dependent, and you may have to reconfigure your system (possibly even recompile your kernel) to increase it. See "File Descriptor Limits" for complete details. There are tons of other possible settings; you may want to read through inn.conf(5) to get a feel for your options. Don't worry if you don't understand the purpose of most of them right now. Some of the settings are only needed for very obscure things, and with more experience running your news server the rest will make more sense. newsfeeds newsfeeds determines how incoming articles are redistributed to your peers and to other INN processes. newsfeeds is very versatile and contains dozens of options; we will touch on just the basics here. The man page contains more detailed information. newsfeeds is organized as a series of feed entries. Each feed entry is composed of four fields separated by colons. Entries may span multiple lines by using a backslash ("\") to indicate that the next line is a continuation of the current line. (Note that comments don't interact with backslashes in the way you might expect. A commented-out line ending in a backslash will still be considered continued on the next line, possibly resulting in more commented out than you intended or bizarre syntax errors. In general, it's best to avoid commenting out lines in the middle of continuation lines.) The first field in an entry is the name of the feed. It must be unique, and for feeds to other news servers it is usually set to the actual hostname of the remote server (this makes things easier). The name can optionally be followed by a slash ("/") and a comma-separated exclude list. If the feed name or any of the names in the exclude list appear in the Path: header of an article, then that article will not be forwarded to the feed as it is assumed that it has passed through that site once already. The exclude list is useful when a news server's hostname is not the same as what it puts in the Path: header of its articles, or when you don't want a feed to receive articles from a certain source. The second field specifies a set of desired newsgroups and distribution lists, given as newsgroup-pattern/distribution-list. The distribution list is not described here; see newsfeeds(5) for information (it's not used that frequently in practice). The newsgroup pattern is a wildmat-style pattern list as described above (supporting "@"). The third field is a comma-separated list of flags that determine both the type of feed entry and sets certain parameters for the entry. See newsfeeds(5) for information on the flag settings; you can do a surprising amount with them. The three most common patterns, and the ones mainly used for outgoing news feeds to other sites, are "Tf,Wnm" (to write out a batch file of articles to be sent, suitable for processing by nntpsend and innxmit), "Tm" (to send the article to a funnel feed, used with innfeed), and "Tc,Wnm*" (to collect a funnel feed and send it via a channel feed to an external program, used to send articles to innfeed). The fourth field is a multi-purpose parameter whose meaning depends on the settings of the flags in the third field. To get a feel for it using the examples above, for file feeds ("Tf") it's the name of the file to write, for funnel feeds ("Tm") it's the name of the feed entry to funnel into, and for channel feeds ("Tc") it's the name of the program to run and feed references to articles. Now that you have a rough idea of the file layout, we'll begin to add the actual feed entries. First, we'll set up the special "ME" entry. This entry is required and serves two purposes: the newsgroup pattern specified here is prepended to the newsgroup list of all other feeds, and the distribution pattern for this entry determines what distributions (from the Distribution: header of incoming articles) are accepted from remote sites by your server. The example in the sample newsfeeds file is a good starting point. If you are going to create a local hierarchy that should not be distributed off of your system, it may be useful to exclude it from the default subscription pattern, but default subscription patterns are somewhat difficult to use right so you may want to just exclude it specifically from every feed instead. The "ME" entry tends to confuse a lot of people, so this point is worth repeating: the newsgroup patterns set the default subscription for *outgoing* feeds, and the distribution patterns set the acceptable Distribution: header entries for *incoming* articles. This is confusing enough that it may change in later versions of INN. There are two basic ways to feed articles to remote sites. The most common for large sites and particularly for transit news servers is innfeed(8), which sends articles to remote sites in real time (the article goes out to all peers that are supposed to receive it immediately after your server accepts it). For smaller sites, particularly sites where the only outgoing messages will be locally posted articles, it's more common to batch outgoing articles and send them every ten minutes or so from cron using nntpsend(8) and innxmit(8). Batching gives you more control and tends to be extremely stable and reliable, but it's much slower and can't handle high volume very well. Batching outgoing posts is easy to set up; for each peer, add an entry to newsfeeds that looks like: remote.example.com/news.example.com\ :\ :Tf,Wnm: where is the wildmat pattern for the newsgroups that site wants. In this example, the actual name of the remote site is "remote.example.com", but it puts "news.example.com" in the Path: header. If the remote site puts its actual hostname in the Path: header, you won't need the "/news.example.com" part. This entry will cause innd to write out a file in *pathspool*/outgoing named remote.example.com and containing the Message-ID and storage token of each message to send to that site. (The storage token is INN's internal pointer to where an article is stored; to retrieve an article given its storage token, use sm(8)). innxmit knows how to read files of this format and send those articles to the remote site. For information on setting it up to run periodically, see "Setting Up the Cron Jobs" below. You will also need to set up a config file for nntpsend; see the man page for nntpsend.ctl(5) for more information. If instead you want to use innfeed to send outgoing messages (recommended for sites with more than a couple of peers), you need some slightly more complex magic. You still set up a separate entry for each of your peers, but rather than writing out batch files, they all "funnel" into a special innfeed entry. That special entry collects all of the separate funnel feeds and sends the data through a special sort of feed to an external program (innfeed in this case); this is a "channel" feed. First, the special channel feed entry for innfeed that will collect all the funnel feeds: innfeed!\ :!*\ :Tc,Wnm*:/innfeed -y (adjust the path to innfeed(8) if you installed it elsewhere). Note that we don't feed this entry any articles directly (its newsgroup pattern is "!*"). Note also that the name of this entry ends in an exclamation point. This is a standard convention for all special feeds; since the delimiter for the Path: header is "!", no site name containing that character can ever match the name of a real site. Next, set up entries for each remote site to which you will be feeding articles. All of these entries should be of the form: remote.example.com/news.example.com\ :\ :Tm:innfeed! specifying that they funnel into the "innfeed!" feed. As in the previous example for batching, "remote.example.com" is the actual name of the remote peer, "news.example.com" is what it puts in the Path: header (if different than the actual name of the server), and is the wildmat pattern of newsgroups to be sent. As an alternative to NNTP, INN may also feed news out to an IMAP server, by using imapfeed(8), which is almost identical to innfeed. The feed entry for this is as follows: imapfeed!\ :!*\ :Tc,Wnm*,S16384:/imapfeed And set up entries for each remote site like: remote.example.com/news.example.com\ :\ :Tm:imapfeed! For more information on imapfeed, look at the innfeed/imap_connection.c file. For more information on IMAP in general, see RFC 3501. Finally, there is a special entry for controlchan(8), which processes newsgroup control messages, that should always be in newsfeeds unless you never want to honor any control messages. This entry should look like: controlchan!\ :!*,control,control.*,!control.cancel\ :AC,Tc,Wnsm:/controlchan (modified for the actual path to controlchan if you put it somewhere else). See "Processing Newsgroup Control Messages" for more details. For those of you upgrading from earlier versions of INN, note that the functionality of overchan(8) and crosspost is now incorporated into INN and neither of those programs is necessary. Although crosspost is no longer shipped with INN (and will not be working if used), you can still use overchan if you make sure to set *useoverchan* to true in inn.conf so that innd doesn't write overview data itself, but be careful: innd may accept articles faster than overchan can process the data. incoming.conf incoming.conf file specifies which machines are permitted to connect to your host and feed it articles. Remote servers you peer with should be listed here. Connections from hosts not listed in this file will (if you don't allow readers) be rejected or (if you allow readers) be handed off to nnrpd and checked against the access restrictions in readers.conf. Start with the sample incoming.conf and, for each remote peer, add an entry like: peer remote.example.com { } This uses the default parameters for that feed and allows incoming connections from a machine named "remote.example.com". If that peer could be connecting from several different machines, instead use an entry like: peer remote.example.com { hostname: "remote.example.com, news.example.com" } This will allow either "remote.example.com" or "news.example.com" to feed articles to you. (In general, you should add new peer lines for each separate remote site you peer with, and list multiple host names using the *hostname* key if one particular remote site uses multiple servers.) You can restrict the newsgroups a remote site is allowed to send you, using the same sort of pattern that newsfeeds(5) uses. For example, if you want to prevent "example.com" hosts from sending you any articles in the "local.*" hierarchy (even if they're crossposted to other groups), change the above to: peer remote.example.com { patterns: "*, @local.*" hostname: "remote.example.com, news.example.com" } Note, however, that restricting what a remote side can send you will *not* reduce your incoming bandwidth usage. The remote site will still send you the entire article; INN will just reject it rather than saving it to disk. To reduce bandwidth, you have to contact your peers and ask them not to send you the traffic you don't want. There are various other things you can set, including the maximum number of connections the remote host will be allowed. See incoming.conf(5) for all the details. Note for those familiar with older versions of INN: this file replaces the old hosts.nntp configuration file. cycbuff.conf cycbuff.conf is only required if CNFS is used. If you aren't using CNFS, skip this section. CNFS stores articles in logical objects called *metacycbuffs*. Each metacycbuff is in turn composed of one or more physical buffers called *cycbuffs*. As articles are written to the metacycbuff, each article is written to the next cycbuff in the list in a round-robin fashion (unless "sequential" mode is specified, in which case each cycbuff is filled before moving on to the next). This is so that you can distribute the individual cycbuffs across multiple physical disks and balance the load between them. There are two ways to create your cycbuffs: 1. Use a block device directly. This will probably give you the most speed since it avoids the file system overhead of large files, but it requires your OS support mmap(2) on a block device. Solaris supports this, as do late Linux 2.4 kernels. FreeBSD does not at last report. Also on many PC-based Unixes it is difficult to create more than eight partitions, which may limit your options. 2. Use a real file on a filesystem. This will probably be a bit slower than using a block device directly, but it should work on any Unix system. If you're having doubts, use option #2; it's easier to set up and should work regardless of your operating system. More information about the creation of these cycbuffs can be found in cycbuff.conf(5) man page. Now you need to decide on the sizes of your cycbuffs and metacycbuffs. You'll probably want to separate the heavy-traffic groups ("alt.binaries.*" and maybe a few other things like "*.jobs*" and "news.lists.filters") into their own metacycbuff so that they don't overrun the server and push out articles on the more useful groups. If you have any local groups that you want to stay around for a while then you should put them in their own metacycbuff as well, so that they don't get pushed out by other traffic. (Or you might store them in one of the other storage methods, such as tradspool.) For each metacycbuff, you now need to determine how many cycbuffs will make up the metacycbuff, the size of those cycbuffs, and where they will be stored. Also, when laying out your cycbuffs, you will want to try to arrange them across as many physical disks as possible (or use a striped disk array and put them all on that). In order to use any cycbuff larger than 2 GB on 32-bit platforms (and some very rare 64-bit platforms that aren't Linux), you need to build INN with the --enable-largefiles option. See "Installing INN" for more information and some caveats. For each cycbuff you will be creating, add a line to cycbuff.conf like the following: cycbuff:NAME:/path/to/buffer:SIZE NAME must be unique and must be at most seven characters long. Something simple like "BUFF00", "BUFF01", etc. is a decent choice, or you may want to use something that includes the SCSI target and slice number of the partition. SIZE is the buffer size in kilobytes (if you're trying to stay under 2 GB, keep your sizes below 2097152). Now, you need to tell INN how to group your cycbuffs into metacycbuffs. This is similar to creating cycbuff entries: metacycbuff:BUFFNAME:CYCBUF1,CYCBUF2,CYCBUF3 BUFFNAME is the name of the metacycbuff and must be unique and at most eight characters long. These should be a bit more meaningful than the cycbuff names since they will be used in other config files as well. Try to name them after what will be stored in them; for example, if this metacycbuff will hold alt.binaries postings, "BINARIES" would be a good choice. The last part of the entry is a comma-separated list of all of the cycbuffs that should be used to build this metacycbuff. Each cycbuff should only appear in one metacycbuff line, and all metacycbuff lines must occur after all cycbuff lines in the file. If you want INN to fill each cycbuff before moving on to the next one rather than writing to them round-robin, add ":SEQUENTIAL" to the end of the metacycbuff line. This may give noticeably better performance when using multiple cycbuffs on the same spindle (such as partitions or slices of a larger disk), but will probably give worse performance if your cycbuffs are spread out across a lot of spindles. By default, CNFS data is flushed to disk every 25 articles. If you're running a small server with a light article load, this could mean losing quite a few articles in a crash. You can change this interval by adding a cycbuffupdate: line to your cycbuff.conf file; see cycbuff.conf(5) for more details. Finally, you have to create the cycbuffs. See "Creating the Article Spool (CNFS only)" for more information on how to do that. storage.conf storage.conf determines where incoming articles will be stored (what storage method, and in the case of CNFS, what metacycbuff). Each entry in the file defines a storage class for articles. The first matching storage class is used to store the article; if no storage class matches, INN will reject that article. (This is almost never what you want, so make sure this file ends in a catch-all entry that will match everything.) A storage class definition looks like this: method { newsgroups: class: size: [,] expires: [,] options: exactmatch: } is the name of the storage method to use to store articles in this class ("cnfs", "timehash", "timecaf", "tradspool", or the special method "trash" that accepts the article and throws it away). The first parameter is a wildmat pattern in the same format used by the newsfeeds(5) file, and determines what newsgroups are accepted by this storage class. The second parameter is a unique number identifying this storage class and should be between 0 and 255. It can be used to control article expiration, and for timehash and timecaf will set the top-level directory in which articles accepted by this storage class are stored. The easiest way to deal with this parameter is to just number all storage classes in storage.conf sequentially. The assignment of a particular number to a storage class is arbitrary but *permanent* (since it is used in storage tokens). The third parameter can be used to accept only articles in a certain size range into this storage class. A of 0 (or a missing ) means no upper limit (and of course a of 0 would mean no lower limit, because all articles are more than zero bytes long). If you don't want to limit the size of articles accepted by this storage class, leave this parameter out entirely. The fourth parameter you probably don't want to use lets you assign storage classes based on the Expires: header of incoming articles. The exact details are in storage.conf(5). It's very easy to use this parameter incorrectly; leave it out entirely unless you've read the man page and know what you're doing. The fifth parameter is the options parameter. Currently only CNFS uses this field; it should contain the name of the metacycbuff used to store articles in this storage class. The sixth parameter is a boolean which is false by default: any non-zero number of matching newsgroups is sufficient, provided no newsgroup matches a poison wildmat. If it is set to true, all the newsgroups in the Newsgroups: header of incoming articles will be examined to see if they match the newsgroups wildmat pattern. If you're using CNFS exclusively, just create one storage class for each metacycbuff that you have defined in cycbuff.conf and set the newsgroups pattern according to what newsgroups should be stored in that buffer. If you're using timehash or timecaf, the storage class IDs are used to store articles in separate directory trees, which you can take advantage of to put particular storage classes on different disks. Also, currently storage class is the only way to specify expiration time, so you will need to divide up your newsgroups based on how long you want to retain articles in those groups and create a storage class for each such collection of newsgroups. Make note of the storage class IDs you assign as they will be needed when you edit expire.ctl a bit later. expire.ctl expire.ctl sets the expiration policy for articles stored on the server. Be careful, since the default configuration will expire most articles after 15 days; in most circumstances this deletion is *permanent*, so read this whole section carefully if you want to keep local hierarchies forever. (See archive(8) for a way to automate backups of important articles.) Only one entry is required for all storage classes; it looks like: /remember/:11 This entry says how long to keep the message-IDs for articles that have already expired in the history file so that the server doesn't accept them again. Occasionally, fairly old articles will get regurgitated somewhere and offered to you again, so even after you've expired articles from your spool, you want to keep them around in your history file for a little while to ensure you don't get duplicates. INN will reject any articles more than a certain number of days old (the *artcutoff* parameter in inn.conf, defaulting to 10); the number on the "/remember/" line should be one more than that number in order to take into account articles whose posting date is one day into the future. CNFS makes no further use of expire.ctl, since articles stored in CNFS buffers expire automatically when the buffer runs out of free space (but see the "-N" option in expireover(8) if you really want to expire them earlier). For other storage methods, there are two different syntaxes of this file, depending on *groupbaseexpiry* in inn.conf. If it is set to false, expire.ctl takes entries of the form: ::: is the number assigned to a storage class in storage.conf. is the number of days to keep normal articles in that storage class (decimal values are allowed). For articles that don't have an Expires: header, those are the only two values that matter. For articles with an Expires: header, the other two values come into play; the date given in the Expires: header of an article will be honored, subject to the constraints set by and . All articles in this storage class will be kept for at least days, regardless of their Expires: headers, and all articles in this storage class will be expired after days, even if their Expires: headers specify a longer life. All three of these fields can also contain the special keyword "never". If is "never", only articles with explicit Expires: headers will ever be expired. If is "never", articles with explicit Expires: headers will be kept forever. Setting to "never" says to honor Expires: headers even if they specify dates far into the future. (Note that if is set to "never", all articles with Expires: headers are kept forever and the value of is not used.) If the value of *groupbaseexpiry* is true, expire.ctl takes entries of the form: :::: is a wildmat expression ("!" and "@" not permitted, and only a single expression, not a comma-separated set of them). Each expiration line applies to groups matching the wildmat expression. is "M" for moderated groups, "U" for unmoderated groups, and "A" for groups with any moderation status; the line only matches groups with the indicated expiration status. All of the other fields have the same meaning as above. readers.conf Provided that *noreader* is set to false in inn.conf, any connection from a host that doesn't match an entry in incoming.conf (as well as any connection from a host that does match such an entry, but has issued a MODE READER command) will be handed off to nnrpd(8), the part of INN that supports newsreading clients. nnrpd uses readers.conf to determine whether a given connection is allowed to read news, and if so what newsgroups the client can read and post to. There are a variety of fairly complicated things that one can do with readers.conf, things like run external authentication programs that can query RADIUS servers. See readers.conf(5) and the example file for all the gory details. Here's an example of probably the simplest reasonable configuration, one that only allows clients in the "example.com" domain to read from the server and allows any host in that domain to read and post to all groups: auth "example.com" { hosts: "example.com, *.example.com" default: "" default-domain: "example.com" } access "all" { users: "*@example.com" newsgroups: "*" } If you're running a server for one particular domain, want to allow all hosts within that domain to read and post to any group on the server, and want to deny access to anyone outside that domain, just use the above and change "example.com" in the above to your domain and you're all set. Lots of examples of more complicated things are in the sample file. Creating the Article Spool (CNFS only) If you are using actual files as your CNFS buffers, you will need to pre-create those files, ensuring they're the right size. The easiest way to do this is with dd. For each cycbuff in cycbuff.conf, create the buffer with the following commands (as the news user): dd if=/dev/zero of=/path/to/buffer bs=1k count=BUFFERSIZE chmod 664 /path/to/buffer Substitute the correct path to the buffer and the size of the buffer as specified in cycbuff.conf. This will create a zero-filled file of the correct size; it may take a while, so be prepared to wait. Here's a command that will print out the dd(1) commands that you should run: awk -F: \ '/^cy/ { printf "dd if=/dev/zero of=%s bs=1k count=%s\n", $3, $4 }' \ /cycbuff.conf If you are using block devices, you don't technically have to do anything at all (since INN is capable of using the devices in /dev), but you probably want to create special device files for those devices somewhere for INN's private use. It is more convenient to keep all of INN's stuff together, but more importantly, the device files used by INN really should be owned by the news user and group, and you may not want to do that with the files in /dev. To create the device files for INN, use mknod(8) with a type of "b", getting the major and minor device numbers from the existing devices in /dev. There's a small shell script in cycbuff.conf(5) that may help with this. Make sure to create the device files in the location INN expects them (specified in cycbuff.conf). Solaris users please note: on Solaris, do not use block devices that include the first cylinder of the disk. Solaris doesn't protect the superblock from being overwritten by an application writing to block devices and includes it in the first cylinder of the disk, so unless you use a slice that starts with cylinder 1 instead of 0, INN will invalidate the partition table when it tries to initialize the cycbuff and all further accesses will fail until you repartition. Creating the Database Files At this point, you need to set up the news database directory (in *pathdb*). This directory will hold the active(5) file (the list of newsgroups you carry), the active.times(5) file (the creator and creation time of newsgroups created since the server was initialized), the newsgroups(5) file (descriptions for all the newsgroups you carry), and the history(5) file (a record of every article the server currently has or has seen in the past few days, used to decide whether to accept or refuse new incoming messages). Before starting to work on this, make sure you're logged on as the news user, since all of these files need to be owned by that user. This is a good policy to always follow; if you are doing any maintenance work on your news server, log on as the news user. Don't do maintenance work as root. Also make sure that *pathbin* is in the default path of the news user (and while you're at it, make sure *pathnews*/share/man is in the default MANPATH) so that you can run INN maintenance commands without having to type the full path. If you already have a server set up (if you're upgrading, or setting up a new server based on an existing server), copy active and newsgroups from that server into *pathdb*. Otherwise, you'll need to figure out what newsgroups you want to carry and create new active and newsgroups files for them. If you plan to carry a full feed, or something close to that, go to and download active and newsgroups from there; that will start you off with reasonably complete files. If you plan to only carry a small set of groups, the default minimal active file installed by INN is a good place to start; you can create additional groups after the server is running by using "ctlinnd newgroup". (Another option is to use actsync(8) to synchronize your newsgroup list to that of another server.) "control", "control.cancel" and "junk" must exist as newsgroups in your active file for INN to start, and creating pseudogroups for the major types of control messages is strongly encouraged for all servers that aren't standalone. If you don't want these groups to be visible to clients, do *not* delete them; simply hide them in readers.conf. "to" must also exist as a newsgroup if you have *mergetogroups* set in inn.conf. Next, you need to create an empty history database. To do this, type: cd touch history makedbz -i -o (Note that if you install INN with "make install", you do not need to run these commands: the installation takes care of creating the history database.) When it finishes, make sure the file permissions are correct on all the files you've just created: chmod 644 * Your news database files are now ready to go. Configuring syslog While some logs are handled internally, INN also logs a wide variety of information via syslog. INN's nightly report programs know how to roll and summarize those syslog log files, but when you first install INN you need to set them up. If your system understands the "news" syslog facility, INN will use it; otherwise, it will log to "local1". Nearly every modern system has a "news" syslog facility so you can safely assume that yours does, but if in doubt take a look at the output from running "configure". You should see a line that looks like: checking log level for news... LOG_NEWS If that says LOG_LOCAL1 instead, change the below instructions to use "local1" instead of "news". Edit /etc/syslog.conf on your system and add lines that look like the following: news.crit /news.crit news.err /news.err news.notice /news.notice (Change the path names as necessary in order to match *pathlog*, which defaults to /usr/local/news/log.) These lines *must* be tab-delimited, so don't copy and paste from these instructions. Type it in by hand and make sure you use a tab, or you'll get mysterious failures. You'll also want to make sure that news log messages don't fill your other log files (INN generates a lot of log traffic); so for every entry in /etc/syslog.conf that starts with "*", add ";news.none" to the end of the first column. For example, if you have a line like: *.err /dev/console change it to: *.err;news.none /dev/console (You can choose not to do this for the higher priority log messages, if you want to make sure they go to your normal high-priority log files as well as INN's. Don't bother with anything lower priority than "crit", though. news.err isn't interesting enough to want to see all the time.) Now, make sure that the news log files exist; syslog generally won't create files automatically. Enter the following commands: touch /news.crit touch /news.err touch /news.notice chown news /news.* chgrp news /news.* (again adjusting the paths if necessary for your installation). Finally, send a HUP signal to syslogd to make it re-read its configuration file. Setting Up the Cron Jobs INN requires a special cron job to be set up on your system to run news.daily(8) which performs daily server maintenance tasks such as article expiration and the processing and rotation of the server logs. Since it will slow the server down while it is running, it should be run during periods of low server usage, such as in the middle of the night. To run it at 3am, for example, add the following entry to the news user's crontab file: 0 3 * * * /news.daily expireover lowmark or, if your system does not have per-user crontabs, put the following line into your system crontab instead: 0 3 * * * su news -s /bin/sh -c '/news.daily expireover lowmark' If you're using any non-CNFS storage methods, add "delayrm" to the above option list for news.daily. The news user obviously must be able to run cron jobs. On Solaris, this means that it must have a valid /etc/shadow entry and must not be locked (although it may be a non-login account). There may be similar restrictions with other operating systems. If you use the batching method to send news, also set up a cron job to run nntpsend(8) every ten minutes. nntpsend will run innxmit for all non-empty pending batch files to send pending news to your peers. That cron entry should look something like: 0,10,20,30,40,50 * * * * /nntpsend The pathnames and user ID used above are the installation defaults; change them to match your installation if you used something other than the defaults. The parameters passed to news.daily in the above example are the most common (and usually the most efficient) ones to use. More information on what these parameters do can be found in the news.daily(8) man page. You may also want to run rnews each hour to process spooled messages created while innd is not available: 12 * * * * /rnews -U And it is also a good practice to refresh each day INN's cached IP addresses: 30 2 * * * /ctlinnd -t 120 -s reload incoming.conf 'flush cache' File Descriptor Limits INN likes to use a lot of file descriptors, particularly if you have a lot of peers. Depending on what your system defaults are, you may need to make sure the default limit is increased for INN (particularly for innd and innfeed). This is vital on Solaris, which defaults (at least as of 2.6) to an absurdly low limit of 64 file descriptors per process. One way to increase the number of file descriptors is to set *rlimitnofile* in inn.conf to a higher value. This will cause innd and innfeed to try to increase the file descriptor limits when they start. Note, however, that INN won't be able to increase the limits above the hard limits set by your operating system; on some systems, that hard limit is normally 256 file descriptors (Linux, for example). On others, like Solaris, it's 1024. Increasing the limit beyond that value may require serious system configuration work. (On some operating systems, it requires patching and recompiling the kernel. On Solaris it can be changed in /etc/system, but for 2.6 or earlier the limit cannot be increased beyond 1024 without breaking select(2) and thereby breaking all of INN. For current versions of Linux, you may be able to change the maximum by writing to /proc/sys/fs/file-max.) 256 file descriptors will probably be enough for all but the largest sites. There is no harm in setting the limits higher than you actually need (provided they're set to something lower than or equal to your system hard limit). 256 is therefore a reasonable value to try. If you're installing INN on a Solaris system, particularly if you're installing it on a dedicated news server machine, it may be easier to just increase the default file descriptor limit across the board for all processes. You can do that by putting the line: set rlim_fd_cur = 256 in /etc/system and rebooting. You can increase it all the way to 1024 (and may need to if you have a particularly large site), but that can cause RPC and some stdio applications to break. It therefore probably isn't a good idea on a machine that isn't dedicated to INN. Starting and Stopping the System INN is started via the shell script rc.news. This must be run as the news user and not as root. To start INN on system boot, you therefore want to put something like: su news -s /bin/sh -c /rc.news in the system boot scripts. If innd is stopped or killed, you can restart it by running rc.news by hand as the news user. The rc.news script may also be used to shut down INN, with the "stop" option: su news -s /bin/sh -c '/rc.news stop' In the contrib directory of this source tree, two sample init scripts are provided: one for people using System V-style init.d directories, and another for people using systemd-style init scripts. If you wish to use TLS/SSL for your readers, you need to start a second nnrpd to listen to these connections to NNTPS port 563 and put something like that in your init scripts: su news -s /bin/sh -c '/nnrpd -D -c /readers-ssl.conf -p 563 -S' where readers-ssl.conf is the file which indicates whether a given connection is allowed to read and post news (you can also use the previously created readers.conf file to handle TLS/SSL connections). Note that a news client which supports the STARTTLS command can also use the conventional NNTP port 119 to dynamically upgrade from unencrypted to TLS-protected traffic during an NNTP session. However, this practice is discouraged in favour of using the separate port 563. See nnrpd(8) for more information about TLS support. In the shutdown section of the init script, you can put: start-stop-daemon --stop --name nnrpd --quiet --oknodo or if you do not have a start-stop-daemon utility: su news -s /bin/sh -c 'killall nnrpd' Processing Newsgroup Control Messages Control messages are specially-formatted messages that tell news servers to take various actions. Cancels (commands to delete messages) are handled internally by INN, and all other control messages are processed by controlchan, a channel feed program which should be run out of newsfeeds if you want your news server to process any control messages; see "Configuring INN" for specific instructions. Note that *pgpverify* must also be set to true in inn.conf. The actions of controlchan are determined by control.ctl, which lists who can perform what actions. The primary control messages to be concerned with are "newgroup" (to create a newsgroup), "rmgroup" (to remove a newsgroup), and "checkgroups" (to compare the list of groups carried in a hierarchy to a canonical list). INN comes with a control.ctl file that processes control messages in most major public hierarchies; if you don't want to act on all those control messages, you should remove from that file all entries for hierarchies you don't want to carry. The last version of that file is available from . You can tell INN to just authenticate control messages based on the From: header of the message, but this is obviously perilous and control messages are widely forged. Many hierarchies sign all of their control messages with PGP, allowing news servers to verify their authenticity, and checking those signatures for hierarchies that use them is highly recommended. controlchan knows how to do this (using pgpverify) without additional configuration, but you do have to provide it with a public key ring containing the public keys of all of the hierarchy administrators whose control messages you want to check. INN expects the public key ring to either be in the default location for a PGP public key ring for the news user (generally *pathnews*/.gnupg for GnuPG and *pathnews*/.pgp for old PGP implementations), or in *pathetc*/pgp (/usr/local/news/etc/pgp by default). The latter is the recommended path. To add a key to that key ring, use: gpg --import --homedir=/pgp where is a file containing the hierarchy key. Change the homedir setting to point to *pathetc*/pgp if you have INN installed in a non-default location. If you're using the old-style PGP program, an equivalent command is: env PGPPATH=/pgp pgp You can safely answer "no" to questions about whether you want to sign, trust, or certify keys. And you may afterwards do: cp /pgp/pubring.gpg /pgp/trustedkeys.gpg The URLs from which you can get hierarchy keys are noted in comments in control.ctl. tries to collect the major hierarchy keys and you can just import the whole file. If you want to make sure that the keys have been correcly imported, use: gpg --list-keys If you are using GnuPG, please note that the first user ID on the key will be the one that's used by INN for verification and must match the key listed in control.ctl. If a hierarchy key has multiple user IDs, you may have to remove all the user IDs except the one that matches the control.ctl entry using "gpg --edit-key" and the "delkey" command. $Id: install.pod 10535 2021-01-20 17:55:18Z iulius $ inn-2.6.4/m4/0000755000175200017520000000000014002373701012236 5ustar iuliusiuliusinn-2.6.4/m4/openssl.m40000644000175200017520000001225114002373703014166 0ustar iuliusiuliusdnl Find the compiler and linker flags for OpenSSL. dnl $Id: openssl.m4 10306 2018-12-02 14:26:13Z iulius $ dnl dnl Finds the compiler and linker flags for linking with both the OpenSSL SSL dnl library and its crypto library. Provides the --with-openssl, dnl --with-openssl-lib, and --with-openssl-include configure options to dnl specify non-standard paths to the OpenSSL libraries. dnl dnl Provides the macro INN_LIB_OPENSSL and sets the substitution variables dnl OPENSSL_CPPFLAGS, OPENSSL_LDFLAGS, OPENSSL_LIBS, CRYPTO_CPPFLAGS, dnl CRYPTO_LDFLAGS, and CRYPTO_LIBS. Also provides INN_LIB_OPENSSL_SWITCH and dnl INN_LIB_CRYPTO_SWITCH to set CPPFLAGS, LDFLAGS, and LIBS to include the dnl SSL or crypto libraries, saving the current values first, and dnl INN_LIB_OPENSSL_RESTORE and INN_LIB_CRYPTO_RESTORE to restore those dnl settings to before the last INN_LIB_OPENSSL_SWITCH or dnl INN_LIB_CRYPTO_SWITCH. Defines HAVE_OPENSSL and sets inn_use_OPENSSL to dnl true if the library is found. dnl dnl Provides the INN_LIB_OPENSSL_OPTIONAL macro, which should be used if dnl OpenSSL support is optional. This macro will still set the substitution dnl variables and shell variables described above, but they'll be empty unless dnl OpenSSL libraries are detected. HAVE_OPENSSL will be defined only if the dnl library is found. dnl dnl Depends on INN_ENABLE_REDUCED_DEPENDS and the lib-helper.m4 framework. dnl dnl The canonical version of this file is maintained in the rra-c-util dnl package, available at . dnl dnl Written by Russ Allbery dnl Copyright 2016, 2018 Russ Allbery dnl Copyright 2010, 2013 dnl The Board of Trustees of the Leland Stanford Junior University dnl dnl This file is free software; the authors give unlimited permission to copy dnl and/or distribute it, with or without modifications, as long as this dnl notice is preserved. dnl dnl SPDX-License-Identifier: FSFULLR dnl Save the current CPPFLAGS, LDFLAGS, and LIBS settings and switch to dnl versions that include the SSL or crypto flags. Used as a wrapper, with dnl INN_LIB_OPENSSL_RESTORE or INN_LIB_CRYPTO_RESTORE, around tests. AC_DEFUN([INN_LIB_OPENSSL_SWITCH], [INN_LIB_HELPER_SWITCH([OPENSSL])]) AC_DEFUN([INN_LIB_CRYPTO_SWITCH], [INN_LIB_HELPER_SWITCH([CRYPTO])]) dnl Restore CPPFLAGS, LDFLAGS, and LIBS to their previous values (before dnl INN_LIB_OPENSSL_SWITCH or INN_LIB_CRYPTO_SWITCH were called). AC_DEFUN([INN_LIB_OPENSSL_RESTORE], [INN_LIB_HELPER_RESTORE([OPENSSL])]) AC_DEFUN([INN_LIB_CRYPTO_RESTORE], [INN_LIB_HELPER_RESTORE([CRYPTO])]) dnl Check for the OpenSSL and crypto libraries and assemble OPENSSL_LIBS and dnl CRYPTO_LIBS. Helper function for _INN_LIB_OPENSSL_INTERNAL. Must be dnl called with INN_LIB_OPENSSL_SWITCH enabled. AC_DEFUN([_INN_LIB_OPENSSL_INTERNAL_LIBS], [inn_openssl_extra= LIBS= AS_IF([test x"$inn_reduced_depends" != xtrue], [AC_SEARCH_LIBS([dlopen], [dl])]) inn_openssl_extra="$LIBS" LIBS="$inn_OPENSSL_save_LIBS" AC_CHECK_LIB([crypto], [AES_cbc_encrypt], [CRYPTO_LIBS="-lcrypto $inn_openssl_extra"], [AS_IF([test x"$1" = xtrue], [AC_MSG_ERROR([cannot find usable OpenSSL crypto library])])], [$inn_openssl_extra]) AS_IF([test x"$inn_reduced_depends" = xtrue], [AC_CHECK_LIB([ssl], [SSL_accept], [OPENSSL_LIBS=-lssl], [AS_IF([test x"$1" = xtrue], [AC_MSG_ERROR([cannot find usable OpenSSL library])])])], [AC_CHECK_LIB([ssl], [SSL_accept], [OPENSSL_LIBS="-lssl $CRYPTO_LIBS"], [AS_IF([test x"$1" = xtrue], [AC_MSG_ERROR([cannot find usable OpenSSL library])])], [$CRYPTO_LIBS])])]) dnl Checks if the OpenSSL header and OpenSSL and crypto libraries are present. dnl The single argument, if "true", says to fail if the OpenSSL SSL library dnl could not be found. AC_DEFUN([_INN_LIB_OPENSSL_INTERNAL], [AC_REQUIRE([INN_ENABLE_REDUCED_DEPENDS]) INN_LIB_HELPER_PATHS([OPENSSL]) CRYPTO_CPPFLAGS="$OPENSSL_CPPFLAGS" CRYPTO_LDFLAGS="$OPENSSL_LDFLAGS" CRYPTO_LIBS= AC_SUBST([CRYPTO_CPPFLAGS]) AC_SUBST([CRYPTO_LDFLAGS]) AC_SUBST([CRYPTO_LIBS]) INN_LIB_OPENSSL_SWITCH AC_CHECK_HEADER([openssl/ssl.h], [_INN_LIB_OPENSSL_INTERNAL_LIBS([$1])], [AS_IF([test x"$1" = xtrue], [AC_MSG_ERROR([cannot find usable OpenSSL header])])]) INN_LIB_OPENSSL_RESTORE]) dnl The main macro for packages with mandatory OpenSSL support. AC_DEFUN([INN_LIB_OPENSSL], [INN_LIB_HELPER_VAR_INIT([OPENSSL]) INN_LIB_HELPER_WITH([openssl], [OpenSSL], [OPENSSL]) _INN_LIB_OPENSSL_INTERNAL([true]) inn_use_OPENSSL=true AC_DEFINE([HAVE_OPENSSL], 1, [Define if libssl is available.])]) dnl The main macro for packages with optional OpenSSL support. AC_DEFUN([INN_LIB_OPENSSL_OPTIONAL], [INN_LIB_HELPER_VAR_INIT([OPENSSL]) INN_LIB_HELPER_WITH_OPTIONAL([openssl], [OpenSSL], [OPENSSL]) AS_IF([test x"$inn_use_OPENSSL" != xfalse], [AS_IF([test x"$inn_use_OPENSSL" = xtrue], [_INN_LIB_OPENSSL_INTERNAL([true])], [_INN_LIB_OPENSSL_INTERNAL([false])])]) AS_IF([test x"$OPENSSL_LIBS" = x], [INN_LIB_HELPER_VAR_CLEAR([OPENSSL]) INN_LIB_HELPER_VAR_CLEAR([CRYPTO])], [inn_use_OPENSSL=true AC_DEFINE([HAVE_OPENSSL], 1, [Define if libssl is available.])])]) inn-2.6.4/m4/pkg.m40000644000175200017520000002400414002373703013263 0ustar iuliusiulius# pkg.m4 - Macros to locate and use pkg-config. -*- Autoconf -*- # serial 12 (pkg-config-0.29.2) dnl Copyright © 2004 Scott James Remnant . dnl Copyright © 2012-2015 Dan Nicholson dnl dnl This program is free software; you can redistribute it and/or modify dnl it under the terms of the GNU General Public License as published by dnl the Free Software Foundation; either version 2 of the License, or dnl (at your option) any later version. dnl dnl This program is distributed in the hope that it will be useful, but dnl WITHOUT ANY WARRANTY; without even the implied warranty of dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU dnl General Public License for more details. dnl dnl You should have received a copy of the GNU General Public License dnl along with this program; if not, write to the Free Software dnl Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA dnl 02111-1307, USA. dnl dnl As a special exception to the GNU General Public License, if you dnl distribute this file as part of a program that contains a dnl configuration script generated by Autoconf, you may include it under dnl the same distribution terms that you use for the rest of that dnl program. dnl PKG_PREREQ(MIN-VERSION) dnl ----------------------- dnl Since: 0.29 dnl dnl Verify that the version of the pkg-config macros are at least dnl MIN-VERSION. Unlike PKG_PROG_PKG_CONFIG, which checks the user's dnl installed version of pkg-config, this checks the developer's version dnl of pkg.m4 when generating configure. dnl dnl To ensure that this macro is defined, also add: dnl m4_ifndef([PKG_PREREQ], dnl [m4_fatal([must install pkg-config 0.29 or later before running autoconf/autogen])]) dnl dnl See the "Since" comment for each macro you use to see what version dnl of the macros you require. m4_defun([PKG_PREREQ], [m4_define([PKG_MACROS_VERSION], [0.29.2]) m4_if(m4_version_compare(PKG_MACROS_VERSION, [$1]), -1, [m4_fatal([pkg.m4 version $1 or higher is required but ]PKG_MACROS_VERSION[ found])]) ])dnl PKG_PREREQ dnl PKG_PROG_PKG_CONFIG([MIN-VERSION]) dnl ---------------------------------- dnl Since: 0.16 dnl dnl Search for the pkg-config tool and set the PKG_CONFIG variable to dnl first found in the path. Checks that the version of pkg-config found dnl is at least MIN-VERSION. If MIN-VERSION is not specified, 0.9.0 is dnl used since that's the first version where most current features of dnl pkg-config existed. AC_DEFUN([PKG_PROG_PKG_CONFIG], [m4_pattern_forbid([^_?PKG_[A-Z_]+$]) m4_pattern_allow([^PKG_CONFIG(_(PATH|LIBDIR|SYSROOT_DIR|ALLOW_SYSTEM_(CFLAGS|LIBS)))?$]) m4_pattern_allow([^PKG_CONFIG_(DISABLE_UNINSTALLED|TOP_BUILD_DIR|DEBUG_SPEW)$]) AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility]) AC_ARG_VAR([PKG_CONFIG_PATH], [directories to add to pkg-config's search path]) AC_ARG_VAR([PKG_CONFIG_LIBDIR], [path overriding pkg-config's built-in search path]) if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then AC_PATH_TOOL([PKG_CONFIG], [pkg-config]) fi if test -n "$PKG_CONFIG"; then _pkg_min_version=m4_default([$1], [0.9.0]) AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version]) if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) PKG_CONFIG="" fi fi[]dnl ])dnl PKG_PROG_PKG_CONFIG dnl PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) dnl ------------------------------------------------------------------- dnl Since: 0.18 dnl dnl Check to see whether a particular set of modules exists. Similar to dnl PKG_CHECK_MODULES(), but does not set variables or print errors. dnl dnl Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG]) dnl only at the first occurrence in configure.ac, so if the first place dnl it's called might be skipped (such as if it is within an "if", you dnl have to call PKG_CHECK_EXISTS manually AC_DEFUN([PKG_CHECK_EXISTS], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl if test -n "$PKG_CONFIG" && \ AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then m4_default([$2], [:]) m4_ifvaln([$3], [else $3])dnl fi]) dnl _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES]) dnl --------------------------------------------- dnl Internal wrapper calling pkg-config via PKG_CONFIG and setting dnl pkg_failed based on the result. m4_define([_PKG_CONFIG], [if test -n "$$1"; then pkg_cv_[]$1="$$1" elif test -n "$PKG_CONFIG"; then PKG_CHECK_EXISTS([$3], [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes ], [pkg_failed=yes]) else pkg_failed=untried fi[]dnl ])dnl _PKG_CONFIG dnl _PKG_SHORT_ERRORS_SUPPORTED dnl --------------------------- dnl Internal check to see if pkg-config supports short errors. AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED], [AC_REQUIRE([PKG_PROG_PKG_CONFIG]) if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi[]dnl ])dnl _PKG_SHORT_ERRORS_SUPPORTED dnl PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], dnl [ACTION-IF-NOT-FOUND]) dnl -------------------------------------------------------------- dnl Since: 0.4.0 dnl dnl Note that if there is a possibility the first call to dnl PKG_CHECK_MODULES might not happen, you should be sure to include an dnl explicit call to PKG_PROG_PKG_CONFIG in your configure.ac AC_DEFUN([PKG_CHECK_MODULES], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl pkg_failed=no AC_MSG_CHECKING([for $2]) _PKG_CONFIG([$1][_CFLAGS], [cflags], [$2]) _PKG_CONFIG([$1][_LIBS], [libs], [$2]) m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS and $1[]_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details.]) if test $pkg_failed = yes; then AC_MSG_RESULT([no]) _PKG_SHORT_ERRORS_SUPPORTED if test $_pkg_short_errors_supported = yes; then $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$2" 2>&1` else $1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$2" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD m4_default([$4], [AC_MSG_ERROR( [Package requirements ($2) were not met: $$1_PKG_ERRORS Consider adjusting the PKG_CONFIG_PATH environment variable if you installed software in a non-standard prefix. _PKG_TEXT])[]dnl ]) elif test $pkg_failed = untried; then AC_MSG_RESULT([no]) m4_default([$4], [AC_MSG_FAILURE( [The pkg-config script could not be found or is too old. Make sure it is in your PATH or set the PKG_CONFIG environment variable to the full path to pkg-config. _PKG_TEXT To get pkg-config, see .])[]dnl ]) else $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS $1[]_LIBS=$pkg_cv_[]$1[]_LIBS AC_MSG_RESULT([yes]) $3 fi[]dnl ])dnl PKG_CHECK_MODULES dnl PKG_CHECK_MODULES_STATIC(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], dnl [ACTION-IF-NOT-FOUND]) dnl --------------------------------------------------------------------- dnl Since: 0.29 dnl dnl Checks for existence of MODULES and gathers its build flags with dnl static libraries enabled. Sets VARIABLE-PREFIX_CFLAGS from --cflags dnl and VARIABLE-PREFIX_LIBS from --libs. dnl dnl Note that if there is a possibility the first call to dnl PKG_CHECK_MODULES_STATIC might not happen, you should be sure to dnl include an explicit call to PKG_PROG_PKG_CONFIG in your dnl configure.ac. AC_DEFUN([PKG_CHECK_MODULES_STATIC], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl _save_PKG_CONFIG=$PKG_CONFIG PKG_CONFIG="$PKG_CONFIG --static" PKG_CHECK_MODULES($@) PKG_CONFIG=$_save_PKG_CONFIG[]dnl ])dnl PKG_CHECK_MODULES_STATIC dnl PKG_INSTALLDIR([DIRECTORY]) dnl ------------------------- dnl Since: 0.27 dnl dnl Substitutes the variable pkgconfigdir as the location where a module dnl should install pkg-config .pc files. By default the directory is dnl $libdir/pkgconfig, but the default can be changed by passing dnl DIRECTORY. The user can override through the --with-pkgconfigdir dnl parameter. AC_DEFUN([PKG_INSTALLDIR], [m4_pushdef([pkg_default], [m4_default([$1], ['${libdir}/pkgconfig'])]) m4_pushdef([pkg_description], [pkg-config installation directory @<:@]pkg_default[@:>@]) AC_ARG_WITH([pkgconfigdir], [AS_HELP_STRING([--with-pkgconfigdir], pkg_description)],, [with_pkgconfigdir=]pkg_default) AC_SUBST([pkgconfigdir], [$with_pkgconfigdir]) m4_popdef([pkg_default]) m4_popdef([pkg_description]) ])dnl PKG_INSTALLDIR dnl PKG_NOARCH_INSTALLDIR([DIRECTORY]) dnl -------------------------------- dnl Since: 0.27 dnl dnl Substitutes the variable noarch_pkgconfigdir as the location where a dnl module should install arch-independent pkg-config .pc files. By dnl default the directory is $datadir/pkgconfig, but the default can be dnl changed by passing DIRECTORY. The user can override through the dnl --with-noarch-pkgconfigdir parameter. AC_DEFUN([PKG_NOARCH_INSTALLDIR], [m4_pushdef([pkg_default], [m4_default([$1], ['${datadir}/pkgconfig'])]) m4_pushdef([pkg_description], [pkg-config arch-independent installation directory @<:@]pkg_default[@:>@]) AC_ARG_WITH([noarch-pkgconfigdir], [AS_HELP_STRING([--with-noarch-pkgconfigdir], pkg_description)],, [with_noarch_pkgconfigdir=]pkg_default) AC_SUBST([noarch_pkgconfigdir], [$with_noarch_pkgconfigdir]) m4_popdef([pkg_default]) m4_popdef([pkg_description]) ])dnl PKG_NOARCH_INSTALLDIR dnl PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE, dnl [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) dnl ------------------------------------------- dnl Since: 0.28 dnl dnl Retrieves the value of the pkg-config variable for the given module. AC_DEFUN([PKG_CHECK_VAR], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl AC_ARG_VAR([$1], [value of $3 for $2, overriding pkg-config])dnl _PKG_CONFIG([$1], [variable="][$3]["], [$2]) AS_VAR_COPY([$1], [pkg_cv_][$1]) AS_VAR_IF([$1], [""], [$5], [$4])dnl ])dnl PKG_CHECK_VAR inn-2.6.4/m4/lt~obsolete.m40000644000175200017520000001377414002373703015070 0ustar iuliusiulius# lt~obsolete.m4 -- aclocal satisfying obsolete definitions. -*-Autoconf-*- # # Copyright (C) 2004-2005, 2007, 2009, 2011-2015 Free Software # Foundation, Inc. # Written by Scott James Remnant, 2004. # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # serial 5 lt~obsolete.m4 # These exist entirely to fool aclocal when bootstrapping libtool. # # In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN), # which have later been changed to m4_define as they aren't part of the # exported API, or moved to Autoconf or Automake where they belong. # # The trouble is, aclocal is a bit thick. It'll see the old AC_DEFUN # in /usr/share/aclocal/libtool.m4 and remember it, then when it sees us # using a macro with the same name in our local m4/libtool.m4 it'll # pull the old libtool.m4 in (it doesn't see our shiny new m4_define # and doesn't know about Autoconf macros at all.) # # So we provide this file, which has a silly filename so it's always # included after everything else. This provides aclocal with the # AC_DEFUNs it wants, but when m4 processes it, it doesn't do anything # because those macros already exist, or will be overwritten later. # We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6. # # Anytime we withdraw an AC_DEFUN or AU_DEFUN, remember to add it here. # Yes, that means every name once taken will need to remain here until # we give up compatibility with versions before 1.7, at which point # we need to keep only those names which we still refer to. # This is to help aclocal find these macros, as it can't see m4_define. AC_DEFUN([LTOBSOLETE_VERSION], [m4_if([1])]) m4_ifndef([AC_LIBTOOL_LINKER_OPTION], [AC_DEFUN([AC_LIBTOOL_LINKER_OPTION])]) m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP])]) m4_ifndef([_LT_AC_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH])]) m4_ifndef([_LT_AC_SHELL_INIT], [AC_DEFUN([_LT_AC_SHELL_INIT])]) m4_ifndef([_LT_AC_SYS_LIBPATH_AIX], [AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX])]) m4_ifndef([_LT_PROG_LTMAIN], [AC_DEFUN([_LT_PROG_LTMAIN])]) m4_ifndef([_LT_AC_TAGVAR], [AC_DEFUN([_LT_AC_TAGVAR])]) m4_ifndef([AC_LTDL_ENABLE_INSTALL], [AC_DEFUN([AC_LTDL_ENABLE_INSTALL])]) m4_ifndef([AC_LTDL_PREOPEN], [AC_DEFUN([AC_LTDL_PREOPEN])]) m4_ifndef([_LT_AC_SYS_COMPILER], [AC_DEFUN([_LT_AC_SYS_COMPILER])]) m4_ifndef([_LT_AC_LOCK], [AC_DEFUN([_LT_AC_LOCK])]) m4_ifndef([AC_LIBTOOL_SYS_OLD_ARCHIVE], [AC_DEFUN([AC_LIBTOOL_SYS_OLD_ARCHIVE])]) m4_ifndef([_LT_AC_TRY_DLOPEN_SELF], [AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF])]) m4_ifndef([AC_LIBTOOL_PROG_CC_C_O], [AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O])]) m4_ifndef([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], [AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS])]) m4_ifndef([AC_LIBTOOL_OBJDIR], [AC_DEFUN([AC_LIBTOOL_OBJDIR])]) m4_ifndef([AC_LTDL_OBJDIR], [AC_DEFUN([AC_LTDL_OBJDIR])]) m4_ifndef([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], [AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH])]) m4_ifndef([AC_LIBTOOL_SYS_LIB_STRIP], [AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP])]) m4_ifndef([AC_PATH_MAGIC], [AC_DEFUN([AC_PATH_MAGIC])]) m4_ifndef([AC_PROG_LD_GNU], [AC_DEFUN([AC_PROG_LD_GNU])]) m4_ifndef([AC_PROG_LD_RELOAD_FLAG], [AC_DEFUN([AC_PROG_LD_RELOAD_FLAG])]) m4_ifndef([AC_DEPLIBS_CHECK_METHOD], [AC_DEFUN([AC_DEPLIBS_CHECK_METHOD])]) m4_ifndef([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI])]) m4_ifndef([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], [AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])]) m4_ifndef([AC_LIBTOOL_PROG_COMPILER_PIC], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC])]) m4_ifndef([AC_LIBTOOL_PROG_LD_SHLIBS], [AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS])]) m4_ifndef([AC_LIBTOOL_POSTDEP_PREDEP], [AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP])]) m4_ifndef([LT_AC_PROG_EGREP], [AC_DEFUN([LT_AC_PROG_EGREP])]) m4_ifndef([LT_AC_PROG_SED], [AC_DEFUN([LT_AC_PROG_SED])]) m4_ifndef([_LT_CC_BASENAME], [AC_DEFUN([_LT_CC_BASENAME])]) m4_ifndef([_LT_COMPILER_BOILERPLATE], [AC_DEFUN([_LT_COMPILER_BOILERPLATE])]) m4_ifndef([_LT_LINKER_BOILERPLATE], [AC_DEFUN([_LT_LINKER_BOILERPLATE])]) m4_ifndef([_AC_PROG_LIBTOOL], [AC_DEFUN([_AC_PROG_LIBTOOL])]) m4_ifndef([AC_LIBTOOL_SETUP], [AC_DEFUN([AC_LIBTOOL_SETUP])]) m4_ifndef([_LT_AC_CHECK_DLFCN], [AC_DEFUN([_LT_AC_CHECK_DLFCN])]) m4_ifndef([AC_LIBTOOL_SYS_DYNAMIC_LINKER], [AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER])]) m4_ifndef([_LT_AC_TAGCONFIG], [AC_DEFUN([_LT_AC_TAGCONFIG])]) m4_ifndef([AC_DISABLE_FAST_INSTALL], [AC_DEFUN([AC_DISABLE_FAST_INSTALL])]) m4_ifndef([_LT_AC_LANG_CXX], [AC_DEFUN([_LT_AC_LANG_CXX])]) m4_ifndef([_LT_AC_LANG_F77], [AC_DEFUN([_LT_AC_LANG_F77])]) m4_ifndef([_LT_AC_LANG_GCJ], [AC_DEFUN([_LT_AC_LANG_GCJ])]) m4_ifndef([AC_LIBTOOL_LANG_C_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG])]) m4_ifndef([_LT_AC_LANG_C_CONFIG], [AC_DEFUN([_LT_AC_LANG_C_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_CXX_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG])]) m4_ifndef([_LT_AC_LANG_CXX_CONFIG], [AC_DEFUN([_LT_AC_LANG_CXX_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_F77_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG])]) m4_ifndef([_LT_AC_LANG_F77_CONFIG], [AC_DEFUN([_LT_AC_LANG_F77_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_GCJ_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG])]) m4_ifndef([_LT_AC_LANG_GCJ_CONFIG], [AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_RC_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG])]) m4_ifndef([_LT_AC_LANG_RC_CONFIG], [AC_DEFUN([_LT_AC_LANG_RC_CONFIG])]) m4_ifndef([AC_LIBTOOL_CONFIG], [AC_DEFUN([AC_LIBTOOL_CONFIG])]) m4_ifndef([_LT_AC_FILE_LTDLL_C], [AC_DEFUN([_LT_AC_FILE_LTDLL_C])]) m4_ifndef([_LT_REQUIRED_DARWIN_CHECKS], [AC_DEFUN([_LT_REQUIRED_DARWIN_CHECKS])]) m4_ifndef([_LT_AC_PROG_CXXCPP], [AC_DEFUN([_LT_AC_PROG_CXXCPP])]) m4_ifndef([_LT_PREPARE_SED_QUOTE_VARS], [AC_DEFUN([_LT_PREPARE_SED_QUOTE_VARS])]) m4_ifndef([_LT_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_PROG_ECHO_BACKSLASH])]) m4_ifndef([_LT_PROG_F77], [AC_DEFUN([_LT_PROG_F77])]) m4_ifndef([_LT_PROG_FC], [AC_DEFUN([_LT_PROG_FC])]) m4_ifndef([_LT_PROG_CXX], [AC_DEFUN([_LT_PROG_CXX])]) inn-2.6.4/m4/python.m40000644000175200017520000001530514002373703014027 0ustar iuliusiuliusdnl Probe for Python properties and, optionally, flags for embedding Python. dnl $Id: python.m4 10521 2021-01-17 21:48:51Z iulius $ dnl dnl Provides the following macros: dnl dnl INN_PROG_PYTHON dnl Checks for a specific Python version and sets the PYTHON environment dnl variable to the full path, or aborts the configure run if the version dnl of Python is not new enough or couldn't be found. Marks PYTHON as a dnl substitution variable. dnl dnl The first argument is a Python version related to the 2.x series (if dnl empty, it means that Python 2 is not supported). The second argument dnl is a Python version related to at least the 3.x series (if empty, dnl it means that Python 3 or later is not supported). dnl dnl INN_PYTHON_CHECK_MODULE dnl Checks for the existence of a Python module. Runs the second argument dnl if it is present and the third argument if it is not. dnl dnl INN_LIB_PYTHON dnl Determines the flags required for embedding Python and sets dnl PYTHON_CPPFLAGS and PYTHON_LIBS. dnl dnl INN_PROG_PYTHON should generally be called before the other two macros. dnl If it isn't, the PYTHON environment variable must be set in some other dnl way. (It cannot be run automatically via dependencies because it takes a dnl mandatory minimum version argument, which should be provided by the dnl calling configure script.) dnl dnl This macro uses the distutils.sysconfig module shipped with Python 2.2.0 dnl and later to find the compiler and linker flags to use to embed Python. dnl It also expects libpython to be in the main library location, which it is dnl since Python 2.3.0. dnl dnl The canonical version of this file is maintained in the rra-c-util dnl package, available at . dnl dnl Copyright 2018 Russ Allbery dnl Copyright 2009, 2011, 2015, 2018 Julien ÉLIE dnl Copyright 1998-2003 The Internet Software Consortium dnl dnl Permission to use, copy, modify, and distribute this software for any dnl purpose with or without fee is hereby granted, provided that the above dnl copyright notice and this permission notice appear in all copies. dnl dnl THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH dnl REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF dnl MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY dnl SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES dnl WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN dnl ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR dnl IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. dnl dnl SPDX-License-Identifier: ISC dnl Command used to probe the Python version. AC_DEFUN([_INN_PROG_PYTHON_CMD], [[ import sys two_okay = False three_okay = False if len(sys.argv) > 1 and sys.argv[1]: two_tuple = tuple(map(int, sys.argv[1].split("."))) if sys.version_info[0] == 2 and sys.version_info >= two_tuple: two_okay = True if len(sys.argv) > 2 and sys.argv[2]: three_tuple = tuple(map(int, sys.argv[2].split("."))) if sys.version_info[0] > 2 and sys.version_info >= three_tuple: three_okay = True assert(two_okay or three_okay) ]]) dnl Check for the path to Python and ensure it meets our minimum version dnl requirement. The first argument specifies the minimum Python 2 version dnl and the second argument specifies the minimum Python 3 (or later) version. dnl At least one constraint must be met. Honor the $PYTHON environment dnl variable, if set. AC_DEFUN([INN_PROG_PYTHON], [AC_ARG_VAR([PYTHON], [Location of Python interpreter]) AS_IF([test x"$1" != x], [inn_py_expected_ver="$1 (2.x series)"], [inn_py_expected_ver=""]) AS_IF([test x"$2" != x], [AS_IF([test x"$1" != x], [inn_py_expected_ver="$inn_py_expected_ver or "]) inn_py_expected_ver="${inn_py_expected_ver}$2"]) AS_IF([test x"$PYTHON" != x], [AS_IF([! test -x "$PYTHON"], [AC_MSG_ERROR([Python binary $PYTHON not found])]) AS_IF([! "$PYTHON" -c '_INN_PROG_PYTHON_CMD()' '$1' '$2' >/dev/null 2>&1], [AC_MSG_ERROR([Python $inn_py_expected_ver or greater is required])])], [AC_CACHE_CHECK([for Python version $inn_py_expected_ver or later], [ac_cv_path_PYTHON], [AC_PATH_PROGS_FEATURE_CHECK([PYTHON], [python python3 python2], [AS_IF(["$ac_path_PYTHON" -c '_INN_PROG_PYTHON_CMD()' \ '$1' '$2' >/dev/null 2>&1], [ac_cv_path_PYTHON="$ac_path_PYTHON" ac_path_PYTHON_found=:])])]) AS_IF([test x"$ac_cv_path_PYTHON" = x], [AC_MSG_ERROR([Python $inn_py_expected_ver or greater is required])]) PYTHON="$ac_cv_path_PYTHON" AC_SUBST([PYTHON])])]) dnl Check whether a given Python module can be loaded. Runs the second dnl argument if it can, and the third argument if it cannot. AC_DEFUN([INN_PYTHON_CHECK_MODULE], [AS_LITERAL_IF([$1], [], [m4_fatal([$0: requires literal arguments])])dnl AS_VAR_PUSHDEF([ac_Module], [inn_cv_python_module_$1])dnl AC_CACHE_CHECK([for Python module $1], [ac_Module], [AS_IF(["$PYTHON" -c 'import $1' >/dev/null 2>&1], [AS_VAR_SET([ac_Module], [yes])], [AS_VAR_SET([ac_Module], [no])])]) AS_VAR_IF([ac_Module], [yes], [$2], [$3]) AS_VAR_POPDEF([ac_Module])]) dnl Determine the flags used for embedding Python. AC_DEFUN([INN_LIB_PYTHON], [AC_SUBST([PYTHON_CPPFLAGS]) AC_SUBST([PYTHON_LIBS]) AC_MSG_CHECKING([for flags to link with Python]) py_include=`$PYTHON -c 'import distutils.sysconfig; \ print(distutils.sysconfig.get_python_inc())'` PYTHON_CPPFLAGS="-I$py_include" py_libdir=`$PYTHON -c 'import distutils.sysconfig; \ print(" -L".join(distutils.sysconfig.get_config_vars("LIBDIR")))'` py_ldlibrary=`$PYTHON -c 'import distutils.sysconfig; \ print(distutils.sysconfig.get_config_vars("LDLIBRARY")@<:@0@:>@)'` py_linkage=`$PYTHON -c 'import distutils.sysconfig; \ print(" ".join(distutils.sysconfig.get_config_vars( \ "LIBS", "LIBC", "LIBM", "LOCALMODLIBS", "BASEMODLIBS", \ "LINKFORSHARED", "LDFLAGS")))'` py_libpython=`AS_ECHO(["$py_ldlibrary"]) | sed "s/^lib//" | sed "s/\.@<:@a-z@:>@*$//"` PYTHON_LIBS="-L$py_libdir -l$py_libpython $py_linkage" PYTHON_LIBS=`AS_ECHO(["$PYTHON_LIBS"]) | sed -e 's/[ \\t]*/ /g'` AC_MSG_RESULT([$PYTHON_LIBS]) inn_python_save_CPPFLAGS="$CPPFLAGS" inn_python_save_LIBS="$LIBS" CPPFLAGS="$PYTHON_CPPFLAGS $CPPFLAGS" LIBS="$PYTHON_LIBS $LIBS" AC_CHECK_HEADER([Python.h], [], [AC_MSG_FAILURE([unable to compile with Python.h])]) AC_CHECK_FUNC([Py_Initialize], [], [AC_MSG_FAILURE([unable to link with Python library])]) CPPFLAGS="$inn_python_save_CPPFLAGS" LIBS="$inn_python_save_LIBS"]) inn-2.6.4/m4/socket.m40000644000175200017520000000767714002373703014013 0ustar iuliusiuliusdnl Various checks for socket support and macros. dnl $Id: socket.m4 10397 2020-11-12 20:22:51Z iulius $ dnl dnl This is a collection of various Autoconf macros for checking networking dnl and socket properties. The macros provided are: dnl dnl INN_FUNC_GETADDRINFO_ADDRCONFIG dnl INN_MACRO_IN6_ARE_ADDR_EQUAL dnl dnl They use a separate internal source macro to make the code easier to read. dnl dnl The canonical version of this file is maintained in the rra-c-util dnl package, available at . dnl dnl Copyright 2017, 2020 Russ Allbery dnl Copyright 2008-2009, 2011 dnl The Board of Trustees of the Leland Stanford Junior University dnl Copyright 2004-2009 Internet Systems Consortium, Inc. ("ISC") dnl Copyright 1991, 1994-2003 The Internet Software Consortium and Rich Salz dnl dnl This code is derived from software contributed to the Internet Software dnl Consortium by Rich Salz. dnl dnl Permission to use, copy, modify, and distribute this software for any dnl purpose with or without fee is hereby granted, provided that the above dnl copyright notice and this permission notice appear in all copies. dnl dnl THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH dnl REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF dnl MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY dnl SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES dnl WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN dnl ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR dnl IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. dnl dnl SPDX-License-Identifier: ISC dnl Source used by INN_FUNC_GETADDRINFO_ADDRCONFIG. AC_DEFUN([_INN_FUNC_GETADDRINFO_ADDRCONFIG_SOURCE], [[ #include #include #include #include #include int main(void) { struct addrinfo hints, *ai; memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_ADDRCONFIG; return (getaddrinfo("localhost", NULL, &hints, &ai) != 0); } ]]) dnl Check whether the AI_ADDRCONFIG flag works properly with getaddrinfo. dnl If so, set HAVE_GETADDRINFO_ADDRCONFIG. AC_DEFUN([INN_FUNC_GETADDRINFO_ADDRCONFIG], [AC_CACHE_CHECK([for working AI_ADDRCONFIG flag], [inn_cv_func_getaddrinfo_addrconfig_works], [AC_RUN_IFELSE([AC_LANG_SOURCE([_INN_FUNC_GETADDRINFO_ADDRCONFIG_SOURCE])], [inn_cv_func_getaddrinfo_addrconfig_works=yes], [inn_cv_func_getaddrinfo_addrconfig_works=no], [inn_cv_func_getaddrinfo_addrconfig_works=no])]) AS_IF([test x"$inn_cv_func_getaddrinfo_addrconfig_works" = xyes], [AC_DEFINE([HAVE_GETADDRINFO_ADDRCONFIG], 1, [Define if the AI_ADDRCONFIG flag works with getaddrinfo.])])]) dnl Source used by INN_MACRO_IN6_ARE_ADDR_EQUAL. Test borrowed from a bug dnl report by tmoestl@gmx.net for glibc. AC_DEFUN([_INN_MACRO_IN6_ARE_ADDR_EQUAL_SOURCE], [[ #include #include #include #include int main (void) { struct in6_addr a; struct in6_addr b; inet_pton(AF_INET6, "fe80::1234:5678:abcd", &a); inet_pton(AF_INET6, "fe80::1234:5678:abcd", &b); return IN6_ARE_ADDR_EQUAL(&a, &b) ? 0 : 1; } ]]) dnl Check whether the IN6_ARE_ADDR_EQUAL macro is broken (like glibc 2.1.3) or dnl missing. AC_DEFUN([INN_MACRO_IN6_ARE_ADDR_EQUAL], [AC_CACHE_CHECK([whether IN6_ARE_ADDR_EQUAL macro is broken], [inn_cv_in6_are_addr_equal_broken], [AC_RUN_IFELSE([AC_LANG_SOURCE([_INN_MACRO_IN6_ARE_ADDR_EQUAL_SOURCE])], [inn_cv_in6_are_addr_equal_broken=no], [inn_cv_in6_are_addr_equal_broken=yes], [inn_cv_in6_are_addr_equal_broken=yes])]) AS_IF([test x"$inn_cv_in6_are_addr_equal_broken" = xyes], [AC_DEFINE([HAVE_BROKEN_IN6_ARE_ADDR_EQUAL], 1, [Define if your IN6_ARE_ADDR_EQUAL macro is broken.])])]) inn-2.6.4/m4/aux-libs.m40000644000175200017520000000113014002373703014221 0ustar iuliusiuliusdnl aux-libs.m4 -- Search for libraries and store them a variable. dnl $Id: aux-libs.m4 6544 2003-12-26 03:23:31Z rra $ dnl dnl Search for a particular library, and if found, add that library to the dnl specified variable (the third argument) and run the commands given in the dnl fourth argument, if any. This is for libraries we don't want to pollute dnl LIBS with. Takes the same arguments as AC_SEARCH_LIBS otherwise. AC_DEFUN([INN_SEARCH_AUX_LIBS], [inn_save_LIBS=$LIBS LIBS=${$3} AC_SEARCH_LIBS($1, $2, [$3=$LIBS $4], $5, $6) LIBS=$inn_save_LIBS AC_SUBST($3)]) inn-2.6.4/m4/lib-pathname.m40000644000175200017520000000531614002373703015050 0ustar iuliusiuliusdnl Determine the library path name. dnl $Id: lib-pathname.m4 10520 2021-01-17 21:48:06Z iulius $ dnl dnl Red Hat systems and some other Linux systems use lib64 and lib32 rather dnl than just lib in some circumstances. This file provides an Autoconf dnl macro, INN_SET_LDFLAGS, which given a variable, a prefix, and an optional dnl suffix, adds -Lprefix/lib, -Lprefix/lib32, or -Lprefix/lib64 to the dnl variable depending on which directories exist and the size of a long in dnl the compilation environment. If a suffix is given, a slash and that dnl suffix will be appended, to allow for adding a subdirectory of the library dnl directory. dnl dnl This file also provides the Autoconf macro INN_SET_LIBDIR, which sets the dnl libdir variable to PREFIX/lib{,32,64} as appropriate. dnl dnl The canonical version of this file is maintained in the rra-c-util dnl package, available at . dnl dnl Written by Russ Allbery dnl Copyright 2008-2009 dnl The Board of Trustees of the Leland Stanford Junior University dnl dnl This file is free software; the authors give unlimited permission to copy dnl and/or distribute it, with or without modifications, as long as this dnl notice is preserved. dnl dnl SPDX-License-Identifier: FSFULLR dnl Probe for the alternate library name that we should attempt on this dnl architecture, given the size of an int, and set inn_lib_arch_name to that dnl name. Separated out so that it can be AC_REQUIRE'd and not run multiple dnl times. dnl dnl There is an unfortunate abstraction violation here where we assume we know dnl the cache variable name used by Autoconf. Unfortunately, Autoconf doesn't dnl provide any other way of getting at that information in shell that I can dnl see. AC_DEFUN([_INN_LIB_ARCH_NAME], [inn_lib_arch_name=lib AC_CHECK_SIZEOF([long]) AS_IF([test "$ac_cv_sizeof_long" -eq 4 && test -d /usr/lib32], [inn_lib_arch_name=lib32], [AS_IF([test "$ac_cv_sizeof_long" -eq 8 && test -d /usr/lib64], [inn_lib_arch_name=lib64])])]) dnl Set VARIABLE to -LPREFIX/lib{,32,64} or -LPREFIX/lib{,32,64}/SUFFIX as dnl appropriate. AC_DEFUN([INN_SET_LDFLAGS], [AC_REQUIRE([_INN_LIB_ARCH_NAME]) AS_IF([test -d "$2/$inn_lib_arch_name"], [AS_IF([test x"$3" = x], [$1="[$]$1 -L$2/${inn_lib_arch_name}"], [$1="[$]$1 -L$2/${inn_lib_arch_name}/$3"])], [AS_IF([test x"$3" = x], [$1="[$]$1 -L$2/lib"], [$1="[$]$1 -L$2/lib/$3"])]) $1=`AS_ECHO(["[$]$1"]) | sed -e 's/^ *//'`]) dnl Set libdir to PREFIX/lib{,32,64} as appropriate. AC_DEFUN([INN_SET_LIBDIR], [AC_REQUIRE([_INN_LIB_ARCH_NAME]) AS_IF([test -d "$1/$inn_lib_arch_name"], [libdir="$1/${inn_lib_arch_name}"], [libdir="$1/lib"])]) inn-2.6.4/m4/ltoptions.m40000644000175200017520000003426214002373703014544 0ustar iuliusiulius# Helper functions for option handling. -*- Autoconf -*- # # Copyright (C) 2004-2005, 2007-2009, 2011-2015 Free Software # Foundation, Inc. # Written by Gary V. Vaughan, 2004 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # serial 8 ltoptions.m4 # This is to help aclocal find these macros, as it can't see m4_define. AC_DEFUN([LTOPTIONS_VERSION], [m4_if([1])]) # _LT_MANGLE_OPTION(MACRO-NAME, OPTION-NAME) # ------------------------------------------ m4_define([_LT_MANGLE_OPTION], [[_LT_OPTION_]m4_bpatsubst($1__$2, [[^a-zA-Z0-9_]], [_])]) # _LT_SET_OPTION(MACRO-NAME, OPTION-NAME) # --------------------------------------- # Set option OPTION-NAME for macro MACRO-NAME, and if there is a # matching handler defined, dispatch to it. Other OPTION-NAMEs are # saved as a flag. m4_define([_LT_SET_OPTION], [m4_define(_LT_MANGLE_OPTION([$1], [$2]))dnl m4_ifdef(_LT_MANGLE_DEFUN([$1], [$2]), _LT_MANGLE_DEFUN([$1], [$2]), [m4_warning([Unknown $1 option '$2'])])[]dnl ]) # _LT_IF_OPTION(MACRO-NAME, OPTION-NAME, IF-SET, [IF-NOT-SET]) # ------------------------------------------------------------ # Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. m4_define([_LT_IF_OPTION], [m4_ifdef(_LT_MANGLE_OPTION([$1], [$2]), [$3], [$4])]) # _LT_UNLESS_OPTIONS(MACRO-NAME, OPTION-LIST, IF-NOT-SET) # ------------------------------------------------------- # Execute IF-NOT-SET unless all options in OPTION-LIST for MACRO-NAME # are set. m4_define([_LT_UNLESS_OPTIONS], [m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), [m4_ifdef(_LT_MANGLE_OPTION([$1], _LT_Option), [m4_define([$0_found])])])[]dnl m4_ifdef([$0_found], [m4_undefine([$0_found])], [$3 ])[]dnl ]) # _LT_SET_OPTIONS(MACRO-NAME, OPTION-LIST) # ---------------------------------------- # OPTION-LIST is a space-separated list of Libtool options associated # with MACRO-NAME. If any OPTION has a matching handler declared with # LT_OPTION_DEFINE, dispatch to that macro; otherwise complain about # the unknown option and exit. m4_defun([_LT_SET_OPTIONS], [# Set options m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), [_LT_SET_OPTION([$1], _LT_Option)]) m4_if([$1],[LT_INIT],[ dnl dnl Simply set some default values (i.e off) if boolean options were not dnl specified: _LT_UNLESS_OPTIONS([LT_INIT], [dlopen], [enable_dlopen=no ]) _LT_UNLESS_OPTIONS([LT_INIT], [win32-dll], [enable_win32_dll=no ]) dnl dnl If no reference was made to various pairs of opposing options, then dnl we run the default mode handler for the pair. For example, if neither dnl 'shared' nor 'disable-shared' was passed, we enable building of shared dnl archives by default: _LT_UNLESS_OPTIONS([LT_INIT], [shared disable-shared], [_LT_ENABLE_SHARED]) _LT_UNLESS_OPTIONS([LT_INIT], [static disable-static], [_LT_ENABLE_STATIC]) _LT_UNLESS_OPTIONS([LT_INIT], [pic-only no-pic], [_LT_WITH_PIC]) _LT_UNLESS_OPTIONS([LT_INIT], [fast-install disable-fast-install], [_LT_ENABLE_FAST_INSTALL]) _LT_UNLESS_OPTIONS([LT_INIT], [aix-soname=aix aix-soname=both aix-soname=svr4], [_LT_WITH_AIX_SONAME([aix])]) ]) ])# _LT_SET_OPTIONS ## --------------------------------- ## ## Macros to handle LT_INIT options. ## ## --------------------------------- ## # _LT_MANGLE_DEFUN(MACRO-NAME, OPTION-NAME) # ----------------------------------------- m4_define([_LT_MANGLE_DEFUN], [[_LT_OPTION_DEFUN_]m4_bpatsubst(m4_toupper([$1__$2]), [[^A-Z0-9_]], [_])]) # LT_OPTION_DEFINE(MACRO-NAME, OPTION-NAME, CODE) # ----------------------------------------------- m4_define([LT_OPTION_DEFINE], [m4_define(_LT_MANGLE_DEFUN([$1], [$2]), [$3])[]dnl ])# LT_OPTION_DEFINE # dlopen # ------ LT_OPTION_DEFINE([LT_INIT], [dlopen], [enable_dlopen=yes ]) AU_DEFUN([AC_LIBTOOL_DLOPEN], [_LT_SET_OPTION([LT_INIT], [dlopen]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the 'dlopen' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_DLOPEN], []) # win32-dll # --------- # Declare package support for building win32 dll's. LT_OPTION_DEFINE([LT_INIT], [win32-dll], [enable_win32_dll=yes case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-cegcc*) AC_CHECK_TOOL(AS, as, false) AC_CHECK_TOOL(DLLTOOL, dlltool, false) AC_CHECK_TOOL(OBJDUMP, objdump, false) ;; esac test -z "$AS" && AS=as _LT_DECL([], [AS], [1], [Assembler program])dnl test -z "$DLLTOOL" && DLLTOOL=dlltool _LT_DECL([], [DLLTOOL], [1], [DLL creation program])dnl test -z "$OBJDUMP" && OBJDUMP=objdump _LT_DECL([], [OBJDUMP], [1], [Object dumper program])dnl ])# win32-dll AU_DEFUN([AC_LIBTOOL_WIN32_DLL], [AC_REQUIRE([AC_CANONICAL_HOST])dnl _LT_SET_OPTION([LT_INIT], [win32-dll]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the 'win32-dll' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_WIN32_DLL], []) # _LT_ENABLE_SHARED([DEFAULT]) # ---------------------------- # implement the --enable-shared flag, and supports the 'shared' and # 'disable-shared' LT_INIT options. # DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'. m4_define([_LT_ENABLE_SHARED], [m4_define([_LT_ENABLE_SHARED_DEFAULT], [m4_if($1, no, no, yes)])dnl AC_ARG_ENABLE([shared], [AS_HELP_STRING([--enable-shared@<:@=PKGS@:>@], [build shared libraries @<:@default=]_LT_ENABLE_SHARED_DEFAULT[@:>@])], [p=${PACKAGE-default} case $enableval in yes) enable_shared=yes ;; no) enable_shared=no ;; *) enable_shared=no # Look at the argument we got. We use all the common list separators. lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for pkg in $enableval; do IFS=$lt_save_ifs if test "X$pkg" = "X$p"; then enable_shared=yes fi done IFS=$lt_save_ifs ;; esac], [enable_shared=]_LT_ENABLE_SHARED_DEFAULT) _LT_DECL([build_libtool_libs], [enable_shared], [0], [Whether or not to build shared libraries]) ])# _LT_ENABLE_SHARED LT_OPTION_DEFINE([LT_INIT], [shared], [_LT_ENABLE_SHARED([yes])]) LT_OPTION_DEFINE([LT_INIT], [disable-shared], [_LT_ENABLE_SHARED([no])]) # Old names: AC_DEFUN([AC_ENABLE_SHARED], [_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[shared]) ]) AC_DEFUN([AC_DISABLE_SHARED], [_LT_SET_OPTION([LT_INIT], [disable-shared]) ]) AU_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)]) AU_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AM_ENABLE_SHARED], []) dnl AC_DEFUN([AM_DISABLE_SHARED], []) # _LT_ENABLE_STATIC([DEFAULT]) # ---------------------------- # implement the --enable-static flag, and support the 'static' and # 'disable-static' LT_INIT options. # DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'. m4_define([_LT_ENABLE_STATIC], [m4_define([_LT_ENABLE_STATIC_DEFAULT], [m4_if($1, no, no, yes)])dnl AC_ARG_ENABLE([static], [AS_HELP_STRING([--enable-static@<:@=PKGS@:>@], [build static libraries @<:@default=]_LT_ENABLE_STATIC_DEFAULT[@:>@])], [p=${PACKAGE-default} case $enableval in yes) enable_static=yes ;; no) enable_static=no ;; *) enable_static=no # Look at the argument we got. We use all the common list separators. lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for pkg in $enableval; do IFS=$lt_save_ifs if test "X$pkg" = "X$p"; then enable_static=yes fi done IFS=$lt_save_ifs ;; esac], [enable_static=]_LT_ENABLE_STATIC_DEFAULT) _LT_DECL([build_old_libs], [enable_static], [0], [Whether or not to build static libraries]) ])# _LT_ENABLE_STATIC LT_OPTION_DEFINE([LT_INIT], [static], [_LT_ENABLE_STATIC([yes])]) LT_OPTION_DEFINE([LT_INIT], [disable-static], [_LT_ENABLE_STATIC([no])]) # Old names: AC_DEFUN([AC_ENABLE_STATIC], [_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[static]) ]) AC_DEFUN([AC_DISABLE_STATIC], [_LT_SET_OPTION([LT_INIT], [disable-static]) ]) AU_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)]) AU_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AM_ENABLE_STATIC], []) dnl AC_DEFUN([AM_DISABLE_STATIC], []) # _LT_ENABLE_FAST_INSTALL([DEFAULT]) # ---------------------------------- # implement the --enable-fast-install flag, and support the 'fast-install' # and 'disable-fast-install' LT_INIT options. # DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'. m4_define([_LT_ENABLE_FAST_INSTALL], [m4_define([_LT_ENABLE_FAST_INSTALL_DEFAULT], [m4_if($1, no, no, yes)])dnl AC_ARG_ENABLE([fast-install], [AS_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@], [optimize for fast installation @<:@default=]_LT_ENABLE_FAST_INSTALL_DEFAULT[@:>@])], [p=${PACKAGE-default} case $enableval in yes) enable_fast_install=yes ;; no) enable_fast_install=no ;; *) enable_fast_install=no # Look at the argument we got. We use all the common list separators. lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for pkg in $enableval; do IFS=$lt_save_ifs if test "X$pkg" = "X$p"; then enable_fast_install=yes fi done IFS=$lt_save_ifs ;; esac], [enable_fast_install=]_LT_ENABLE_FAST_INSTALL_DEFAULT) _LT_DECL([fast_install], [enable_fast_install], [0], [Whether or not to optimize for fast installation])dnl ])# _LT_ENABLE_FAST_INSTALL LT_OPTION_DEFINE([LT_INIT], [fast-install], [_LT_ENABLE_FAST_INSTALL([yes])]) LT_OPTION_DEFINE([LT_INIT], [disable-fast-install], [_LT_ENABLE_FAST_INSTALL([no])]) # Old names: AU_DEFUN([AC_ENABLE_FAST_INSTALL], [_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[fast-install]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the 'fast-install' option into LT_INIT's first parameter.]) ]) AU_DEFUN([AC_DISABLE_FAST_INSTALL], [_LT_SET_OPTION([LT_INIT], [disable-fast-install]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the 'disable-fast-install' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_ENABLE_FAST_INSTALL], []) dnl AC_DEFUN([AM_DISABLE_FAST_INSTALL], []) # _LT_WITH_AIX_SONAME([DEFAULT]) # ---------------------------------- # implement the --with-aix-soname flag, and support the `aix-soname=aix' # and `aix-soname=both' and `aix-soname=svr4' LT_INIT options. DEFAULT # is either `aix', `both' or `svr4'. If omitted, it defaults to `aix'. m4_define([_LT_WITH_AIX_SONAME], [m4_define([_LT_WITH_AIX_SONAME_DEFAULT], [m4_if($1, svr4, svr4, m4_if($1, both, both, aix))])dnl shared_archive_member_spec= case $host,$enable_shared in power*-*-aix[[5-9]]*,yes) AC_MSG_CHECKING([which variant of shared library versioning to provide]) AC_ARG_WITH([aix-soname], [AS_HELP_STRING([--with-aix-soname=aix|svr4|both], [shared library versioning (aka "SONAME") variant to provide on AIX, @<:@default=]_LT_WITH_AIX_SONAME_DEFAULT[@:>@.])], [case $withval in aix|svr4|both) ;; *) AC_MSG_ERROR([Unknown argument to --with-aix-soname]) ;; esac lt_cv_with_aix_soname=$with_aix_soname], [AC_CACHE_VAL([lt_cv_with_aix_soname], [lt_cv_with_aix_soname=]_LT_WITH_AIX_SONAME_DEFAULT) with_aix_soname=$lt_cv_with_aix_soname]) AC_MSG_RESULT([$with_aix_soname]) if test aix != "$with_aix_soname"; then # For the AIX way of multilib, we name the shared archive member # based on the bitwidth used, traditionally 'shr.o' or 'shr_64.o', # and 'shr.imp' or 'shr_64.imp', respectively, for the Import File. # Even when GNU compilers ignore OBJECT_MODE but need '-maix64' flag, # the AIX toolchain works better with OBJECT_MODE set (default 32). if test 64 = "${OBJECT_MODE-32}"; then shared_archive_member_spec=shr_64 else shared_archive_member_spec=shr fi fi ;; *) with_aix_soname=aix ;; esac _LT_DECL([], [shared_archive_member_spec], [0], [Shared archive member basename, for filename based shared library versioning on AIX])dnl ])# _LT_WITH_AIX_SONAME LT_OPTION_DEFINE([LT_INIT], [aix-soname=aix], [_LT_WITH_AIX_SONAME([aix])]) LT_OPTION_DEFINE([LT_INIT], [aix-soname=both], [_LT_WITH_AIX_SONAME([both])]) LT_OPTION_DEFINE([LT_INIT], [aix-soname=svr4], [_LT_WITH_AIX_SONAME([svr4])]) # _LT_WITH_PIC([MODE]) # -------------------- # implement the --with-pic flag, and support the 'pic-only' and 'no-pic' # LT_INIT options. # MODE is either 'yes' or 'no'. If omitted, it defaults to 'both'. m4_define([_LT_WITH_PIC], [AC_ARG_WITH([pic], [AS_HELP_STRING([--with-pic@<:@=PKGS@:>@], [try to use only PIC/non-PIC objects @<:@default=use both@:>@])], [lt_p=${PACKAGE-default} case $withval in yes|no) pic_mode=$withval ;; *) pic_mode=default # Look at the argument we got. We use all the common list separators. lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for lt_pkg in $withval; do IFS=$lt_save_ifs if test "X$lt_pkg" = "X$lt_p"; then pic_mode=yes fi done IFS=$lt_save_ifs ;; esac], [pic_mode=m4_default([$1], [default])]) _LT_DECL([], [pic_mode], [0], [What type of objects to build])dnl ])# _LT_WITH_PIC LT_OPTION_DEFINE([LT_INIT], [pic-only], [_LT_WITH_PIC([yes])]) LT_OPTION_DEFINE([LT_INIT], [no-pic], [_LT_WITH_PIC([no])]) # Old name: AU_DEFUN([AC_LIBTOOL_PICMODE], [_LT_SET_OPTION([LT_INIT], [pic-only]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the 'pic-only' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_PICMODE], []) ## ----------------- ## ## LTDL_INIT Options ## ## ----------------- ## m4_define([_LTDL_MODE], []) LT_OPTION_DEFINE([LTDL_INIT], [nonrecursive], [m4_define([_LTDL_MODE], [nonrecursive])]) LT_OPTION_DEFINE([LTDL_INIT], [recursive], [m4_define([_LTDL_MODE], [recursive])]) LT_OPTION_DEFINE([LTDL_INIT], [subproject], [m4_define([_LTDL_MODE], [subproject])]) m4_define([_LTDL_TYPE], []) LT_OPTION_DEFINE([LTDL_INIT], [installable], [m4_define([_LTDL_TYPE], [installable])]) LT_OPTION_DEFINE([LTDL_INIT], [convenience], [m4_define([_LTDL_TYPE], [convenience])]) inn-2.6.4/m4/compress.m40000644000175200017520000000607314002373703014343 0ustar iuliusiuliusdnl compress.m4 -- Log compression handling. dnl $Id: compress.m4 9075 2010-06-05 08:38:06Z iulius $ dnl dnl By default, INN compresses logs with gzip, but some people may want to use dnl compress instead, and others may want to use bzip2, or even not compress dnl at all their logs. INN also needs to locate gzip regardless, since it's dnl used for compressed rnews batches, and needs to know how to uncompress .Z dnl files. dnl dnl There are two macros defined here. The first, INN_ARG_COMPRESS, sets the dnl command-line option that lets the user specify what compression program to dnl use for logs. The second, INN_PATH_COMPRESS, hunts down the appropriate dnl compression programs. dnl Choose the log compression method; the argument should not be a full path, dnl just the name of the compression type. AC_DEFUN([INN_ARG_COMPRESS], [AC_ARG_WITH([log-compress], [AS_HELP_STRING([--with-log-compress=METHOD], [Log compression method [gzip]])], LOG_COMPRESS=$with_log_compress, LOG_COMPRESS=gzip) case "$LOG_COMPRESS" in bzip2) LOG_COMPRESSEXT=".bz2" ;; cat) LOG_COMPRESSEXT="" ;; compress) LOG_COMPRESSEXT=".Z" ;; gzip) LOG_COMPRESSEXT=".gz" ;; *) AC_MSG_ERROR([unknown log compression type $LOG_COMPRESS]) ;; esac AC_SUBST([LOG_COMPRESS]) AC_SUBST([LOG_COMPRESSEXT])]) dnl Track down the appropriate compression programs. We always look for gzip dnl and compress (although we may not use the result of looking for compress dnl in the future; right now, the only user is innshellvars), and we also look dnl for some other compression program if another was requested. We also need dnl to find a program to use to uncompress .Z files, preferring gzip if found. dnl dnl Only the program for log compression has to be found; for other purposes, dnl use the bare program name if it can't be found in the path. AC_DEFUN([INN_PATH_COMPRESS], [AC_ARG_VAR([BZIP2], [Location of bzip2 program]) AC_ARG_VAR([CAT], [Location of cat program]) AC_ARG_VAR([COMPRESS], [Location of compress program]) AC_ARG_VAR([GZIP], [Location of gzip program]) AC_PATH_PROG([BZIP2], [bzip2], [bzip2]) AC_PATH_PROG([CAT], [cat], [cat]) AC_PATH_PROG([COMPRESS], [compress], [compress]) AC_PATH_PROG([GZIP], [gzip], [gzip]) case "$LOG_COMPRESS" in bzip2) if test x"$BZIP2" = xbzip2 ; then AC_MSG_ERROR([bzip2 not found but specified for log compression]) fi LOG_COMPRESS=$BZIP2 ;; cat) if test x"$CAT" = xcat ; then AC_MSG_ERROR([cat not found but specified for log compression]) fi LOG_COMPRESS=$CAT ;; compress) if test x"$COMPRESS" = xcompress ; then AC_MSG_ERROR([compress not found but specified for log compression]) fi LOG_COMPRESS=$COMPRESS ;; gzip) if test x"$GZIP" = xgzip ; then AC_MSG_ERROR([gzip not found but specified for log compression]) fi LOG_COMPRESS=$GZIP ;; *) INN_PATH_PROG_ENSURE([LOG_COMPRESS], [$LOG_COMPRESS]) ;; esac if test x"$GZIP" != xgzip || test x"$COMPRESS" = xcompress ; then UNCOMPRESS="$GZIP -d" else UNCOMPRESS="$COMPRESS -d" fi AC_SUBST([UNCOMPRESS])]) inn-2.6.4/m4/paths.m40000644000175200017520000000465514002373703013633 0ustar iuliusiuliusdnl paths.m4 -- Configure various paths used by INN. dnl $Id: paths.m4 8495 2009-05-24 12:28:19Z iulius $ dnl dnl INN has quite a few more configurable paths than autoconf supports by dnl default. The regular --*dir options are honored where appropriate, but dnl for the rest that are non-standard, add --with-*-dir options. dnl dnl Also set the output variables PATH_CONFIG and PATH_TMP with fully expanded dnl versions of tmpdir and sysconfdir, suitable for use in C code. dnl This is the generic macro for those arguments; it takes the name of the dnl directory, the path relative to $prefix if none given to configure, the dnl variable to set, and the help string. AC_DEFUN([_INN_ARG_DIR], [AC_ARG_WITH([$1-dir], [$4], [$3=$with_$1_dir], [$3=$2]) AC_SUBST($3)]) dnl And here are all the paths. AC_DEFUN([INN_ARG_PATHS], [_INN_ARG_DIR([control], ['${bindir}/control'], [CONTROLDIR], [AS_HELP_STRING([--with-control-dir=PATH], [Path for control programs [PREFIX/bin/control]])]) _INN_ARG_DIR([db], ['${prefix}/db'], [DBDIR], [AS_HELP_STRING([--with-db-dir=PATH], [Path for news database files [PREFIX/db]])]) _INN_ARG_DIR([doc], ['${prefix}/doc'], [docdir], [AS_HELP_STRING([--with-doc-dir=PATH], [Path for news documentation [PREFIX/doc]])]) _INN_ARG_DIR([filter], ['${bindir}/filter'], [FILTERDIR], [AS_HELP_STRING([--with-filter-dir=PATH], [Path for embedded filters [PREFIX/bin/filter]])]) _INN_ARG_DIR([http], ['${prefix}/http'], [HTTPDIR], [AS_HELP_STRING([--with-http-dir=PATH], [Path for web pages [PREFIX/http]])]) _INN_ARG_DIR([libperl], ['${libdir}/perl'], [LIBPERLDIR], [AS_HELP_STRING([--with-libperl-dir=PATH], [Path for Perl modules [PREFIX/lib/perl]])]) _INN_ARG_DIR([log], ['${prefix}/log'], [LOGDIR], [AS_HELP_STRING([--with-log-dir=PATH], [Path for news logs [PREFIX/log]])]) _INN_ARG_DIR([run], ['${prefix}/run'], [RUNDIR], [AS_HELP_STRING([--with-run-dir=PATH], [Path for news PID/runtime files [PREFIX/run]])]) _INN_ARG_DIR([spool], ['${prefix}/spool'], [SPOOLDIR], [AS_HELP_STRING([--with-spool-dir=PATH], [Path for news storage [PREFIX/spool]])]) _INN_ARG_DIR([tmp], ['${prefix}/tmp'], [tmpdir], [AS_HELP_STRING([--with-tmp-dir=PATH], [Path for temporary files [PREFIX/tmp]])]) dnl Some additional paths used by inn/paths.h. eval PATH_CONFIG="$sysconfdir" eval PATH_TMP="$tmpdir" AC_SUBST([PATH_CONFIG]) AC_SUBST([PATH_TMP])]) inn-2.6.4/m4/lib-depends.m40000644000175200017520000000254314002373703014674 0ustar iuliusiuliusdnl Provides option to change library probes. dnl $Id: lib-depends.m4 10246 2018-02-16 21:12:42Z iulius $ dnl dnl This file provides INN_ENABLE_REDUCED_DEPENDS, which adds the configure dnl option --enable-reduced-depends to request that library probes assume dnl shared libraries are in use and dependencies of libraries should not be dnl probed. If this option is given, the shell variable inn_reduced_depends dnl is set to true; otherwise, it is set to false. dnl dnl This macro doesn't do much but is defined separately so that other macros dnl can require it with AC_REQUIRE. dnl dnl The canonical version of this file is maintained in the rra-c-util dnl package, available at . dnl dnl Written by Russ Allbery dnl Copyright 2005-2007 dnl The Board of Trustees of the Leland Stanford Junior University dnl dnl This file is free software; the authors give unlimited permission to copy dnl and/or distribute it, with or without modifications, as long as this dnl notice is preserved. dnl dnl SPDX-License-Identifier: FSFULLR AC_DEFUN([INN_ENABLE_REDUCED_DEPENDS], [inn_reduced_depends=false AC_ARG_ENABLE([reduced-depends], [AS_HELP_STRING([--enable-reduced-depends], [Try to minimize shared library dependencies])], [AS_IF([test x"$enableval" = xyes], [inn_reduced_depends=true])])]) inn-2.6.4/m4/libtool.m40000644000175200017520000112677114002373703014165 0ustar iuliusiulius# libtool.m4 - Configure libtool for the host system. -*-Autoconf-*- # # Copyright (C) 1996-2001, 2003-2015 Free Software Foundation, Inc. # Written by Gordon Matzigkeit, 1996 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. m4_define([_LT_COPYING], [dnl # Copyright (C) 2014 Free Software Foundation, Inc. # This is free software; see the source for copying conditions. There is NO # warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # GNU Libtool is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of of the License, or # (at your option) any later version. # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program or library that is built # using GNU Libtool, you may include this file under the same # distribution terms that you use for the rest of that program. # # GNU Libtool is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . ]) # serial 58 LT_INIT # LT_PREREQ(VERSION) # ------------------ # Complain and exit if this libtool version is less that VERSION. m4_defun([LT_PREREQ], [m4_if(m4_version_compare(m4_defn([LT_PACKAGE_VERSION]), [$1]), -1, [m4_default([$3], [m4_fatal([Libtool version $1 or higher is required], 63)])], [$2])]) # _LT_CHECK_BUILDDIR # ------------------ # Complain if the absolute build directory name contains unusual characters m4_defun([_LT_CHECK_BUILDDIR], [case `pwd` in *\ * | *\ *) AC_MSG_WARN([Libtool does not cope well with whitespace in `pwd`]) ;; esac ]) # LT_INIT([OPTIONS]) # ------------------ AC_DEFUN([LT_INIT], [AC_PREREQ([2.62])dnl We use AC_PATH_PROGS_FEATURE_CHECK AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl AC_BEFORE([$0], [LT_LANG])dnl AC_BEFORE([$0], [LT_OUTPUT])dnl AC_BEFORE([$0], [LTDL_INIT])dnl m4_require([_LT_CHECK_BUILDDIR])dnl dnl Autoconf doesn't catch unexpanded LT_ macros by default: m4_pattern_forbid([^_?LT_[A-Z_]+$])dnl m4_pattern_allow([^(_LT_EOF|LT_DLGLOBAL|LT_DLLAZY_OR_NOW|LT_MULTI_MODULE)$])dnl dnl aclocal doesn't pull ltoptions.m4, ltsugar.m4, or ltversion.m4 dnl unless we require an AC_DEFUNed macro: AC_REQUIRE([LTOPTIONS_VERSION])dnl AC_REQUIRE([LTSUGAR_VERSION])dnl AC_REQUIRE([LTVERSION_VERSION])dnl AC_REQUIRE([LTOBSOLETE_VERSION])dnl m4_require([_LT_PROG_LTMAIN])dnl _LT_SHELL_INIT([SHELL=${CONFIG_SHELL-/bin/sh}]) dnl Parse OPTIONS _LT_SET_OPTIONS([$0], [$1]) # This can be used to rebuild libtool when needed LIBTOOL_DEPS=$ltmain # Always use our own libtool. LIBTOOL='$(SHELL) $(top_builddir)/libtool' AC_SUBST(LIBTOOL)dnl _LT_SETUP # Only expand once: m4_define([LT_INIT]) ])# LT_INIT # Old names: AU_ALIAS([AC_PROG_LIBTOOL], [LT_INIT]) AU_ALIAS([AM_PROG_LIBTOOL], [LT_INIT]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_PROG_LIBTOOL], []) dnl AC_DEFUN([AM_PROG_LIBTOOL], []) # _LT_PREPARE_CC_BASENAME # ----------------------- m4_defun([_LT_PREPARE_CC_BASENAME], [ # Calculate cc_basename. Skip known compiler wrappers and cross-prefix. func_cc_basename () { for cc_temp in @S|@*""; do case $cc_temp in compile | *[[\\/]]compile | ccache | *[[\\/]]ccache ) ;; distcc | *[[\\/]]distcc | purify | *[[\\/]]purify ) ;; \-*) ;; *) break;; esac done func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` } ])# _LT_PREPARE_CC_BASENAME # _LT_CC_BASENAME(CC) # ------------------- # It would be clearer to call AC_REQUIREs from _LT_PREPARE_CC_BASENAME, # but that macro is also expanded into generated libtool script, which # arranges for $SED and $ECHO to be set by different means. m4_defun([_LT_CC_BASENAME], [m4_require([_LT_PREPARE_CC_BASENAME])dnl AC_REQUIRE([_LT_DECL_SED])dnl AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl func_cc_basename $1 cc_basename=$func_cc_basename_result ]) # _LT_FILEUTILS_DEFAULTS # ---------------------- # It is okay to use these file commands and assume they have been set # sensibly after 'm4_require([_LT_FILEUTILS_DEFAULTS])'. m4_defun([_LT_FILEUTILS_DEFAULTS], [: ${CP="cp -f"} : ${MV="mv -f"} : ${RM="rm -f"} ])# _LT_FILEUTILS_DEFAULTS # _LT_SETUP # --------- m4_defun([_LT_SETUP], [AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_CANONICAL_BUILD])dnl AC_REQUIRE([_LT_PREPARE_SED_QUOTE_VARS])dnl AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl _LT_DECL([], [PATH_SEPARATOR], [1], [The PATH separator for the build system])dnl dnl _LT_DECL([], [host_alias], [0], [The host system])dnl _LT_DECL([], [host], [0])dnl _LT_DECL([], [host_os], [0])dnl dnl _LT_DECL([], [build_alias], [0], [The build system])dnl _LT_DECL([], [build], [0])dnl _LT_DECL([], [build_os], [0])dnl dnl AC_REQUIRE([AC_PROG_CC])dnl AC_REQUIRE([LT_PATH_LD])dnl AC_REQUIRE([LT_PATH_NM])dnl dnl AC_REQUIRE([AC_PROG_LN_S])dnl test -z "$LN_S" && LN_S="ln -s" _LT_DECL([], [LN_S], [1], [Whether we need soft or hard links])dnl dnl AC_REQUIRE([LT_CMD_MAX_LEN])dnl _LT_DECL([objext], [ac_objext], [0], [Object file suffix (normally "o")])dnl _LT_DECL([], [exeext], [0], [Executable file suffix (normally "")])dnl dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_CHECK_SHELL_FEATURES])dnl m4_require([_LT_PATH_CONVERSION_FUNCTIONS])dnl m4_require([_LT_CMD_RELOAD])dnl m4_require([_LT_CHECK_MAGIC_METHOD])dnl m4_require([_LT_CHECK_SHAREDLIB_FROM_LINKLIB])dnl m4_require([_LT_CMD_OLD_ARCHIVE])dnl m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl m4_require([_LT_WITH_SYSROOT])dnl m4_require([_LT_CMD_TRUNCATE])dnl _LT_CONFIG_LIBTOOL_INIT([ # See if we are running on zsh, and set the options that allow our # commands through without removal of \ escapes INIT. if test -n "\${ZSH_VERSION+set}"; then setopt NO_GLOB_SUBST fi ]) if test -n "${ZSH_VERSION+set}"; then setopt NO_GLOB_SUBST fi _LT_CHECK_OBJDIR m4_require([_LT_TAG_COMPILER])dnl case $host_os in aix3*) # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test set != "${COLLECT_NAMES+set}"; then COLLECT_NAMES= export COLLECT_NAMES fi ;; esac # Global variables: ofile=libtool can_build_shared=yes # All known linkers require a '.a' archive for static linking (except MSVC, # which needs '.lib'). libext=a with_gnu_ld=$lt_cv_prog_gnu_ld old_CC=$CC old_CFLAGS=$CFLAGS # Set sane defaults for various variables test -z "$CC" && CC=cc test -z "$LTCC" && LTCC=$CC test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS test -z "$LD" && LD=ld test -z "$ac_objext" && ac_objext=o _LT_CC_BASENAME([$compiler]) # Only perform the check for file, if the check method requires it test -z "$MAGIC_CMD" && MAGIC_CMD=file case $deplibs_check_method in file_magic*) if test "$file_magic_cmd" = '$MAGIC_CMD'; then _LT_PATH_MAGIC fi ;; esac # Use C for the default configuration in the libtool script LT_SUPPORTED_TAG([CC]) _LT_LANG_C_CONFIG _LT_LANG_DEFAULT_CONFIG _LT_CONFIG_COMMANDS ])# _LT_SETUP # _LT_PREPARE_SED_QUOTE_VARS # -------------------------- # Define a few sed substitution that help us do robust quoting. m4_defun([_LT_PREPARE_SED_QUOTE_VARS], [# Backslashify metacharacters that are still active within # double-quoted strings. sed_quote_subst='s/\([["`$\\]]\)/\\\1/g' # Same as above, but do not quote variable references. double_quote_subst='s/\([["`\\]]\)/\\\1/g' # Sed substitution to delay expansion of an escaped shell variable in a # double_quote_subst'ed string. delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' # Sed substitution to delay expansion of an escaped single quote. delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' # Sed substitution to avoid accidental globbing in evaled expressions no_glob_subst='s/\*/\\\*/g' ]) # _LT_PROG_LTMAIN # --------------- # Note that this code is called both from 'configure', and 'config.status' # now that we use AC_CONFIG_COMMANDS to generate libtool. Notably, # 'config.status' has no value for ac_aux_dir unless we are using Automake, # so we pass a copy along to make sure it has a sensible value anyway. m4_defun([_LT_PROG_LTMAIN], [m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([ltmain.sh])])dnl _LT_CONFIG_LIBTOOL_INIT([ac_aux_dir='$ac_aux_dir']) ltmain=$ac_aux_dir/ltmain.sh ])# _LT_PROG_LTMAIN ## ------------------------------------- ## ## Accumulate code for creating libtool. ## ## ------------------------------------- ## # So that we can recreate a full libtool script including additional # tags, we accumulate the chunks of code to send to AC_CONFIG_COMMANDS # in macros and then make a single call at the end using the 'libtool' # label. # _LT_CONFIG_LIBTOOL_INIT([INIT-COMMANDS]) # ---------------------------------------- # Register INIT-COMMANDS to be passed to AC_CONFIG_COMMANDS later. m4_define([_LT_CONFIG_LIBTOOL_INIT], [m4_ifval([$1], [m4_append([_LT_OUTPUT_LIBTOOL_INIT], [$1 ])])]) # Initialize. m4_define([_LT_OUTPUT_LIBTOOL_INIT]) # _LT_CONFIG_LIBTOOL([COMMANDS]) # ------------------------------ # Register COMMANDS to be passed to AC_CONFIG_COMMANDS later. m4_define([_LT_CONFIG_LIBTOOL], [m4_ifval([$1], [m4_append([_LT_OUTPUT_LIBTOOL_COMMANDS], [$1 ])])]) # Initialize. m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS]) # _LT_CONFIG_SAVE_COMMANDS([COMMANDS], [INIT_COMMANDS]) # ----------------------------------------------------- m4_defun([_LT_CONFIG_SAVE_COMMANDS], [_LT_CONFIG_LIBTOOL([$1]) _LT_CONFIG_LIBTOOL_INIT([$2]) ]) # _LT_FORMAT_COMMENT([COMMENT]) # ----------------------------- # Add leading comment marks to the start of each line, and a trailing # full-stop to the whole comment if one is not present already. m4_define([_LT_FORMAT_COMMENT], [m4_ifval([$1], [ m4_bpatsubst([m4_bpatsubst([$1], [^ *], [# ])], [['`$\]], [\\\&])]m4_bmatch([$1], [[!?.]$], [], [.]) )]) ## ------------------------ ## ## FIXME: Eliminate VARNAME ## ## ------------------------ ## # _LT_DECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION], [IS-TAGGED?]) # ------------------------------------------------------------------- # CONFIGNAME is the name given to the value in the libtool script. # VARNAME is the (base) name used in the configure script. # VALUE may be 0, 1 or 2 for a computed quote escaped value based on # VARNAME. Any other value will be used directly. m4_define([_LT_DECL], [lt_if_append_uniq([lt_decl_varnames], [$2], [, ], [lt_dict_add_subkey([lt_decl_dict], [$2], [libtool_name], [m4_ifval([$1], [$1], [$2])]) lt_dict_add_subkey([lt_decl_dict], [$2], [value], [$3]) m4_ifval([$4], [lt_dict_add_subkey([lt_decl_dict], [$2], [description], [$4])]) lt_dict_add_subkey([lt_decl_dict], [$2], [tagged?], [m4_ifval([$5], [yes], [no])])]) ]) # _LT_TAGDECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION]) # -------------------------------------------------------- m4_define([_LT_TAGDECL], [_LT_DECL([$1], [$2], [$3], [$4], [yes])]) # lt_decl_tag_varnames([SEPARATOR], [VARNAME1...]) # ------------------------------------------------ m4_define([lt_decl_tag_varnames], [_lt_decl_filter([tagged?], [yes], $@)]) # _lt_decl_filter(SUBKEY, VALUE, [SEPARATOR], [VARNAME1..]) # --------------------------------------------------------- m4_define([_lt_decl_filter], [m4_case([$#], [0], [m4_fatal([$0: too few arguments: $#])], [1], [m4_fatal([$0: too few arguments: $#: $1])], [2], [lt_dict_filter([lt_decl_dict], [$1], [$2], [], lt_decl_varnames)], [3], [lt_dict_filter([lt_decl_dict], [$1], [$2], [$3], lt_decl_varnames)], [lt_dict_filter([lt_decl_dict], $@)])[]dnl ]) # lt_decl_quote_varnames([SEPARATOR], [VARNAME1...]) # -------------------------------------------------- m4_define([lt_decl_quote_varnames], [_lt_decl_filter([value], [1], $@)]) # lt_decl_dquote_varnames([SEPARATOR], [VARNAME1...]) # --------------------------------------------------- m4_define([lt_decl_dquote_varnames], [_lt_decl_filter([value], [2], $@)]) # lt_decl_varnames_tagged([SEPARATOR], [VARNAME1...]) # --------------------------------------------------- m4_define([lt_decl_varnames_tagged], [m4_assert([$# <= 2])dnl _$0(m4_quote(m4_default([$1], [[, ]])), m4_ifval([$2], [[$2]], [m4_dquote(lt_decl_tag_varnames)]), m4_split(m4_normalize(m4_quote(_LT_TAGS)), [ ]))]) m4_define([_lt_decl_varnames_tagged], [m4_ifval([$3], [lt_combine([$1], [$2], [_], $3)])]) # lt_decl_all_varnames([SEPARATOR], [VARNAME1...]) # ------------------------------------------------ m4_define([lt_decl_all_varnames], [_$0(m4_quote(m4_default([$1], [[, ]])), m4_if([$2], [], m4_quote(lt_decl_varnames), m4_quote(m4_shift($@))))[]dnl ]) m4_define([_lt_decl_all_varnames], [lt_join($@, lt_decl_varnames_tagged([$1], lt_decl_tag_varnames([[, ]], m4_shift($@))))dnl ]) # _LT_CONFIG_STATUS_DECLARE([VARNAME]) # ------------------------------------ # Quote a variable value, and forward it to 'config.status' so that its # declaration there will have the same value as in 'configure'. VARNAME # must have a single quote delimited value for this to work. m4_define([_LT_CONFIG_STATUS_DECLARE], [$1='`$ECHO "$][$1" | $SED "$delay_single_quote_subst"`']) # _LT_CONFIG_STATUS_DECLARATIONS # ------------------------------ # We delimit libtool config variables with single quotes, so when # we write them to config.status, we have to be sure to quote all # embedded single quotes properly. In configure, this macro expands # each variable declared with _LT_DECL (and _LT_TAGDECL) into: # # ='`$ECHO "$" | $SED "$delay_single_quote_subst"`' m4_defun([_LT_CONFIG_STATUS_DECLARATIONS], [m4_foreach([_lt_var], m4_quote(lt_decl_all_varnames), [m4_n([_LT_CONFIG_STATUS_DECLARE(_lt_var)])])]) # _LT_LIBTOOL_TAGS # ---------------- # Output comment and list of tags supported by the script m4_defun([_LT_LIBTOOL_TAGS], [_LT_FORMAT_COMMENT([The names of the tagged configurations supported by this script])dnl available_tags='_LT_TAGS'dnl ]) # _LT_LIBTOOL_DECLARE(VARNAME, [TAG]) # ----------------------------------- # Extract the dictionary values for VARNAME (optionally with TAG) and # expand to a commented shell variable setting: # # # Some comment about what VAR is for. # visible_name=$lt_internal_name m4_define([_LT_LIBTOOL_DECLARE], [_LT_FORMAT_COMMENT(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [description])))[]dnl m4_pushdef([_libtool_name], m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [libtool_name])))[]dnl m4_case(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [value])), [0], [_libtool_name=[$]$1], [1], [_libtool_name=$lt_[]$1], [2], [_libtool_name=$lt_[]$1], [_libtool_name=lt_dict_fetch([lt_decl_dict], [$1], [value])])[]dnl m4_ifval([$2], [_$2])[]m4_popdef([_libtool_name])[]dnl ]) # _LT_LIBTOOL_CONFIG_VARS # ----------------------- # Produce commented declarations of non-tagged libtool config variables # suitable for insertion in the LIBTOOL CONFIG section of the 'libtool' # script. Tagged libtool config variables (even for the LIBTOOL CONFIG # section) are produced by _LT_LIBTOOL_TAG_VARS. m4_defun([_LT_LIBTOOL_CONFIG_VARS], [m4_foreach([_lt_var], m4_quote(_lt_decl_filter([tagged?], [no], [], lt_decl_varnames)), [m4_n([_LT_LIBTOOL_DECLARE(_lt_var)])])]) # _LT_LIBTOOL_TAG_VARS(TAG) # ------------------------- m4_define([_LT_LIBTOOL_TAG_VARS], [m4_foreach([_lt_var], m4_quote(lt_decl_tag_varnames), [m4_n([_LT_LIBTOOL_DECLARE(_lt_var, [$1])])])]) # _LT_TAGVAR(VARNAME, [TAGNAME]) # ------------------------------ m4_define([_LT_TAGVAR], [m4_ifval([$2], [$1_$2], [$1])]) # _LT_CONFIG_COMMANDS # ------------------- # Send accumulated output to $CONFIG_STATUS. Thanks to the lists of # variables for single and double quote escaping we saved from calls # to _LT_DECL, we can put quote escaped variables declarations # into 'config.status', and then the shell code to quote escape them in # for loops in 'config.status'. Finally, any additional code accumulated # from calls to _LT_CONFIG_LIBTOOL_INIT is expanded. m4_defun([_LT_CONFIG_COMMANDS], [AC_PROVIDE_IFELSE([LT_OUTPUT], dnl If the libtool generation code has been placed in $CONFIG_LT, dnl instead of duplicating it all over again into config.status, dnl then we will have config.status run $CONFIG_LT later, so it dnl needs to know what name is stored there: [AC_CONFIG_COMMANDS([libtool], [$SHELL $CONFIG_LT || AS_EXIT(1)], [CONFIG_LT='$CONFIG_LT'])], dnl If the libtool generation code is destined for config.status, dnl expand the accumulated commands and init code now: [AC_CONFIG_COMMANDS([libtool], [_LT_OUTPUT_LIBTOOL_COMMANDS], [_LT_OUTPUT_LIBTOOL_COMMANDS_INIT])]) ])#_LT_CONFIG_COMMANDS # Initialize. m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS_INIT], [ # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH sed_quote_subst='$sed_quote_subst' double_quote_subst='$double_quote_subst' delay_variable_subst='$delay_variable_subst' _LT_CONFIG_STATUS_DECLARATIONS LTCC='$LTCC' LTCFLAGS='$LTCFLAGS' compiler='$compiler_DEFAULT' # A function that is used when there is no print builtin or printf. func_fallback_echo () { eval 'cat <<_LTECHO_EOF \$[]1 _LTECHO_EOF' } # Quote evaled strings. for var in lt_decl_all_varnames([[ \ ]], lt_decl_quote_varnames); do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[[\\\\\\\`\\"\\\$]]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" ;; esac done # Double-quote double-evaled strings. for var in lt_decl_all_varnames([[ \ ]], lt_decl_dquote_varnames); do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[[\\\\\\\`\\"\\\$]]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" ;; esac done _LT_OUTPUT_LIBTOOL_INIT ]) # _LT_GENERATED_FILE_INIT(FILE, [COMMENT]) # ------------------------------------ # Generate a child script FILE with all initialization necessary to # reuse the environment learned by the parent script, and make the # file executable. If COMMENT is supplied, it is inserted after the # '#!' sequence but before initialization text begins. After this # macro, additional text can be appended to FILE to form the body of # the child script. The macro ends with non-zero status if the # file could not be fully written (such as if the disk is full). m4_ifdef([AS_INIT_GENERATED], [m4_defun([_LT_GENERATED_FILE_INIT],[AS_INIT_GENERATED($@)])], [m4_defun([_LT_GENERATED_FILE_INIT], [m4_require([AS_PREPARE])]dnl [m4_pushdef([AS_MESSAGE_LOG_FD])]dnl [lt_write_fail=0 cat >$1 <<_ASEOF || lt_write_fail=1 #! $SHELL # Generated by $as_me. $2 SHELL=\${CONFIG_SHELL-$SHELL} export SHELL _ASEOF cat >>$1 <<\_ASEOF || lt_write_fail=1 AS_SHELL_SANITIZE _AS_PREPARE exec AS_MESSAGE_FD>&1 _ASEOF test 0 = "$lt_write_fail" && chmod +x $1[]dnl m4_popdef([AS_MESSAGE_LOG_FD])])])# _LT_GENERATED_FILE_INIT # LT_OUTPUT # --------- # This macro allows early generation of the libtool script (before # AC_OUTPUT is called), incase it is used in configure for compilation # tests. AC_DEFUN([LT_OUTPUT], [: ${CONFIG_LT=./config.lt} AC_MSG_NOTICE([creating $CONFIG_LT]) _LT_GENERATED_FILE_INIT(["$CONFIG_LT"], [# Run this file to recreate a libtool stub with the current configuration.]) cat >>"$CONFIG_LT" <<\_LTEOF lt_cl_silent=false exec AS_MESSAGE_LOG_FD>>config.log { echo AS_BOX([Running $as_me.]) } >&AS_MESSAGE_LOG_FD lt_cl_help="\ '$as_me' creates a local libtool stub from the current configuration, for use in further configure time tests before the real libtool is generated. Usage: $[0] [[OPTIONS]] -h, --help print this help, then exit -V, --version print version number, then exit -q, --quiet do not print progress messages -d, --debug don't remove temporary files Report bugs to ." lt_cl_version="\ m4_ifset([AC_PACKAGE_NAME], [AC_PACKAGE_NAME ])config.lt[]dnl m4_ifset([AC_PACKAGE_VERSION], [ AC_PACKAGE_VERSION]) configured by $[0], generated by m4_PACKAGE_STRING. Copyright (C) 2011 Free Software Foundation, Inc. This config.lt script is free software; the Free Software Foundation gives unlimited permision to copy, distribute and modify it." while test 0 != $[#] do case $[1] in --version | --v* | -V ) echo "$lt_cl_version"; exit 0 ;; --help | --h* | -h ) echo "$lt_cl_help"; exit 0 ;; --debug | --d* | -d ) debug=: ;; --quiet | --q* | --silent | --s* | -q ) lt_cl_silent=: ;; -*) AC_MSG_ERROR([unrecognized option: $[1] Try '$[0] --help' for more information.]) ;; *) AC_MSG_ERROR([unrecognized argument: $[1] Try '$[0] --help' for more information.]) ;; esac shift done if $lt_cl_silent; then exec AS_MESSAGE_FD>/dev/null fi _LTEOF cat >>"$CONFIG_LT" <<_LTEOF _LT_OUTPUT_LIBTOOL_COMMANDS_INIT _LTEOF cat >>"$CONFIG_LT" <<\_LTEOF AC_MSG_NOTICE([creating $ofile]) _LT_OUTPUT_LIBTOOL_COMMANDS AS_EXIT(0) _LTEOF chmod +x "$CONFIG_LT" # configure is writing to config.log, but config.lt does its own redirection, # appending to config.log, which fails on DOS, as config.log is still kept # open by configure. Here we exec the FD to /dev/null, effectively closing # config.log, so it can be properly (re)opened and appended to by config.lt. lt_cl_success=: test yes = "$silent" && lt_config_lt_args="$lt_config_lt_args --quiet" exec AS_MESSAGE_LOG_FD>/dev/null $SHELL "$CONFIG_LT" $lt_config_lt_args || lt_cl_success=false exec AS_MESSAGE_LOG_FD>>config.log $lt_cl_success || AS_EXIT(1) ])# LT_OUTPUT # _LT_CONFIG(TAG) # --------------- # If TAG is the built-in tag, create an initial libtool script with a # default configuration from the untagged config vars. Otherwise add code # to config.status for appending the configuration named by TAG from the # matching tagged config vars. m4_defun([_LT_CONFIG], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl _LT_CONFIG_SAVE_COMMANDS([ m4_define([_LT_TAG], m4_if([$1], [], [C], [$1]))dnl m4_if(_LT_TAG, [C], [ # See if we are running on zsh, and set the options that allow our # commands through without removal of \ escapes. if test -n "${ZSH_VERSION+set}"; then setopt NO_GLOB_SUBST fi cfgfile=${ofile}T trap "$RM \"$cfgfile\"; exit 1" 1 2 15 $RM "$cfgfile" cat <<_LT_EOF >> "$cfgfile" #! $SHELL # Generated automatically by $as_me ($PACKAGE) $VERSION # NOTE: Changes made to this file will be lost: look at ltmain.sh. # Provide generalized library-building support services. # Written by Gordon Matzigkeit, 1996 _LT_COPYING _LT_LIBTOOL_TAGS # Configured defaults for sys_lib_dlsearch_path munging. : \${LT_SYS_LIBRARY_PATH="$configure_time_lt_sys_library_path"} # ### BEGIN LIBTOOL CONFIG _LT_LIBTOOL_CONFIG_VARS _LT_LIBTOOL_TAG_VARS # ### END LIBTOOL CONFIG _LT_EOF cat <<'_LT_EOF' >> "$cfgfile" # ### BEGIN FUNCTIONS SHARED WITH CONFIGURE _LT_PREPARE_MUNGE_PATH_LIST _LT_PREPARE_CC_BASENAME # ### END FUNCTIONS SHARED WITH CONFIGURE _LT_EOF case $host_os in aix3*) cat <<\_LT_EOF >> "$cfgfile" # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test set != "${COLLECT_NAMES+set}"; then COLLECT_NAMES= export COLLECT_NAMES fi _LT_EOF ;; esac _LT_PROG_LTMAIN # We use sed instead of cat because bash on DJGPP gets confused if # if finds mixed CR/LF and LF-only lines. Since sed operates in # text mode, it properly converts lines to CR/LF. This bash problem # is reportedly fixed, but why not run on old versions too? sed '$q' "$ltmain" >> "$cfgfile" \ || (rm -f "$cfgfile"; exit 1) mv -f "$cfgfile" "$ofile" || (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") chmod +x "$ofile" ], [cat <<_LT_EOF >> "$ofile" dnl Unfortunately we have to use $1 here, since _LT_TAG is not expanded dnl in a comment (ie after a #). # ### BEGIN LIBTOOL TAG CONFIG: $1 _LT_LIBTOOL_TAG_VARS(_LT_TAG) # ### END LIBTOOL TAG CONFIG: $1 _LT_EOF ])dnl /m4_if ], [m4_if([$1], [], [ PACKAGE='$PACKAGE' VERSION='$VERSION' RM='$RM' ofile='$ofile'], []) ])dnl /_LT_CONFIG_SAVE_COMMANDS ])# _LT_CONFIG # LT_SUPPORTED_TAG(TAG) # --------------------- # Trace this macro to discover what tags are supported by the libtool # --tag option, using: # autoconf --trace 'LT_SUPPORTED_TAG:$1' AC_DEFUN([LT_SUPPORTED_TAG], []) # C support is built-in for now m4_define([_LT_LANG_C_enabled], []) m4_define([_LT_TAGS], []) # LT_LANG(LANG) # ------------- # Enable libtool support for the given language if not already enabled. AC_DEFUN([LT_LANG], [AC_BEFORE([$0], [LT_OUTPUT])dnl m4_case([$1], [C], [_LT_LANG(C)], [C++], [_LT_LANG(CXX)], [Go], [_LT_LANG(GO)], [Java], [_LT_LANG(GCJ)], [Fortran 77], [_LT_LANG(F77)], [Fortran], [_LT_LANG(FC)], [Windows Resource], [_LT_LANG(RC)], [m4_ifdef([_LT_LANG_]$1[_CONFIG], [_LT_LANG($1)], [m4_fatal([$0: unsupported language: "$1"])])])dnl ])# LT_LANG # _LT_LANG(LANGNAME) # ------------------ m4_defun([_LT_LANG], [m4_ifdef([_LT_LANG_]$1[_enabled], [], [LT_SUPPORTED_TAG([$1])dnl m4_append([_LT_TAGS], [$1 ])dnl m4_define([_LT_LANG_]$1[_enabled], [])dnl _LT_LANG_$1_CONFIG($1)])dnl ])# _LT_LANG m4_ifndef([AC_PROG_GO], [ ############################################################ # NOTE: This macro has been submitted for inclusion into # # GNU Autoconf as AC_PROG_GO. When it is available in # # a released version of Autoconf we should remove this # # macro and use it instead. # ############################################################ m4_defun([AC_PROG_GO], [AC_LANG_PUSH(Go)dnl AC_ARG_VAR([GOC], [Go compiler command])dnl AC_ARG_VAR([GOFLAGS], [Go compiler flags])dnl _AC_ARG_VAR_LDFLAGS()dnl AC_CHECK_TOOL(GOC, gccgo) if test -z "$GOC"; then if test -n "$ac_tool_prefix"; then AC_CHECK_PROG(GOC, [${ac_tool_prefix}gccgo], [${ac_tool_prefix}gccgo]) fi fi if test -z "$GOC"; then AC_CHECK_PROG(GOC, gccgo, gccgo, false) fi ])#m4_defun ])#m4_ifndef # _LT_LANG_DEFAULT_CONFIG # ----------------------- m4_defun([_LT_LANG_DEFAULT_CONFIG], [AC_PROVIDE_IFELSE([AC_PROG_CXX], [LT_LANG(CXX)], [m4_define([AC_PROG_CXX], defn([AC_PROG_CXX])[LT_LANG(CXX)])]) AC_PROVIDE_IFELSE([AC_PROG_F77], [LT_LANG(F77)], [m4_define([AC_PROG_F77], defn([AC_PROG_F77])[LT_LANG(F77)])]) AC_PROVIDE_IFELSE([AC_PROG_FC], [LT_LANG(FC)], [m4_define([AC_PROG_FC], defn([AC_PROG_FC])[LT_LANG(FC)])]) dnl The call to [A][M_PROG_GCJ] is quoted like that to stop aclocal dnl pulling things in needlessly. AC_PROVIDE_IFELSE([AC_PROG_GCJ], [LT_LANG(GCJ)], [AC_PROVIDE_IFELSE([A][M_PROG_GCJ], [LT_LANG(GCJ)], [AC_PROVIDE_IFELSE([LT_PROG_GCJ], [LT_LANG(GCJ)], [m4_ifdef([AC_PROG_GCJ], [m4_define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[LT_LANG(GCJ)])]) m4_ifdef([A][M_PROG_GCJ], [m4_define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[LT_LANG(GCJ)])]) m4_ifdef([LT_PROG_GCJ], [m4_define([LT_PROG_GCJ], defn([LT_PROG_GCJ])[LT_LANG(GCJ)])])])])]) AC_PROVIDE_IFELSE([AC_PROG_GO], [LT_LANG(GO)], [m4_define([AC_PROG_GO], defn([AC_PROG_GO])[LT_LANG(GO)])]) AC_PROVIDE_IFELSE([LT_PROG_RC], [LT_LANG(RC)], [m4_define([LT_PROG_RC], defn([LT_PROG_RC])[LT_LANG(RC)])]) ])# _LT_LANG_DEFAULT_CONFIG # Obsolete macros: AU_DEFUN([AC_LIBTOOL_CXX], [LT_LANG(C++)]) AU_DEFUN([AC_LIBTOOL_F77], [LT_LANG(Fortran 77)]) AU_DEFUN([AC_LIBTOOL_FC], [LT_LANG(Fortran)]) AU_DEFUN([AC_LIBTOOL_GCJ], [LT_LANG(Java)]) AU_DEFUN([AC_LIBTOOL_RC], [LT_LANG(Windows Resource)]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_CXX], []) dnl AC_DEFUN([AC_LIBTOOL_F77], []) dnl AC_DEFUN([AC_LIBTOOL_FC], []) dnl AC_DEFUN([AC_LIBTOOL_GCJ], []) dnl AC_DEFUN([AC_LIBTOOL_RC], []) # _LT_TAG_COMPILER # ---------------- m4_defun([_LT_TAG_COMPILER], [AC_REQUIRE([AC_PROG_CC])dnl _LT_DECL([LTCC], [CC], [1], [A C compiler])dnl _LT_DECL([LTCFLAGS], [CFLAGS], [1], [LTCC compiler flags])dnl _LT_TAGDECL([CC], [compiler], [1], [A language specific compiler])dnl _LT_TAGDECL([with_gcc], [GCC], [0], [Is the compiler the GNU compiler?])dnl # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # If no C compiler flags were specified, use CFLAGS. LTCFLAGS=${LTCFLAGS-"$CFLAGS"} # Allow CC to be a program name with arguments. compiler=$CC ])# _LT_TAG_COMPILER # _LT_COMPILER_BOILERPLATE # ------------------------ # Check for compiler boilerplate output or warnings with # the simple compiler test code. m4_defun([_LT_COMPILER_BOILERPLATE], [m4_require([_LT_DECL_SED])dnl ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" >conftest.$ac_ext eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_compiler_boilerplate=`cat conftest.err` $RM conftest* ])# _LT_COMPILER_BOILERPLATE # _LT_LINKER_BOILERPLATE # ---------------------- # Check for linker boilerplate output or warnings with # the simple link test code. m4_defun([_LT_LINKER_BOILERPLATE], [m4_require([_LT_DECL_SED])dnl ac_outfile=conftest.$ac_objext echo "$lt_simple_link_test_code" >conftest.$ac_ext eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_linker_boilerplate=`cat conftest.err` $RM -r conftest* ])# _LT_LINKER_BOILERPLATE # _LT_REQUIRED_DARWIN_CHECKS # ------------------------- m4_defun_once([_LT_REQUIRED_DARWIN_CHECKS],[ case $host_os in rhapsody* | darwin*) AC_CHECK_TOOL([DSYMUTIL], [dsymutil], [:]) AC_CHECK_TOOL([NMEDIT], [nmedit], [:]) AC_CHECK_TOOL([LIPO], [lipo], [:]) AC_CHECK_TOOL([OTOOL], [otool], [:]) AC_CHECK_TOOL([OTOOL64], [otool64], [:]) _LT_DECL([], [DSYMUTIL], [1], [Tool to manipulate archived DWARF debug symbol files on Mac OS X]) _LT_DECL([], [NMEDIT], [1], [Tool to change global to local symbols on Mac OS X]) _LT_DECL([], [LIPO], [1], [Tool to manipulate fat objects and archives on Mac OS X]) _LT_DECL([], [OTOOL], [1], [ldd/readelf like tool for Mach-O binaries on Mac OS X]) _LT_DECL([], [OTOOL64], [1], [ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4]) AC_CACHE_CHECK([for -single_module linker flag],[lt_cv_apple_cc_single_mod], [lt_cv_apple_cc_single_mod=no if test -z "$LT_MULTI_MODULE"; then # By default we will add the -single_module flag. You can override # by either setting the environment variable LT_MULTI_MODULE # non-empty at configure time, or by adding -multi_module to the # link flags. rm -rf libconftest.dylib* echo "int foo(void){return 1;}" > conftest.c echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib -Wl,-single_module conftest.c" >&AS_MESSAGE_LOG_FD $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib -Wl,-single_module conftest.c 2>conftest.err _lt_result=$? # If there is a non-empty error log, and "single_module" # appears in it, assume the flag caused a linker warning if test -s conftest.err && $GREP single_module conftest.err; then cat conftest.err >&AS_MESSAGE_LOG_FD # Otherwise, if the output was created with a 0 exit code from # the compiler, it worked. elif test -f libconftest.dylib && test 0 = "$_lt_result"; then lt_cv_apple_cc_single_mod=yes else cat conftest.err >&AS_MESSAGE_LOG_FD fi rm -rf libconftest.dylib* rm -f conftest.* fi]) AC_CACHE_CHECK([for -exported_symbols_list linker flag], [lt_cv_ld_exported_symbols_list], [lt_cv_ld_exported_symbols_list=no save_LDFLAGS=$LDFLAGS echo "_main" > conftest.sym LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], [lt_cv_ld_exported_symbols_list=yes], [lt_cv_ld_exported_symbols_list=no]) LDFLAGS=$save_LDFLAGS ]) AC_CACHE_CHECK([for -force_load linker flag],[lt_cv_ld_force_load], [lt_cv_ld_force_load=no cat > conftest.c << _LT_EOF int forced_loaded() { return 2;} _LT_EOF echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&AS_MESSAGE_LOG_FD $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&AS_MESSAGE_LOG_FD echo "$AR cr libconftest.a conftest.o" >&AS_MESSAGE_LOG_FD $AR cr libconftest.a conftest.o 2>&AS_MESSAGE_LOG_FD echo "$RANLIB libconftest.a" >&AS_MESSAGE_LOG_FD $RANLIB libconftest.a 2>&AS_MESSAGE_LOG_FD cat > conftest.c << _LT_EOF int main() { return 0;} _LT_EOF echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&AS_MESSAGE_LOG_FD $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err _lt_result=$? if test -s conftest.err && $GREP force_load conftest.err; then cat conftest.err >&AS_MESSAGE_LOG_FD elif test -f conftest && test 0 = "$_lt_result" && $GREP forced_load conftest >/dev/null 2>&1; then lt_cv_ld_force_load=yes else cat conftest.err >&AS_MESSAGE_LOG_FD fi rm -f conftest.err libconftest.a conftest conftest.c rm -rf conftest.dSYM ]) case $host_os in rhapsody* | darwin1.[[012]]) _lt_dar_allow_undefined='$wl-undefined ${wl}suppress' ;; darwin1.*) _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; darwin*) # darwin 5.x on # if running on 10.5 or later, the deployment target defaults # to the OS version, if on x86, and 10.4, the deployment # target defaults to 10.4. Don't you love it? case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in 10.0,*86*-darwin8*|10.0,*-darwin[[912]]*) _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; 10.[[012]][[,.]]*) _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; 10.*|11.*) _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; esac ;; esac if test yes = "$lt_cv_apple_cc_single_mod"; then _lt_dar_single_mod='$single_module' fi if test yes = "$lt_cv_ld_exported_symbols_list"; then _lt_dar_export_syms=' $wl-exported_symbols_list,$output_objdir/$libname-symbols.expsym' else _lt_dar_export_syms='~$NMEDIT -s $output_objdir/$libname-symbols.expsym $lib' fi if test : != "$DSYMUTIL" && test no = "$lt_cv_ld_force_load"; then _lt_dsymutil='~$DSYMUTIL $lib || :' else _lt_dsymutil= fi ;; esac ]) # _LT_DARWIN_LINKER_FEATURES([TAG]) # --------------------------------- # Checks for linker and compiler features on darwin m4_defun([_LT_DARWIN_LINKER_FEATURES], [ m4_require([_LT_REQUIRED_DARWIN_CHECKS]) _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_automatic, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported if test yes = "$lt_cv_ld_force_load"; then _LT_TAGVAR(whole_archive_flag_spec, $1)='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience $wl-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' m4_case([$1], [F77], [_LT_TAGVAR(compiler_needs_object, $1)=yes], [FC], [_LT_TAGVAR(compiler_needs_object, $1)=yes]) else _LT_TAGVAR(whole_archive_flag_spec, $1)='' fi _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(allow_undefined_flag, $1)=$_lt_dar_allow_undefined case $cc_basename in ifort*|nagfor*) _lt_dar_can_shared=yes ;; *) _lt_dar_can_shared=$GCC ;; esac if test yes = "$_lt_dar_can_shared"; then output_verbose_link_cmd=func_echo_all _LT_TAGVAR(archive_cmds, $1)="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dsymutil" _LT_TAGVAR(module_cmds, $1)="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dsymutil" _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil" _LT_TAGVAR(module_expsym_cmds, $1)="sed -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil" m4_if([$1], [CXX], [ if test yes != "$lt_cv_apple_cc_single_mod"; then _LT_TAGVAR(archive_cmds, $1)="\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dsymutil" _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dar_export_syms$_lt_dsymutil" fi ],[]) else _LT_TAGVAR(ld_shlibs, $1)=no fi ]) # _LT_SYS_MODULE_PATH_AIX([TAGNAME]) # ---------------------------------- # Links a minimal program and checks the executable # for the system default hardcoded library path. In most cases, # this is /usr/lib:/lib, but when the MPI compilers are used # the location of the communication and MPI libs are included too. # If we don't find anything, use the default library path according # to the aix ld manual. # Store the results from the different compilers for each TAGNAME. # Allow to override them for all tags through lt_cv_aix_libpath. m4_defun([_LT_SYS_MODULE_PATH_AIX], [m4_require([_LT_DECL_SED])dnl if test set = "${lt_cv_aix_libpath+set}"; then aix_libpath=$lt_cv_aix_libpath else AC_CACHE_VAL([_LT_TAGVAR([lt_cv_aix_libpath_], [$1])], [AC_LINK_IFELSE([AC_LANG_PROGRAM],[ lt_aix_libpath_sed='[ /Import File Strings/,/^$/ { /^0/ { s/^0 *\([^ ]*\) *$/\1/ p } }]' _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi],[]) if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=/usr/lib:/lib fi ]) aix_libpath=$_LT_TAGVAR([lt_cv_aix_libpath_], [$1]) fi ])# _LT_SYS_MODULE_PATH_AIX # _LT_SHELL_INIT(ARG) # ------------------- m4_define([_LT_SHELL_INIT], [m4_divert_text([M4SH-INIT], [$1 ])])# _LT_SHELL_INIT # _LT_PROG_ECHO_BACKSLASH # ----------------------- # Find how we can fake an echo command that does not interpret backslash. # In particular, with Autoconf 2.60 or later we add some code to the start # of the generated configure script that will find a shell with a builtin # printf (that we can use as an echo command). m4_defun([_LT_PROG_ECHO_BACKSLASH], [ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO AC_MSG_CHECKING([how to print strings]) # Test print first, because it will be a builtin if present. if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \ test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then ECHO='print -r --' elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then ECHO='printf %s\n' else # Use this function as a fallback that always works. func_fallback_echo () { eval 'cat <<_LTECHO_EOF $[]1 _LTECHO_EOF' } ECHO='func_fallback_echo' fi # func_echo_all arg... # Invoke $ECHO with all args, space-separated. func_echo_all () { $ECHO "$*" } case $ECHO in printf*) AC_MSG_RESULT([printf]) ;; print*) AC_MSG_RESULT([print -r]) ;; *) AC_MSG_RESULT([cat]) ;; esac m4_ifdef([_AS_DETECT_SUGGESTED], [_AS_DETECT_SUGGESTED([ test -n "${ZSH_VERSION+set}${BASH_VERSION+set}" || ( ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO PATH=/empty FPATH=/empty; export PATH FPATH test "X`printf %s $ECHO`" = "X$ECHO" \ || test "X`print -r -- $ECHO`" = "X$ECHO" )])]) _LT_DECL([], [SHELL], [1], [Shell to use when invoking shell scripts]) _LT_DECL([], [ECHO], [1], [An echo program that protects backslashes]) ])# _LT_PROG_ECHO_BACKSLASH # _LT_WITH_SYSROOT # ---------------- AC_DEFUN([_LT_WITH_SYSROOT], [AC_MSG_CHECKING([for sysroot]) AC_ARG_WITH([sysroot], [AS_HELP_STRING([--with-sysroot@<:@=DIR@:>@], [Search for dependent libraries within DIR (or the compiler's sysroot if not specified).])], [], [with_sysroot=no]) dnl lt_sysroot will always be passed unquoted. We quote it here dnl in case the user passed a directory name. lt_sysroot= case $with_sysroot in #( yes) if test yes = "$GCC"; then lt_sysroot=`$CC --print-sysroot 2>/dev/null` fi ;; #( /*) lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"` ;; #( no|'') ;; #( *) AC_MSG_RESULT([$with_sysroot]) AC_MSG_ERROR([The sysroot must be an absolute path.]) ;; esac AC_MSG_RESULT([${lt_sysroot:-no}]) _LT_DECL([], [lt_sysroot], [0], [The root where to search for ]dnl [dependent libraries, and where our libraries should be installed.])]) # _LT_ENABLE_LOCK # --------------- m4_defun([_LT_ENABLE_LOCK], [AC_ARG_ENABLE([libtool-lock], [AS_HELP_STRING([--disable-libtool-lock], [avoid locking (might break parallel builds)])]) test no = "$enable_libtool_lock" || enable_libtool_lock=yes # Some flags need to be propagated to the compiler or linker for good # libtool support. case $host in ia64-*-hpux*) # Find out what ABI is being produced by ac_compile, and set mode # options accordingly. echo 'int i;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then case `/usr/bin/file conftest.$ac_objext` in *ELF-32*) HPUX_IA64_MODE=32 ;; *ELF-64*) HPUX_IA64_MODE=64 ;; esac fi rm -rf conftest* ;; *-*-irix6*) # Find out what ABI is being produced by ac_compile, and set linker # options accordingly. echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then if test yes = "$lt_cv_prog_gnu_ld"; then case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -melf32bsmip" ;; *N32*) LD="${LD-ld} -melf32bmipn32" ;; *64-bit*) LD="${LD-ld} -melf64bmip" ;; esac else case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -32" ;; *N32*) LD="${LD-ld} -n32" ;; *64-bit*) LD="${LD-ld} -64" ;; esac fi fi rm -rf conftest* ;; mips64*-*linux*) # Find out what ABI is being produced by ac_compile, and set linker # options accordingly. echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then emul=elf case `/usr/bin/file conftest.$ac_objext` in *32-bit*) emul="${emul}32" ;; *64-bit*) emul="${emul}64" ;; esac case `/usr/bin/file conftest.$ac_objext` in *MSB*) emul="${emul}btsmip" ;; *LSB*) emul="${emul}ltsmip" ;; esac case `/usr/bin/file conftest.$ac_objext` in *N32*) emul="${emul}n32" ;; esac LD="${LD-ld} -m $emul" fi rm -rf conftest* ;; x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) # Find out what ABI is being produced by ac_compile, and set linker # options accordingly. Note that the listed cases only cover the # situations where additional linker options are needed (such as when # doing 32-bit compilation for a host where ld defaults to 64-bit, or # vice versa); the common cases where no linker options are needed do # not appear in the list. echo 'int i;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then case `/usr/bin/file conftest.o` in *32-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_i386_fbsd" ;; x86_64-*linux*) case `/usr/bin/file conftest.o` in *x86-64*) LD="${LD-ld} -m elf32_x86_64" ;; *) LD="${LD-ld} -m elf_i386" ;; esac ;; powerpc64le-*linux*) LD="${LD-ld} -m elf32lppclinux" ;; powerpc64-*linux*) LD="${LD-ld} -m elf32ppclinux" ;; s390x-*linux*) LD="${LD-ld} -m elf_s390" ;; sparc64-*linux*) LD="${LD-ld} -m elf32_sparc" ;; esac ;; *64-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_x86_64_fbsd" ;; x86_64-*linux*) LD="${LD-ld} -m elf_x86_64" ;; powerpcle-*linux*) LD="${LD-ld} -m elf64lppc" ;; powerpc-*linux*) LD="${LD-ld} -m elf64ppc" ;; s390*-*linux*|s390*-*tpf*) LD="${LD-ld} -m elf64_s390" ;; sparc*-*linux*) LD="${LD-ld} -m elf64_sparc" ;; esac ;; esac fi rm -rf conftest* ;; *-*-sco3.2v5*) # On SCO OpenServer 5, we need -belf to get full-featured binaries. SAVE_CFLAGS=$CFLAGS CFLAGS="$CFLAGS -belf" AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf, [AC_LANG_PUSH(C) AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],[[]])],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no]) AC_LANG_POP]) if test yes != "$lt_cv_cc_needs_belf"; then # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf CFLAGS=$SAVE_CFLAGS fi ;; *-*solaris*) # Find out what ABI is being produced by ac_compile, and set linker # options accordingly. echo 'int i;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then case `/usr/bin/file conftest.o` in *64-bit*) case $lt_cv_prog_gnu_ld in yes*) case $host in i?86-*-solaris*|x86_64-*-solaris*) LD="${LD-ld} -m elf_x86_64" ;; sparc*-*-solaris*) LD="${LD-ld} -m elf64_sparc" ;; esac # GNU ld 2.21 introduced _sol2 emulations. Use them if available. if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then LD=${LD-ld}_sol2 fi ;; *) if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then LD="${LD-ld} -64" fi ;; esac ;; esac fi rm -rf conftest* ;; esac need_locks=$enable_libtool_lock ])# _LT_ENABLE_LOCK # _LT_PROG_AR # ----------- m4_defun([_LT_PROG_AR], [AC_CHECK_TOOLS(AR, [ar], false) : ${AR=ar} : ${AR_FLAGS=cr} _LT_DECL([], [AR], [1], [The archiver]) _LT_DECL([], [AR_FLAGS], [1], [Flags to create an archive]) AC_CACHE_CHECK([for archiver @FILE support], [lt_cv_ar_at_file], [lt_cv_ar_at_file=no AC_COMPILE_IFELSE([AC_LANG_PROGRAM], [echo conftest.$ac_objext > conftest.lst lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&AS_MESSAGE_LOG_FD' AC_TRY_EVAL([lt_ar_try]) if test 0 -eq "$ac_status"; then # Ensure the archiver fails upon bogus file names. rm -f conftest.$ac_objext libconftest.a AC_TRY_EVAL([lt_ar_try]) if test 0 -ne "$ac_status"; then lt_cv_ar_at_file=@ fi fi rm -f conftest.* libconftest.a ]) ]) if test no = "$lt_cv_ar_at_file"; then archiver_list_spec= else archiver_list_spec=$lt_cv_ar_at_file fi _LT_DECL([], [archiver_list_spec], [1], [How to feed a file listing to the archiver]) ])# _LT_PROG_AR # _LT_CMD_OLD_ARCHIVE # ------------------- m4_defun([_LT_CMD_OLD_ARCHIVE], [_LT_PROG_AR AC_CHECK_TOOL(STRIP, strip, :) test -z "$STRIP" && STRIP=: _LT_DECL([], [STRIP], [1], [A symbol stripping program]) AC_CHECK_TOOL(RANLIB, ranlib, :) test -z "$RANLIB" && RANLIB=: _LT_DECL([], [RANLIB], [1], [Commands used to install an old-style archive]) # Determine commands to create old-style static archives. old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' old_postinstall_cmds='chmod 644 $oldlib' old_postuninstall_cmds= if test -n "$RANLIB"; then case $host_os in bitrig* | openbsd*) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib" ;; *) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$tool_oldlib" ;; esac old_archive_cmds="$old_archive_cmds~\$RANLIB \$tool_oldlib" fi case $host_os in darwin*) lock_old_archive_extraction=yes ;; *) lock_old_archive_extraction=no ;; esac _LT_DECL([], [old_postinstall_cmds], [2]) _LT_DECL([], [old_postuninstall_cmds], [2]) _LT_TAGDECL([], [old_archive_cmds], [2], [Commands used to build an old-style archive]) _LT_DECL([], [lock_old_archive_extraction], [0], [Whether to use a lock for old archive extraction]) ])# _LT_CMD_OLD_ARCHIVE # _LT_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, # [OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE]) # ---------------------------------------------------------------- # Check whether the given compiler option works AC_DEFUN([_LT_COMPILER_OPTION], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_SED])dnl AC_CACHE_CHECK([$1], [$2], [$2=no m4_if([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4]) echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="$3" ## exclude from sc_useless_quotes_in_assignment # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&AS_MESSAGE_LOG_FD echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then $2=yes fi fi $RM conftest* ]) if test yes = "[$]$2"; then m4_if([$5], , :, [$5]) else m4_if([$6], , :, [$6]) fi ])# _LT_COMPILER_OPTION # Old name: AU_ALIAS([AC_LIBTOOL_COMPILER_OPTION], [_LT_COMPILER_OPTION]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION], []) # _LT_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, # [ACTION-SUCCESS], [ACTION-FAILURE]) # ---------------------------------------------------- # Check whether the given linker option works AC_DEFUN([_LT_LINKER_OPTION], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_SED])dnl AC_CACHE_CHECK([$1], [$2], [$2=no save_LDFLAGS=$LDFLAGS LDFLAGS="$LDFLAGS $3" echo "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then # The linker can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then # Append any errors to the config.log. cat conftest.err 1>&AS_MESSAGE_LOG_FD $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if diff conftest.exp conftest.er2 >/dev/null; then $2=yes fi else $2=yes fi fi $RM -r conftest* LDFLAGS=$save_LDFLAGS ]) if test yes = "[$]$2"; then m4_if([$4], , :, [$4]) else m4_if([$5], , :, [$5]) fi ])# _LT_LINKER_OPTION # Old name: AU_ALIAS([AC_LIBTOOL_LINKER_OPTION], [_LT_LINKER_OPTION]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_LINKER_OPTION], []) # LT_CMD_MAX_LEN #--------------- AC_DEFUN([LT_CMD_MAX_LEN], [AC_REQUIRE([AC_CANONICAL_HOST])dnl # find the maximum length of command line arguments AC_MSG_CHECKING([the maximum length of command line arguments]) AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl i=0 teststring=ABCD case $build_os in msdosdjgpp*) # On DJGPP, this test can blow up pretty badly due to problems in libc # (any single argument exceeding 2000 bytes causes a buffer overrun # during glob expansion). Even if it were fixed, the result of this # check would be larger than it should be. lt_cv_sys_max_cmd_len=12288; # 12K is about right ;; gnu*) # Under GNU Hurd, this test is not required because there is # no limit to the length of command line arguments. # Libtool will interpret -1 as no limit whatsoever lt_cv_sys_max_cmd_len=-1; ;; cygwin* | mingw* | cegcc*) # On Win9x/ME, this test blows up -- it succeeds, but takes # about 5 minutes as the teststring grows exponentially. # Worse, since 9x/ME are not pre-emptively multitasking, # you end up with a "frozen" computer, even though with patience # the test eventually succeeds (with a max line length of 256k). # Instead, let's just punt: use the minimum linelength reported by # all of the supported platforms: 8192 (on NT/2K/XP). lt_cv_sys_max_cmd_len=8192; ;; mint*) # On MiNT this can take a long time and run out of memory. lt_cv_sys_max_cmd_len=8192; ;; amigaos*) # On AmigaOS with pdksh, this test takes hours, literally. # So we just punt and use a minimum line length of 8192. lt_cv_sys_max_cmd_len=8192; ;; bitrig* | darwin* | dragonfly* | freebsd* | netbsd* | openbsd*) # This has been around since 386BSD, at least. Likely further. if test -x /sbin/sysctl; then lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` elif test -x /usr/sbin/sysctl; then lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` else lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs fi # And add a safety zone lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` ;; interix*) # We know the value 262144 and hardcode it with a safety zone (like BSD) lt_cv_sys_max_cmd_len=196608 ;; os2*) # The test takes a long time on OS/2. lt_cv_sys_max_cmd_len=8192 ;; osf*) # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not # nice to cause kernel panics so lets avoid the loop below. # First set a reasonable default. lt_cv_sys_max_cmd_len=16384 # if test -x /sbin/sysconfig; then case `/sbin/sysconfig -q proc exec_disable_arg_limit` in *1*) lt_cv_sys_max_cmd_len=-1 ;; esac fi ;; sco3.2v5*) lt_cv_sys_max_cmd_len=102400 ;; sysv5* | sco5v6* | sysv4.2uw2*) kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` if test -n "$kargmax"; then lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[[ ]]//'` else lt_cv_sys_max_cmd_len=32768 fi ;; *) lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` if test -n "$lt_cv_sys_max_cmd_len" && \ test undefined != "$lt_cv_sys_max_cmd_len"; then lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` else # Make teststring a little bigger before we do anything with it. # a 1K string should be a reasonable start. for i in 1 2 3 4 5 6 7 8; do teststring=$teststring$teststring done SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} # If test is not a shell built-in, we'll probably end up computing a # maximum length that is only half of the actual maximum length, but # we can't tell. while { test X`env echo "$teststring$teststring" 2>/dev/null` \ = "X$teststring$teststring"; } >/dev/null 2>&1 && test 17 != "$i" # 1/2 MB should be enough do i=`expr $i + 1` teststring=$teststring$teststring done # Only check the string length outside the loop. lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` teststring= # Add a significant safety factor because C++ compilers can tack on # massive amounts of additional arguments before passing them to the # linker. It appears as though 1/2 is a usable value. lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` fi ;; esac ]) if test -n "$lt_cv_sys_max_cmd_len"; then AC_MSG_RESULT($lt_cv_sys_max_cmd_len) else AC_MSG_RESULT(none) fi max_cmd_len=$lt_cv_sys_max_cmd_len _LT_DECL([], [max_cmd_len], [0], [What is the maximum length of a command?]) ])# LT_CMD_MAX_LEN # Old name: AU_ALIAS([AC_LIBTOOL_SYS_MAX_CMD_LEN], [LT_CMD_MAX_LEN]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN], []) # _LT_HEADER_DLFCN # ---------------- m4_defun([_LT_HEADER_DLFCN], [AC_CHECK_HEADERS([dlfcn.h], [], [], [AC_INCLUDES_DEFAULT])dnl ])# _LT_HEADER_DLFCN # _LT_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE, # ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING) # ---------------------------------------------------------------- m4_defun([_LT_TRY_DLOPEN_SELF], [m4_require([_LT_HEADER_DLFCN])dnl if test yes = "$cross_compiling"; then : [$4] else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF [#line $LINENO "configure" #include "confdefs.h" #if HAVE_DLFCN_H #include #endif #include #ifdef RTLD_GLOBAL # define LT_DLGLOBAL RTLD_GLOBAL #else # ifdef DL_GLOBAL # define LT_DLGLOBAL DL_GLOBAL # else # define LT_DLGLOBAL 0 # endif #endif /* We may have to define LT_DLLAZY_OR_NOW in the command line if we find out it does not work in some platform. */ #ifndef LT_DLLAZY_OR_NOW # ifdef RTLD_LAZY # define LT_DLLAZY_OR_NOW RTLD_LAZY # else # ifdef DL_LAZY # define LT_DLLAZY_OR_NOW DL_LAZY # else # ifdef RTLD_NOW # define LT_DLLAZY_OR_NOW RTLD_NOW # else # ifdef DL_NOW # define LT_DLLAZY_OR_NOW DL_NOW # else # define LT_DLLAZY_OR_NOW 0 # endif # endif # endif # endif #endif /* When -fvisibility=hidden is used, assume the code has been annotated correspondingly for the symbols needed. */ #if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) int fnord () __attribute__((visibility("default"))); #endif int fnord () { return 42; } int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); int status = $lt_dlunknown; if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; else { if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; else puts (dlerror ()); } /* dlclose (self); */ } else puts (dlerror ()); return status; }] _LT_EOF if AC_TRY_EVAL(ac_link) && test -s "conftest$ac_exeext" 2>/dev/null; then (./conftest; exit; ) >&AS_MESSAGE_LOG_FD 2>/dev/null lt_status=$? case x$lt_status in x$lt_dlno_uscore) $1 ;; x$lt_dlneed_uscore) $2 ;; x$lt_dlunknown|x*) $3 ;; esac else : # compilation failed $3 fi fi rm -fr conftest* ])# _LT_TRY_DLOPEN_SELF # LT_SYS_DLOPEN_SELF # ------------------ AC_DEFUN([LT_SYS_DLOPEN_SELF], [m4_require([_LT_HEADER_DLFCN])dnl if test yes != "$enable_dlopen"; then enable_dlopen=unknown enable_dlopen_self=unknown enable_dlopen_self_static=unknown else lt_cv_dlopen=no lt_cv_dlopen_libs= case $host_os in beos*) lt_cv_dlopen=load_add_on lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ;; mingw* | pw32* | cegcc*) lt_cv_dlopen=LoadLibrary lt_cv_dlopen_libs= ;; cygwin*) lt_cv_dlopen=dlopen lt_cv_dlopen_libs= ;; darwin*) # if libdl is installed we need to link against it AC_CHECK_LIB([dl], [dlopen], [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl],[ lt_cv_dlopen=dyld lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ]) ;; tpf*) # Don't try to run any link tests for TPF. We know it's impossible # because TPF is a cross-compiler, and we know how we open DSOs. lt_cv_dlopen=dlopen lt_cv_dlopen_libs= lt_cv_dlopen_self=no ;; *) AC_CHECK_FUNC([shl_load], [lt_cv_dlopen=shl_load], [AC_CHECK_LIB([dld], [shl_load], [lt_cv_dlopen=shl_load lt_cv_dlopen_libs=-ldld], [AC_CHECK_FUNC([dlopen], [lt_cv_dlopen=dlopen], [AC_CHECK_LIB([dl], [dlopen], [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl], [AC_CHECK_LIB([svld], [dlopen], [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-lsvld], [AC_CHECK_LIB([dld], [dld_link], [lt_cv_dlopen=dld_link lt_cv_dlopen_libs=-ldld]) ]) ]) ]) ]) ]) ;; esac if test no = "$lt_cv_dlopen"; then enable_dlopen=no else enable_dlopen=yes fi case $lt_cv_dlopen in dlopen) save_CPPFLAGS=$CPPFLAGS test yes = "$ac_cv_header_dlfcn_h" && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" save_LDFLAGS=$LDFLAGS wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" save_LIBS=$LIBS LIBS="$lt_cv_dlopen_libs $LIBS" AC_CACHE_CHECK([whether a program can dlopen itself], lt_cv_dlopen_self, [dnl _LT_TRY_DLOPEN_SELF( lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes, lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross) ]) if test yes = "$lt_cv_dlopen_self"; then wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" AC_CACHE_CHECK([whether a statically linked program can dlopen itself], lt_cv_dlopen_self_static, [dnl _LT_TRY_DLOPEN_SELF( lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=no, lt_cv_dlopen_self_static=cross) ]) fi CPPFLAGS=$save_CPPFLAGS LDFLAGS=$save_LDFLAGS LIBS=$save_LIBS ;; esac case $lt_cv_dlopen_self in yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; *) enable_dlopen_self=unknown ;; esac case $lt_cv_dlopen_self_static in yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; *) enable_dlopen_self_static=unknown ;; esac fi _LT_DECL([dlopen_support], [enable_dlopen], [0], [Whether dlopen is supported]) _LT_DECL([dlopen_self], [enable_dlopen_self], [0], [Whether dlopen of programs is supported]) _LT_DECL([dlopen_self_static], [enable_dlopen_self_static], [0], [Whether dlopen of statically linked programs is supported]) ])# LT_SYS_DLOPEN_SELF # Old name: AU_ALIAS([AC_LIBTOOL_DLOPEN_SELF], [LT_SYS_DLOPEN_SELF]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF], []) # _LT_COMPILER_C_O([TAGNAME]) # --------------------------- # Check to see if options -c and -o are simultaneously supported by compiler. # This macro does not hard code the compiler like AC_PROG_CC_C_O. m4_defun([_LT_COMPILER_C_O], [m4_require([_LT_DECL_SED])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_TAG_COMPILER])dnl AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext], [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)], [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no $RM -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&AS_MESSAGE_LOG_FD echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then _LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes fi fi chmod u+w . 2>&AS_MESSAGE_LOG_FD $RM conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files $RM out/* && rmdir out cd .. $RM -r conftest $RM conftest* ]) _LT_TAGDECL([compiler_c_o], [lt_cv_prog_compiler_c_o], [1], [Does compiler simultaneously support -c and -o options?]) ])# _LT_COMPILER_C_O # _LT_COMPILER_FILE_LOCKS([TAGNAME]) # ---------------------------------- # Check to see if we can do hard links to lock some files if needed m4_defun([_LT_COMPILER_FILE_LOCKS], [m4_require([_LT_ENABLE_LOCK])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl _LT_COMPILER_C_O([$1]) hard_links=nottested if test no = "$_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)" && test no != "$need_locks"; then # do not overwrite the value of need_locks provided by the user AC_MSG_CHECKING([if we can lock with hard links]) hard_links=yes $RM conftest* ln conftest.a conftest.b 2>/dev/null && hard_links=no touch conftest.a ln conftest.a conftest.b 2>&5 || hard_links=no ln conftest.a conftest.b 2>/dev/null && hard_links=no AC_MSG_RESULT([$hard_links]) if test no = "$hard_links"; then AC_MSG_WARN(['$CC' does not support '-c -o', so 'make -j' may be unsafe]) need_locks=warn fi else need_locks=no fi _LT_DECL([], [need_locks], [1], [Must we lock files when doing compilation?]) ])# _LT_COMPILER_FILE_LOCKS # _LT_CHECK_OBJDIR # ---------------- m4_defun([_LT_CHECK_OBJDIR], [AC_CACHE_CHECK([for objdir], [lt_cv_objdir], [rm -f .libs 2>/dev/null mkdir .libs 2>/dev/null if test -d .libs; then lt_cv_objdir=.libs else # MS-DOS does not allow filenames that begin with a dot. lt_cv_objdir=_libs fi rmdir .libs 2>/dev/null]) objdir=$lt_cv_objdir _LT_DECL([], [objdir], [0], [The name of the directory that contains temporary libtool files])dnl m4_pattern_allow([LT_OBJDIR])dnl AC_DEFINE_UNQUOTED([LT_OBJDIR], "$lt_cv_objdir/", [Define to the sub-directory where libtool stores uninstalled libraries.]) ])# _LT_CHECK_OBJDIR # _LT_LINKER_HARDCODE_LIBPATH([TAGNAME]) # -------------------------------------- # Check hardcoding attributes. m4_defun([_LT_LINKER_HARDCODE_LIBPATH], [AC_MSG_CHECKING([how to hardcode library paths into programs]) _LT_TAGVAR(hardcode_action, $1)= if test -n "$_LT_TAGVAR(hardcode_libdir_flag_spec, $1)" || test -n "$_LT_TAGVAR(runpath_var, $1)" || test yes = "$_LT_TAGVAR(hardcode_automatic, $1)"; then # We can hardcode non-existent directories. if test no != "$_LT_TAGVAR(hardcode_direct, $1)" && # If the only mechanism to avoid hardcoding is shlibpath_var, we # have to relink, otherwise we might link with an installed library # when we should be linking with a yet-to-be-installed one ## test no != "$_LT_TAGVAR(hardcode_shlibpath_var, $1)" && test no != "$_LT_TAGVAR(hardcode_minus_L, $1)"; then # Linking always hardcodes the temporary library directory. _LT_TAGVAR(hardcode_action, $1)=relink else # We can link without hardcoding, and we can hardcode nonexisting dirs. _LT_TAGVAR(hardcode_action, $1)=immediate fi else # We cannot hardcode anything, or else we can only hardcode existing # directories. _LT_TAGVAR(hardcode_action, $1)=unsupported fi AC_MSG_RESULT([$_LT_TAGVAR(hardcode_action, $1)]) if test relink = "$_LT_TAGVAR(hardcode_action, $1)" || test yes = "$_LT_TAGVAR(inherit_rpath, $1)"; then # Fast installation is not supported enable_fast_install=no elif test yes = "$shlibpath_overrides_runpath" || test no = "$enable_shared"; then # Fast installation is not necessary enable_fast_install=needless fi _LT_TAGDECL([], [hardcode_action], [0], [How to hardcode a shared library path into an executable]) ])# _LT_LINKER_HARDCODE_LIBPATH # _LT_CMD_STRIPLIB # ---------------- m4_defun([_LT_CMD_STRIPLIB], [m4_require([_LT_DECL_EGREP]) striplib= old_striplib= AC_MSG_CHECKING([whether stripping libraries is possible]) if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" test -z "$striplib" && striplib="$STRIP --strip-unneeded" AC_MSG_RESULT([yes]) else # FIXME - insert some real tests, host_os isn't really good enough case $host_os in darwin*) if test -n "$STRIP"; then striplib="$STRIP -x" old_striplib="$STRIP -S" AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) fi ;; *) AC_MSG_RESULT([no]) ;; esac fi _LT_DECL([], [old_striplib], [1], [Commands to strip libraries]) _LT_DECL([], [striplib], [1]) ])# _LT_CMD_STRIPLIB # _LT_PREPARE_MUNGE_PATH_LIST # --------------------------- # Make sure func_munge_path_list() is defined correctly. m4_defun([_LT_PREPARE_MUNGE_PATH_LIST], [[# func_munge_path_list VARIABLE PATH # ----------------------------------- # VARIABLE is name of variable containing _space_ separated list of # directories to be munged by the contents of PATH, which is string # having a format: # "DIR[:DIR]:" # string "DIR[ DIR]" will be prepended to VARIABLE # ":DIR[:DIR]" # string "DIR[ DIR]" will be appended to VARIABLE # "DIRP[:DIRP]::[DIRA:]DIRA" # string "DIRP[ DIRP]" will be prepended to VARIABLE and string # "DIRA[ DIRA]" will be appended to VARIABLE # "DIR[:DIR]" # VARIABLE will be replaced by "DIR[ DIR]" func_munge_path_list () { case x@S|@2 in x) ;; *:) eval @S|@1=\"`$ECHO @S|@2 | $SED 's/:/ /g'` \@S|@@S|@1\" ;; x:*) eval @S|@1=\"\@S|@@S|@1 `$ECHO @S|@2 | $SED 's/:/ /g'`\" ;; *::*) eval @S|@1=\"\@S|@@S|@1\ `$ECHO @S|@2 | $SED -e 's/.*:://' -e 's/:/ /g'`\" eval @S|@1=\"`$ECHO @S|@2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \@S|@@S|@1\" ;; *) eval @S|@1=\"`$ECHO @S|@2 | $SED 's/:/ /g'`\" ;; esac } ]])# _LT_PREPARE_PATH_LIST # _LT_SYS_DYNAMIC_LINKER([TAG]) # ----------------------------- # PORTME Fill in your ld.so characteristics m4_defun([_LT_SYS_DYNAMIC_LINKER], [AC_REQUIRE([AC_CANONICAL_HOST])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_OBJDUMP])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_CHECK_SHELL_FEATURES])dnl m4_require([_LT_PREPARE_MUNGE_PATH_LIST])dnl AC_MSG_CHECKING([dynamic linker characteristics]) m4_if([$1], [], [ if test yes = "$GCC"; then case $host_os in darwin*) lt_awk_arg='/^libraries:/,/LR/' ;; *) lt_awk_arg='/^libraries:/' ;; esac case $host_os in mingw* | cegcc*) lt_sed_strip_eq='s|=\([[A-Za-z]]:\)|\1|g' ;; *) lt_sed_strip_eq='s|=/|/|g' ;; esac lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq` case $lt_search_path_spec in *\;*) # if the path contains ";" then we assume it to be the separator # otherwise default to the standard path separator (i.e. ":") - it is # assumed that no part of a normal pathname contains ";" but that should # okay in the real world where ";" in dirpaths is itself problematic. lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'` ;; *) lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"` ;; esac # Ok, now we have the path, separated by spaces, we can step through it # and add multilib dir if necessary... lt_tmp_lt_search_path_spec= lt_multi_os_dir=/`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` # ...but if some path component already ends with the multilib dir we assume # that all is fine and trust -print-search-dirs as is (GCC 4.2? or newer). case "$lt_multi_os_dir; $lt_search_path_spec " in "/; "* | "/.; "* | "/./; "* | *"$lt_multi_os_dir "* | *"$lt_multi_os_dir/ "*) lt_multi_os_dir= ;; esac for lt_sys_path in $lt_search_path_spec; do if test -d "$lt_sys_path$lt_multi_os_dir"; then lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path$lt_multi_os_dir" elif test -n "$lt_multi_os_dir"; then test -d "$lt_sys_path" && \ lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" fi done lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk ' BEGIN {RS = " "; FS = "/|\n";} { lt_foo = ""; lt_count = 0; for (lt_i = NF; lt_i > 0; lt_i--) { if ($lt_i != "" && $lt_i != ".") { if ($lt_i == "..") { lt_count++; } else { if (lt_count == 0) { lt_foo = "/" $lt_i lt_foo; } else { lt_count--; } } } } if (lt_foo != "") { lt_freq[[lt_foo]]++; } if (lt_freq[[lt_foo]] == 1) { print lt_foo; } }'` # AWK program above erroneously prepends '/' to C:/dos/paths # for these hosts. case $host_os in mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\ $SED 's|/\([[A-Za-z]]:\)|\1|g'` ;; esac sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP` else sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" fi]) library_names_spec= libname_spec='lib$name' soname_spec= shrext_cmds=.so postinstall_cmds= postuninstall_cmds= finish_cmds= finish_eval= shlibpath_var= shlibpath_overrides_runpath=unknown version_type=none dynamic_linker="$host_os ld.so" sys_lib_dlsearch_path_spec="/lib /usr/lib" need_lib_prefix=unknown hardcode_into_libs=no # when you set need_version to no, make sure it does not cause -set_version # flags to be left without arguments need_version=unknown AC_ARG_VAR([LT_SYS_LIBRARY_PATH], [User-defined run-time library search path.]) case $host_os in aix3*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname.a' shlibpath_var=LIBPATH # AIX 3 has no versioning support, so we append a major version to the name. soname_spec='$libname$release$shared_ext$major' ;; aix[[4-9]]*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no hardcode_into_libs=yes if test ia64 = "$host_cpu"; then # AIX 5 supports IA64 library_names_spec='$libname$release$shared_ext$major $libname$release$shared_ext$versuffix $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH else # With GCC up to 2.95.x, collect2 would create an import file # for dependence libraries. The import file would start with # the line '#! .'. This would cause the generated library to # depend on '.', always an invalid library. This was fixed in # development snapshots of GCC prior to 3.0. case $host_os in aix4 | aix4.[[01]] | aix4.[[01]].*) if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' echo ' yes ' echo '#endif'; } | $CC -E - | $GREP yes > /dev/null; then : else can_build_shared=no fi ;; esac # Using Import Files as archive members, it is possible to support # filename-based versioning of shared library archives on AIX. While # this would work for both with and without runtime linking, it will # prevent static linking of such archives. So we do filename-based # shared library versioning with .so extension only, which is used # when both runtime linking and shared linking is enabled. # Unfortunately, runtime linking may impact performance, so we do # not want this to be the default eventually. Also, we use the # versioned .so libs for executables only if there is the -brtl # linker flag in LDFLAGS as well, or --with-aix-soname=svr4 only. # To allow for filename-based versioning support, we need to create # libNAME.so.V as an archive file, containing: # *) an Import File, referring to the versioned filename of the # archive as well as the shared archive member, telling the # bitwidth (32 or 64) of that shared object, and providing the # list of exported symbols of that shared object, eventually # decorated with the 'weak' keyword # *) the shared object with the F_LOADONLY flag set, to really avoid # it being seen by the linker. # At run time we better use the real file rather than another symlink, # but for link time we create the symlink libNAME.so -> libNAME.so.V case $with_aix_soname,$aix_use_runtimelinking in # AIX (on Power*) has no versioning support, so currently we cannot hardcode correct # soname into executable. Probably we can add versioning support to # collect2, so additional links can be useful in future. aix,yes) # traditional libtool dynamic_linker='AIX unversionable lib.so' # If using run time linking (on AIX 4.2 or later) use lib.so # instead of lib.a to let people know that these are not # typical AIX shared libraries. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' ;; aix,no) # traditional AIX only dynamic_linker='AIX lib.a[(]lib.so.V[)]' # We preserve .a as extension for shared libraries through AIX4.2 # and later when we are not doing run time linking. library_names_spec='$libname$release.a $libname.a' soname_spec='$libname$release$shared_ext$major' ;; svr4,*) # full svr4 only dynamic_linker="AIX lib.so.V[(]$shared_archive_member_spec.o[)]" library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' # We do not specify a path in Import Files, so LIBPATH fires. shlibpath_overrides_runpath=yes ;; *,yes) # both, prefer svr4 dynamic_linker="AIX lib.so.V[(]$shared_archive_member_spec.o[)], lib.a[(]lib.so.V[)]" library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' # unpreferred sharedlib libNAME.a needs extra handling postinstall_cmds='test -n "$linkname" || linkname="$realname"~func_stripname "" ".so" "$linkname"~$install_shared_prog "$dir/$func_stripname_result.$libext" "$destdir/$func_stripname_result.$libext"~test -z "$tstripme" || test -z "$striplib" || $striplib "$destdir/$func_stripname_result.$libext"' postuninstall_cmds='for n in $library_names $old_library; do :; done~func_stripname "" ".so" "$n"~test "$func_stripname_result" = "$n" || func_append rmfiles " $odir/$func_stripname_result.$libext"' # We do not specify a path in Import Files, so LIBPATH fires. shlibpath_overrides_runpath=yes ;; *,no) # both, prefer aix dynamic_linker="AIX lib.a[(]lib.so.V[)], lib.so.V[(]$shared_archive_member_spec.o[)]" library_names_spec='$libname$release.a $libname.a' soname_spec='$libname$release$shared_ext$major' # unpreferred sharedlib libNAME.so.V and symlink libNAME.so need extra handling postinstall_cmds='test -z "$dlname" || $install_shared_prog $dir/$dlname $destdir/$dlname~test -z "$tstripme" || test -z "$striplib" || $striplib $destdir/$dlname~test -n "$linkname" || linkname=$realname~func_stripname "" ".a" "$linkname"~(cd "$destdir" && $LN_S -f $dlname $func_stripname_result.so)' postuninstall_cmds='test -z "$dlname" || func_append rmfiles " $odir/$dlname"~for n in $old_library $library_names; do :; done~func_stripname "" ".a" "$n"~func_append rmfiles " $odir/$func_stripname_result.so"' ;; esac shlibpath_var=LIBPATH fi ;; amigaos*) case $host_cpu in powerpc) # Since July 2007 AmigaOS4 officially supports .so libraries. # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' ;; m68k) library_names_spec='$libname.ixlibrary $libname.a' # Create ${libname}_ixlibrary.a entries in /sys/libs. finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' ;; esac ;; beos*) library_names_spec='$libname$shared_ext' dynamic_linker="$host_os ld.so" shlibpath_var=LIBRARY_PATH ;; bsdi[[45]]*) version_type=linux # correct to gnu/linux during the next big refactor need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" # the default ld.so.conf also contains /usr/contrib/lib and # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow # libtool to hard-code these into programs ;; cygwin* | mingw* | pw32* | cegcc*) version_type=windows shrext_cmds=.dll need_version=no need_lib_prefix=no case $GCC,$cc_basename in yes,*) # gcc library_names_spec='$libname.dll.a' # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \$file`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ chmod a+x \$dldir/$dlname~ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; fi' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes case $host_os in cygwin*) # Cygwin DLLs use 'cyg' prefix rather than 'lib' soname_spec='`echo $libname | sed -e 's/^lib/cyg/'``echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' m4_if([$1], [],[ sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api"]) ;; mingw* | cegcc*) # MinGW DLLs use traditional 'lib' prefix soname_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' library_names_spec='`echo $libname | sed -e 's/^lib/pw/'``echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' ;; esac dynamic_linker='Win32 ld.exe' ;; *,cl*) # Native MSVC libname_spec='$name' soname_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' library_names_spec='$libname.dll.lib' case $build_os in mingw*) sys_lib_search_path_spec= lt_save_ifs=$IFS IFS=';' for lt_path in $LIB do IFS=$lt_save_ifs # Let DOS variable expansion print the short 8.3 style file name. lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" done IFS=$lt_save_ifs # Convert to MSYS style. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([[a-zA-Z]]\\):| /\\1|g' -e 's|^ ||'` ;; cygwin*) # Convert to unix form, then to dos form, then back to unix form # but this time dos style (no spaces!) so that the unix form looks # like /cygdrive/c/PROGRA~1:/cygdr... sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` ;; *) sys_lib_search_path_spec=$LIB if $ECHO "$sys_lib_search_path_spec" | [$GREP ';[c-zC-Z]:/' >/dev/null]; then # It is most probably a Windows format PATH. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` else sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi # FIXME: find the short name or the path components, as spaces are # common. (e.g. "Program Files" -> "PROGRA~1") ;; esac # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \$file`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes dynamic_linker='Win32 link.exe' ;; *) # Assume MSVC wrapper library_names_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext $libname.lib' dynamic_linker='Win32 ld.exe' ;; esac # FIXME: first we should search . and the directory the executable is in shlibpath_var=PATH ;; darwin* | rhapsody*) dynamic_linker="$host_os dyld" version_type=darwin need_lib_prefix=no need_version=no library_names_spec='$libname$release$major$shared_ext $libname$shared_ext' soname_spec='$libname$release$major$shared_ext' shlibpath_overrides_runpath=yes shlibpath_var=DYLD_LIBRARY_PATH shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' m4_if([$1], [],[ sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"]) sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' ;; dgux*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH ;; freebsd* | dragonfly*) # DragonFly does not have aout. When/if they implement a new # versioning mechanism, adjust this. if test -x /usr/bin/objformat; then objformat=`/usr/bin/objformat` else case $host_os in freebsd[[23]].*) objformat=aout ;; *) objformat=elf ;; esac fi version_type=freebsd-$objformat case $version_type in freebsd-elf*) library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' need_version=no need_lib_prefix=no ;; freebsd-*) library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' need_version=yes ;; esac shlibpath_var=LD_LIBRARY_PATH case $host_os in freebsd2.*) shlibpath_overrides_runpath=yes ;; freebsd3.[[01]]* | freebsdelf3.[[01]]*) shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; freebsd3.[[2-9]]* | freebsdelf3.[[2-9]]* | \ freebsd4.[[0-5]] | freebsdelf4.[[0-5]] | freebsd4.1.1 | freebsdelf4.1.1) shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; *) # from 4.6 on, and DragonFly shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; esac ;; haiku*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no dynamic_linker="$host_os runtime_loader" library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LIBRARY_PATH shlibpath_overrides_runpath=no sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' hardcode_into_libs=yes ;; hpux9* | hpux10* | hpux11*) # Give a soname corresponding to the major version so that dld.sl refuses to # link against other versions. version_type=sunos need_lib_prefix=no need_version=no case $host_cpu in ia64*) shrext_cmds='.so' hardcode_into_libs=yes dynamic_linker="$host_os dld.so" shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' if test 32 = "$HPUX_IA64_MODE"; then sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" sys_lib_dlsearch_path_spec=/usr/lib/hpux32 else sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" sys_lib_dlsearch_path_spec=/usr/lib/hpux64 fi ;; hppa*64*) shrext_cmds='.sl' hardcode_into_libs=yes dynamic_linker="$host_os dld.sl" shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; *) shrext_cmds='.sl' dynamic_linker="$host_os dld.sl" shlibpath_var=SHLIB_PATH shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' ;; esac # HP-UX runs *really* slowly unless shared libraries are mode 555, ... postinstall_cmds='chmod 555 $lib' # or fails outright, so override atomically: install_override_mode=555 ;; interix[[3-9]]*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; irix5* | irix6* | nonstopux*) case $host_os in nonstopux*) version_type=nonstopux ;; *) if test yes = "$lt_cv_prog_gnu_ld"; then version_type=linux # correct to gnu/linux during the next big refactor else version_type=irix fi ;; esac need_lib_prefix=no need_version=no soname_spec='$libname$release$shared_ext$major' library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$release$shared_ext $libname$shared_ext' case $host_os in irix5* | nonstopux*) libsuff= shlibsuff= ;; *) case $LD in # libtool.m4 will add one of these switches to LD *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= libmagic=32-bit;; *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 libmagic=N32;; *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 libmagic=64-bit;; *) libsuff= shlibsuff= libmagic=never-match;; esac ;; esac shlibpath_var=LD_LIBRARY${shlibsuff}_PATH shlibpath_overrides_runpath=no sys_lib_search_path_spec="/usr/lib$libsuff /lib$libsuff /usr/local/lib$libsuff" sys_lib_dlsearch_path_spec="/usr/lib$libsuff /lib$libsuff" hardcode_into_libs=yes ;; # No shared lib support for Linux oldld, aout, or coff. linux*oldld* | linux*aout* | linux*coff*) dynamic_linker=no ;; linux*android*) version_type=none # Android doesn't support versioned libraries. need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext' soname_spec='$libname$release$shared_ext' finish_cmds= shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes dynamic_linker='Android linker' # Don't embed -rpath directories since the linker doesn't support them. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' ;; # This must be glibc/ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no # Some binutils ld are patched to set DT_RUNPATH AC_CACHE_VAL([lt_cv_shlibpath_overrides_runpath], [lt_cv_shlibpath_overrides_runpath=no save_LDFLAGS=$LDFLAGS save_libdir=$libdir eval "libdir=/foo; wl=\"$_LT_TAGVAR(lt_prog_compiler_wl, $1)\"; \ LDFLAGS=\"\$LDFLAGS $_LT_TAGVAR(hardcode_libdir_flag_spec, $1)\"" AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], [AS_IF([ ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null], [lt_cv_shlibpath_overrides_runpath=yes])]) LDFLAGS=$save_LDFLAGS libdir=$save_libdir ]) shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes # Ideally, we could use ldconfig to report *all* directores which are # searched for libraries, however this is still not possible. Aside from not # being certain /sbin/ldconfig is available, command # 'ldconfig -N -X -v | grep ^/' on 64bit Fedora does not report /usr/lib64, # even though it is searched at run-time. Try to do the best guess by # appending ld.so.conf contents (and includes) to the search path. if test -f /etc/ld.so.conf; then lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" fi # We used to test for /lib/ld.so.1 and disable shared libraries on # powerpc, because MkLinux only supported shared libraries with the # GNU dynamic linker. Since this was broken with cross compilers, # most powerpc-linux boxes support dynamic linking these days and # people can always --disable-shared, the test was removed, and we # assume the GNU/Linux dynamic linker is in use. dynamic_linker='GNU/Linux ld.so' ;; netbsdelf*-gnu) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='NetBSD ld.elf_so' ;; netbsd*) version_type=sunos need_lib_prefix=no need_version=no if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' dynamic_linker='NetBSD (a.out) ld.so' else library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' dynamic_linker='NetBSD ld.elf_so' fi shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; newsos6) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; *nto* | *qnx*) version_type=qnx need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='ldqnx.so' ;; openbsd* | bitrig*) version_type=sunos sys_lib_dlsearch_path_spec=/usr/lib need_lib_prefix=no if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then need_version=no else need_version=yes fi library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; os2*) libname_spec='$name' version_type=windows shrext_cmds=.dll need_version=no need_lib_prefix=no # OS/2 can only load a DLL with a base name of 8 characters or less. soname_spec='`test -n "$os2dllname" && libname="$os2dllname"; v=$($ECHO $release$versuffix | tr -d .-); n=$($ECHO $libname | cut -b -$((8 - ${#v})) | tr . _); $ECHO $n$v`$shared_ext' library_names_spec='${libname}_dll.$libext' dynamic_linker='OS/2 ld.exe' shlibpath_var=BEGINLIBPATH sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec postinstall_cmds='base_file=`basename \$file`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; $ECHO \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ chmod a+x \$dldir/$dlname~ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; fi' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; $ECHO \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' ;; osf3* | osf4* | osf5*) version_type=osf need_lib_prefix=no need_version=no soname_spec='$libname$release$shared_ext$major' library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; rdos*) dynamic_linker=no ;; solaris*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes # ldd complains unless libraries are executable postinstall_cmds='chmod +x $lib' ;; sunos4*) version_type=sunos library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes if test yes = "$with_gnu_ld"; then need_lib_prefix=no fi need_version=yes ;; sysv4 | sysv4.3*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH case $host_vendor in sni) shlibpath_overrides_runpath=no need_lib_prefix=no runpath_var=LD_RUN_PATH ;; siemens) need_lib_prefix=no ;; motorola) need_lib_prefix=no need_version=no shlibpath_overrides_runpath=no sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' ;; esac ;; sysv4*MP*) if test -d /usr/nec; then version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$shared_ext.$versuffix $libname$shared_ext.$major $libname$shared_ext' soname_spec='$libname$shared_ext.$major' shlibpath_var=LD_LIBRARY_PATH fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) version_type=sco need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes if test yes = "$with_gnu_ld"; then sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' else sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' case $host_os in sco3.2v5*) sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" ;; esac fi sys_lib_dlsearch_path_spec='/usr/lib' ;; tpf*) # TPF is a cross-target only. Preferred cross-host = GNU/Linux. version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; uts4*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH ;; *) dynamic_linker=no ;; esac AC_MSG_RESULT([$dynamic_linker]) test no = "$dynamic_linker" && can_build_shared=no variables_saved_for_relink="PATH $shlibpath_var $runpath_var" if test yes = "$GCC"; then variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" fi if test set = "${lt_cv_sys_lib_search_path_spec+set}"; then sys_lib_search_path_spec=$lt_cv_sys_lib_search_path_spec fi if test set = "${lt_cv_sys_lib_dlsearch_path_spec+set}"; then sys_lib_dlsearch_path_spec=$lt_cv_sys_lib_dlsearch_path_spec fi # remember unaugmented sys_lib_dlsearch_path content for libtool script decls... configure_time_dlsearch_path=$sys_lib_dlsearch_path_spec # ... but it needs LT_SYS_LIBRARY_PATH munging for other configure-time code func_munge_path_list sys_lib_dlsearch_path_spec "$LT_SYS_LIBRARY_PATH" # to be used as default LT_SYS_LIBRARY_PATH value in generated libtool configure_time_lt_sys_library_path=$LT_SYS_LIBRARY_PATH _LT_DECL([], [variables_saved_for_relink], [1], [Variables whose values should be saved in libtool wrapper scripts and restored at link time]) _LT_DECL([], [need_lib_prefix], [0], [Do we need the "lib" prefix for modules?]) _LT_DECL([], [need_version], [0], [Do we need a version for libraries?]) _LT_DECL([], [version_type], [0], [Library versioning type]) _LT_DECL([], [runpath_var], [0], [Shared library runtime path variable]) _LT_DECL([], [shlibpath_var], [0],[Shared library path variable]) _LT_DECL([], [shlibpath_overrides_runpath], [0], [Is shlibpath searched before the hard-coded library search path?]) _LT_DECL([], [libname_spec], [1], [Format of library name prefix]) _LT_DECL([], [library_names_spec], [1], [[List of archive names. First name is the real one, the rest are links. The last name is the one that the linker finds with -lNAME]]) _LT_DECL([], [soname_spec], [1], [[The coded name of the library, if different from the real name]]) _LT_DECL([], [install_override_mode], [1], [Permission mode override for installation of shared libraries]) _LT_DECL([], [postinstall_cmds], [2], [Command to use after installation of a shared archive]) _LT_DECL([], [postuninstall_cmds], [2], [Command to use after uninstallation of a shared archive]) _LT_DECL([], [finish_cmds], [2], [Commands used to finish a libtool library installation in a directory]) _LT_DECL([], [finish_eval], [1], [[As "finish_cmds", except a single script fragment to be evaled but not shown]]) _LT_DECL([], [hardcode_into_libs], [0], [Whether we should hardcode library paths into libraries]) _LT_DECL([], [sys_lib_search_path_spec], [2], [Compile-time system search path for libraries]) _LT_DECL([sys_lib_dlsearch_path_spec], [configure_time_dlsearch_path], [2], [Detected run-time system search path for libraries]) _LT_DECL([], [configure_time_lt_sys_library_path], [2], [Explicit LT_SYS_LIBRARY_PATH set during ./configure time]) ])# _LT_SYS_DYNAMIC_LINKER # _LT_PATH_TOOL_PREFIX(TOOL) # -------------------------- # find a file program that can recognize shared library AC_DEFUN([_LT_PATH_TOOL_PREFIX], [m4_require([_LT_DECL_EGREP])dnl AC_MSG_CHECKING([for $1]) AC_CACHE_VAL(lt_cv_path_MAGIC_CMD, [case $MAGIC_CMD in [[\\/*] | ?:[\\/]*]) lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path. ;; *) lt_save_MAGIC_CMD=$MAGIC_CMD lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR dnl $ac_dummy forces splitting on constant user-supplied paths. dnl POSIX.2 word splitting is done only on the output of word expansions, dnl not every word. This closes a longstanding sh security hole. ac_dummy="m4_if([$2], , $PATH, [$2])" for ac_dir in $ac_dummy; do IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$1"; then lt_cv_path_MAGIC_CMD=$ac_dir/"$1" if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` MAGIC_CMD=$lt_cv_path_MAGIC_CMD if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | $EGREP "$file_magic_regex" > /dev/null; then : else cat <<_LT_EOF 1>&2 *** Warning: the command libtool uses to detect shared libraries, *** $file_magic_cmd, produces output that libtool cannot recognize. *** The result is that libtool may fail to recognize shared libraries *** as such. This will affect the creation of libtool libraries that *** depend on shared libraries, but programs linked with such libtool *** libraries will work regardless of this problem. Nevertheless, you *** may want to report the problem to your system manager and/or to *** bug-libtool@gnu.org _LT_EOF fi ;; esac fi break fi done IFS=$lt_save_ifs MAGIC_CMD=$lt_save_MAGIC_CMD ;; esac]) MAGIC_CMD=$lt_cv_path_MAGIC_CMD if test -n "$MAGIC_CMD"; then AC_MSG_RESULT($MAGIC_CMD) else AC_MSG_RESULT(no) fi _LT_DECL([], [MAGIC_CMD], [0], [Used to examine libraries when file_magic_cmd begins with "file"])dnl ])# _LT_PATH_TOOL_PREFIX # Old name: AU_ALIAS([AC_PATH_TOOL_PREFIX], [_LT_PATH_TOOL_PREFIX]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_PATH_TOOL_PREFIX], []) # _LT_PATH_MAGIC # -------------- # find a file program that can recognize a shared library m4_defun([_LT_PATH_MAGIC], [_LT_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH) if test -z "$lt_cv_path_MAGIC_CMD"; then if test -n "$ac_tool_prefix"; then _LT_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH) else MAGIC_CMD=: fi fi ])# _LT_PATH_MAGIC # LT_PATH_LD # ---------- # find the pathname to the GNU or non-GNU linker AC_DEFUN([LT_PATH_LD], [AC_REQUIRE([AC_PROG_CC])dnl AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_CANONICAL_BUILD])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_PROG_ECHO_BACKSLASH])dnl AC_ARG_WITH([gnu-ld], [AS_HELP_STRING([--with-gnu-ld], [assume the C compiler uses GNU ld @<:@default=no@:>@])], [test no = "$withval" || with_gnu_ld=yes], [with_gnu_ld=no])dnl ac_prog=ld if test yes = "$GCC"; then # Check if gcc -print-prog-name=ld gives a path. AC_MSG_CHECKING([for ld used by $CC]) case $host in *-*-mingw*) # gcc leaves a trailing carriage return, which upsets mingw ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; *) ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; esac case $ac_prog in # Accept absolute paths. [[\\/]]* | ?:[[\\/]]*) re_direlt='/[[^/]][[^/]]*/\.\./' # Canonicalize the pathname of ld ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` done test -z "$LD" && LD=$ac_prog ;; "") # If it fails, then pretend we aren't using GCC. ac_prog=ld ;; *) # If it is relative, then search for the first ld in PATH. with_gnu_ld=unknown ;; esac elif test yes = "$with_gnu_ld"; then AC_MSG_CHECKING([for GNU ld]) else AC_MSG_CHECKING([for non-GNU ld]) fi AC_CACHE_VAL(lt_cv_path_LD, [if test -z "$LD"; then lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR for ac_dir in $PATH; do IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then lt_cv_path_LD=$ac_dir/$ac_prog # Check to see if the program is GNU ld. I'd rather use --version, # but apparently some variants of GNU ld only accept -v. # Break only if it was the GNU/non-GNU ld that we prefer. case `"$lt_cv_path_LD" -v 2>&1 &1 conftest.i cat conftest.i conftest.i >conftest2.i : ${lt_DD:=$DD} AC_PATH_PROGS_FEATURE_CHECK([lt_DD], [dd], [if "$ac_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then cmp -s conftest.i conftest.out \ && ac_cv_path_lt_DD="$ac_path_lt_DD" ac_path_lt_DD_found=: fi]) rm -f conftest.i conftest2.i conftest.out]) ])# _LT_PATH_DD # _LT_CMD_TRUNCATE # ---------------- # find command to truncate a binary pipe m4_defun([_LT_CMD_TRUNCATE], [m4_require([_LT_PATH_DD]) AC_CACHE_CHECK([how to truncate binary pipes], [lt_cv_truncate_bin], [printf 0123456789abcdef0123456789abcdef >conftest.i cat conftest.i conftest.i >conftest2.i lt_cv_truncate_bin= if "$ac_cv_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then cmp -s conftest.i conftest.out \ && lt_cv_truncate_bin="$ac_cv_path_lt_DD bs=4096 count=1" fi rm -f conftest.i conftest2.i conftest.out test -z "$lt_cv_truncate_bin" && lt_cv_truncate_bin="$SED -e 4q"]) _LT_DECL([lt_truncate_bin], [lt_cv_truncate_bin], [1], [Command to truncate a binary pipe]) ])# _LT_CMD_TRUNCATE # _LT_CHECK_MAGIC_METHOD # ---------------------- # how to check for library dependencies # -- PORTME fill in with the dynamic library characteristics m4_defun([_LT_CHECK_MAGIC_METHOD], [m4_require([_LT_DECL_EGREP]) m4_require([_LT_DECL_OBJDUMP]) AC_CACHE_CHECK([how to recognize dependent libraries], lt_cv_deplibs_check_method, [lt_cv_file_magic_cmd='$MAGIC_CMD' lt_cv_file_magic_test_file= lt_cv_deplibs_check_method='unknown' # Need to set the preceding variable on all platforms that support # interlibrary dependencies. # 'none' -- dependencies not supported. # 'unknown' -- same as none, but documents that we really don't know. # 'pass_all' -- all dependencies passed with no checks. # 'test_compile' -- check by making test program. # 'file_magic [[regex]]' -- check by looking for files in library path # that responds to the $file_magic_cmd with a given extended regex. # If you have 'file' or equivalent on your system and you're not sure # whether 'pass_all' will *always* work, you probably want this one. case $host_os in aix[[4-9]]*) lt_cv_deplibs_check_method=pass_all ;; beos*) lt_cv_deplibs_check_method=pass_all ;; bsdi[[45]]*) lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib)' lt_cv_file_magic_cmd='/usr/bin/file -L' lt_cv_file_magic_test_file=/shlib/libc.so ;; cygwin*) # func_win32_libid is a shell function defined in ltmain.sh lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' lt_cv_file_magic_cmd='func_win32_libid' ;; mingw* | pw32*) # Base MSYS/MinGW do not provide the 'file' command needed by # func_win32_libid shell function, so use a weaker test based on 'objdump', # unless we find 'file', for example because we are cross-compiling. if ( file / ) >/dev/null 2>&1; then lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' lt_cv_file_magic_cmd='func_win32_libid' else # Keep this pattern in sync with the one in func_win32_libid. lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' lt_cv_file_magic_cmd='$OBJDUMP -f' fi ;; cegcc*) # use the weaker test based on 'objdump'. See mingw*. lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' lt_cv_file_magic_cmd='$OBJDUMP -f' ;; darwin* | rhapsody*) lt_cv_deplibs_check_method=pass_all ;; freebsd* | dragonfly*) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then case $host_cpu in i*86 ) # Not sure whether the presence of OpenBSD here was a mistake. # Let's accept both of them until this is cleared up. lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[[3-9]]86 (compact )?demand paged shared library' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` ;; esac else lt_cv_deplibs_check_method=pass_all fi ;; haiku*) lt_cv_deplibs_check_method=pass_all ;; hpux10.20* | hpux11*) lt_cv_file_magic_cmd=/usr/bin/file case $host_cpu in ia64*) lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64' lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so ;; hppa*64*) [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]'] lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl ;; *) lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]]\.[[0-9]]) shared library' lt_cv_file_magic_test_file=/usr/lib/libc.sl ;; esac ;; interix[[3-9]]*) # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|\.a)$' ;; irix5* | irix6* | nonstopux*) case $LD in *-32|*"-32 ") libmagic=32-bit;; *-n32|*"-n32 ") libmagic=N32;; *-64|*"-64 ") libmagic=64-bit;; *) libmagic=never-match;; esac lt_cv_deplibs_check_method=pass_all ;; # This must be glibc/ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) lt_cv_deplibs_check_method=pass_all ;; netbsd* | netbsdelf*-gnu) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|_pic\.a)$' fi ;; newos6*) lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=/usr/lib/libnls.so ;; *nto* | *qnx*) lt_cv_deplibs_check_method=pass_all ;; openbsd* | bitrig*) if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|\.so|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' fi ;; osf3* | osf4* | osf5*) lt_cv_deplibs_check_method=pass_all ;; rdos*) lt_cv_deplibs_check_method=pass_all ;; solaris*) lt_cv_deplibs_check_method=pass_all ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) lt_cv_deplibs_check_method=pass_all ;; sysv4 | sysv4.3*) case $host_vendor in motorola) lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]' lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` ;; ncr) lt_cv_deplibs_check_method=pass_all ;; sequent) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )' ;; sni) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib" lt_cv_file_magic_test_file=/lib/libc.so ;; siemens) lt_cv_deplibs_check_method=pass_all ;; pc) lt_cv_deplibs_check_method=pass_all ;; esac ;; tpf*) lt_cv_deplibs_check_method=pass_all ;; os2*) lt_cv_deplibs_check_method=pass_all ;; esac ]) file_magic_glob= want_nocaseglob=no if test "$build" = "$host"; then case $host_os in mingw* | pw32*) if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then want_nocaseglob=yes else file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[[\1]]\/[[\1]]\/g;/g"` fi ;; esac fi file_magic_cmd=$lt_cv_file_magic_cmd deplibs_check_method=$lt_cv_deplibs_check_method test -z "$deplibs_check_method" && deplibs_check_method=unknown _LT_DECL([], [deplibs_check_method], [1], [Method to check whether dependent libraries are shared objects]) _LT_DECL([], [file_magic_cmd], [1], [Command to use when deplibs_check_method = "file_magic"]) _LT_DECL([], [file_magic_glob], [1], [How to find potential files when deplibs_check_method = "file_magic"]) _LT_DECL([], [want_nocaseglob], [1], [Find potential files using nocaseglob when deplibs_check_method = "file_magic"]) ])# _LT_CHECK_MAGIC_METHOD # LT_PATH_NM # ---------- # find the pathname to a BSD- or MS-compatible name lister AC_DEFUN([LT_PATH_NM], [AC_REQUIRE([AC_PROG_CC])dnl AC_CACHE_CHECK([for BSD- or MS-compatible name lister (nm)], lt_cv_path_NM, [if test -n "$NM"; then # Let the user override the test. lt_cv_path_NM=$NM else lt_nm_to_check=${ac_tool_prefix}nm if test -n "$ac_tool_prefix" && test "$build" = "$host"; then lt_nm_to_check="$lt_nm_to_check nm" fi for lt_tmp_nm in $lt_nm_to_check; do lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. tmp_nm=$ac_dir/$lt_tmp_nm if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext"; then # Check to see if the nm accepts a BSD-compat flag. # Adding the 'sed 1q' prevents false positives on HP-UX, which says: # nm: unknown option "B" ignored # Tru64's nm complains that /dev/null is an invalid object file # MSYS converts /dev/null to NUL, MinGW nm treats NUL as empty case $build_os in mingw*) lt_bad_file=conftest.nm/nofile ;; *) lt_bad_file=/dev/null ;; esac case `"$tmp_nm" -B $lt_bad_file 2>&1 | sed '1q'` in *$lt_bad_file* | *'Invalid file or object type'*) lt_cv_path_NM="$tmp_nm -B" break 2 ;; *) case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in */dev/null*) lt_cv_path_NM="$tmp_nm -p" break 2 ;; *) lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but continue # so that we can try to find one that supports BSD flags ;; esac ;; esac fi done IFS=$lt_save_ifs done : ${lt_cv_path_NM=no} fi]) if test no != "$lt_cv_path_NM"; then NM=$lt_cv_path_NM else # Didn't find any BSD compatible name lister, look for dumpbin. if test -n "$DUMPBIN"; then : # Let the user override the test. else AC_CHECK_TOOLS(DUMPBIN, [dumpbin "link -dump"], :) case `$DUMPBIN -symbols -headers /dev/null 2>&1 | sed '1q'` in *COFF*) DUMPBIN="$DUMPBIN -symbols -headers" ;; *) DUMPBIN=: ;; esac fi AC_SUBST([DUMPBIN]) if test : != "$DUMPBIN"; then NM=$DUMPBIN fi fi test -z "$NM" && NM=nm AC_SUBST([NM]) _LT_DECL([], [NM], [1], [A BSD- or MS-compatible name lister])dnl AC_CACHE_CHECK([the name lister ($NM) interface], [lt_cv_nm_interface], [lt_cv_nm_interface="BSD nm" echo "int some_variable = 0;" > conftest.$ac_ext (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&AS_MESSAGE_LOG_FD) (eval "$ac_compile" 2>conftest.err) cat conftest.err >&AS_MESSAGE_LOG_FD (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&AS_MESSAGE_LOG_FD) (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) cat conftest.err >&AS_MESSAGE_LOG_FD (eval echo "\"\$as_me:$LINENO: output\"" >&AS_MESSAGE_LOG_FD) cat conftest.out >&AS_MESSAGE_LOG_FD if $GREP 'External.*some_variable' conftest.out > /dev/null; then lt_cv_nm_interface="MS dumpbin" fi rm -f conftest*]) ])# LT_PATH_NM # Old names: AU_ALIAS([AM_PROG_NM], [LT_PATH_NM]) AU_ALIAS([AC_PROG_NM], [LT_PATH_NM]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AM_PROG_NM], []) dnl AC_DEFUN([AC_PROG_NM], []) # _LT_CHECK_SHAREDLIB_FROM_LINKLIB # -------------------------------- # how to determine the name of the shared library # associated with a specific link library. # -- PORTME fill in with the dynamic library characteristics m4_defun([_LT_CHECK_SHAREDLIB_FROM_LINKLIB], [m4_require([_LT_DECL_EGREP]) m4_require([_LT_DECL_OBJDUMP]) m4_require([_LT_DECL_DLLTOOL]) AC_CACHE_CHECK([how to associate runtime and link libraries], lt_cv_sharedlib_from_linklib_cmd, [lt_cv_sharedlib_from_linklib_cmd='unknown' case $host_os in cygwin* | mingw* | pw32* | cegcc*) # two different shell functions defined in ltmain.sh; # decide which one to use based on capabilities of $DLLTOOL case `$DLLTOOL --help 2>&1` in *--identify-strict*) lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib ;; *) lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback ;; esac ;; *) # fallback: assume linklib IS sharedlib lt_cv_sharedlib_from_linklib_cmd=$ECHO ;; esac ]) sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO _LT_DECL([], [sharedlib_from_linklib_cmd], [1], [Command to associate shared and link libraries]) ])# _LT_CHECK_SHAREDLIB_FROM_LINKLIB # _LT_PATH_MANIFEST_TOOL # ---------------------- # locate the manifest tool m4_defun([_LT_PATH_MANIFEST_TOOL], [AC_CHECK_TOOL(MANIFEST_TOOL, mt, :) test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt AC_CACHE_CHECK([if $MANIFEST_TOOL is a manifest tool], [lt_cv_path_mainfest_tool], [lt_cv_path_mainfest_tool=no echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&AS_MESSAGE_LOG_FD $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out cat conftest.err >&AS_MESSAGE_LOG_FD if $GREP 'Manifest Tool' conftest.out > /dev/null; then lt_cv_path_mainfest_tool=yes fi rm -f conftest*]) if test yes != "$lt_cv_path_mainfest_tool"; then MANIFEST_TOOL=: fi _LT_DECL([], [MANIFEST_TOOL], [1], [Manifest tool])dnl ])# _LT_PATH_MANIFEST_TOOL # _LT_DLL_DEF_P([FILE]) # --------------------- # True iff FILE is a Windows DLL '.def' file. # Keep in sync with func_dll_def_p in the libtool script AC_DEFUN([_LT_DLL_DEF_P], [dnl test DEF = "`$SED -n dnl -e '\''s/^[[ ]]*//'\'' dnl Strip leading whitespace -e '\''/^\(;.*\)*$/d'\'' dnl Delete empty lines and comments -e '\''s/^\(EXPORTS\|LIBRARY\)\([[ ]].*\)*$/DEF/p'\'' dnl -e q dnl Only consider the first "real" line $1`" dnl ])# _LT_DLL_DEF_P # LT_LIB_M # -------- # check for math library AC_DEFUN([LT_LIB_M], [AC_REQUIRE([AC_CANONICAL_HOST])dnl LIBM= case $host in *-*-beos* | *-*-cegcc* | *-*-cygwin* | *-*-haiku* | *-*-pw32* | *-*-darwin*) # These system don't have libm, or don't need it ;; *-ncr-sysv4.3*) AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM=-lmw) AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm") ;; *) AC_CHECK_LIB(m, cos, LIBM=-lm) ;; esac AC_SUBST([LIBM]) ])# LT_LIB_M # Old name: AU_ALIAS([AC_CHECK_LIBM], [LT_LIB_M]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_CHECK_LIBM], []) # _LT_COMPILER_NO_RTTI([TAGNAME]) # ------------------------------- m4_defun([_LT_COMPILER_NO_RTTI], [m4_require([_LT_TAG_COMPILER])dnl _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= if test yes = "$GCC"; then case $cc_basename in nvcc*) _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -Xcompiler -fno-builtin' ;; *) _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' ;; esac _LT_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions], lt_cv_prog_compiler_rtti_exceptions, [-fno-rtti -fno-exceptions], [], [_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"]) fi _LT_TAGDECL([no_builtin_flag], [lt_prog_compiler_no_builtin_flag], [1], [Compiler flag to turn off builtin functions]) ])# _LT_COMPILER_NO_RTTI # _LT_CMD_GLOBAL_SYMBOLS # ---------------------- m4_defun([_LT_CMD_GLOBAL_SYMBOLS], [AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_PROG_CC])dnl AC_REQUIRE([AC_PROG_AWK])dnl AC_REQUIRE([LT_PATH_NM])dnl AC_REQUIRE([LT_PATH_LD])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_TAG_COMPILER])dnl # Check for command to grab the raw symbol name followed by C symbol from nm. AC_MSG_CHECKING([command to parse $NM output from $compiler object]) AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe], [ # These are sane defaults that work on at least a few old systems. # [They come from Ultrix. What could be older than Ultrix?!! ;)] # Character class describing NM global symbol codes. symcode='[[BCDEGRST]]' # Regexp to match symbols that can be accessed directly from C. sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)' # Define system-specific variables. case $host_os in aix*) symcode='[[BCDT]]' ;; cygwin* | mingw* | pw32* | cegcc*) symcode='[[ABCDGISTW]]' ;; hpux*) if test ia64 = "$host_cpu"; then symcode='[[ABCDEGRST]]' fi ;; irix* | nonstopux*) symcode='[[BCDEGRST]]' ;; osf*) symcode='[[BCDEGQRST]]' ;; solaris*) symcode='[[BDRT]]' ;; sco3.2v5*) symcode='[[DT]]' ;; sysv4.2uw2*) symcode='[[DT]]' ;; sysv5* | sco5v6* | unixware* | OpenUNIX*) symcode='[[ABDT]]' ;; sysv4) symcode='[[DFNSTU]]' ;; esac # If we're using GNU nm, then use its standard symbol codes. case `$NM -V 2>&1` in *GNU* | *'with BFD'*) symcode='[[ABCDGIRSTW]]' ;; esac if test "$lt_cv_nm_interface" = "MS dumpbin"; then # Gets list of data symbols to import. lt_cv_sys_global_symbol_to_import="sed -n -e 's/^I .* \(.*\)$/\1/p'" # Adjust the below global symbol transforms to fixup imported variables. lt_cdecl_hook=" -e 's/^I .* \(.*\)$/extern __declspec(dllimport) char \1;/p'" lt_c_name_hook=" -e 's/^I .* \(.*\)$/ {\"\1\", (void *) 0},/p'" lt_c_name_lib_hook="\ -e 's/^I .* \(lib.*\)$/ {\"\1\", (void *) 0},/p'\ -e 's/^I .* \(.*\)$/ {\"lib\1\", (void *) 0},/p'" else # Disable hooks by default. lt_cv_sys_global_symbol_to_import= lt_cdecl_hook= lt_c_name_hook= lt_c_name_lib_hook= fi # Transform an extracted symbol line into a proper C declaration. # Some systems (esp. on ia64) link data and code symbols differently, # so use this general approach. lt_cv_sys_global_symbol_to_cdecl="sed -n"\ $lt_cdecl_hook\ " -e 's/^T .* \(.*\)$/extern int \1();/p'"\ " -e 's/^$symcode$symcode* .* \(.*\)$/extern char \1;/p'" # Transform an extracted symbol line into symbol name and symbol address lt_cv_sys_global_symbol_to_c_name_address="sed -n"\ $lt_c_name_hook\ " -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ " -e 's/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/p'" # Transform an extracted symbol line into symbol name with lib prefix and # symbol address. lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n"\ $lt_c_name_lib_hook\ " -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ " -e 's/^$symcode$symcode* .* \(lib.*\)$/ {\"\1\", (void *) \&\1},/p'"\ " -e 's/^$symcode$symcode* .* \(.*\)$/ {\"lib\1\", (void *) \&\1},/p'" # Handle CRLF in mingw tool chain opt_cr= case $build_os in mingw*) opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp ;; esac # Try without a prefix underscore, then with it. for ac_symprfx in "" "_"; do # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. symxfrm="\\1 $ac_symprfx\\2 \\2" # Write the raw and C identifiers. if test "$lt_cv_nm_interface" = "MS dumpbin"; then # Fake it for dumpbin and say T for any non-static function, # D for any global variable and I for any imported variable. # Also find C++ and __fastcall symbols from MSVC++, # which start with @ or ?. lt_cv_sys_global_symbol_pipe="$AWK ['"\ " {last_section=section; section=\$ 3};"\ " /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\ " /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ " /^ *Symbol name *: /{split(\$ 0,sn,\":\"); si=substr(sn[2],2)};"\ " /^ *Type *: code/{print \"T\",si,substr(si,length(prfx))};"\ " /^ *Type *: data/{print \"I\",si,substr(si,length(prfx))};"\ " \$ 0!~/External *\|/{next};"\ " / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ " {if(hide[section]) next};"\ " {f=\"D\"}; \$ 0~/\(\).*\|/{f=\"T\"};"\ " {split(\$ 0,a,/\||\r/); split(a[2],s)};"\ " s[1]~/^[@?]/{print f,s[1],s[1]; next};"\ " s[1]~prfx {split(s[1],t,\"@\"); print f,t[1],substr(t[1],length(prfx))}"\ " ' prfx=^$ac_symprfx]" else lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" fi lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'" # Check to see that the pipe works correctly. pipe_works=no rm -f conftest* cat > conftest.$ac_ext <<_LT_EOF #ifdef __cplusplus extern "C" { #endif char nm_test_var; void nm_test_func(void); void nm_test_func(void){} #ifdef __cplusplus } #endif int main(){nm_test_var='a';nm_test_func();return(0);} _LT_EOF if AC_TRY_EVAL(ac_compile); then # Now try to grab the symbols. nlist=conftest.nm $ECHO "$as_me:$LINENO: $NM conftest.$ac_objext | $lt_cv_sys_global_symbol_pipe > $nlist" >&AS_MESSAGE_LOG_FD if eval "$NM" conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist 2>&AS_MESSAGE_LOG_FD && test -s "$nlist"; then # Try sorting and uniquifying the output. if sort "$nlist" | uniq > "$nlist"T; then mv -f "$nlist"T "$nlist" else rm -f "$nlist"T fi # Make sure that we snagged all the symbols we need. if $GREP ' nm_test_var$' "$nlist" >/dev/null; then if $GREP ' nm_test_func$' "$nlist" >/dev/null; then cat <<_LT_EOF > conftest.$ac_ext /* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ #if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE /* DATA imports from DLLs on WIN32 can't be const, because runtime relocations are performed -- see ld's documentation on pseudo-relocs. */ # define LT@&t@_DLSYM_CONST #elif defined __osf__ /* This system does not cope well with relocations in const data. */ # define LT@&t@_DLSYM_CONST #else # define LT@&t@_DLSYM_CONST const #endif #ifdef __cplusplus extern "C" { #endif _LT_EOF # Now generate the symbol file. eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' cat <<_LT_EOF >> conftest.$ac_ext /* The mapping between symbol names and symbols. */ LT@&t@_DLSYM_CONST struct { const char *name; void *address; } lt__PROGRAM__LTX_preloaded_symbols[[]] = { { "@PROGRAM@", (void *) 0 }, _LT_EOF $SED "s/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext cat <<\_LT_EOF >> conftest.$ac_ext {0, (void *) 0} }; /* This works around a problem in FreeBSD linker */ #ifdef FREEBSD_WORKAROUND static const void *lt_preloaded_setup() { return lt__PROGRAM__LTX_preloaded_symbols; } #endif #ifdef __cplusplus } #endif _LT_EOF # Now try linking the two files. mv conftest.$ac_objext conftstm.$ac_objext lt_globsym_save_LIBS=$LIBS lt_globsym_save_CFLAGS=$CFLAGS LIBS=conftstm.$ac_objext CFLAGS="$CFLAGS$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)" if AC_TRY_EVAL(ac_link) && test -s conftest$ac_exeext; then pipe_works=yes fi LIBS=$lt_globsym_save_LIBS CFLAGS=$lt_globsym_save_CFLAGS else echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD fi else echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD fi else echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD fi else echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD cat conftest.$ac_ext >&5 fi rm -rf conftest* conftst* # Do not use the global_symbol_pipe unless it works. if test yes = "$pipe_works"; then break else lt_cv_sys_global_symbol_pipe= fi done ]) if test -z "$lt_cv_sys_global_symbol_pipe"; then lt_cv_sys_global_symbol_to_cdecl= fi if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then AC_MSG_RESULT(failed) else AC_MSG_RESULT(ok) fi # Response file support. if test "$lt_cv_nm_interface" = "MS dumpbin"; then nm_file_list_spec='@' elif $NM --help 2>/dev/null | grep '[[@]]FILE' >/dev/null; then nm_file_list_spec='@' fi _LT_DECL([global_symbol_pipe], [lt_cv_sys_global_symbol_pipe], [1], [Take the output of nm and produce a listing of raw symbols and C names]) _LT_DECL([global_symbol_to_cdecl], [lt_cv_sys_global_symbol_to_cdecl], [1], [Transform the output of nm in a proper C declaration]) _LT_DECL([global_symbol_to_import], [lt_cv_sys_global_symbol_to_import], [1], [Transform the output of nm into a list of symbols to manually relocate]) _LT_DECL([global_symbol_to_c_name_address], [lt_cv_sys_global_symbol_to_c_name_address], [1], [Transform the output of nm in a C name address pair]) _LT_DECL([global_symbol_to_c_name_address_lib_prefix], [lt_cv_sys_global_symbol_to_c_name_address_lib_prefix], [1], [Transform the output of nm in a C name address pair when lib prefix is needed]) _LT_DECL([nm_interface], [lt_cv_nm_interface], [1], [The name lister interface]) _LT_DECL([], [nm_file_list_spec], [1], [Specify filename containing input files for $NM]) ]) # _LT_CMD_GLOBAL_SYMBOLS # _LT_COMPILER_PIC([TAGNAME]) # --------------------------- m4_defun([_LT_COMPILER_PIC], [m4_require([_LT_TAG_COMPILER])dnl _LT_TAGVAR(lt_prog_compiler_wl, $1)= _LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_static, $1)= m4_if([$1], [CXX], [ # C++ specific cases for pic, static, wl, etc. if test yes = "$GXX"; then _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' case $host_os in aix*) # All AIX code is PIC. if test ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; m68k) # FIXME: we need at least 68020 code to build shared libraries, but # adding the '-m68020' flag to GCC prevents building anything better, # like '-m68040'. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' ;; esac ;; beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | cygwin* | os2* | pw32* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). # Although the cygwin gcc ignores -fPIC, still need this for old-style # (--disable-auto-import) libraries m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) case $host_os in os2*) _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static' ;; esac ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' ;; *djgpp*) # DJGPP does not support shared libraries at all _LT_TAGVAR(lt_prog_compiler_pic, $1)= ;; haiku*) # PIC is the default for Haiku. # The "-static" flag exists, but is broken. _LT_TAGVAR(lt_prog_compiler_static, $1)= ;; interix[[3-9]]*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. ;; sysv4*MP*) if test -d /usr/nec; then _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic fi ;; hpux*) # PIC is the default for 64-bit PA HP-UX, but not for 32-bit # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag # sets the default TLS model and affects inlining. case $host_cpu in hppa*64*) ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac ;; *qnx* | *nto*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac else case $host_os in aix[[4-9]]*) # All AIX code is PIC. if test ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' else _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' fi ;; chorus*) case $cc_basename in cxch68*) # Green Hills C++ Compiler # _LT_TAGVAR(lt_prog_compiler_static, $1)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" ;; esac ;; mingw* | cygwin* | os2* | pw32* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) ;; dgux*) case $cc_basename in ec++*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' ;; ghcx*) # Green Hills C++ Compiler _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' ;; *) ;; esac ;; freebsd* | dragonfly*) # FreeBSD uses GNU C++ ;; hpux9* | hpux10* | hpux11*) case $cc_basename in CC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive' if test ia64 != "$host_cpu"; then _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' fi ;; aCC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive' case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' ;; esac ;; *) ;; esac ;; interix*) # This is c89, which is MS Visual C++ (no shared libs) # Anyone wants to do a port? ;; irix5* | irix6* | nonstopux*) case $cc_basename in CC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' # CC pic flag -KPIC is the default. ;; *) ;; esac ;; linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) case $cc_basename in KCC*) # KAI C++ Compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; ecpc* ) # old Intel C++ for x86_64, which still supported -KPIC. _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; icpc* ) # Intel C++, used to be incompatible with GCC. # ICC 10 doesn't accept -KPIC any more. _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; pgCC* | pgcpp*) # Portland Group C++ compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; cxx*) # Compaq C++ # Make sure the PIC flag is empty. It appears that all Alpha # Linux and Compaq Tru64 Unix objects are PIC. _LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; xlc* | xlC* | bgxl[[cC]]* | mpixl[[cC]]*) # IBM XL 8.0, 9.0 on PPC and BlueGene _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C++ 5.9 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' ;; esac ;; esac ;; lynxos*) ;; m88k*) ;; mvs*) case $cc_basename in cxx*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall' ;; *) ;; esac ;; netbsd* | netbsdelf*-gnu) ;; *qnx* | *nto*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; osf3* | osf4* | osf5*) case $cc_basename in KCC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' ;; RCC*) # Rational C++ 2.4.1 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' ;; cxx*) # Digital/Compaq C++ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # Make sure the PIC flag is empty. It appears that all Alpha # Linux and Compaq Tru64 Unix objects are PIC. _LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; *) ;; esac ;; psos*) ;; solaris*) case $cc_basename in CC* | sunCC*) # Sun C++ 4.2, 5.x and Centerline C++ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' ;; gcx*) # Green Hills C++ Compiler _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' ;; *) ;; esac ;; sunos4*) case $cc_basename in CC*) # Sun C++ 4.x _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; lcc*) # Lucid _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' ;; *) ;; esac ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) case $cc_basename in CC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; esac ;; tandem*) case $cc_basename in NCC*) # NonStop-UX NCC 3.20 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' ;; *) ;; esac ;; vxworks*) ;; *) _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no ;; esac fi ], [ if test yes = "$GCC"; then _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' case $host_os in aix*) # All AIX code is PIC. if test ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; m68k) # FIXME: we need at least 68020 code to build shared libraries, but # adding the '-m68020' flag to GCC prevents building anything better, # like '-m68040'. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' ;; esac ;; beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). # Although the cygwin gcc ignores -fPIC, still need this for old-style # (--disable-auto-import) libraries m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) case $host_os in os2*) _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static' ;; esac ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' ;; haiku*) # PIC is the default for Haiku. # The "-static" flag exists, but is broken. _LT_TAGVAR(lt_prog_compiler_static, $1)= ;; hpux*) # PIC is the default for 64-bit PA HP-UX, but not for 32-bit # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag # sets the default TLS model and affects inlining. case $host_cpu in hppa*64*) # +Z the default ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac ;; interix[[3-9]]*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. ;; msdosdjgpp*) # Just because we use GCC doesn't mean we suddenly get shared libraries # on systems that don't support them. _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no enable_shared=no ;; *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; sysv4*MP*) if test -d /usr/nec; then _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic fi ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac case $cc_basename in nvcc*) # Cuda Compiler Driver 2.2 _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Xlinker ' if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then _LT_TAGVAR(lt_prog_compiler_pic, $1)="-Xcompiler $_LT_TAGVAR(lt_prog_compiler_pic, $1)" fi ;; esac else # PORTME Check for flag to pass linker flags through the system compiler. case $host_os in aix*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' if test ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' else _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' fi ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' case $cc_basename in nagfor*) # NAG Fortran compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; esac ;; mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) case $host_os in os2*) _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static' ;; esac ;; hpux9* | hpux10* | hpux11*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but # not for PA HP-UX. case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' ;; esac # Is there a better lt_prog_compiler_static that works with the bundled CC? _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive' ;; irix5* | irix6* | nonstopux*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # PIC (with -KPIC) is the default. _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) case $cc_basename in # old Intel for x86_64, which still supported -KPIC. ecc*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; # flang / f18. f95 an alias for gfortran or flang on Debian flang* | f18* | f95*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; # icc used to be incompatible with GCC. # ICC 10 doesn't accept -KPIC any more. icc* | ifort*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; # Lahey Fortran 8.1. lf95*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='--shared' _LT_TAGVAR(lt_prog_compiler_static, $1)='--static' ;; nagfor*) # NAG Fortran compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; tcc*) # Fabrice Bellard et al's Tiny C Compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group compilers (*not* the Pentium gcc compiler, # which looks to be a dead project) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; ccc*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # All Alpha code is PIC. _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; xl* | bgxl* | bgf* | mpixl*) # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [[1-7]].* | *Sun*Fortran*\ 8.[[0-3]]*) # Sun Fortran 8.3 passes all unrecognized flags to the linker _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='' ;; *Sun\ F* | *Sun*Fortran*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' ;; *Sun\ C*) # Sun C 5.9 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' ;; *Intel*\ [[CF]]*Compiler*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; *Portland\ Group*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; esac ;; esac ;; newsos6) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; osf3* | osf4* | osf5*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # All OSF/1 code is PIC. _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; rdos*) _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; solaris*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' case $cc_basename in f77* | f90* | f95* | sunf77* | sunf90* | sunf95*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ';; *) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,';; esac ;; sunos4*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; sysv4 | sysv4.2uw2* | sysv4.3*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; sysv4*MP*) if test -d /usr/nec; then _LT_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; unicos*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no ;; uts4*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; *) _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no ;; esac fi ]) case $host_os in # For platforms that do not support PIC, -DPIC is meaningless: *djgpp*) _LT_TAGVAR(lt_prog_compiler_pic, $1)= ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])" ;; esac AC_CACHE_CHECK([for $compiler option to produce PIC], [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)], [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_prog_compiler_pic, $1)]) _LT_TAGVAR(lt_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_cv_prog_compiler_pic, $1) # # Check to make sure the PIC flag actually works. # if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then _LT_COMPILER_OPTION([if $compiler PIC flag $_LT_TAGVAR(lt_prog_compiler_pic, $1) works], [_LT_TAGVAR(lt_cv_prog_compiler_pic_works, $1)], [$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])], [], [case $_LT_TAGVAR(lt_prog_compiler_pic, $1) in "" | " "*) ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_TAGVAR(lt_prog_compiler_pic, $1)" ;; esac], [_LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no]) fi _LT_TAGDECL([pic_flag], [lt_prog_compiler_pic], [1], [Additional compiler flags for building library objects]) _LT_TAGDECL([wl], [lt_prog_compiler_wl], [1], [How to pass a linker flag through the compiler]) # # Check to make sure the static flag actually works. # wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) eval lt_tmp_static_flag=\"$_LT_TAGVAR(lt_prog_compiler_static, $1)\" _LT_LINKER_OPTION([if $compiler static flag $lt_tmp_static_flag works], _LT_TAGVAR(lt_cv_prog_compiler_static_works, $1), $lt_tmp_static_flag, [], [_LT_TAGVAR(lt_prog_compiler_static, $1)=]) _LT_TAGDECL([link_static_flag], [lt_prog_compiler_static], [1], [Compiler flag to prevent dynamic linking]) ])# _LT_COMPILER_PIC # _LT_LINKER_SHLIBS([TAGNAME]) # ---------------------------- # See if the linker supports building shared libraries. m4_defun([_LT_LINKER_SHLIBS], [AC_REQUIRE([LT_PATH_LD])dnl AC_REQUIRE([LT_PATH_NM])dnl m4_require([_LT_PATH_MANIFEST_TOOL])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl m4_require([_LT_TAG_COMPILER])dnl AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) m4_if([$1], [CXX], [ _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] case $host_os in aix[[4-9]]*) # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to GNU nm, but means don't demangle to AIX nm. # Without the "-l" option, or with the "-B" option, AIX nm treats # weak defined symbols like other global defined symbols, whereas # GNU nm marks them as "W". # While the 'weak' keyword is ignored in the Export File, we need # it in the Import File for the 'aix-soname' feature, so we have # to replace the "-B" option with "-P" for AIX nm. if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' else _LT_TAGVAR(export_symbols_cmds, $1)='`func_echo_all $NM | $SED -e '\''s/B\([[^B]]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && ([substr](\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' fi ;; pw32*) _LT_TAGVAR(export_symbols_cmds, $1)=$ltdll_cmds ;; cygwin* | mingw* | cegcc*) case $cc_basename in cl*) _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' ;; *) _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'] ;; esac ;; linux* | k*bsd*-gnu | gnu*) _LT_TAGVAR(link_all_deplibs, $1)=no ;; *) _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' ;; esac ], [ runpath_var= _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_cmds, $1)= _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(compiler_needs_object, $1)=no _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(old_archive_from_new_cmds, $1)= _LT_TAGVAR(old_archive_from_expsyms_cmds, $1)= _LT_TAGVAR(thread_safe_flag_spec, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= # include_expsyms should be a list of space-separated symbols to be *always* # included in the symbol list _LT_TAGVAR(include_expsyms, $1)= # exclude_expsyms can be an extended regexp of symbols to exclude # it will be wrapped by ' (' and ')$', so one must not match beginning or # end of line. Example: 'a|bc|.*d.*' will exclude the symbols 'a' and 'bc', # as well as any symbol that contains 'd'. _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out # platforms (ab)use it in PIC code, but their linkers get confused if # the symbol is explicitly referenced. Since portable code cannot # rely on this symbol name, it's probably fine to never include it in # preloaded symbol tables. # Exclude shared library initialization/finalization symbols. dnl Note also adjust exclude_expsyms for C++ above. extract_expsyms_cmds= case $host_os in cygwin* | mingw* | pw32* | cegcc*) # FIXME: the MSVC++ port hasn't been tested in a loooong time # When not using gcc, we currently assume that we are using # Microsoft Visual C++. if test yes != "$GCC"; then with_gnu_ld=no fi ;; interix*) # we just hope/assume this is gcc and not c89 (= MSVC++) with_gnu_ld=yes ;; openbsd* | bitrig*) with_gnu_ld=no ;; linux* | k*bsd*-gnu | gnu*) _LT_TAGVAR(link_all_deplibs, $1)=no ;; esac _LT_TAGVAR(ld_shlibs, $1)=yes # On some targets, GNU ld is compatible enough with the native linker # that we're better off using the native interface for both. lt_use_gnu_ld_interface=no if test yes = "$with_gnu_ld"; then case $host_os in aix*) # The AIX port of GNU ld has always aspired to compatibility # with the native linker. However, as the warning in the GNU ld # block says, versions before 2.19.5* couldn't really create working # shared libraries, regardless of the interface used. case `$LD -v 2>&1` in *\ \(GNU\ Binutils\)\ 2.19.5*) ;; *\ \(GNU\ Binutils\)\ 2.[[2-9]]*) ;; *\ \(GNU\ Binutils\)\ [[3-9]]*) ;; *) lt_use_gnu_ld_interface=yes ;; esac ;; *) lt_use_gnu_ld_interface=yes ;; esac fi if test yes = "$lt_use_gnu_ld_interface"; then # If archive_cmds runs LD, not CC, wlarc should be empty wlarc='$wl' # Set some defaults for GNU ld with shared library support. These # are reset later if shared libraries are not supported. Putting them # here allows them to be overridden if necessary. runpath_var=LD_RUN_PATH _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' # ancient GNU ld didn't support --whole-archive et. al. if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' else _LT_TAGVAR(whole_archive_flag_spec, $1)= fi supports_anon_versioning=no case `$LD -v | $SED -e 's/([^)]\+)\s\+//' 2>&1` in *GNU\ gold*) supports_anon_versioning=yes ;; *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11 *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... *\ 2.11.*) ;; # other 2.11 versions *) supports_anon_versioning=yes ;; esac # See if GNU ld supports shared libraries. case $host_os in aix[[3-9]]*) # On AIX/PPC, the GNU linker is very broken if test ia64 != "$host_cpu"; then _LT_TAGVAR(ld_shlibs, $1)=no cat <<_LT_EOF 1>&2 *** Warning: the GNU linker, at least up to release 2.19, is reported *** to be unable to reliably create shared libraries on AIX. *** Therefore, libtool is disabling shared libraries support. If you *** really care for shared libraries, you may want to install binutils *** 2.20 or above, or modify your PATH so that a non-GNU linker is found. *** You will then need to restart the configuration process. _LT_EOF fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='' ;; m68k) _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes ;; esac ;; beos*) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(allow_undefined_flag, $1)=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; cygwin* | mingw* | pw32* | cegcc*) # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, # as there is no search path for DLLs. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-all-symbols' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'] if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' # If the export-symbols file already is a .def file, use it as # is; otherwise, prepend EXPORTS... _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; haiku*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(link_all_deplibs, $1)=yes ;; os2*) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(allow_undefined_flag, $1)=unsupported shrext_cmds=.dll _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ prefix_cmds="$SED"~ if test EXPORTS = "`$SED 1q $export_symbols`"; then prefix_cmds="$prefix_cmds -e 1d"; fi~ prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes ;; interix[[3-9]]*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) tmp_diet=no if test linux-dietlibc = "$host_os"; then case $cc_basename in diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) esac fi if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ && test no = "$tmp_diet" then tmp_addflag=' $pic_flag' tmp_sharedflag='-shared' case $cc_basename,$host_cpu in pgcc*) # Portland Group C compiler _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' tmp_addflag=' $pic_flag' ;; pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group f77 and f90 compilers _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' tmp_addflag=' $pic_flag -Mnomain' ;; ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 tmp_addflag=' -i_dynamic' ;; efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 tmp_addflag=' -i_dynamic -nofor_main' ;; ifc* | ifort*) # Intel Fortran compiler tmp_addflag=' -nofor_main' ;; lf95*) # Lahey Fortran 8.1 _LT_TAGVAR(whole_archive_flag_spec, $1)= tmp_sharedflag='--shared' ;; nagfor*) # NAGFOR 5.3 tmp_sharedflag='-Wl,-shared' ;; xl[[cC]]* | bgxl[[cC]]* | mpixl[[cC]]*) # IBM XL C 8.0 on PPC (deal with xlf below) tmp_sharedflag='-qmkshrobj' tmp_addflag= ;; nvcc*) # Cuda Compiler Driver 2.2 _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' _LT_TAGVAR(compiler_needs_object, $1)=yes ;; esac case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C 5.9 _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' _LT_TAGVAR(compiler_needs_object, $1)=yes tmp_sharedflag='-G' ;; *Sun\ F*) # Sun Fortran 8.3 tmp_sharedflag='-G' ;; esac _LT_TAGVAR(archive_cmds, $1)='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' if test yes = "$supports_anon_versioning"; then _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' fi case $cc_basename in tcc*) _LT_TAGVAR(export_dynamic_flag_spec, $1)='-rdynamic' ;; xlf* | bgf* | bgxlf* | mpixlf*) # IBM XL Fortran 10.1 on PPC cannot create shared libs itself _LT_TAGVAR(whole_archive_flag_spec, $1)='--whole-archive$convenience --no-whole-archive' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' if test yes = "$supports_anon_versioning"; then _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' fi ;; esac else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; netbsd* | netbsdelf*-gnu) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' wlarc= else _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' fi ;; solaris*) if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then _LT_TAGVAR(ld_shlibs, $1)=no cat <<_LT_EOF 1>&2 *** Warning: The releases 2.8.* of the GNU linker cannot reliably *** create shared libraries on Solaris systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.9.1 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) case `$LD -v 2>&1` in *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.1[[0-5]].*) _LT_TAGVAR(ld_shlibs, $1)=no cat <<_LT_EOF 1>&2 *** Warning: Releases of the GNU linker prior to 2.16.91.0.3 cannot *** reliably create shared libraries on SCO systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.16.91.0.3 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF ;; *) # For security reasons, it is highly recommended that you always # use absolute paths for naming shared libraries, and exclude the # DT_RUNPATH tag from executables and libraries. But doing so # requires that you compile everything twice, which is a pain. if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; sunos4*) _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' wlarc= _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac if test no = "$_LT_TAGVAR(ld_shlibs, $1)"; then runpath_var= _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= fi else # PORTME fill in a description of your system's linker (not GNU ld) case $host_os in aix3*) _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=yes _LT_TAGVAR(archive_expsym_cmds, $1)='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' # Note: this linker hardcodes the directories in LIBPATH if there # are no directories specified by -L. _LT_TAGVAR(hardcode_minus_L, $1)=yes if test yes = "$GCC" && test -z "$lt_prog_compiler_static"; then # Neither direct hardcoding nor static linking is supported with a # broken collect2. _LT_TAGVAR(hardcode_direct, $1)=unsupported fi ;; aix[[4-9]]*) if test ia64 = "$host_cpu"; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag= else # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to GNU nm, but means don't demangle to AIX nm. # Without the "-l" option, or with the "-B" option, AIX nm treats # weak defined symbols like other global defined symbols, whereas # GNU nm marks them as "W". # While the 'weak' keyword is ignored in the Export File, we need # it in the Import File for the 'aix-soname' feature, so we have # to replace the "-B" option with "-P" for AIX nm. if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' else _LT_TAGVAR(export_symbols_cmds, $1)='`func_echo_all $NM | $SED -e '\''s/B\([[^B]]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && ([substr](\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' fi aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # have runtime linking enabled, and use it for executables. # For shared libraries, we enable/disable runtime linking # depending on the kind of the shared library created - # when "with_aix_soname,aix_use_runtimelinking" is: # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables # "aix,yes" lib.so shared, rtl:yes, for executables # lib.a static archive # "both,no" lib.so.V(shr.o) shared, rtl:yes # lib.a(lib.so.V) shared, rtl:no, for executables # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables # lib.a(lib.so.V) shared, rtl:no # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables # lib.a static archive case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) for ld_flag in $LDFLAGS; do if (test x-brtl = "x$ld_flag" || test x-Wl,-brtl = "x$ld_flag"); then aix_use_runtimelinking=yes break fi done if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then # With aix-soname=svr4, we create the lib.so.V shared archives only, # so we don't have lib.a shared libs to link our executables. # We have to force runtime linking in this case. aix_use_runtimelinking=yes LDFLAGS="$LDFLAGS -Wl,-brtl" fi ;; esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. _LT_TAGVAR(archive_cmds, $1)='' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(file_list_spec, $1)='$wl-f,' case $with_aix_soname,$aix_use_runtimelinking in aix,*) ;; # traditional, no import file svr4,* | *,yes) # use import file # The Import File defines what to hardcode. _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no ;; esac if test yes = "$GCC"; then case $host_os in aix4.[[012]]|aix4.[[012]].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`$CC -print-prog-name=collect2` if test -f "$collect2name" && strings "$collect2name" | $GREP resolve_lib_name >/dev/null then # We have reworked collect2 : else # We have old collect2 _LT_TAGVAR(hardcode_direct, $1)=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)= fi ;; esac shared_flag='-shared' if test yes = "$aix_use_runtimelinking"; then shared_flag="$shared_flag "'$wl-G' fi # Need to ensure runtime linking is disabled for the traditional # shared library, or the linker may eventually find shared libraries # /with/ Import File - we do not want to mix them. shared_flag_aix='-shared' shared_flag_svr4='-shared $wl-G' else # not using gcc if test ia64 = "$host_cpu"; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test yes = "$aix_use_runtimelinking"; then shared_flag='$wl-G' else shared_flag='$wl-bM:SRE' fi shared_flag_aix='$wl-bM:SRE' shared_flag_svr4='$wl-G' fi fi _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-bexpall' # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to export. _LT_TAGVAR(always_export_symbols, $1)=yes if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. _LT_TAGVAR(allow_undefined_flag, $1)='-berok' # Determine the default libpath from the value encoded in an # empty executable. _LT_SYS_MODULE_PATH_AIX([$1]) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag else if test ia64 = "$host_cpu"; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $libdir:/usr/lib:/lib' _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an # empty executable. _LT_SYS_MODULE_PATH_AIX([$1]) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. _LT_TAGVAR(no_undefined_flag, $1)=' $wl-bernotok' _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-berok' if test yes = "$with_gnu_ld"; then # We only use this code for GNU lds that support --whole-archive. _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive' else # Exported symbols can be pulled into shared objects from archives _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' fi _LT_TAGVAR(archive_cmds_need_lc, $1)=yes _LT_TAGVAR(archive_expsym_cmds, $1)='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' # -brtl affects multiple linker settings, -berok does not and is overridden later compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([[, ]]\\)%-berok\\1%g"`' if test svr4 != "$with_aix_soname"; then # This is similar to how AIX traditionally builds its shared libraries. _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' fi if test aix != "$with_aix_soname"; then _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' else # used by -dlpreopen to get the symbols _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$MV $output_objdir/$realname.d/$soname $output_objdir' fi _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$RM -r $output_objdir/$realname.d' fi fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='' ;; m68k) _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes ;; esac ;; bsdi[[45]]*) _LT_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic ;; cygwin* | mingw* | pw32* | cegcc*) # When not using gcc, we currently assume that we are using # Microsoft Visual C++. # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. case $cc_basename in cl*) # Native MSVC _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=yes _LT_TAGVAR(file_list_spec, $1)='@' # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=.dll # FIXME: Setting linknames here is a bad hack. _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then cp "$export_symbols" "$output_objdir/$soname.def"; echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; else $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp; fi~ $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ linknames=' # The linker will not automatically build a static lib if we build a DLL. # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1,DATA/'\'' | $SED -e '\''/^[[AITW]][[ ]]/s/.*[[ ]]//'\'' | sort | uniq > $export_symbols' # Don't use ranlib _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~ lt_tool_outputfile="@TOOL_OUTPUT@"~ case $lt_outputfile in *.exe|*.EXE) ;; *) lt_outputfile=$lt_outputfile.exe lt_tool_outputfile=$lt_tool_outputfile.exe ;; esac~ if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; $RM "$lt_outputfile.manifest"; fi' ;; *) # Assume MSVC wrapper _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=.dll # FIXME: Setting linknames here is a bad hack. _LT_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames=' # The linker will automatically build a .lib file if we build a DLL. _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' # FIXME: Should let the user specify the lib program. _LT_TAGVAR(old_archive_cmds, $1)='lib -OUT:$oldlib$oldobjs$old_deplibs' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes ;; esac ;; darwin* | rhapsody*) _LT_DARWIN_LINKER_FEATURES($1) ;; dgux*) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor # support. Future versions do this automatically, but an explicit c++rt0.o # does not break anything, and helps significantly (at the cost of a little # extra space). freebsd2.2*) _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; # Unfortunately, older versions of FreeBSD 2 do not have this feature. freebsd2.*) _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; # FreeBSD 3 and greater uses gcc -shared to do shared libraries. freebsd* | dragonfly*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; hpux9*) if test yes = "$GCC"; then _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' else _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(hardcode_direct, $1)=yes # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' ;; hpux10*) if test yes,no = "$GCC,$with_gnu_ld"; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' fi if test no = "$with_gnu_ld"; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. _LT_TAGVAR(hardcode_minus_L, $1)=yes fi ;; hpux11*) if test yes,no = "$GCC,$with_gnu_ld"; then case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' ;; esac else case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) m4_if($1, [], [ # Older versions of the 11.00 compiler do not understand -b yet # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does) _LT_LINKER_OPTION([if $CC understands -b], _LT_TAGVAR(lt_cv_prog_compiler__b, $1), [-b], [_LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags'], [_LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'])], [_LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags']) ;; esac fi if test no = "$with_gnu_ld"; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: case $host_cpu in hppa*64*|ia64*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. _LT_TAGVAR(hardcode_minus_L, $1)=yes ;; esac fi ;; irix5* | irix6* | nonstopux*) if test yes = "$GCC"; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' # Try to use the -exported_symbol ld option, if it does not # work, assume that -exports_file does not work either and # implicitly export all symbols. # This should be the same for all languages, so no per-tag cache variable. AC_CACHE_CHECK([whether the $host_os linker accepts -exported_symbol], [lt_cv_irix_exported_symbol], [save_LDFLAGS=$LDFLAGS LDFLAGS="$LDFLAGS -shared $wl-exported_symbol ${wl}foo $wl-update_registry $wl/dev/null" AC_LINK_IFELSE( [AC_LANG_SOURCE( [AC_LANG_CASE([C], [[int foo (void) { return 0; }]], [C++], [[int foo (void) { return 0; }]], [Fortran 77], [[ subroutine foo end]], [Fortran], [[ subroutine foo end]])])], [lt_cv_irix_exported_symbol=yes], [lt_cv_irix_exported_symbol=no]) LDFLAGS=$save_LDFLAGS]) if test yes = "$lt_cv_irix_exported_symbol"; then _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations $wl-exports_file $wl$export_symbols -o $lib' fi _LT_TAGVAR(link_all_deplibs, $1)=no else _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -exports_file $export_symbols -o $lib' fi _LT_TAGVAR(archive_cmds_need_lc, $1)='no' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(inherit_rpath, $1)=yes _LT_TAGVAR(link_all_deplibs, $1)=yes ;; linux*) case $cc_basename in tcc*) # Fabrice Bellard et al's Tiny C Compiler _LT_TAGVAR(ld_shlibs, $1)=yes _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; netbsd* | netbsdelf*-gnu) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out else _LT_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; newsos6) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *nto* | *qnx*) ;; openbsd* | bitrig*) if test -f /usr/libexec/ld.so; then _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=yes if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags $wl-retain-symbols-file,$export_symbols' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' else _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' fi else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; os2*) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(allow_undefined_flag, $1)=unsupported shrext_cmds=.dll _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ prefix_cmds="$SED"~ if test EXPORTS = "`$SED 1q $export_symbols`"; then prefix_cmds="$prefix_cmds -e 1d"; fi~ prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes ;; osf3*) if test yes = "$GCC"; then _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' else _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' fi _LT_TAGVAR(archive_cmds_need_lc, $1)='no' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: ;; osf4* | osf5*) # as osf3* with the addition of -msym flag if test yes = "$GCC"; then _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $pic_flag $libobjs $deplibs $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' else _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ $CC -shared$allow_undefined_flag $wl-input $wl$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~$RM $lib.exp' # Both c and cxx compiler support -rpath directly _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' fi _LT_TAGVAR(archive_cmds_need_lc, $1)='no' _LT_TAGVAR(hardcode_libdir_separator, $1)=: ;; solaris*) _LT_TAGVAR(no_undefined_flag, $1)=' -z defs' if test yes = "$GCC"; then wlarc='$wl' _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl-z ${wl}text $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -shared $pic_flag $wl-z ${wl}text $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' else case `$CC -V 2>&1` in *"Compilers 5.0"*) wlarc='' _LT_TAGVAR(archive_cmds, $1)='$LD -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $LD -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' ;; *) wlarc='$wl' _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' ;; esac fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no case $host_os in solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; *) # The compiler driver will combine and reorder linker options, # but understands '-z linker_flag'. GCC discards it without '$wl', # but is careful enough not to reorder. # Supported since Solaris 2.6 (maybe 2.5.1?) if test yes = "$GCC"; then _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' else _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' fi ;; esac _LT_TAGVAR(link_all_deplibs, $1)=yes ;; sunos4*) if test sequent = "$host_vendor"; then # Use $CC to link under sequent, because it throws in some extra .o # files that make .init and .fini sections work. _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h $soname -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; sysv4) case $host_vendor in sni) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=yes # is this really true??? ;; siemens) ## LD is ld it makes a PLAMLIB ## CC just makes a GrossModule. _LT_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs' _LT_TAGVAR(hardcode_direct, $1)=no ;; motorola) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie ;; esac runpath_var='LD_RUN_PATH' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; sysv4.3*) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport' ;; sysv4*MP*) if test -d /usr/nec; then _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no runpath_var=LD_RUN_PATH hardcode_runpath_var=yes _LT_TAGVAR(ld_shlibs, $1)=yes fi ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no runpath_var='LD_RUN_PATH' if test yes = "$GCC"; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; sysv5* | sco3.2v5* | sco5v6*) # Note: We CANNOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' _LT_TAGVAR(allow_undefined_flag, $1)='$wl-z,nodefs' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R,$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Bexport' runpath_var='LD_RUN_PATH' if test yes = "$GCC"; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; uts4*) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) _LT_TAGVAR(ld_shlibs, $1)=no ;; esac if test sni = "$host_vendor"; then case $host in sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Blargedynsym' ;; esac fi fi ]) AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) test no = "$_LT_TAGVAR(ld_shlibs, $1)" && can_build_shared=no _LT_TAGVAR(with_gnu_ld, $1)=$with_gnu_ld _LT_DECL([], [libext], [0], [Old archive suffix (normally "a")])dnl _LT_DECL([], [shrext_cmds], [1], [Shared library suffix (normally ".so")])dnl _LT_DECL([], [extract_expsyms_cmds], [2], [The commands to extract the exported symbol list from a shared archive]) # # Do we need to explicitly link libc? # case "x$_LT_TAGVAR(archive_cmds_need_lc, $1)" in x|xyes) # Assume -lc should be added _LT_TAGVAR(archive_cmds_need_lc, $1)=yes if test yes,yes = "$GCC,$enable_shared"; then case $_LT_TAGVAR(archive_cmds, $1) in *'~'*) # FIXME: we may have to deal with multi-command sequences. ;; '$CC '*) # Test whether the compiler implicitly links with -lc since on some # systems, -lgcc has to come before -lc. If gcc already passes -lc # to ld, don't add -lc before -lgcc. AC_CACHE_CHECK([whether -lc should be explicitly linked in], [lt_cv_]_LT_TAGVAR(archive_cmds_need_lc, $1), [$RM conftest* echo "$lt_simple_compile_test_code" > conftest.$ac_ext if AC_TRY_EVAL(ac_compile) 2>conftest.err; then soname=conftest lib=conftest libobjs=conftest.$ac_objext deplibs= wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) pic_flag=$_LT_TAGVAR(lt_prog_compiler_pic, $1) compiler_flags=-v linker_flags=-v verstring= output_objdir=. libname=conftest lt_save_allow_undefined_flag=$_LT_TAGVAR(allow_undefined_flag, $1) _LT_TAGVAR(allow_undefined_flag, $1)= if AC_TRY_EVAL(_LT_TAGVAR(archive_cmds, $1) 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) then lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=no else lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=yes fi _LT_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag else cat conftest.err 1>&5 fi $RM conftest* ]) _LT_TAGVAR(archive_cmds_need_lc, $1)=$lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1) ;; esac fi ;; esac _LT_TAGDECL([build_libtool_need_lc], [archive_cmds_need_lc], [0], [Whether or not to add -lc for building shared libraries]) _LT_TAGDECL([allow_libtool_libs_with_static_runtimes], [enable_shared_with_static_runtimes], [0], [Whether or not to disallow shared libs when runtime libs are static]) _LT_TAGDECL([], [export_dynamic_flag_spec], [1], [Compiler flag to allow reflexive dlopens]) _LT_TAGDECL([], [whole_archive_flag_spec], [1], [Compiler flag to generate shared objects directly from archives]) _LT_TAGDECL([], [compiler_needs_object], [1], [Whether the compiler copes with passing no objects directly]) _LT_TAGDECL([], [old_archive_from_new_cmds], [2], [Create an old-style archive from a shared archive]) _LT_TAGDECL([], [old_archive_from_expsyms_cmds], [2], [Create a temporary old-style archive to link instead of a shared archive]) _LT_TAGDECL([], [archive_cmds], [2], [Commands used to build a shared archive]) _LT_TAGDECL([], [archive_expsym_cmds], [2]) _LT_TAGDECL([], [module_cmds], [2], [Commands used to build a loadable module if different from building a shared archive.]) _LT_TAGDECL([], [module_expsym_cmds], [2]) _LT_TAGDECL([], [with_gnu_ld], [1], [Whether we are building with GNU ld or not]) _LT_TAGDECL([], [allow_undefined_flag], [1], [Flag that allows shared libraries with undefined symbols to be built]) _LT_TAGDECL([], [no_undefined_flag], [1], [Flag that enforces no undefined symbols]) _LT_TAGDECL([], [hardcode_libdir_flag_spec], [1], [Flag to hardcode $libdir into a binary during linking. This must work even if $libdir does not exist]) _LT_TAGDECL([], [hardcode_libdir_separator], [1], [Whether we need a single "-rpath" flag with a separated argument]) _LT_TAGDECL([], [hardcode_direct], [0], [Set to "yes" if using DIR/libNAME$shared_ext during linking hardcodes DIR into the resulting binary]) _LT_TAGDECL([], [hardcode_direct_absolute], [0], [Set to "yes" if using DIR/libNAME$shared_ext during linking hardcodes DIR into the resulting binary and the resulting library dependency is "absolute", i.e impossible to change by setting $shlibpath_var if the library is relocated]) _LT_TAGDECL([], [hardcode_minus_L], [0], [Set to "yes" if using the -LDIR flag during linking hardcodes DIR into the resulting binary]) _LT_TAGDECL([], [hardcode_shlibpath_var], [0], [Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into the resulting binary]) _LT_TAGDECL([], [hardcode_automatic], [0], [Set to "yes" if building a shared library automatically hardcodes DIR into the library and all subsequent libraries and executables linked against it]) _LT_TAGDECL([], [inherit_rpath], [0], [Set to yes if linker adds runtime paths of dependent libraries to runtime path list]) _LT_TAGDECL([], [link_all_deplibs], [0], [Whether libtool must link a program against all its dependency libraries]) _LT_TAGDECL([], [always_export_symbols], [0], [Set to "yes" if exported symbols are required]) _LT_TAGDECL([], [export_symbols_cmds], [2], [The commands to list exported symbols]) _LT_TAGDECL([], [exclude_expsyms], [1], [Symbols that should not be listed in the preloaded symbols]) _LT_TAGDECL([], [include_expsyms], [1], [Symbols that must always be exported]) _LT_TAGDECL([], [prelink_cmds], [2], [Commands necessary for linking programs (against libraries) with templates]) _LT_TAGDECL([], [postlink_cmds], [2], [Commands necessary for finishing linking programs]) _LT_TAGDECL([], [file_list_spec], [1], [Specify filename containing input files]) dnl FIXME: Not yet implemented dnl _LT_TAGDECL([], [thread_safe_flag_spec], [1], dnl [Compiler flag to generate thread safe objects]) ])# _LT_LINKER_SHLIBS # _LT_LANG_C_CONFIG([TAG]) # ------------------------ # Ensure that the configuration variables for a C compiler are suitably # defined. These variables are subsequently used by _LT_CONFIG to write # the compiler configuration to 'libtool'. m4_defun([_LT_LANG_C_CONFIG], [m4_require([_LT_DECL_EGREP])dnl lt_save_CC=$CC AC_LANG_PUSH(C) # Source file extension for C test sources. ac_ext=c # Object file extension for compiled C test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;" # Code to be used in simple link tests lt_simple_link_test_code='int main(){return(0);}' _LT_TAG_COMPILER # Save the default compiler, since it gets overwritten when the other # tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP. compiler_DEFAULT=$CC # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... if test -n "$compiler"; then _LT_COMPILER_NO_RTTI($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) LT_SYS_DLOPEN_SELF _LT_CMD_STRIPLIB # Report what library types will actually be built AC_MSG_CHECKING([if libtool supports shared libraries]) AC_MSG_RESULT([$can_build_shared]) AC_MSG_CHECKING([whether to build shared libraries]) test no = "$can_build_shared" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test yes = "$enable_shared" && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[[4-9]]*) if test ia64 != "$host_cpu"; then case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in yes,aix,yes) ;; # shared object as lib.so file only yes,svr4,*) ;; # shared object as lib.so archive member only yes,*) enable_static=no ;; # shared object in lib.a archive as well esac fi ;; esac AC_MSG_RESULT([$enable_shared]) AC_MSG_CHECKING([whether to build static libraries]) # Make sure either enable_shared or enable_static is yes. test yes = "$enable_shared" || enable_static=yes AC_MSG_RESULT([$enable_static]) _LT_CONFIG($1) fi AC_LANG_POP CC=$lt_save_CC ])# _LT_LANG_C_CONFIG # _LT_LANG_CXX_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for a C++ compiler are suitably # defined. These variables are subsequently used by _LT_CONFIG to write # the compiler configuration to 'libtool'. m4_defun([_LT_LANG_CXX_CONFIG], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_PATH_MANIFEST_TOOL])dnl if test -n "$CXX" && ( test no != "$CXX" && ( (test g++ = "$CXX" && `g++ -v >/dev/null 2>&1` ) || (test g++ != "$CXX"))); then AC_PROG_CXXCPP else _lt_caught_CXX_error=yes fi AC_LANG_PUSH(C++) _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(compiler_needs_object, $1)=no _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds _LT_TAGVAR(no_undefined_flag, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no # Source file extension for C++ test sources. ac_ext=cpp # Object file extension for compiled C++ test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # No sense in running all these tests if we already determined that # the CXX compiler isn't working. Some variables (like enable_shared) # are currently assumed to apply to all compilers on this platform, # and will be corrupted by setting them based on a non-working compiler. if test yes != "$_lt_caught_CXX_error"; then # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;" # Code to be used in simple link tests lt_simple_link_test_code='int main(int, char *[[]]) { return(0); }' # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_CFLAGS=$CFLAGS lt_save_LD=$LD lt_save_GCC=$GCC GCC=$GXX lt_save_with_gnu_ld=$with_gnu_ld lt_save_path_LD=$lt_cv_path_LD if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx else $as_unset lt_cv_prog_gnu_ld fi if test -n "${lt_cv_path_LDCXX+set}"; then lt_cv_path_LD=$lt_cv_path_LDCXX else $as_unset lt_cv_path_LD fi test -z "${LDCXX+set}" || LD=$LDCXX CC=${CXX-"c++"} CFLAGS=$CXXFLAGS compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) if test -n "$compiler"; then # We don't want -fno-exception when compiling C++ code, so set the # no_builtin_flag separately if test yes = "$GXX"; then _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' else _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= fi if test yes = "$GXX"; then # Set up default GNU C++ configuration LT_PATH_LD # Check if GNU C++ uses GNU ld as the underlying linker, since the # archiving commands below assume that GNU ld is being used. if test yes = "$with_gnu_ld"; then _LT_TAGVAR(archive_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' # If archive_cmds runs LD, not CC, wlarc should be empty # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to # investigate it a little bit more. (MM) wlarc='$wl' # ancient GNU ld didn't support --whole-archive et. al. if eval "`$CC -print-prog-name=ld` --help 2>&1" | $GREP 'no-whole-archive' > /dev/null; then _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' else _LT_TAGVAR(whole_archive_flag_spec, $1)= fi else with_gnu_ld=no wlarc= # A generic and very simple default shared library creation # command for GNU C++ for the case where it uses the native # linker, instead of GNU ld. If possible, this setting should # overridden to take advantage of the native linker features on # the platform it is being used on. _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' fi # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP " \-L"' else GXX=no with_gnu_ld=no wlarc= fi # PORTME: fill in a description of your system's C++ link characteristics AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) _LT_TAGVAR(ld_shlibs, $1)=yes case $host_os in aix3*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; aix[[4-9]]*) if test ia64 = "$host_cpu"; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag= else aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # have runtime linking enabled, and use it for executables. # For shared libraries, we enable/disable runtime linking # depending on the kind of the shared library created - # when "with_aix_soname,aix_use_runtimelinking" is: # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables # "aix,yes" lib.so shared, rtl:yes, for executables # lib.a static archive # "both,no" lib.so.V(shr.o) shared, rtl:yes # lib.a(lib.so.V) shared, rtl:no, for executables # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables # lib.a(lib.so.V) shared, rtl:no # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables # lib.a static archive case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) for ld_flag in $LDFLAGS; do case $ld_flag in *-brtl*) aix_use_runtimelinking=yes break ;; esac done if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then # With aix-soname=svr4, we create the lib.so.V shared archives only, # so we don't have lib.a shared libs to link our executables. # We have to force runtime linking in this case. aix_use_runtimelinking=yes LDFLAGS="$LDFLAGS -Wl,-brtl" fi ;; esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. _LT_TAGVAR(archive_cmds, $1)='' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(file_list_spec, $1)='$wl-f,' case $with_aix_soname,$aix_use_runtimelinking in aix,*) ;; # no import file svr4,* | *,yes) # use import file # The Import File defines what to hardcode. _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no ;; esac if test yes = "$GXX"; then case $host_os in aix4.[[012]]|aix4.[[012]].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`$CC -print-prog-name=collect2` if test -f "$collect2name" && strings "$collect2name" | $GREP resolve_lib_name >/dev/null then # We have reworked collect2 : else # We have old collect2 _LT_TAGVAR(hardcode_direct, $1)=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)= fi esac shared_flag='-shared' if test yes = "$aix_use_runtimelinking"; then shared_flag=$shared_flag' $wl-G' fi # Need to ensure runtime linking is disabled for the traditional # shared library, or the linker may eventually find shared libraries # /with/ Import File - we do not want to mix them. shared_flag_aix='-shared' shared_flag_svr4='-shared $wl-G' else # not using gcc if test ia64 = "$host_cpu"; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test yes = "$aix_use_runtimelinking"; then shared_flag='$wl-G' else shared_flag='$wl-bM:SRE' fi shared_flag_aix='$wl-bM:SRE' shared_flag_svr4='$wl-G' fi fi _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-bexpall' # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to # export. _LT_TAGVAR(always_export_symbols, $1)=yes if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. # The "-G" linker flag allows undefined symbols. _LT_TAGVAR(no_undefined_flag, $1)='-bernotok' # Determine the default libpath from the value encoded in an empty # executable. _LT_SYS_MODULE_PATH_AIX([$1]) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag else if test ia64 = "$host_cpu"; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $libdir:/usr/lib:/lib' _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an # empty executable. _LT_SYS_MODULE_PATH_AIX([$1]) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. _LT_TAGVAR(no_undefined_flag, $1)=' $wl-bernotok' _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-berok' if test yes = "$with_gnu_ld"; then # We only use this code for GNU lds that support --whole-archive. _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive' else # Exported symbols can be pulled into shared objects from archives _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' fi _LT_TAGVAR(archive_cmds_need_lc, $1)=yes _LT_TAGVAR(archive_expsym_cmds, $1)='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' # -brtl affects multiple linker settings, -berok does not and is overridden later compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([[, ]]\\)%-berok\\1%g"`' if test svr4 != "$with_aix_soname"; then # This is similar to how AIX traditionally builds its shared # libraries. Need -bnortl late, we may have -brtl in LDFLAGS. _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' fi if test aix != "$with_aix_soname"; then _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' else # used by -dlpreopen to get the symbols _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$MV $output_objdir/$realname.d/$soname $output_objdir' fi _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$RM -r $output_objdir/$realname.d' fi fi ;; beos*) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(allow_undefined_flag, $1)=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; chorus*) case $cc_basename in *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; cygwin* | mingw* | pw32* | cegcc*) case $GXX,$cc_basename in ,cl* | no,cl*) # Native MSVC # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=yes _LT_TAGVAR(file_list_spec, $1)='@' # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=.dll # FIXME: Setting linknames here is a bad hack. _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then cp "$export_symbols" "$output_objdir/$soname.def"; echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; else $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp; fi~ $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ linknames=' # The linker will not automatically build a static lib if we build a DLL. # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes # Don't use ranlib _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~ lt_tool_outputfile="@TOOL_OUTPUT@"~ case $lt_outputfile in *.exe|*.EXE) ;; *) lt_outputfile=$lt_outputfile.exe lt_tool_outputfile=$lt_tool_outputfile.exe ;; esac~ func_to_tool_file "$lt_outputfile"~ if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; $RM "$lt_outputfile.manifest"; fi' ;; *) # g++ # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, # as there is no search path for DLLs. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-all-symbols' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' # If the export-symbols file already is a .def file, use it as # is; otherwise, prepend EXPORTS... _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; darwin* | rhapsody*) _LT_DARWIN_LINKER_FEATURES($1) ;; os2*) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(allow_undefined_flag, $1)=unsupported shrext_cmds=.dll _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ prefix_cmds="$SED"~ if test EXPORTS = "`$SED 1q $export_symbols`"; then prefix_cmds="$prefix_cmds -e 1d"; fi~ prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes ;; dgux*) case $cc_basename in ec++*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; ghcx*) # Green Hills C++ Compiler # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; freebsd2.*) # C++ shared libraries reported to be fairly broken before # switch to ELF _LT_TAGVAR(ld_shlibs, $1)=no ;; freebsd-elf*) _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;; freebsd* | dragonfly*) # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF # conventions _LT_TAGVAR(ld_shlibs, $1)=yes ;; haiku*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(link_all_deplibs, $1)=yes ;; hpux9*) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, # but as the default # location of the library. case $cc_basename in CC*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; aCC*) _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -b $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP " \-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test yes = "$GXX"; then _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -nostdlib $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' else # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; hpux10*|hpux11*) if test no = "$with_gnu_ld"; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: case $host_cpu in hppa*64*|ia64*) ;; *) _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' ;; esac fi case $host_cpu in hppa*64*|ia64*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, # but as the default # location of the library. ;; esac case $cc_basename in CC*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; aCC*) case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; esac # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP " \-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test yes = "$GXX"; then if test no = "$with_gnu_ld"; then case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; esac fi else # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; interix[[3-9]]*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; irix5* | irix6*) case $cc_basename in CC*) # SGI C++ _LT_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' # Archives containing C++ object files must be created using # "CC -ar", where "CC" is the IRIX C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs' ;; *) if test yes = "$GXX"; then if test no = "$with_gnu_ld"; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' else _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` -o $lib' fi fi _LT_TAGVAR(link_all_deplibs, $1)=yes ;; esac _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(inherit_rpath, $1)=yes ;; linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) case $cc_basename in KCC*) # Kuck and Associates, Inc. (KAI) C++ Compiler # KCC will only create a shared library if the output file # ends with ".so" (or ".sl" for HP-UX), so rename the library # to its proper name (with version) after linking. _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib $wl-retain-symbols-file,$export_symbols; mv \$templib $lib' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' # Archives containing C++ object files must be created using # "CC -Bstatic", where "CC" is the KAI C++ compiler. _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;; icpc* | ecpc* ) # Intel C++ with_gnu_ld=yes # version 8.0 and above of icpc choke on multiply defined symbols # if we add $predep_objects and $postdep_objects, however 7.1 and # earlier do not add the objects themselves. case `$CC -V 2>&1` in *"Version 7."*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' ;; *) # Version 8.0 or newer tmp_idyn= case $host_cpu in ia64*) tmp_idyn=' -i_dynamic';; esac _LT_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' ;; esac _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive' ;; pgCC* | pgcpp*) # Portland Group C++ compiler case `$CC -V` in *pgCC\ [[1-5]].* | *pgcpp\ [[1-5]].*) _LT_TAGVAR(prelink_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~ compile_command="$compile_command `find $tpldir -name \*.o | sort | $NL2SP`"' _LT_TAGVAR(old_archive_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~ $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | sort | $NL2SP`~ $RANLIB $oldlib' _LT_TAGVAR(archive_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' ;; *) # Version 6 and above use weak symbols _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' ;; esac _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl--rpath $wl$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' ;; cxx*) # Compaq C++ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib $wl-retain-symbols-file $wl$export_symbols' runpath_var=LD_RUN_PATH _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "X$list" | $Xsed' ;; xl* | mpixl* | bgxl*) # IBM XL 8.0 on PPC, with GNU ld _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' _LT_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' if test yes = "$supports_anon_versioning"; then _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' fi ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C++ 5.9 _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file $wl$export_symbols' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' _LT_TAGVAR(compiler_needs_object, $1)=yes # Not sure whether something based on # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 # would be better. output_verbose_link_cmd='func_echo_all' # Archives containing C++ object files must be created using # "CC -xar", where "CC" is the Sun C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' ;; esac ;; esac ;; lynxos*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; m88k*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; mvs*) case $cc_basename in cxx*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' wlarc= _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no fi # Workaround some broken pre-1.5 toolchains output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' ;; *nto* | *qnx*) _LT_TAGVAR(ld_shlibs, $1)=yes ;; openbsd* | bitrig*) if test -f /usr/libexec/ld.so; then _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`"; then _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file,$export_symbols -o $lib' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' fi output_verbose_link_cmd=func_echo_all else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; osf3* | osf4* | osf5*) case $cc_basename in KCC*) # Kuck and Associates, Inc. (KAI) C++ Compiler # KCC will only create a shared library if the output file # ends with ".so" (or ".sl" for HP-UX), so rename the library # to its proper name (with version) after linking. _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Archives containing C++ object files must be created using # the KAI C++ compiler. case $host in osf3*) _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;; *) _LT_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs' ;; esac ;; RCC*) # Rational C++ 2.4.1 # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; cxx*) case $host in osf3*) _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $soname `test -n "$verstring" && func_echo_all "$wl-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' ;; *) _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ echo "-hidden">> $lib.exp~ $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname $wl-input $wl$lib.exp `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~ $RM $lib.exp' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' ;; esac _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test yes,no = "$GXX,$with_gnu_ld"; then _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' case $host in osf3*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' ;; esac _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP " \-L"' else # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; psos*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; sunos4*) case $cc_basename in CC*) # Sun C++ 4.x # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; lcc*) # Lucid # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; solaris*) case $cc_basename in CC* | sunCC*) # Sun C++ 4.2, 5.x and Centerline C++ _LT_TAGVAR(archive_cmds_need_lc,$1)=yes _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G$allow_undefined_flag $wl-M $wl$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no case $host_os in solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; *) # The compiler driver will combine and reorder linker options, # but understands '-z linker_flag'. # Supported since Solaris 2.6 (maybe 2.5.1?) _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' ;; esac _LT_TAGVAR(link_all_deplibs, $1)=yes output_verbose_link_cmd='func_echo_all' # Archives containing C++ object files must be created using # "CC -xar", where "CC" is the Sun C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' ;; gcx*) # Green Hills C++ Compiler _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' # The C++ compiler must be used to create the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs' ;; *) # GNU C++ compiler with Solaris linker if test yes,no = "$GXX,$with_gnu_ld"; then _LT_TAGVAR(no_undefined_flag, $1)=' $wl-z ${wl}defs' if $CC --version | $GREP -v '^2\.7' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -shared $pic_flag -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP " \-L"' else # g++ 2.7 appears to require '-G' NOT '-shared' on this # platform. _LT_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP " \-L"' fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $wl$libdir' case $host_os in solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; *) _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' ;; esac fi ;; esac ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no runpath_var='LD_RUN_PATH' case $cc_basename in CC*) _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; sysv5* | sco3.2v5* | sco5v6*) # Note: We CANNOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' _LT_TAGVAR(allow_undefined_flag, $1)='$wl-z,nodefs' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R,$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Bexport' runpath_var='LD_RUN_PATH' case $cc_basename in CC*) _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(old_archive_cmds, $1)='$CC -Tprelink_objects $oldobjs~ '"$_LT_TAGVAR(old_archive_cmds, $1)" _LT_TAGVAR(reload_cmds, $1)='$CC -Tprelink_objects $reload_objs~ '"$_LT_TAGVAR(reload_cmds, $1)" ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; tandem*) case $cc_basename in NCC*) # NonStop-UX NCC 3.20 # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; vxworks*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) test no = "$_LT_TAGVAR(ld_shlibs, $1)" && can_build_shared=no _LT_TAGVAR(GCC, $1)=$GXX _LT_TAGVAR(LD, $1)=$LD ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... _LT_SYS_HIDDEN_LIBDEPS($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi # test -n "$compiler" CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS LDCXX=$LD LD=$lt_save_LD GCC=$lt_save_GCC with_gnu_ld=$lt_save_with_gnu_ld lt_cv_path_LDCXX=$lt_cv_path_LD lt_cv_path_LD=$lt_save_path_LD lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld fi # test yes != "$_lt_caught_CXX_error" AC_LANG_POP ])# _LT_LANG_CXX_CONFIG # _LT_FUNC_STRIPNAME_CNF # ---------------------- # func_stripname_cnf prefix suffix name # strip PREFIX and SUFFIX off of NAME. # PREFIX and SUFFIX must not contain globbing or regex special # characters, hashes, percent signs, but SUFFIX may contain a leading # dot (in which case that matches only a dot). # # This function is identical to the (non-XSI) version of func_stripname, # except this one can be used by m4 code that may be executed by configure, # rather than the libtool script. m4_defun([_LT_FUNC_STRIPNAME_CNF],[dnl AC_REQUIRE([_LT_DECL_SED]) AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH]) func_stripname_cnf () { case @S|@2 in .*) func_stripname_result=`$ECHO "@S|@3" | $SED "s%^@S|@1%%; s%\\\\@S|@2\$%%"`;; *) func_stripname_result=`$ECHO "@S|@3" | $SED "s%^@S|@1%%; s%@S|@2\$%%"`;; esac } # func_stripname_cnf ])# _LT_FUNC_STRIPNAME_CNF # _LT_SYS_HIDDEN_LIBDEPS([TAGNAME]) # --------------------------------- # Figure out "hidden" library dependencies from verbose # compiler output when linking a shared library. # Parse the compiler output and extract the necessary # objects, libraries and library flags. m4_defun([_LT_SYS_HIDDEN_LIBDEPS], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl AC_REQUIRE([_LT_FUNC_STRIPNAME_CNF])dnl # Dependencies to place before and after the object being linked: _LT_TAGVAR(predep_objects, $1)= _LT_TAGVAR(postdep_objects, $1)= _LT_TAGVAR(predeps, $1)= _LT_TAGVAR(postdeps, $1)= _LT_TAGVAR(compiler_lib_search_path, $1)= dnl we can't use the lt_simple_compile_test_code here, dnl because it contains code intended for an executable, dnl not a library. It's possible we should let each dnl tag define a new lt_????_link_test_code variable, dnl but it's only used here... m4_if([$1], [], [cat > conftest.$ac_ext <<_LT_EOF int a; void foo (void) { a = 0; } _LT_EOF ], [$1], [CXX], [cat > conftest.$ac_ext <<_LT_EOF class Foo { public: Foo (void) { a = 0; } private: int a; }; _LT_EOF ], [$1], [F77], [cat > conftest.$ac_ext <<_LT_EOF subroutine foo implicit none integer*4 a a=0 return end _LT_EOF ], [$1], [FC], [cat > conftest.$ac_ext <<_LT_EOF subroutine foo implicit none integer a a=0 return end _LT_EOF ], [$1], [GCJ], [cat > conftest.$ac_ext <<_LT_EOF public class foo { private int a; public void bar (void) { a = 0; } }; _LT_EOF ], [$1], [GO], [cat > conftest.$ac_ext <<_LT_EOF package foo func foo() { } _LT_EOF ]) _lt_libdeps_save_CFLAGS=$CFLAGS case "$CC $CFLAGS " in #( *\ -flto*\ *) CFLAGS="$CFLAGS -fno-lto" ;; *\ -fwhopr*\ *) CFLAGS="$CFLAGS -fno-whopr" ;; *\ -fuse-linker-plugin*\ *) CFLAGS="$CFLAGS -fno-use-linker-plugin" ;; esac dnl Parse the compiler output and extract the necessary dnl objects, libraries and library flags. if AC_TRY_EVAL(ac_compile); then # Parse the compiler output and extract the necessary # objects, libraries and library flags. # Sentinel used to keep track of whether or not we are before # the conftest object file. pre_test_object_deps_done=no for p in `eval "$output_verbose_link_cmd"`; do case $prev$p in -L* | -R* | -l*) # Some compilers place space between "-{L,R}" and the path. # Remove the space. if test x-L = "$p" || test x-R = "$p"; then prev=$p continue fi # Expand the sysroot to ease extracting the directories later. if test -z "$prev"; then case $p in -L*) func_stripname_cnf '-L' '' "$p"; prev=-L; p=$func_stripname_result ;; -R*) func_stripname_cnf '-R' '' "$p"; prev=-R; p=$func_stripname_result ;; -l*) func_stripname_cnf '-l' '' "$p"; prev=-l; p=$func_stripname_result ;; esac fi case $p in =*) func_stripname_cnf '=' '' "$p"; p=$lt_sysroot$func_stripname_result ;; esac if test no = "$pre_test_object_deps_done"; then case $prev in -L | -R) # Internal compiler library paths should come after those # provided the user. The postdeps already come after the # user supplied libs so there is no need to process them. if test -z "$_LT_TAGVAR(compiler_lib_search_path, $1)"; then _LT_TAGVAR(compiler_lib_search_path, $1)=$prev$p else _LT_TAGVAR(compiler_lib_search_path, $1)="${_LT_TAGVAR(compiler_lib_search_path, $1)} $prev$p" fi ;; # The "-l" case would never come before the object being # linked, so don't bother handling this case. esac else if test -z "$_LT_TAGVAR(postdeps, $1)"; then _LT_TAGVAR(postdeps, $1)=$prev$p else _LT_TAGVAR(postdeps, $1)="${_LT_TAGVAR(postdeps, $1)} $prev$p" fi fi prev= ;; *.lto.$objext) ;; # Ignore GCC LTO objects *.$objext) # This assumes that the test object file only shows up # once in the compiler output. if test "$p" = "conftest.$objext"; then pre_test_object_deps_done=yes continue fi if test no = "$pre_test_object_deps_done"; then if test -z "$_LT_TAGVAR(predep_objects, $1)"; then _LT_TAGVAR(predep_objects, $1)=$p else _LT_TAGVAR(predep_objects, $1)="$_LT_TAGVAR(predep_objects, $1) $p" fi else if test -z "$_LT_TAGVAR(postdep_objects, $1)"; then _LT_TAGVAR(postdep_objects, $1)=$p else _LT_TAGVAR(postdep_objects, $1)="$_LT_TAGVAR(postdep_objects, $1) $p" fi fi ;; *) ;; # Ignore the rest. esac done # Clean up. rm -f a.out a.exe else echo "libtool.m4: error: problem compiling $1 test program" fi $RM -f confest.$objext CFLAGS=$_lt_libdeps_save_CFLAGS # PORTME: override above test on systems where it is broken m4_if([$1], [CXX], [case $host_os in interix[[3-9]]*) # Interix 3.5 installs completely hosed .la files for C++, so rather than # hack all around it, let's just trust "g++" to DTRT. _LT_TAGVAR(predep_objects,$1)= _LT_TAGVAR(postdep_objects,$1)= _LT_TAGVAR(postdeps,$1)= ;; esac ]) case " $_LT_TAGVAR(postdeps, $1) " in *" -lc "*) _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;; esac _LT_TAGVAR(compiler_lib_search_dirs, $1)= if test -n "${_LT_TAGVAR(compiler_lib_search_path, $1)}"; then _LT_TAGVAR(compiler_lib_search_dirs, $1)=`echo " ${_LT_TAGVAR(compiler_lib_search_path, $1)}" | $SED -e 's! -L! !g' -e 's!^ !!'` fi _LT_TAGDECL([], [compiler_lib_search_dirs], [1], [The directories searched by this compiler when creating a shared library]) _LT_TAGDECL([], [predep_objects], [1], [Dependencies to place before and after the objects being linked to create a shared library]) _LT_TAGDECL([], [postdep_objects], [1]) _LT_TAGDECL([], [predeps], [1]) _LT_TAGDECL([], [postdeps], [1]) _LT_TAGDECL([], [compiler_lib_search_path], [1], [The library search path used internally by the compiler when linking a shared library]) ])# _LT_SYS_HIDDEN_LIBDEPS # _LT_LANG_F77_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for a Fortran 77 compiler are # suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to 'libtool'. m4_defun([_LT_LANG_F77_CONFIG], [AC_LANG_PUSH(Fortran 77) if test -z "$F77" || test no = "$F77"; then _lt_disable_F77=yes fi _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds _LT_TAGVAR(no_undefined_flag, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no # Source file extension for f77 test sources. ac_ext=f # Object file extension for compiled f77 test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # No sense in running all these tests if we already determined that # the F77 compiler isn't working. Some variables (like enable_shared) # are currently assumed to apply to all compilers on this platform, # and will be corrupted by setting them based on a non-working compiler. if test yes != "$_lt_disable_F77"; then # Code to be used in simple compile tests lt_simple_compile_test_code="\ subroutine t return end " # Code to be used in simple link tests lt_simple_link_test_code="\ program t end " # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_GCC=$GCC lt_save_CFLAGS=$CFLAGS CC=${F77-"f77"} CFLAGS=$FFLAGS compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) GCC=$G77 if test -n "$compiler"; then AC_MSG_CHECKING([if libtool supports shared libraries]) AC_MSG_RESULT([$can_build_shared]) AC_MSG_CHECKING([whether to build shared libraries]) test no = "$can_build_shared" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test yes = "$enable_shared" && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[[4-9]]*) if test ia64 != "$host_cpu"; then case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in yes,aix,yes) ;; # shared object as lib.so file only yes,svr4,*) ;; # shared object as lib.so archive member only yes,*) enable_static=no ;; # shared object in lib.a archive as well esac fi ;; esac AC_MSG_RESULT([$enable_shared]) AC_MSG_CHECKING([whether to build static libraries]) # Make sure either enable_shared or enable_static is yes. test yes = "$enable_shared" || enable_static=yes AC_MSG_RESULT([$enable_static]) _LT_TAGVAR(GCC, $1)=$G77 _LT_TAGVAR(LD, $1)=$LD ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi # test -n "$compiler" GCC=$lt_save_GCC CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS fi # test yes != "$_lt_disable_F77" AC_LANG_POP ])# _LT_LANG_F77_CONFIG # _LT_LANG_FC_CONFIG([TAG]) # ------------------------- # Ensure that the configuration variables for a Fortran compiler are # suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to 'libtool'. m4_defun([_LT_LANG_FC_CONFIG], [AC_LANG_PUSH(Fortran) if test -z "$FC" || test no = "$FC"; then _lt_disable_FC=yes fi _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds _LT_TAGVAR(no_undefined_flag, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no # Source file extension for fc test sources. ac_ext=${ac_fc_srcext-f} # Object file extension for compiled fc test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # No sense in running all these tests if we already determined that # the FC compiler isn't working. Some variables (like enable_shared) # are currently assumed to apply to all compilers on this platform, # and will be corrupted by setting them based on a non-working compiler. if test yes != "$_lt_disable_FC"; then # Code to be used in simple compile tests lt_simple_compile_test_code="\ subroutine t return end " # Code to be used in simple link tests lt_simple_link_test_code="\ program t end " # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_GCC=$GCC lt_save_CFLAGS=$CFLAGS CC=${FC-"f95"} CFLAGS=$FCFLAGS compiler=$CC GCC=$ac_cv_fc_compiler_gnu _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) if test -n "$compiler"; then AC_MSG_CHECKING([if libtool supports shared libraries]) AC_MSG_RESULT([$can_build_shared]) AC_MSG_CHECKING([whether to build shared libraries]) test no = "$can_build_shared" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test yes = "$enable_shared" && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[[4-9]]*) if test ia64 != "$host_cpu"; then case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in yes,aix,yes) ;; # shared object as lib.so file only yes,svr4,*) ;; # shared object as lib.so archive member only yes,*) enable_static=no ;; # shared object in lib.a archive as well esac fi ;; esac AC_MSG_RESULT([$enable_shared]) AC_MSG_CHECKING([whether to build static libraries]) # Make sure either enable_shared or enable_static is yes. test yes = "$enable_shared" || enable_static=yes AC_MSG_RESULT([$enable_static]) _LT_TAGVAR(GCC, $1)=$ac_cv_fc_compiler_gnu _LT_TAGVAR(LD, $1)=$LD ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... _LT_SYS_HIDDEN_LIBDEPS($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi # test -n "$compiler" GCC=$lt_save_GCC CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS fi # test yes != "$_lt_disable_FC" AC_LANG_POP ])# _LT_LANG_FC_CONFIG # _LT_LANG_GCJ_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for the GNU Java Compiler compiler # are suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to 'libtool'. m4_defun([_LT_LANG_GCJ_CONFIG], [AC_REQUIRE([LT_PROG_GCJ])dnl AC_LANG_SAVE # Source file extension for Java test sources. ac_ext=java # Object file extension for compiled Java test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="class foo {}" # Code to be used in simple link tests lt_simple_link_test_code='public class conftest { public static void main(String[[]] argv) {}; }' # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_CFLAGS=$CFLAGS lt_save_GCC=$GCC GCC=yes CC=${GCJ-"gcj"} CFLAGS=$GCJFLAGS compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_TAGVAR(LD, $1)=$LD _LT_CC_BASENAME([$compiler]) # GCJ did not exist at the time GCC didn't implicitly link libc in. _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... if test -n "$compiler"; then _LT_COMPILER_NO_RTTI($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi AC_LANG_RESTORE GCC=$lt_save_GCC CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS ])# _LT_LANG_GCJ_CONFIG # _LT_LANG_GO_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for the GNU Go compiler # are suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to 'libtool'. m4_defun([_LT_LANG_GO_CONFIG], [AC_REQUIRE([LT_PROG_GO])dnl AC_LANG_SAVE # Source file extension for Go test sources. ac_ext=go # Object file extension for compiled Go test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="package main; func main() { }" # Code to be used in simple link tests lt_simple_link_test_code='package main; func main() { }' # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_CFLAGS=$CFLAGS lt_save_GCC=$GCC GCC=yes CC=${GOC-"gccgo"} CFLAGS=$GOFLAGS compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_TAGVAR(LD, $1)=$LD _LT_CC_BASENAME([$compiler]) # Go did not exist at the time GCC didn't implicitly link libc in. _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... if test -n "$compiler"; then _LT_COMPILER_NO_RTTI($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi AC_LANG_RESTORE GCC=$lt_save_GCC CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS ])# _LT_LANG_GO_CONFIG # _LT_LANG_RC_CONFIG([TAG]) # ------------------------- # Ensure that the configuration variables for the Windows resource compiler # are suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to 'libtool'. m4_defun([_LT_LANG_RC_CONFIG], [AC_REQUIRE([LT_PROG_RC])dnl AC_LANG_SAVE # Source file extension for RC test sources. ac_ext=rc # Object file extension for compiled RC test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }' # Code to be used in simple link tests lt_simple_link_test_code=$lt_simple_compile_test_code # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_CFLAGS=$CFLAGS lt_save_GCC=$GCC GCC= CC=${RC-"windres"} CFLAGS= compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) _LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes if test -n "$compiler"; then : _LT_CONFIG($1) fi GCC=$lt_save_GCC AC_LANG_RESTORE CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS ])# _LT_LANG_RC_CONFIG # LT_PROG_GCJ # ----------- AC_DEFUN([LT_PROG_GCJ], [m4_ifdef([AC_PROG_GCJ], [AC_PROG_GCJ], [m4_ifdef([A][M_PROG_GCJ], [A][M_PROG_GCJ], [AC_CHECK_TOOL(GCJ, gcj,) test set = "${GCJFLAGS+set}" || GCJFLAGS="-g -O2" AC_SUBST(GCJFLAGS)])])[]dnl ]) # Old name: AU_ALIAS([LT_AC_PROG_GCJ], [LT_PROG_GCJ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([LT_AC_PROG_GCJ], []) # LT_PROG_GO # ---------- AC_DEFUN([LT_PROG_GO], [AC_CHECK_TOOL(GOC, gccgo,) ]) # LT_PROG_RC # ---------- AC_DEFUN([LT_PROG_RC], [AC_CHECK_TOOL(RC, windres,) ]) # Old name: AU_ALIAS([LT_AC_PROG_RC], [LT_PROG_RC]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([LT_AC_PROG_RC], []) # _LT_DECL_EGREP # -------------- # If we don't have a new enough Autoconf to choose the best grep # available, choose the one first in the user's PATH. m4_defun([_LT_DECL_EGREP], [AC_REQUIRE([AC_PROG_EGREP])dnl AC_REQUIRE([AC_PROG_FGREP])dnl test -z "$GREP" && GREP=grep _LT_DECL([], [GREP], [1], [A grep program that handles long lines]) _LT_DECL([], [EGREP], [1], [An ERE matcher]) _LT_DECL([], [FGREP], [1], [A literal string matcher]) dnl Non-bleeding-edge autoconf doesn't subst GREP, so do it here too AC_SUBST([GREP]) ]) # _LT_DECL_OBJDUMP # -------------- # If we don't have a new enough Autoconf to choose the best objdump # available, choose the one first in the user's PATH. m4_defun([_LT_DECL_OBJDUMP], [AC_CHECK_TOOL(OBJDUMP, objdump, false) test -z "$OBJDUMP" && OBJDUMP=objdump _LT_DECL([], [OBJDUMP], [1], [An object symbol dumper]) AC_SUBST([OBJDUMP]) ]) # _LT_DECL_DLLTOOL # ---------------- # Ensure DLLTOOL variable is set. m4_defun([_LT_DECL_DLLTOOL], [AC_CHECK_TOOL(DLLTOOL, dlltool, false) test -z "$DLLTOOL" && DLLTOOL=dlltool _LT_DECL([], [DLLTOOL], [1], [DLL creation program]) AC_SUBST([DLLTOOL]) ]) # _LT_DECL_SED # ------------ # Check for a fully-functional sed program, that truncates # as few characters as possible. Prefer GNU sed if found. m4_defun([_LT_DECL_SED], [AC_PROG_SED test -z "$SED" && SED=sed Xsed="$SED -e 1s/^X//" _LT_DECL([], [SED], [1], [A sed program that does not truncate output]) _LT_DECL([], [Xsed], ["\$SED -e 1s/^X//"], [Sed that helps us avoid accidentally triggering echo(1) options like -n]) ])# _LT_DECL_SED m4_ifndef([AC_PROG_SED], [ ############################################################ # NOTE: This macro has been submitted for inclusion into # # GNU Autoconf as AC_PROG_SED. When it is available in # # a released version of Autoconf we should remove this # # macro and use it instead. # ############################################################ m4_defun([AC_PROG_SED], [AC_MSG_CHECKING([for a sed that does not truncate output]) AC_CACHE_VAL(lt_cv_path_SED, [# Loop through the user's path and test for sed and gsed. # Then use that list of sed's as ones to test for truncation. as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for lt_ac_prog in sed gsed; do for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext" fi done done done IFS=$as_save_IFS lt_ac_max=0 lt_ac_count=0 # Add /usr/xpg4/bin/sed as it is typically found on Solaris # along with /bin/sed that truncates output. for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do test ! -f "$lt_ac_sed" && continue cat /dev/null > conftest.in lt_ac_count=0 echo $ECHO_N "0123456789$ECHO_C" >conftest.in # Check for GNU sed and select it if it is found. if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then lt_cv_path_SED=$lt_ac_sed break fi while true; do cat conftest.in conftest.in >conftest.tmp mv conftest.tmp conftest.in cp conftest.in conftest.nl echo >>conftest.nl $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break cmp -s conftest.out conftest.nl || break # 10000 chars as input seems more than enough test 10 -lt "$lt_ac_count" && break lt_ac_count=`expr $lt_ac_count + 1` if test "$lt_ac_count" -gt "$lt_ac_max"; then lt_ac_max=$lt_ac_count lt_cv_path_SED=$lt_ac_sed fi done done ]) SED=$lt_cv_path_SED AC_SUBST([SED]) AC_MSG_RESULT([$SED]) ])#AC_PROG_SED ])#m4_ifndef # Old name: AU_ALIAS([LT_AC_PROG_SED], [AC_PROG_SED]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([LT_AC_PROG_SED], []) # _LT_CHECK_SHELL_FEATURES # ------------------------ # Find out whether the shell is Bourne or XSI compatible, # or has some other useful features. m4_defun([_LT_CHECK_SHELL_FEATURES], [if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then lt_unset=unset else lt_unset=false fi _LT_DECL([], [lt_unset], [0], [whether the shell understands "unset"])dnl # test EBCDIC or ASCII case `echo X|tr X '\101'` in A) # ASCII based system # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr lt_SP2NL='tr \040 \012' lt_NL2SP='tr \015\012 \040\040' ;; *) # EBCDIC based system lt_SP2NL='tr \100 \n' lt_NL2SP='tr \r\n \100\100' ;; esac _LT_DECL([SP2NL], [lt_SP2NL], [1], [turn spaces into newlines])dnl _LT_DECL([NL2SP], [lt_NL2SP], [1], [turn newlines into spaces])dnl ])# _LT_CHECK_SHELL_FEATURES # _LT_PATH_CONVERSION_FUNCTIONS # ----------------------------- # Determine what file name conversion functions should be used by # func_to_host_file (and, implicitly, by func_to_host_path). These are needed # for certain cross-compile configurations and native mingw. m4_defun([_LT_PATH_CONVERSION_FUNCTIONS], [AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_CANONICAL_BUILD])dnl AC_MSG_CHECKING([how to convert $build file names to $host format]) AC_CACHE_VAL(lt_cv_to_host_file_cmd, [case $host in *-*-mingw* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32 ;; *-*-cygwin* ) lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32 ;; * ) # otherwise, assume *nix lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32 ;; esac ;; *-*-cygwin* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin ;; *-*-cygwin* ) lt_cv_to_host_file_cmd=func_convert_file_noop ;; * ) # otherwise, assume *nix lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin ;; esac ;; * ) # unhandled hosts (and "normal" native builds) lt_cv_to_host_file_cmd=func_convert_file_noop ;; esac ]) to_host_file_cmd=$lt_cv_to_host_file_cmd AC_MSG_RESULT([$lt_cv_to_host_file_cmd]) _LT_DECL([to_host_file_cmd], [lt_cv_to_host_file_cmd], [0], [convert $build file names to $host format])dnl AC_MSG_CHECKING([how to convert $build file names to toolchain format]) AC_CACHE_VAL(lt_cv_to_tool_file_cmd, [#assume ordinary cross tools, or native build. lt_cv_to_tool_file_cmd=func_convert_file_noop case $host in *-*-mingw* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32 ;; esac ;; esac ]) to_tool_file_cmd=$lt_cv_to_tool_file_cmd AC_MSG_RESULT([$lt_cv_to_tool_file_cmd]) _LT_DECL([to_tool_file_cmd], [lt_cv_to_tool_file_cmd], [0], [convert $build files to toolchain format])dnl ])# _LT_PATH_CONVERSION_FUNCTIONS inn-2.6.4/m4/modes.m40000644000175200017520000000465514002373703013623 0ustar iuliusiuliusdnl modes.m4 -- Setting file and installation modes. dnl $Id: modes.m4 10520 2021-01-17 21:48:06Z iulius $ dnl dnl INN defaults to a umask of 002 for historical reasons, but offers an dnl option to change them. It also has some programs that are occasionally dnl installed with special permissions in some situations but not in others dnl (and not by default). dnl Let the user specify a new umask and also set the directory and file dnl permissions at the same time. Also let the user request inews or rnews dnl be installed with special permissions. AC_DEFUN([INN_ARG_MODES], [NEWSUMASK=02 FILEMODE=0664 DIRMODE=0775 RUNDIRMODE=0770 AC_ARG_WITH([news-umask], [AS_HELP_STRING([--with-news-umask=UMASK], [umask for news files [002]])], with_news_umask=`AS_ECHO(["$with_news_umask"]) | sed 's/^0*//'` if test "x$with_news_umask" = x22 ; then NEWSUMASK=022 FILEMODE=0644 DIRMODE=0755 RUNDIRMODE=0750 else if test "x$with_news_umask" != x2 ; then AC_MSG_ERROR([Valid umasks are 002 or 022]) fi fi) AC_SUBST([NEWSUMASK]) AC_SUBST([FILEMODE]) AC_SUBST([DIRMODE]) AC_SUBST([RUNDIRMODE]) AC_DEFINE_UNQUOTED([ARTFILE_MODE], [$FILEMODE], [Mode that incoming articles are created with.]) AC_DEFINE_UNQUOTED([BATCHFILE_MODE], [$FILEMODE], [Mode that batch files are created with.]) AC_DEFINE_UNQUOTED([GROUPDIR_MODE], [$DIRMODE], [Mode that directories are created with.]) AC_DEFINE_UNQUOTED([NEWSUMASK], [$NEWSUMASK], [The umask used by all INN programs.]) dnl inews used to be installed setgid, but may not be secure. Only do this if dnl it's explicitly requested at configure time. INEWSMODE=0550 AC_ARG_ENABLE([setgid-inews], [AS_HELP_STRING([--enable-setgid-inews], [Install inews setgid])], if test "x$enableval" = xyes ; then INEWSMODE=02555 fi) AC_SUBST([INEWSMODE]) dnl rnews used to be installed setuid root so that it could be run by the uucp dnl user for incoming batches, but this isn't necessary unless you're using dnl UUCP (which most people aren't) and setuid news is all that's needed. dnl Only do even that if it's explicitly requested at configure time. RNEWSGRP=$RUNASGROUP RNEWSMODE=0500 AC_ARG_ENABLE([uucp-rnews], [AS_HELP_STRING([--enable-uucp-rnews], [Install rnews setuid, group uucp])], if test "x$enableval" = xyes ; then RNEWSGRP=uucp RNEWSMODE=04550 fi) AC_SUBST([RNEWSGRP]) AC_SUBST([RNEWSMODE])]) inn-2.6.4/m4/vamacros.m40000644000175200017520000000441414002373703014320 0ustar iuliusiuliusdnl Check for support for variadic macros. dnl $Id: vamacros.m4 10246 2018-02-16 21:12:42Z iulius $ dnl dnl This file defines two macros for probing for compiler support for variadic dnl macros. Provided are INN_C_C99_VAMACROS, which checks for support for the dnl C99 variadic macro syntax, namely: dnl dnl #define macro(...) fprintf(stderr, __VA_ARGS__) dnl dnl and INN_C_GNU_VAMACROS, which checks for support for the older GNU dnl variadic macro syntax, namely: dnl dnl #define macro(args...) fprintf(stderr, args) dnl dnl They set HAVE_C99_VAMACROS or HAVE_GNU_VAMACROS as appropriate. dnl dnl The canonical version of this file is maintained in the rra-c-util dnl package, available at . dnl dnl Written by Russ Allbery dnl Copyright 2006, 2008-2009 dnl The Board of Trustees of the Leland Stanford Junior University dnl dnl This file is free software; the authors give unlimited permission to copy dnl and/or distribute it, with or without modifications, as long as this dnl notice is preserved. dnl dnl SPDX-License-Identifier: FSFULLR AC_DEFUN([_INN_C_C99_VAMACROS_SOURCE], [[ #include #define error(...) fprintf(stderr, __VA_ARGS__) int main(void) { error("foo"); error("foo %d", 0); return 0; } ]]) AC_DEFUN([INN_C_C99_VAMACROS], [AC_CACHE_CHECK([for C99 variadic macros], [inn_cv_c_c99_vamacros], [AC_COMPILE_IFELSE([AC_LANG_SOURCE([_INN_C_C99_VAMACROS_SOURCE])], [inn_cv_c_c99_vamacros=yes], [inn_cv_c_c99_vamacros=no])]) AS_IF([test x"$inn_cv_c_c99_vamacros" = xyes], [AC_DEFINE([HAVE_C99_VAMACROS], 1, [Define if the compiler supports C99 variadic macros.])])]) AC_DEFUN([_INN_C_GNU_VAMACROS_SOURCE], [[ #include #define error(args...) fprintf(stderr, args) int main(void) { error("foo"); error("foo %d", 0); return 0; } ]]) AC_DEFUN([INN_C_GNU_VAMACROS], [AC_CACHE_CHECK([for GNU-style variadic macros], [inn_cv_c_gnu_vamacros], [AC_COMPILE_IFELSE([AC_LANG_SOURCE([_INN_C_GNU_VAMACROS_SOURCE])], [inn_cv_c_gnu_vamacros=yes], [inn_cv_c_gnu_vamacros=no])]) AS_IF([test x"$inn_cv_c_gnu_vamacros" = xyes], [AC_DEFINE([HAVE_GNU_VAMACROS], 1, [Define if the compiler supports GNU-style variadic macros.])])]) inn-2.6.4/m4/sendmail.m40000644000175200017520000000203014002373703014271 0ustar iuliusiuliusdnl sendmail.m4 -- Checks for the path to sendmail. dnl $Id: sendmail.m4 9749 2014-11-23 21:45:56Z iulius $ dnl dnl We have a custom probe for sendmail since we want to look in non-standard dnl locations for it, and another custom macro to allow users to override the dnl path to sendmail picked up by the script. dnl Allow the user to specify the path to sendmail. AC_DEFUN([INN_ARG_SENDMAIL], [AC_ARG_VAR([SENDMAIL], [Location of sendmail binary to use]) AC_ARG_WITH([sendmail], [AS_HELP_STRING([--with-sendmail=PATH], [Path to sendmail])], SENDMAIL=$with_sendmail)]) dnl Search for sendmail, honoring the path set by the user if they've done so dnl and otherwise looking only in /usr/sbin and /usr/lib. AC_DEFUN([INN_PATH_SENDMAIL], [if test "${with_sendmail+set}" = set ; then AC_MSG_CHECKING([for sendmail]) AC_MSG_RESULT([$SENDMAIL]) else AC_PATH_PROG([SENDMAIL], [sendmail], [], [/usr/sbin:/usr/lib]) if test -z "$SENDMAIL" ; then AC_MSG_ERROR([sendmail not found, re-run with --with-sendmail]) fi fi]) inn-2.6.4/m4/syslog.m40000644000175200017520000000340414002373703014023 0ustar iuliusiuliusdnl syslog.m4 -- Options and probes for syslog behavior. dnl $Id: syslog.m4 8594 2009-08-21 08:19:13Z iulius $ dnl dnl Normally, INN just logs everything to the news facility, but some systems dnl don't have that so we have to probe and see if we should use local1 dnl instead. And we also provide an option to change the facility to use. dnl dnl INN_LOG_FACILITY sets the output variable SYSLOG_FACILITY and also defines dnl LOG_INN_SERVER and LOG_INN_PROG in config.h. dnl Set up the --with-syslog-facility option. The result is stored in the dnl inn_syslog_facility variable for later use. AC_DEFUN([INN_ARG_SYSLOG], [AC_ARG_WITH([syslog-facility], [AS_HELP_STRING([--with-syslog-facility=LOG_FAC], [Syslog facility @<:@LOG_NEWS or LOG_LOCAL1@:>@])], SYSLOG_FACILITY=$with_syslog_facility, SYSLOG_FACILITY=none)]) dnl Source used by INN_LOG_FACILITY. AC_DEFUN([_INN_LOG_FACILITY], [[ #include #ifndef LOG_NEWS error: LOG_NEWS not available! #endif ]]) dnl Determine the facility for syslog messages. Default to LOG_NEWS for dnl syslog facility if it's available, but if it's not, fall back on dnl LOG_LOCAL1. Honor the existing SYSLOG_FACILITY value if already set by dnl INN_ARG_SYSLOG. AC_DEFUN([INN_LOG_FACILITY], [AC_CACHE_CHECK([log facility for news], [inn_cv_log_facility], [AC_COMPILE_IFELSE([AC_LANG_SOURCE([_INN_LOG_FACILITY])], [inn_cv_log_facility=LOG_NEWS], [inn_cv_log_facility=LOG_LOCAL1])]) AS_IF([test x"$SYSLOG_FACILITY" = xnone], [SYSLOG_FACILITY=$inn_cv_log_facility]) AC_DEFINE_UNQUOTED([LOG_INN_SERVER], [$SYSLOG_FACILITY], [Syslog facility to use for innd logs.]) AC_DEFINE_UNQUOTED([LOG_INN_PROG], [$SYSLOG_FACILITY], [Syslog facility to use for INN program logs.]) AC_SUBST(SYSLOG_FACILITY)]) inn-2.6.4/m4/iov-max.m40000644000175200017520000000466414002373703014074 0ustar iuliusiuliusdnl iov-max.m4 -- Probe for the maximum number of iovecs accepted by writev. dnl $Id: iov-max.m4 10352 2019-10-31 01:37:59Z eagle $ dnl dnl Check for the maximum number of elements in an iovec (IOV_MAX). SVr4 dnl systems appear to use that name for this limit (checked Solaris 2.6, IRIX dnl 6.5, and HP-UX 11.00). Linux doesn't have it, but instead has UIO_MAXIOV dnl defined in or included from . dnl dnl The platforms that have IOV_MAX appear to also offer it via sysconf(3), dnl but we don't currently handle dynamic values. dnl dnl If IOV_MAX is not defined by or , probe for its dnl value by checking writev calls up to 1024 members of an iovec and set it dnl to an appropriate value. dnl Source used by INN_MACRO_IOV_MAX. define([_INN_MACRO_IOV_MAX_SOURCE], [AC_LANG_SOURCE([[ #include #include #include #include #include #ifdef HAVE_UNISTD_H # include #endif #ifdef HAVE_LIMITS_H # include #endif int main () { int fd, size; struct iovec array[1024]; char data; FILE *f = fopen ("conftestval", "w"); if (f == NULL) return 1; #ifdef UIO_MAXIOV fprintf (f, "%d\n", UIO_MAXIOV); #else fd = open ("/dev/null", O_WRONLY, 0666); if (fd < 0) return 1; for (size = 1; size <= 1024; size++) { array[size - 1].iov_base = &data; array[size - 1].iov_len = sizeof data; if (writev (fd, array, size) < 0) { if (errno != EINVAL) return 1; fprintf (f, "%d\n", size - 1); exit (0); } } fprintf (f, "1024\n"); #endif /* UIO_MAXIOV */ return 0; } ]])]) dnl Headers to use for checking for an IOV_MAX definition. define([_INN_MACRO_IOV_MAX_HEADERS], [AC_INCLUDES_DEFAULT #ifdef HAVE_LIMITS_H # include #endif ]) dnl Do the actual check. AC_DEFUN([INN_MACRO_IOV_MAX], [AC_CHECK_DECL([IOV_MAX], [], [AC_CACHE_CHECK([value of IOV_MAX], [inn_cv_macro_iov_max], [AC_RUN_IFELSE([_INN_MACRO_IOV_MAX_SOURCE], inn_cv_macro_iov_max=`cat conftestval`, inn_cv_macro_iov_max=error, 16) AS_IF([test x"$inn_cv_macro_iov_max" = xerror], [AC_MSG_WARN([probe failure, assuming 16]) inn_cv_macro_iov_max=16])]) AC_DEFINE_UNQUOTED([IOV_MAX], [$inn_cv_macro_iov_max], [Define to the max vectors in an iovec.])], [_INN_MACRO_IOV_MAX_HEADERS])]) inn-2.6.4/m4/sendfd.m40000644000175200017520000000351114002373703013745 0ustar iuliusiuliusdnl sendfd.m4 -- Check whether I_SENDFD/I_RECVFD is supported. dnl $Id: sendfd.m4 9762 2014-12-07 18:33:37Z iulius $ dnl dnl Check whether the system supports STREAMS and can send and receive file dnl descriptors via the I_SENDFD and I_RECVFD ioctls. Provides dnl INN_SYS_STREAMS_SENDFD and defines HAVE_STREAMS_SENDFD if this facility is dnl available. dnl Source used by INN_SYS_STREAMS_SENDFD. define([_INN_SYS_STREAMS_SENDFD], [AC_LANG_SOURCE([[ #include #include #include #include #include #if HAVE_UNISTD_H # include #endif int main () { int fd[2], parent; pipe(fd); if (!isastream (fd[0])) { fprintf (stderr, "%d is not a stream\n", fd[0]); return 1; } if (fork () == 0) { int child; close (fd[0]); child = socket (AF_INET, SOCK_STREAM, 0); if (child < 0) return 1; if (ioctl (fd[1], I_SENDFD, child) < 0) return 1; return 0; } else { struct strrecvfd fdrec; memset (&fdrec, 0, sizeof(fdrec)); close (fd[1]); if (ioctl (fd[0], I_RECVFD, &fdrec) < 0) { perror("ioctl"); return 1; } if (fdrec.fd < 0) { fprintf(stderr, "Bad file descriptor %d\n", fd); return 1; } return 0; } } ]])]) dnl The public macro. AC_DEFUN([INN_SYS_STREAMS_SENDFD], [AC_CACHE_CHECK([whether STREAMS fd passing is supported], [inn_cv_sys_streams_sendfd], [AC_RUN_IFELSE([_INN_SYS_STREAMS_SENDFD], [inn_cv_sys_streams_sendfd=yes], [inn_cv_sys_streams_sendfd=no], [inn_cv_sys_streams_sendfd=no])]) if test "$inn_cv_sys_streams_sendfd" = yes ; then AC_DEFINE([HAVE_STREAMS_SENDFD], 1, [Define if your system supports STREAMS file descriptor passing.]) fi]) inn-2.6.4/m4/large-fpos.m40000644000175200017520000000222314002373703014540 0ustar iuliusiuliusdnl large-fpos.m4 -- Check for an off_t-compatible fpos_t. dnl $Id: large-fpos.m4 8312 2009-01-31 20:35:04Z iulius $ dnl dnl Some operating systems (most notably BSDI) support large files but don't dnl have the fseeko and ftello functions. However, fseeko and ftello can be dnl implemented in terms of fsetpos and fgetpos if fpos_t can be cast to and dnl from off_t. This checks for that capability. dnl Source used by INN_TYPE_FPOS_T_LARGE. define([_INN_TYPE_FPOS_T_LARGE_SOURCE], [AC_LANG_SOURCE([[ #include #include int main () { fpos_t fpos = 9223372036854775807ULL; off_t off; off = fpos; exit(off == (off_t) 9223372036854775807ULL ? 0 : 1); } ]])]) dnl The user-callable macro. AC_DEFUN([INN_TYPE_FPOS_T_LARGE], [AC_CACHE_CHECK([for off_t-compatible fpos_t], [inn_cv_type_fpos_t_large], [AC_RUN_IFELSE([_INN_TYPE_FPOS_T_LARGE_SOURCE], [inn_cv_type_fpos_t_large=yes], [inn_cv_type_fpos_t_large=no], [inn_cv_type_fpos_t_large=no])]) if test "$inn_cv_type_fpos_t_large" = yes ; then AC_DEFINE([HAVE_LARGE_FPOS_T], 1, [Define if fpos_t is at least 64 bits and compatible with off_t.]) fi]) inn-2.6.4/m4/sasl.m40000644000175200017520000000701214002373703013444 0ustar iuliusiuliusdnl Find the compiler and linker flags for Cyrus SASL. dnl $Id: sasl.m4 10306 2018-12-02 14:26:13Z iulius $ dnl dnl Finds the compiler and linker flags for linking with the Cyrus SASL dnl library. Provides the --with-sasl, --with-sasl-lib, and dnl --with-sasl-include configure options to specify non-standard paths to the dnl Cyrus SASL library. dnl dnl Provides the macro INN_LIB_SASL and sets the substitution variables dnl SASL_CPPFLAGS, SASL_LDFLAGS, and SASL_LIBS. Also provides dnl INN_LIB_SASL_SWITCH to set CPPFLAGS, LDFLAGS, and LIBS to include the dnl Cyrus SASL v2 library, saving the current values first, and dnl INN_LIB_SASL_RESTORE to restore those settings to before the last dnl INN_LIB_SASL_SWITCH. Defines HAVE_SASL and sets inn_use_SASL to true if dnl the library is found and is version two. dnl dnl Provides the INN_LIB_SASL_OPTIONAL macro, which should be used if Cyrus dnl SASL support is optional. This macro will still always set the dnl substitution variables, but they'll be empty unless --with-sasl is given. dnl Defines HAVE_SASL and sets inn_use_SASL to true if the Cyrus SASL library dnl is found and is version two. dnl dnl Depends on the lib-helper.m4 framework. dnl dnl The canonical version of this file is maintained in the rra-c-util dnl package, available at . dnl dnl Written by Russ Allbery dnl Copyright 2018 Russ Allbery dnl Copyright 2013 dnl The Board of Trustees of the Leland Stanford Junior University dnl dnl This file is free software; the authors give unlimited permission to copy dnl and/or distribute it, with or without modifications, as long as this dnl notice is preserved. dnl dnl SPDX-License-Identifier: FSFULLR dnl Save the current CPPFLAGS, LDFLAGS, and LIBS settings and switch to dnl versions that include the Cyrus SASL flags. Used as a wrapper, with dnl INN_LIB_SASL_RESTORE, around tests. AC_DEFUN([INN_LIB_SASL_SWITCH], [INN_LIB_HELPER_SWITCH([SASL])]) dnl Restore CPPFLAGS, LDFLAGS, and LIBS to their previous values (before dnl INN_LIB_SASL_SWITCH was called). AC_DEFUN([INN_LIB_SASL_RESTORE], [INN_LIB_HELPER_RESTORE([SASL])]) dnl Checks if the Cyrus SASL library is present. The single argument, if dnl "true", says to fail if the Cyrus SASL library could not be found. AC_DEFUN([_INN_LIB_SASL_INTERNAL], [INN_LIB_HELPER_PATHS([SASL]) INN_LIB_SASL_SWITCH AC_CHECK_HEADER([sasl/sasl.h], [AC_CHECK_LIB([sasl2], [sasl_getprop], [SASL_LIBS="-lsasl2"], [AS_IF([test x"$1" = xtrue], [AC_MSG_ERROR([cannot find usable Cyrus SASL library])])])], [AS_IF([test x"$1" = xtrue], [AC_MSG_ERROR([cannot find usable Cyrus SASL header])])]) INN_LIB_SASL_RESTORE]) dnl The main macro for packages with mandatory Cyrus SASL support. AC_DEFUN([INN_LIB_SASL], [INN_LIB_HELPER_VAR_INIT([SASL]) INN_LIB_HELPER_WITH([sasl], [Cyrus SASL], [SASL]) _INN_LIB_SASL_INTERNAL([true]) inn_use_SASL=true AC_DEFINE([HAVE_SASL], 1, [Define if libsasl2 is available.])]) dnl The main macro for packages with optional Cyrus SASL support. AC_DEFUN([INN_LIB_SASL_OPTIONAL], [INN_LIB_HELPER_VAR_INIT([SASL]) INN_LIB_HELPER_WITH_OPTIONAL([sasl], [Cyrus SASL], [SASL]) AS_IF([test x"$inn_use_SASL" != xfalse], [AS_IF([test x"$inn_use_SASL" = xtrue], [_INN_LIB_SASL_INTERNAL([true])], [_INN_LIB_SASL_INTERNAL([false])])]) AS_IF([test x"$SASL_LIBS" = x], [INN_LIB_HELPER_VAR_CLEAR([SASL])], [inn_use_SASL=true AC_DEFINE([HAVE_SASL], 1, [Define if libsasl2 is available.])])]) inn-2.6.4/m4/perl.m40000644000175200017520000001275014002373703013451 0ustar iuliusiuliusdnl Probe for Perl properties and, optionally, flags for embedding Perl. dnl $Id: perl.m4 10520 2021-01-17 21:48:06Z iulius $ dnl dnl Provides the following macros: dnl dnl INN_PROG_PERL dnl Checks for a specific Perl version and sets the PERL environment dnl variable to the full path, or aborts the configure run if the version dnl of Perl is not new enough or couldn't be found. Marks PERL as a dnl substitution variable. dnl dnl INN_PERL_CHECK_MODULE dnl Checks for the existence of a Perl module. Runs the second argument dnl if it is present and the third if it is not. dnl dnl INN_LIB_PERL dnl Determines the flags required for embedding Perl and sets dnl PERL_CPPFLAGS and PERL_LIBS. dnl dnl INN_PROG_PERL should generally be called before the other two macros. If dnl it isn't, the PERL environment variable must be set in some other way. dnl (It cannot be run automatically via dependencies because it takes a dnl mandatory minimum version argument, which should be provided by the dnl calling configure script.) dnl dnl The canonical version of this file is maintained in the rra-c-util dnl package, available at . dnl dnl Copyright 2016, 2018 Russ Allbery dnl Copyright 2006, 2009, 2011 Internet Systems Consortium, Inc. ("ISC") dnl Copyright 1998-2003 The Internet Software Consortium dnl dnl Permission to use, copy, modify, and distribute this software for any dnl purpose with or without fee is hereby granted, provided that the above dnl copyright notice and this permission notice appear in all copies. dnl dnl THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH dnl REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF dnl MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY dnl SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES dnl WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN dnl ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR dnl IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. dnl dnl SPDX-License-Identifier: ISC dnl Check for the path to Perl and ensure it meets our minimum version dnl requirement (given as the argument). Honor the $PERL environment dnl variable, if set. AC_DEFUN([INN_PROG_PERL], [AC_ARG_VAR([PERL], [Location of Perl interpreter]) AS_IF([test x"$PERL" != x], [AS_IF([! test -x "$PERL"], [AC_MSG_ERROR([Perl binary $PERL not found])]) AS_IF([! "$PERL" -e 'use $1' >/dev/null 2>&1], [AC_MSG_ERROR([Perl $1 or greater is required])])], [AC_CACHE_CHECK([for Perl version $1 or later], [ac_cv_path_PERL], [AC_PATH_PROGS_FEATURE_CHECK([PERL], [perl], [AS_IF(["$ac_path_PERL" -e 'require $1' >/dev/null 2>&1], [ac_cv_path_PERL="$ac_path_PERL" ac_path_PERL_found=:])])]) AS_IF([test x"$ac_cv_path_PERL" = x], [AC_MSG_ERROR([Perl $1 or greater is required])]) PERL="$ac_cv_path_PERL" AC_SUBST([PERL])])]) dnl Check whether a given Perl module can be loaded. Runs the second argument dnl if it can, and the third argument if it cannot. AC_DEFUN([INN_PERL_CHECK_MODULE], [AS_LITERAL_IF([$1], [], [m4_fatal([$0: requires literal arguments])])dnl AS_VAR_PUSHDEF([ac_Module], [inn_cv_perl_module_$1])dnl AC_CACHE_CHECK([for Perl module $1], [ac_Module], [AS_IF(["$PERL" -e 'use $1' >/dev/null 2>&1], [AS_VAR_SET([ac_Module], [yes])], [AS_VAR_SET([ac_Module], [no])])]) AS_VAR_IF([ac_Module], [yes], [$2], [$3]) AS_VAR_POPDEF([ac_Module])]) dnl Determine the flags used for embedding Perl. dnl dnl Some distributions of Linux have Perl linked with gdbm but don't normally dnl have gdbm installed, so on that platform only strip -lgdbm out of the Perl dnl libraries. Leave it in on other platforms where it may be necessary (it dnl isn't on Linux; Linux shared libraries can manage their own dependencies). dnl Strip -lc out, which is added on some platforms, is unnecessary, and dnl breaks compiles with -pthread (which may be added by Python). AC_DEFUN([INN_LIB_PERL], [AC_REQUIRE([AC_CANONICAL_HOST]) AC_SUBST([PERL_CPPFLAGS]) AC_SUBST([PERL_LIBS]) AC_MSG_CHECKING([for flags to link with Perl]) inn_perl_core_path=`"$PERL" -MConfig -e 'print $Config{archlibexp}'` inn_perl_core_flags=`"$PERL" -MExtUtils::Embed -e ccopts` inn_perl_core_libs=`"$PERL" -MExtUtils::Embed -e ldopts 2>&1 | tail -n 1` inn_perl_core_libs=" $inn_perl_core_libs " inn_perl_core_libs=`AS_ECHO(["$inn_perl_core_libs"]) | sed 's/ -lc / /'` AS_CASE([$host], [*-linux*], [inn_perl_core_libs=`AS_ECHO(["$inn_perl_core_libs"]) | sed 's/ -lgdbm / /'`], [*-cygwin*], [inn_perl_libname=`"$PERL" -MConfig -e 'print $Config{libperl}'` inn_perl_libname=`AS_ECHO(["$inn_perl_libname"]) | sed 's/^lib//; s/\.a$//'` inn_perl_core_libs="${inn_perl_core_libs}-l$inn_perl_libname"]) inn_perl_core_libs=`AS_ECHO(["$inn_perl_core_libs"]) | sed 's/^ *//'` inn_perl_core_libs=`AS_ECHO(["$inn_perl_core_libs"]) | sed 's/ *$//'` PERL_CPPFLAGS="$inn_perl_core_flags" PERL_LIBS="$inn_perl_core_libs" AC_MSG_RESULT([$PERL_LIBS]) inn_perl_save_CPPFLAGS="$CPPFLAGS" inn_perl_save_LIBS="$LIBS" CPPFLAGS="$PERL_CPPFLAGS $CPPFLAGS" LIBS="$PERL_LIBS $LIBS" AC_CHECK_HEADER([EXTERN.h], [], [AC_MSG_FAILURE([unable to compile with EXTERN.h])]) AC_CHECK_FUNC([perl_alloc], [], [AC_MSG_FAILURE([unable to link with Perl library])]) CPPFLAGS="$inn_perl_save_CPPFLAGS" LIBS="$inn_perl_save_LIBS"]) inn-2.6.4/m4/bdb.m40000644000175200017520000001124314002373703013232 0ustar iuliusiuliusdnl Find the compiler and linker flags for the Berkeley DB library. dnl $Id: bdb.m4 10306 2018-12-02 14:26:13Z iulius $ dnl dnl Finds the compiler and linker flags for linking with the Berkeley DB dnl library. Provides the --with-bdb, --with-bdb-lib, and --with-bdb-include dnl configure options to specify non-standard paths to the Berkeley DB dnl library. dnl dnl Provides the macro INN_LIB_BDB and sets the substitution variables dnl BDB_CPPFLAGS, BDB_LDFLAGS, and BDB_LIBS. Also provides INN_LIB_BDB_SWITCH dnl to set CPPFLAGS, LDFLAGS, and LIBS to include the Berkeley DB library, dnl saving the current values first, and INN_LIB_BDB_RESTORE to restore those dnl settings to before the last INN_LIB_BDB_SWITCH. Defines HAVE_BDB and sets dnl inn_use_BDB to true if the library is found. dnl dnl Provides the INN_LIB_BDB_OPTIONAL macro, which should be used if Berkeley dnl DB support is optional. This macro will still always set the substitution dnl variables, but they'll be empty unless --with-bdb is given. Defines dnl HAVE_BDB and sets inn_use_BDB to true if the Berkeley DB library is found. dnl dnl This file also provides INN_LIB_BDB_NDBM, which checks whether the dnl Berkeley DB library has ndbm support. It then defines HAVE_BDB_NDBM and dnl sets inn_cv_lib_bdb_ndbm to yes if ndbm compatibility layer for Berkely DB dnl is available. Either INN_LIB_BDB or INN_LIB_BDB_OPTIONAL must be called dnl before calling this macro. dnl dnl Depends on the lib-helper.m4 framework. dnl dnl The canonical version of this file is maintained in the rra-c-util dnl package, available at . dnl dnl Written by Russ Allbery dnl Copyright 2018 Russ Allbery dnl Copyright 2013 dnl The Board of Trustees of the Leland Stanford Junior University dnl dnl This file is free software; the authors give unlimited permission to copy dnl and/or distribute it, with or without modifications, as long as this dnl notice is preserved. dnl dnl SPDX-License-Identifier: FSFULLR dnl Save the current CPPFLAGS, LDFLAGS, and LIBS settings and switch to dnl versions that include the Berkeley DB flags. Used as a wrapper, with dnl INN_LIB_BDB_RESTORE, around tests. AC_DEFUN([INN_LIB_BDB_SWITCH], [INN_LIB_HELPER_SWITCH([BDB])]) dnl Restore CPPFLAGS, LDFLAGS, and LIBS to their previous values (before dnl INN_LIB_BDB_SWITCH was called). AC_DEFUN([INN_LIB_BDB_RESTORE], [INN_LIB_HELPER_RESTORE([BDB])]) dnl Checks if the Berkeley DB library is present. The single argument, dnl if "true", says to fail if the Berkeley DB library could not be found. AC_DEFUN([_INN_LIB_BDB_INTERNAL], [INN_LIB_HELPER_PATHS([BDB]) INN_LIB_BDB_SWITCH AC_CHECK_HEADER([db.h], [AC_CHECK_LIB([db], [db_create], [BDB_LIBS="-ldb"], [AS_IF([test x"$1" = xtrue], [AC_MSG_ERROR([cannot find usable Berkeley DB library])])])], [AS_IF([test x"$1" = xtrue], [AC_MSG_ERROR([cannot find usable Berkeley DB header])])]) INN_LIB_BDB_RESTORE]) dnl The main macro for packages with mandatory Berkeley DB support. AC_DEFUN([INN_LIB_BDB], [INN_LIB_HELPER_VAR_INIT([BDB]) INN_LIB_HELPER_WITH([bdb], [Berkeley DB], [BDB]) _INN_LIB_BDB_INTERNAL([true]) inn_use_BDB=true AC_DEFINE([HAVE_BDB], 1, [Define if libdb is available.])]) dnl The main macro for packages with optional Berkeley DB support. AC_DEFUN([INN_LIB_BDB_OPTIONAL], [INN_LIB_HELPER_VAR_INIT([BDB]) INN_LIB_HELPER_WITH_OPTIONAL([bdb], [Berkeley DB], [BDB]) AS_IF([test x"$inn_use_BDB" != xfalse], [AS_IF([test x"$inn_use_BDB" = xtrue], [_INN_LIB_BDB_INTERNAL([true])], [_INN_LIB_BDB_INTERNAL([false])])]) AS_IF([test x"$BDB_LIBS" = x], [INN_LIB_HELPER_VAR_CLEAR([BDB])], [inn_use_BDB=true AC_DEFINE([HAVE_BDB], 1, [Define if libdb is available.])])]) dnl Source used by INN_LIB_BDB_NDBM. AC_DEFUN([_INN_LIB_BDB_NDBM_SOURCE], [[ #include #define DB_DBM_HSEARCH 1 #include int main(void) { DBM *database; database = dbm_open("test", 0, 0600); dbm_close(database); return 0; } ]]) dnl Check whether Berkeley DB was compiled with ndbm compatibility layer. If dnl so, set HAVE_BDB_NDBM. Either INN_LIB_BDB or INN_LIB_BDB_OPTIONAL should dnl be called before calling this macro. AC_DEFUN([INN_LIB_BDB_NDBM], [INN_LIB_BDB_SWITCH AC_CACHE_CHECK([for working ndbm compatibility layer with Berkeley DB], [inn_cv_lib_bdb_ndbm], [AC_LINK_IFELSE([AC_LANG_SOURCE([_INN_LIB_BDB_NDBM_SOURCE])], [inn_cv_lib_bdb_ndbm=yes], [inn_cv_lib_bdb_ndbm=no])]) AS_IF([test x"$inn_cv_lib_bdb_ndbm" = xyes], [AC_DEFINE([HAVE_BDB_NDBM], 1, [Define if the Berkeley DB ndbm compatibility layer is available.])]) INN_LIB_BDB_RESTORE]) inn-2.6.4/m4/systemd.m40000644000175200017520000000550014002373703014172 0ustar iuliusiuliusdnl Probe for systemd libraries and installation paths. dnl $Id: systemd.m4 10484 2021-01-04 07:12:59Z iulius $ dnl dnl Provides the INN_WITH_SYSTEMD_UNITDIR macro, which adds the dnl --with-systemdsystemunitdir configure flag, sets the systemdsystemunitdir dnl substitution variable, and provides the HAVE_SYSTEMD Automake conditional dnl to use to control whether to install unit files. dnl dnl Provides the INN_LIB_SYSTEMD_DAEMON_OPTIONAL macro, which sets dnl SYSTEMD_CFLAGS and SYSTEMD_LIBS substitution variables if dnl libsystemd-daemon is available and defines HAVE_SD_NOTIFY. pkg-config dnl support for libsystemd-daemon is required for it to be detected. dnl dnl Depends on the Autoconf macros that come with pkg-config. dnl dnl The canonical version of this file is maintained in the rra-c-util dnl package, available at . dnl dnl Written by Russ Allbery dnl Copyright 2015 Russ Allbery dnl Copyright 2013-2014 dnl The Board of Trustees of the Leland Stanford Junior University dnl dnl This file is free software; the authors give unlimited permission to copy dnl and/or distribute it, with or without modifications, as long as this dnl notice is preserved. dnl dnl SPDX-License-Identifier: FSFULLR dnl Determine the systemd system unit directory, along with a configure flag dnl to override, and sets @systemdsystemunitdir@. Provides the Automake dnl HAVE_SYSTEMD Automake conditional. AC_DEFUN([INN_WITH_SYSTEMD_UNITDIR], [AC_REQUIRE([PKG_PROG_PKG_CONFIG]) AS_IF([test x"$PKG_CONFIG" = x], [PKG_CONFIG=false]) AC_ARG_WITH([systemdsystemunitdir], [AS_HELP_STRING([--with-systemdsystemunitdir=DIR], [Directory for systemd service files])], [], [with_systemdsystemunitdir=`$PKG_CONFIG --variable=systemdsystemunitdir systemd`]) AS_IF([test x"$with_systemdsystemunitdir" != xno], [AC_SUBST([systemdsystemunitdir], [$with_systemdsystemunitdir])]) AM_CONDITIONAL([HAVE_SYSTEMD], [test -n "$with_systemdsystemunitdir" -a x"$with_systemdsystemunitdir" != xno])]) dnl Check for libsystemd or libsystemd-daemon and define SYSTEMD_{CFLAGS,LIBS} dnl if it is available. This is called INN_LIB_SYSTEMD_DAEMON_OPTIONAL since dnl it was originally written when libsystemd-daemon was separate, and only dnl checks for that library. It may eventually make sense to retire this in dnl favor of a simple INN_LIB_SYSTEMD_OPTIONAL that isn't backward-compatible. AC_DEFUN([INN_LIB_SYSTEMD_DAEMON_OPTIONAL], [PKG_CHECK_EXISTS([libsystemd], [PKG_CHECK_MODULES([SYSTEMD], [libsystemd]) AC_DEFINE([HAVE_SD_NOTIFY], 1, [Define if sd_notify is available.])], [PKG_CHECK_EXISTS([libsystemd-daemon], [PKG_CHECK_MODULES([SYSTEMD], [libsystemd-daemon]) AC_DEFINE([HAVE_SD_NOTIFY], 1, [Define if sd_notify is available.])])])]) inn-2.6.4/m4/zlib.m40000644000175200017520000000656014002373703013451 0ustar iuliusiuliusdnl Find the compiler and linker flags for the zlib library. dnl $Id: zlib.m4 10306 2018-12-02 14:26:13Z iulius $ dnl dnl Finds the compiler and linker flags for linking with the zlib library. dnl Provides the --with-zlib, --with-zlib-lib, and --with-zlib-include dnl configure options to specify non-standard paths to the zlib library. dnl dnl Provides the macro INN_LIB_ZLIB and sets the substitution variables dnl ZLIB_CPPFLAGS, ZLIB_LDFLAGS, and ZLIB_LIBS. Also provides dnl INN_LIB_ZLIB_SWITCH to set CPPFLAGS, LDFLAGS, and LIBS to include the dnl zlib library, saving the current values first, and INN_LIB_ZLIB_RESTORE dnl to restore those settings to before the last INN_LIB_ZLIB_SWITCH. dnl Defines HAVE_ZLIB and sets inn_use_ZLIB to true if the library is found. dnl dnl Provides the INN_LIB_ZLIB_OPTIONAL macro, which should be used if zlib dnl support is optional. This macro will still always set the substitution dnl variables, but they'll be empty unless --with-zlib is given. dnl Defines HAVE_ZLIB and sets inn_use_ZLIB to true if the zlib library dnl is found. dnl dnl Depends on the lib-helper.m4 framework. dnl dnl The canonical version of this file is maintained in the rra-c-util dnl package, available at . dnl dnl Written by Russ Allbery dnl Copyright 2018 Russ Allbery dnl Copyright 2013 dnl The Board of Trustees of the Leland Stanford Junior University dnl dnl This file is free software; the authors give unlimited permission to copy dnl and/or distribute it, with or without modifications, as long as this dnl notice is preserved. dnl dnl SPDX-License-Identifier: FSFULLR dnl Save the current CPPFLAGS, LDFLAGS, and LIBS settings and switch to dnl versions that include the zlib flags. Used as a wrapper, with dnl INN_LIB_ZLIB_RESTORE, around tests. AC_DEFUN([INN_LIB_ZLIB_SWITCH], [INN_LIB_HELPER_SWITCH([ZLIB])]) dnl Restore CPPFLAGS, LDFLAGS, and LIBS to their previous values (before dnl INN_LIB_ZLIB_SWITCH was called). AC_DEFUN([INN_LIB_ZLIB_RESTORE], [INN_LIB_HELPER_RESTORE([ZLIB])]) dnl Checks if the zlib library is present. The single argument, if "true", dnl says to fail if the zlib library could not be found. AC_DEFUN([_INN_LIB_ZLIB_INTERNAL], [INN_LIB_HELPER_PATHS([ZLIB]) INN_LIB_ZLIB_SWITCH AC_CHECK_HEADER([zlib.h], [AC_CHECK_LIB([z], [compress], [ZLIB_LIBS="-lz"], [AS_IF([test x"$1" = xtrue], [AC_MSG_ERROR([cannot find usable zlib library])])])], [AS_IF([test x"$1" = xtrue], [AC_MSG_ERROR([cannot find usable zlib header])])]) INN_LIB_ZLIB_RESTORE]) dnl The main macro for packages with mandatory zlib support. AC_DEFUN([INN_LIB_ZLIB], [INN_LIB_HELPER_VAR_INIT([ZLIB]) INN_LIB_HELPER_WITH([zlib], [zlib], [ZLIB]) _INN_LIB_ZLIB_INTERNAL([true]) inn_use_ZLIB=true AC_DEFINE([HAVE_ZLIB], 1, [Define if libz is available.])]) dnl The main macro for packages with optional zlib support. AC_DEFUN([INN_LIB_ZLIB_OPTIONAL], [INN_LIB_HELPER_VAR_INIT([ZLIB]) INN_LIB_HELPER_WITH_OPTIONAL([zlib], [zlib], [ZLIB]) AS_IF([test x"$inn_use_ZLIB" != xfalse], [AS_IF([test x"$inn_use_ZLIB" = xtrue], [_INN_LIB_ZLIB_INTERNAL([true])], [_INN_LIB_ZLIB_INTERNAL([false])])]) AS_IF([test x"$ZLIB_LIBS" = x], [INN_LIB_HELPER_VAR_CLEAR([ZLIB])], [inn_use_ZLIB=true AC_DEFINE([HAVE_ZLIB], 1, [Define if libz is available.])])]) inn-2.6.4/m4/snprintf.m40000644000175200017520000000411214002373703014343 0ustar iuliusiuliusdnl Test for a working C99 snprintf. dnl $Id: snprintf.m4 10396 2020-11-12 20:19:41Z iulius $ dnl dnl Check for a working snprintf. Some systems have an snprintf that doesn't dnl nul-terminate if the buffer isn't large enough. Others return -1 if the dnl string doesn't fit into the buffer instead of returning the number of dnl characters that would have been formatted. Still others don't support dnl NULL as the buffer argument (just to get a count of the formatted length). dnl dnl Provides INN_FUNC_SNPRINTF, which adds snprintf.o to LIBOBJS unless a dnl fully working snprintf is found. dnl dnl The canonical version of this file was maintained (until 2020) in the dnl rra-c-util package, available at dnl . dnl dnl Written by Russ Allbery dnl Copyright 2006, 2008-2009 dnl The Board of Trustees of the Leland Stanford Junior University dnl dnl This file is free software; the authors give unlimited permission to copy dnl and/or distribute it, with or without modifications, as long as this dnl notice is preserved. dnl dnl SPDX-License-Identifier: FSFULLR dnl Source used by INN_FUNC_SNPRINTF. AC_DEFUN([_INN_FUNC_SNPRINTF_SOURCE], [[ #include #include char buf[2]; int test(char *format, ...) { va_list args; int count; va_start(args, format); count = vsnprintf(buf, sizeof buf, format, args); va_end(args); return count; } int main() { return ((test("%s", "abcd") == 4 && buf[0] == 'a' && buf[1] == '\0' && snprintf(NULL, 0, "%s", "abcd") == 4) ? 0 : 1); } ]]) dnl The user-callable test. AC_DEFUN([INN_FUNC_SNPRINTF], [AC_CACHE_CHECK([for working snprintf], [inn_cv_func_snprintf_works], [AC_RUN_IFELSE([AC_LANG_SOURCE([_INN_FUNC_SNPRINTF_SOURCE])], [inn_cv_func_snprintf_works=yes], [inn_cv_func_snprintf_works=no], [inn_cv_func_snprintf_works=no])]) AS_IF([test x"$inn_cv_func_snprintf_works" = xyes], [AC_DEFINE([HAVE_SNPRINTF], 1, [Define if your system has a working snprintf function.])], [AC_LIBOBJ([snprintf])])]) inn-2.6.4/m4/lib-helper.m40000644000175200017520000001404514002373703014531 0ustar iuliusiuliusdnl Helper functions to manage compiler variables. dnl $Id: lib-helper.m4 10306 2018-12-02 14:26:13Z iulius $ dnl dnl These are a wide variety of helper macros to make it easier to construct dnl standard macros to probe for a library and to set library-specific dnl CPPFLAGS, LDFLAGS, and LIBS shell substitution variables. Most of them dnl take as one of the arguments the prefix string to use for variables, which dnl is usually something like "KRB5" or "GSSAPI". dnl dnl Depends on INN_SET_LDFLAGS. dnl dnl The canonical version of this file is maintained in the rra-c-util dnl package, available at . dnl dnl Written by Russ Allbery dnl Copyright 2018 Russ Allbery dnl Copyright 2011, 2013 dnl The Board of Trustees of the Leland Stanford Junior University dnl dnl This file is free software; the authors give unlimited permission to copy dnl and/or distribute it, with or without modifications, as long as this dnl notice is preserved. dnl dnl SPDX-License-Identifier: FSFULLR dnl Add the library flags to the default compiler flags and then remove them. dnl dnl To use these macros, pass the prefix string used for the variables as the dnl only argument. For example, to use these for a library with KRB5 as a dnl prefix, one would use: dnl dnl AC_DEFUN([INN_LIB_KRB5_SWITCH], [INN_LIB_HELPER_SWITCH([KRB5])]) dnl AC_DEFUN([INN_LIB_KRB5_RESTORE], [INN_LIB_HELPER_RESTORE([KRB5])]) dnl dnl Then, wrap checks for library features with INN_LIB_KRB5_SWITCH and dnl INN_LIB_KRB5_RESTORE. AC_DEFUN([INN_LIB_HELPER_SWITCH], [inn_$1[]_save_CPPFLAGS="$CPPFLAGS" inn_$1[]_save_LDFLAGS="$LDFLAGS" inn_$1[]_save_LIBS="$LIBS" CPPFLAGS="$$1[]_CPPFLAGS $CPPFLAGS" LDFLAGS="$$1[]_LDFLAGS $LDFLAGS" LIBS="$$1[]_LIBS $LIBS"]) AC_DEFUN([INN_LIB_HELPER_RESTORE], [CPPFLAGS="$inn_$1[]_save_CPPFLAGS" LDFLAGS="$inn_$1[]_save_LDFLAGS" LIBS="$inn_$1[]_save_LIBS"]) dnl Given _root, _libdir, and _includedir variables set for a library (set by dnl INN_LIB_HELPER_WITH*), set the LDFLAGS and CPPFLAGS variables for that dnl library accordingly. Takes the variable prefix as the only argument. AC_DEFUN([INN_LIB_HELPER_PATHS], [AS_IF([test x"$inn_$1[]_libdir" != x], [$1[]_LDFLAGS="-L$inn_$1[]_libdir"], [AS_IF([test x"$inn_$1[]_root" != x], [INN_SET_LDFLAGS([$1][_LDFLAGS], [${inn_$1[]_root}])])]) AS_IF([test x"$inn_$1[]_includedir" != x], [$1[]_CPPFLAGS="-I$inn_$1[]_includedir"], [AS_IF([test x"$inn_$1[]_root" != x], [AS_IF([test x"$inn_$1[]_root" != x/usr], [$1[]_CPPFLAGS="-I${inn_$1[]_root}/include"])])])]) dnl Check whether a library works. This is used as a sanity check on the dnl results of *-config shell scripts. Takes four arguments; the first, if dnl "true", says that a working library is mandatory and errors out if it dnl doesn't. The second is the variable prefix. The third is a function to dnl look for that should be in the libraries. The fourth is the dnl human-readable name of the library for error messages. AC_DEFUN([INN_LIB_HELPER_CHECK], [INN_LIB_HELPER_SWITCH([$2]) AC_CHECK_FUNC([$3], [], [AS_IF([test x"$1" = xtrue], [AC_MSG_FAILURE([unable to link with $4 library])]) $2[]_CPPFLAGS= $2[]_LDFLAGS= $2[]_LIBS=]) INN_LIB_HELPER_RESTORE([$2])]) dnl Initialize the variables used by a library probe and set the appropriate dnl ones as substitution variables. Takes the library variable prefix as its dnl only argument. AC_DEFUN([INN_LIB_HELPER_VAR_INIT], [inn_$1[]_root= inn_$1[]_libdir= inn_$1[]_includedir= inn_use_$1= $1[]_CPPFLAGS= $1[]_LDFLAGS= $1[]_LIBS= AC_SUBST([$1][_CPPFLAGS]) AC_SUBST([$1][_LDFLAGS]) AC_SUBST([$1][_LIBS])]) dnl Unset all of the variables used by a library probe. Used with the dnl _OPTIONAL versions of header probes when a header or library wasn't found dnl and therefore the library isn't usable. AC_DEFUN([INN_LIB_HELPER_VAR_CLEAR], [$1[]_CPPFLAGS= $1[]_LDFLAGS= $1[]_LIBS=]) dnl Handles --with options for a non-optional library. First argument is the dnl base for the switch names. Second argument is the short description. dnl Third argument is the variable prefix. The variables set are used by dnl INN_LIB_HELPER_PATHS. AC_DEFUN([INN_LIB_HELPER_WITH], [AC_ARG_WITH([$1], [AS_HELP_STRING([--with-][$1][=DIR], [Location of $2 headers and libraries])], [AS_IF([test x"$withval" != xyes && test x"$withval" != xno], [inn_$3[]_root="$withval"])]) AC_ARG_WITH([$1][-include], [AS_HELP_STRING([--with-][$1][-include=DIR], [Location of $2 headers])], [AS_IF([test x"$withval" != xyes && test x"$withval" != xno], [inn_$3[]_includedir="$withval"])]) AC_ARG_WITH([$1][-lib], [AS_HELP_STRING([--with-][$1][-lib=DIR], [Location of $2 libraries])], [AS_IF([test x"$withval" != xyes && test x"$withval" != xno], [inn_$3[]_libdir="$withval"])])]) dnl Handles --with options for an optional library, so --with- can dnl cause the checks to be skipped entirely or become mandatory. Sets an dnl inn_use_PREFIX variable to true or false if the library is explicitly dnl enabled or disabled. dnl dnl First argument is the base for the switch names. Second argument is the dnl short description. Third argument is the variable prefix. dnl dnl The variables set are used by INN_LIB_HELPER_PATHS. AC_DEFUN([INN_LIB_HELPER_WITH_OPTIONAL], [AC_ARG_WITH([$1], [AS_HELP_STRING([--with-][$1][@<:@=DIR@:>@], [Location of $2 headers and libraries])], [AS_IF([test x"$withval" = xno], [inn_use_$3=false], [AS_IF([test x"$withval" != xyes], [inn_$3[]_root="$withval"]) inn_use_$3=true])]) AC_ARG_WITH([$1][-include], [AS_HELP_STRING([--with-][$1][-include=DIR], [Location of $2 headers])], [AS_IF([test x"$withval" != xyes && test x"$withval" != xno], [inn_$3[]_includedir="$withval"])]) AC_ARG_WITH([$1][-lib], [AS_HELP_STRING([--with-][$1][-lib=DIR], [Location of $2 libraries])], [AS_IF([test x"$withval" != xyes && test x"$withval" != xno], [inn_$3[]_libdir="$withval"])])]) inn-2.6.4/m4/ltsugar.m40000644000175200017520000001044014002373703014162 0ustar iuliusiulius# ltsugar.m4 -- libtool m4 base layer. -*-Autoconf-*- # # Copyright (C) 2004-2005, 2007-2008, 2011-2015 Free Software # Foundation, Inc. # Written by Gary V. Vaughan, 2004 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # serial 6 ltsugar.m4 # This is to help aclocal find these macros, as it can't see m4_define. AC_DEFUN([LTSUGAR_VERSION], [m4_if([0.1])]) # lt_join(SEP, ARG1, [ARG2...]) # ----------------------------- # Produce ARG1SEPARG2...SEPARGn, omitting [] arguments and their # associated separator. # Needed until we can rely on m4_join from Autoconf 2.62, since all earlier # versions in m4sugar had bugs. m4_define([lt_join], [m4_if([$#], [1], [], [$#], [2], [[$2]], [m4_if([$2], [], [], [[$2]_])$0([$1], m4_shift(m4_shift($@)))])]) m4_define([_lt_join], [m4_if([$#$2], [2], [], [m4_if([$2], [], [], [[$1$2]])$0([$1], m4_shift(m4_shift($@)))])]) # lt_car(LIST) # lt_cdr(LIST) # ------------ # Manipulate m4 lists. # These macros are necessary as long as will still need to support # Autoconf-2.59, which quotes differently. m4_define([lt_car], [[$1]]) m4_define([lt_cdr], [m4_if([$#], 0, [m4_fatal([$0: cannot be called without arguments])], [$#], 1, [], [m4_dquote(m4_shift($@))])]) m4_define([lt_unquote], $1) # lt_append(MACRO-NAME, STRING, [SEPARATOR]) # ------------------------------------------ # Redefine MACRO-NAME to hold its former content plus 'SEPARATOR''STRING'. # Note that neither SEPARATOR nor STRING are expanded; they are appended # to MACRO-NAME as is (leaving the expansion for when MACRO-NAME is invoked). # No SEPARATOR is output if MACRO-NAME was previously undefined (different # than defined and empty). # # This macro is needed until we can rely on Autoconf 2.62, since earlier # versions of m4sugar mistakenly expanded SEPARATOR but not STRING. m4_define([lt_append], [m4_define([$1], m4_ifdef([$1], [m4_defn([$1])[$3]])[$2])]) # lt_combine(SEP, PREFIX-LIST, INFIX, SUFFIX1, [SUFFIX2...]) # ---------------------------------------------------------- # Produce a SEP delimited list of all paired combinations of elements of # PREFIX-LIST with SUFFIX1 through SUFFIXn. Each element of the list # has the form PREFIXmINFIXSUFFIXn. # Needed until we can rely on m4_combine added in Autoconf 2.62. m4_define([lt_combine], [m4_if(m4_eval([$# > 3]), [1], [m4_pushdef([_Lt_sep], [m4_define([_Lt_sep], m4_defn([lt_car]))])]]dnl [[m4_foreach([_Lt_prefix], [$2], [m4_foreach([_Lt_suffix], ]m4_dquote(m4_dquote(m4_shift(m4_shift(m4_shift($@)))))[, [_Lt_sep([$1])[]m4_defn([_Lt_prefix])[$3]m4_defn([_Lt_suffix])])])])]) # lt_if_append_uniq(MACRO-NAME, VARNAME, [SEPARATOR], [UNIQ], [NOT-UNIQ]) # ----------------------------------------------------------------------- # Iff MACRO-NAME does not yet contain VARNAME, then append it (delimited # by SEPARATOR if supplied) and expand UNIQ, else NOT-UNIQ. m4_define([lt_if_append_uniq], [m4_ifdef([$1], [m4_if(m4_index([$3]m4_defn([$1])[$3], [$3$2$3]), [-1], [lt_append([$1], [$2], [$3])$4], [$5])], [lt_append([$1], [$2], [$3])$4])]) # lt_dict_add(DICT, KEY, VALUE) # ----------------------------- m4_define([lt_dict_add], [m4_define([$1($2)], [$3])]) # lt_dict_add_subkey(DICT, KEY, SUBKEY, VALUE) # -------------------------------------------- m4_define([lt_dict_add_subkey], [m4_define([$1($2:$3)], [$4])]) # lt_dict_fetch(DICT, KEY, [SUBKEY]) # ---------------------------------- m4_define([lt_dict_fetch], [m4_ifval([$3], m4_ifdef([$1($2:$3)], [m4_defn([$1($2:$3)])]), m4_ifdef([$1($2)], [m4_defn([$1($2)])]))]) # lt_if_dict_fetch(DICT, KEY, [SUBKEY], VALUE, IF-TRUE, [IF-FALSE]) # ----------------------------------------------------------------- m4_define([lt_if_dict_fetch], [m4_if(lt_dict_fetch([$1], [$2], [$3]), [$4], [$5], [$6])]) # lt_dict_filter(DICT, [SUBKEY], VALUE, [SEPARATOR], KEY, [...]) # -------------------------------------------------------------- m4_define([lt_dict_filter], [m4_if([$5], [], [], [lt_join(m4_quote(m4_default([$4], [[, ]])), lt_unquote(m4_split(m4_normalize(m4_foreach(_Lt_key, lt_car([m4_shiftn(4, $@)]), [lt_if_dict_fetch([$1], _Lt_key, [$2], [$3], [_Lt_key ])])))))])[]dnl ]) inn-2.6.4/m4/mmap.m40000644000175200017520000001474114002373703013443 0ustar iuliusiuliusdnl mmap.m4 -- Probe for mmap properties. dnl $Id: mmap.m4 10397 2020-11-12 20:22:51Z iulius $ dnl dnl The mmap macro that comes with Autoconf doesn't do anything useful. dnl Define a new INN_FUNC_MMAP that probes for a working mmap that supports dnl shared, non-fixed maps. This function defines HAVE_MMAP if mmap appears dnl to work, and takes an action if found argument that can be used to make dnl other probes. dnl dnl Provide INN_FUNC_MMAP_NEEDS_MSYNC, which defines MMAP_NEEDS_MSYNC if dnl reading from an open file doesn't see changes made to that file through dnl mmap without an intervening msync. dnl dnl Provide INN_FUNC_MMAP_MISSES_WRITES, which defines MMAP_MISSES_WRITES if dnl changes to a file made with write aren't seen in an mmaped region without dnl an intervening msync. dnl dnl (The above two macros together in essence probe for whether the operating dnl system has a unified page cache.) dnl dnl Finally, provide AC_FUNC_MSYNC_ARGS, which defines HAVE_MSYNC_3_ARGS if dnl msync takes three arguments (as on Solaris and Linux) rather than two dnl (most other operating systems). dnl Source used by INN_FUNC_MMAP. define([_INN_FUNC_MMAP_SOURCE], [AC_LANG_SOURCE([[ #include #include #include #include #if HAVE_UNISTD_H # include #endif int main() { int *data, *data2; int i, fd; /* First, make a file with some known garbage in it. Use something larger than one page but still an odd page size. */ data = malloc (20000); if (!data) return 1; for (i = 0; i < 20000 / sizeof (int); i++) data[i] = rand(); umask (0); fd = creat ("conftestmmaps", 0600); if (fd < 0) return 1; if (write (fd, data, 20000) != 20000) return 1; close (fd); /* Next, try to mmap the file and make sure we see the same garbage. */ fd = open ("conftestmmaps", O_RDWR); if (fd < 0) return 1; data2 = mmap (0, 20000, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); if (data2 == (int *) -1) return 1; for (i = 0; i < 20000 / sizeof (int); i++) if (data[i] != data2[i]) return 1; close (fd); unlink ("conftestmmaps"); return 0; } ]])]) dnl This portion is similar to what AC_FUNC_MMAP does, only it tests shared, dnl non-fixed mmaps. AC_DEFUN([INN_FUNC_MMAP], [AC_CACHE_CHECK([for working mmap], [inn_cv_func_mmap], [AC_RUN_IFELSE([_INN_FUNC_MMAP_SOURCE], [inn_cv_func_mmap=yes], [inn_cv_func_mmap=no], [inn_cv_func_mmap=no])]) if test $inn_cv_func_mmap = yes ; then AC_DEFINE([HAVE_MMAP], 1, [Define if mmap exists and works for shared, non-fixed maps.]) $1 else : $2 fi]) dnl Source used by INN_FUNC_MMAP_NEEDS_MSYNC. define([_INN_FUNC_MMAP_NEEDS_MSYNC_SOURCE], [AC_LANG_SOURCE([[ #include #include #include #include #include #if HAVE_UNISTD_H # include #endif int main() { int *data, *data2; int i, fd; /* First, make a file with some known garbage in it. Use something larger than one page but still an odd page size. */ data = malloc (20000); if (!data) return 1; for (i = 0; i < 20000 / sizeof (int); i++) data[i] = rand(); umask (0); fd = creat ("conftestmmaps", 0600); if (fd < 0) return 1; if (write (fd, data, 20000) != 20000) return 1; close (fd); /* Next, try to mmap the file and make sure we see the same garbage. */ fd = open ("conftestmmaps", O_RDWR); if (fd < 0) return 1; data2 = mmap (0, 20000, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); if (data2 == (int *) -1) return 1; /* Finally, see if changes made to the mmaped region propagate back to the file as seen by read (meaning that msync isn't needed). */ for (i = 0; i < 20000 / sizeof (int); i++) data2[i]++; if (read (fd, data, 20000) != 20000) return 1; for (i = 0; i < 20000 / sizeof (int); i++) if (data[i] != data2[i]) return 1; close (fd); unlink ("conftestmmapm"); return 0; } ]])]) dnl Check whether the data read from an open file sees the changes made to an dnl mmaped region, or if msync has to be called for other applications to see dnl those changes. AC_DEFUN([INN_FUNC_MMAP_NEEDS_MSYNC], [AC_CACHE_CHECK([whether msync is needed], [inn_cv_func_mmap_need_msync], [AC_RUN_IFELSE([_INN_FUNC_MMAP_NEEDS_MSYNC_SOURCE], [inn_cv_func_mmap_need_msync=no], [inn_cv_func_mmap_need_msync=yes], [inn_cv_func_mmap_need_msync=yes])]) if test $inn_cv_func_mmap_need_msync = yes ; then AC_DEFINE([MMAP_NEEDS_MSYNC], 1, [Define if you need to call msync for calls to read to see changes.]) fi]) dnl Source used by INN_FUNC_MMAP_SEES_WRITES. define([_INN_FUNC_MMAP_SEES_WRITES_SOURCE], [AC_LANG_SOURCE([[ #include #include #include #include #if HAVE_UNISTD_H # include #endif #include /* Fractional page is probably worst case. */ static char zbuff[1024]; static char fname[] = "conftestw"; int main () { char *map; int i, fd; fd = open (fname, O_RDWR | O_CREAT, 0660); if (fd < 0) return 1; unlink (fname); write (fd, zbuff, sizeof (zbuff)); lseek (fd, 0, SEEK_SET); map = mmap (0, sizeof (zbuff), PROT_READ, MAP_SHARED, fd, 0); if (map == (char *) -1) return 2; for (i = 0; fname[i]; i++) { if (write (fd, &fname[i], 1) != 1) return 3; if (map[i] != fname[i]) return 4; } return 0; } ]])]) dnl Check if an mmaped region will see writes made to the underlying file dnl without an intervening msync. AC_DEFUN([INN_FUNC_MMAP_SEES_WRITES], [AC_CACHE_CHECK([whether mmap sees writes], [inn_cv_func_mmap_sees_writes], [AC_RUN_IFELSE([_INN_FUNC_MMAP_SEES_WRITES_SOURCE], [inn_cv_func_mmap_sees_writes=yes], [inn_cv_func_mmap_sees_writes=no], [inn_cv_func_mmap_sees_writes=no])]) if test $inn_cv_func_mmap_sees_writes = no ; then AC_DEFINE([MMAP_MISSES_WRITES], 1, [Define if you need to call msync after writes.]) fi]) dnl Check whether msync takes three arguments. (It takes three arguments on dnl Solaris and Linux, two arguments on BSDI.) AC_DEFUN([INN_FUNC_MSYNC_ARGS], [AC_CACHE_CHECK([how many arguments msync takes], [inn_cv_func_msync_args], [AC_COMPILE_IFELSE( [AC_LANG_PROGRAM([[ #include #include ]], [[char *p; int psize; msync (p, psize, MS_ASYNC);]])], [inn_cv_func_msync_args=3], [inn_cv_func_msync_args=2])]) if test $inn_cv_func_msync_args = 3 ; then AC_DEFINE([HAVE_MSYNC_3_ARG], 1, [Define if your msync function takes three arguments.]) fi]) inn-2.6.4/m4/inet-ntoa.m40000644000175200017520000000341714002373703014405 0ustar iuliusiuliusdnl Check for a working inet_ntoa. dnl $Id: inet-ntoa.m4 10246 2018-02-16 21:12:42Z iulius $ dnl dnl Check whether inet_ntoa is present and working. Since calling inet_ntoa dnl involves passing small structs on the stack, present and working versions dnl may still not function with gcc on some platforms (such as IRIX). dnl Provides INN_FUNC_INET_NTOA and defines HAVE_INET_NTOA if inet_ntoa is dnl present and working. dnl dnl The canonical version of this file is maintained in the rra-c-util dnl package, available at . dnl dnl Copyright 1999-2001, 2003 Russ Allbery dnl Copyright 2008-2009 dnl The Board of Trustees of the Leland Stanford Junior University dnl dnl This file is free software; the authors give unlimited permission to copy dnl and/or distribute it, with or without modifications, as long as this dnl notice is preserved. dnl dnl SPDX-License-Identifier: FSFULLR dnl Source used by INN_FUNC_INET_NTOA. AC_DEFUN([_INN_FUNC_INET_NTOA_SOURCE], [[ #include #include #include #include #include int main(void) { struct in_addr in; in.s_addr = htonl(0x7f000000L); return (strcmp(inet_ntoa(in), "127.0.0.0") == 0) ? 0 : 1; } ]]) dnl The public macro. AC_DEFUN([INN_FUNC_INET_NTOA], [AC_CACHE_CHECK(for working inet_ntoa, inn_cv_func_inet_ntoa_works, [AC_RUN_IFELSE([AC_LANG_SOURCE([_INN_FUNC_INET_NTOA_SOURCE])], [inn_cv_func_inet_ntoa_works=yes], [inn_cv_func_inet_ntoa_works=no], [inn_cv_func_inet_ntoa_works=no])]) AS_IF([test x"$inn_cv_func_inet_ntoa_works" = xyes], [AC_DEFINE([HAVE_INET_NTOA], 1, [Define if your system has a working inet_ntoa function.])], [AC_LIBOBJ([inet_ntoa])])]) inn-2.6.4/m4/krb5-config.m40000644000175200017520000001127014002373703014611 0ustar iuliusiuliusdnl Use krb5-config to get link paths for Kerberos libraries. dnl $Id: krb5-config.m4 10520 2021-01-17 21:48:06Z iulius $ dnl dnl Provides one macro, INN_KRB5_CONFIG, which attempts to get compiler and dnl linker flags for a library via krb5-config and sets the appropriate shell dnl variables. Defines the Autoconf variable PATH_KRB5_CONFIG, which can be dnl used to find the default path to krb5-config. dnl dnl Depends on INN_ENABLE_REDUCED_DEPENDS. dnl dnl The canonical version of this file is maintained in the rra-c-util dnl package, available at . dnl dnl Written by Russ Allbery dnl Copyright 2018 Russ Allbery dnl Copyright 2011-2012 dnl The Board of Trustees of the Leland Stanford Junior University dnl dnl This file is free software; the authors give unlimited permission to copy dnl and/or distribute it, with or without modifications, as long as this dnl notice is preserved. dnl dnl SPDX-License-Identifier: FSFULLR dnl Check for krb5-config in the user's path and set PATH_KRB5_CONFIG. This dnl is moved into a separate macro so that it can be loaded via AC_REQUIRE, dnl meaning it will only be run once even if we link with multiple krb5-config dnl libraries. AC_DEFUN([_INN_KRB5_CONFIG_PATH], [AC_ARG_VAR([PATH_KRB5_CONFIG], [Path to krb5-config]) AC_PATH_PROG([PATH_KRB5_CONFIG], [krb5-config], [], [${PATH}:/usr/kerberos/bin])]) dnl Check whether the --deps flag is supported by krb5-config. Takes the path dnl to krb5-config to use. Note that this path is not embedded in the cache dnl variable, so this macro implicitly assumes that we will always use the dnl same krb5-config program. AC_DEFUN([_INN_KRB5_CONFIG_DEPS], [AC_REQUIRE([_INN_KRB5_CONFIG_PATH]) AC_CACHE_CHECK([for --deps support in krb5-config], [inn_cv_krb5_config_deps], [AS_IF(["$1" 2>&1 | grep deps >/dev/null 2>&1], [inn_cv_krb5_config_deps=yes], [inn_cv_krb5_config_deps=no])])]) dnl Obtain the library flags for a particular library using krb5-config. dnl Takes the path to the krb5-config program to use, the argument to dnl krb5-config to use, and the variable prefix under which to store the dnl library flags. AC_DEFUN([_INN_KRB5_CONFIG_LIBS], [AC_REQUIRE([_INN_KRB5_CONFIG_PATH]) AC_REQUIRE([INN_ENABLE_REDUCED_DEPENDS]) _INN_KRB5_CONFIG_DEPS([$1]) AS_IF([test x"$inn_reduced_depends" = xfalse \ && test x"$inn_cv_krb5_config_deps" = xyes], [$3[]_LIBS=`"$1" --deps --libs $2 2>/dev/null`], [$3[]_LIBS=`"$1" --libs $2 2>/dev/null`])]) dnl Attempt to find the flags for a library using krb5-config. Takes the dnl following arguments (in order): dnl dnl 1. The root directory for the library in question, generally from an dnl Autoconf --with flag. Used by preference as the path to krb5-config. dnl dnl 2. The argument to krb5-config to retrieve flags for this particular dnl library. dnl dnl 3. The variable prefix to use when setting CPPFLAGS and LIBS variables dnl based on the result of krb5-config. dnl dnl 4. Further actions to take if krb5-config was found and supported that dnl library type. dnl dnl 5. Further actions to take if krb5-config could not be used to get flags dnl for that library type. dnl dnl Special-case a krb5-config argument of krb5 and run krb5-config without an dnl argument if that option was requested and not supported. Old versions of dnl krb5-config didn't take an argument to specify the library type, but dnl always returned the flags for libkrb5. AC_DEFUN([INN_KRB5_CONFIG], [inn_krb5_config_$3= inn_krb5_config_$3[]_ok= AS_IF([test x"$1" != x && test -x "$1/bin/krb5-config"], [inn_krb5_config_$3="$1/bin/krb5-config"], [_INN_KRB5_CONFIG_PATH inn_krb5_config_$3="$PATH_KRB5_CONFIG"]) AS_IF([test x"$inn_krb5_config_$3" != x && test -x "$inn_krb5_config_$3"], [AC_CACHE_CHECK([for $2 support in krb5-config], [inn_cv_lib_$3[]_config], [AS_IF(["$inn_krb5_config_$3" 2>&1 | grep $2 >/dev/null 2>&1], [inn_cv_lib_$3[]_config=yes], [inn_cv_lib_$3[]_config=no])]) AS_IF([test "$inn_cv_lib_$3[]_config" = yes], [$3[]_CPPFLAGS=`"$inn_krb5_config_$3" --cflags $2 2>/dev/null` _INN_KRB5_CONFIG_LIBS([$inn_krb5_config_$3], [$2], [$3]) inn_krb5_config_$3[]_ok=yes], [AS_IF([test x"$2" = xkrb5], [$3[]_CPPFLAGS=`"$inn_krb5_config_$3" --cflags 2>/dev/null` $3[]_LIBS=`"$inn_krb5_config_$3" --libs $2 2>/dev/null` inn_krb5_config_$3[]_ok=yes])])]) AS_IF([test x"$inn_krb5_config_$3[]_ok" = xyes], [$3[]_CPPFLAGS=`AS_ECHO(["$$3[]_CPPFLAGS"]) | sed 's%-I/usr/include %%'` $3[]_CPPFLAGS=`AS_ECHO(["$$3[]_CPPFLAGS"]) | sed 's%-I/usr/include$%%'` $4], [$5])]) inn-2.6.4/m4/cc-flags.m40000644000175200017520000000563214002373703014167 0ustar iuliusiuliusdnl Check whether the compiler supports particular flags. dnl $Id: cc-flags.m4 10520 2021-01-17 21:48:06Z iulius $ dnl dnl Provides INN_PROG_CC_FLAG and INN_PROG_LD_FLAG, which checks whether a dnl compiler supports a given flag for either compilation or linking, dnl respectively. If it does, the commands in the second argument are run. dnl If not, the commands in the third argument are run. dnl dnl The canonical version of this file is maintained in the rra-c-util dnl package, available at . dnl dnl Copyright 2016-2020 Russ Allbery dnl Copyright 2006, 2009, 2016 dnl by Internet Systems Consortium, Inc. ("ISC") dnl dnl Permission to use, copy, modify, and/or distribute this software for any dnl purpose with or without fee is hereby granted, provided that the above dnl copyright notice and this permission notice appear in all copies. dnl dnl THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH dnl REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF dnl MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY dnl SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES dnl WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN dnl ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR dnl IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. dnl dnl SPDX-License-Identifier: ISC dnl Used to build the result cache name. AC_DEFUN([_INN_PROG_CC_FLAG_CACHE], [translit([inn_cv_compiler_c_$1], [-=+,], [____])]) AC_DEFUN([_INN_PROG_LD_FLAG_CACHE], [translit([inn_cv_linker_c_$1], [-=+,], [____])]) dnl Check whether a given flag is supported by the compiler when compiling a C dnl source file. AC_DEFUN([INN_PROG_CC_FLAG], [AC_REQUIRE([AC_PROG_CC]) AC_MSG_CHECKING([if $CC supports $1]) AC_CACHE_VAL([_INN_PROG_CC_FLAG_CACHE([$1])], [save_CFLAGS=$CFLAGS AS_CASE([$1], [-Wno-*], [CFLAGS="$CFLAGS `AS_ECHO(["$1"]) | sed 's/-Wno-/-W/'`"], [*], [CFLAGS="$CFLAGS $1"]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([], [int foo = 0;])], [_INN_PROG_CC_FLAG_CACHE([$1])=yes], [_INN_PROG_CC_FLAG_CACHE([$1])=no]) CFLAGS=$save_CFLAGS]) AC_MSG_RESULT([$_INN_PROG_CC_FLAG_CACHE([$1])]) AS_IF([test x"$_INN_PROG_CC_FLAG_CACHE([$1])" = xyes], [$2], [$3])]) dnl Check whether a given flag is supported by the compiler when linking an dnl executable. AC_DEFUN([INN_PROG_LD_FLAG], [AC_REQUIRE([AC_PROG_CC]) AC_MSG_CHECKING([if $CC supports $1 for linking]) AC_CACHE_VAL([_INN_PROG_LD_FLAG_CACHE([$1])], [save_LDFLAGS=$LDFLAGS LDFLAGS="$LDFLAGS $1" AC_LINK_IFELSE([AC_LANG_PROGRAM([], [int foo = 0;])], [_INN_PROG_LD_FLAG_CACHE([$1])=yes], [_INN_PROG_LD_FLAG_CACHE([$1])=no]) LDFLAGS=$save_LDFLAGS]) AC_MSG_RESULT([$_INN_PROG_LD_FLAG_CACHE([$1])]) AS_IF([test x"$_INN_PROG_LD_FLAG_CACHE([$1])" = xyes], [$2], [$3])]) inn-2.6.4/m4/socket-unix.m40000644000175200017520000000616114002373703014757 0ustar iuliusiuliusdnl Various checks for UNIX domain socket support and macros. dnl $Id: socket-unix.m4 10246 2018-02-16 21:12:42Z iulius $ dnl dnl This is a collection of various Autoconf macros for checking UNIX domain dnl socket properties. The macros provided are: dnl dnl INN_MACRO_SUN_LEN dnl INN_SYS_UNIX_SOCKETS dnl dnl They use a separate internal source macro to make the code easier to read. dnl dnl The canonical version of this file is maintained in the rra-c-util dnl package, available at . dnl dnl Copyright 2009 dnl The Board of Trustees of the Leland Stanford Junior University dnl Copyright 2004-2009 Internet Systems Consortium, Inc. ("ISC") dnl Copyright 1991, 1994-2003 The Internet Software Consortium and Rich Salz dnl dnl This code is derived from software contributed to the Internet Software dnl Consortium by Rich Salz. dnl dnl Permission to use, copy, modify, and distribute this software for any dnl purpose with or without fee is hereby granted, provided that the above dnl copyright notice and this permission notice appear in all copies. dnl dnl THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH dnl REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF dnl MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY dnl SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES dnl WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN dnl ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR dnl IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. dnl dnl SPDX-License-Identifier: ISC dnl Source used by INN_MACRO_SUN_LEN. AC_DEFUN([_INN_MACRO_SUN_LEN_SOURCE], [[ #include #include int main(void) { struct sockaddr_un s_un; int i = SUN_LEN(&s_un); } ]]) dnl Check for SUN_LEN, which returns the size of a struct sockaddr_un. Sets dnl HAVE_SUN_LEN if the macro is available. AC_DEFUN([INN_MACRO_SUN_LEN], [AC_CACHE_CHECK([for SUN_LEN macro], [inn_cv_sun_len_macro], [AC_LINK_IFELSE([AC_LANG_SOURCE([_INN_MACRO_SUN_LEN_SOURCE])], [inn_cv_sun_len_macro=yes], [inn_cv_sun_len_macro=no])]) AS_IF([test x"$inn_cv_sun_len_macro" = xyes], [AC_DEFINE([HAVE_SUN_LEN], 1, [Define if defines the SUN_LEN macro.])])]) dnl Source used by INN_SYS_UNIX_SOCKETS. AC_DEFUN([_INN_SYS_UNIX_SOCKETS], [[ #include #include #ifndef AF_UNIX error: No UNIX domain sockets! #endif ]]) dnl Check if UNIX domain sockets are supported. Assume that they are if dnl AF_UNIX is set in . This loses on really old versions of dnl Linux, where AF_UNIX is available but doesn't work, but we don't care dnl about Linux 1.0 any more. AC_DEFUN([INN_SYS_UNIX_SOCKETS], [AC_CACHE_CHECK([for UNIX domain sockets], [inn_cv_sys_unix_sockets], [AC_COMPILE_IFELSE([AC_LANG_SOURCE([_INN_SYS_UNIX_SOCKETS])], [inn_cv_sys_unix_sockets=yes], [inn_cv_sys_unix_sockets=no])]) AS_IF([test x"$inn_cv_sys_unix_sockets" = xyes], [AC_DEFINE([HAVE_UNIX_DOMAIN_SOCKETS], 1, [Define if you have UNIX domain sockets.])])]) inn-2.6.4/m4/prog-ensure.m40000644000175200017520000000067014002373703014753 0ustar iuliusiuliusdnl prog-ensure.m4 -- Require that a program be found in the PATH. dnl $Id: prog-ensure.m4 8475 2009-05-17 20:30:23Z iulius $ dnl dnl This is a version of AC_PATH_PROG that requires that the program being dnl searched for is found in the user's PATH. AC_DEFUN([INN_PATH_PROG_ENSURE], [if test x"${$1}" = x ; then AC_PATH_PROG([$1], [$2]) fi if test x"${$1}" = x ; then AC_MSG_ERROR([$2 was not found in path and is required]) fi]) inn-2.6.4/m4/krb5.m40000644000175200017520000004265214002373703013356 0ustar iuliusiuliusdnl Find the compiler and linker flags for Kerberos. dnl dnl Finds the compiler and linker flags for linking with Kerberos libraries. dnl Provides the --with-krb5, --with-krb5-include, and --with-krb5-lib dnl configure options to specify non-standard paths to the Kerberos libraries. dnl Uses krb5-config where available unless reduced dependencies is requested dnl or --with-krb5-include or --with-krb5-lib are given. dnl dnl Provides the macro INN_LIB_KRB5 and sets the substitution variables dnl KRB5_CPPFLAGS, KRB5_LDFLAGS, and KRB5_LIBS. Also provides dnl INN_LIB_KRB5_SWITCH to set CPPFLAGS, LDFLAGS, and LIBS to include the dnl Kerberos libraries, saving the current values first, and dnl INN_LIB_KRB5_RESTORE to restore those settings to before the last dnl INN_LIB_KRB5_SWITCH. HAVE_KRB5 will always be defined if INN_LIB_KRB5 is dnl used. dnl dnl If KRB5_CPPFLAGS, KRB5_LDFLAGS, or KRB5_LIBS are set before calling these dnl macros, their values will be added to whatever the macros discover. dnl dnl KRB5_CPPFLAGS_WARNINGS will be set to the same value as KRB5_CPPFLAGS but dnl with any occurrences of -I changed to -isystem. This may be useful to dnl suppress warnings from the Kerberos header files when building with and dnl aggressive warning flags. Be aware that this change will change the dnl compiler header file search order as well. dnl dnl Provides the INN_LIB_KRB5_OPTIONAL macro, which should be used if Kerberos dnl support is optional. In this case, Kerberos libraries are mandatory if dnl --with-krb5 is given, and will not be probed for if --without-krb5 is dnl given. Otherwise, they'll be probed for but will not be required. dnl Defines HAVE_KRB5 and sets inn_use_KRB5 to true if the libraries are dnl found. The substitution variables will always be set, but they will be dnl empty unless Kerberos libraries are found and the user did not disable dnl Kerberos support. dnl dnl Sets the Automake conditional KRB5_USES_COM_ERR saying whether we use dnl com_err, since if we're also linking with AFS libraries, we may have to dnl change library ordering in that case. dnl dnl Depends on INN_KRB5_CONFIG, INN_ENABLE_REDUCED_DEPENDS, and dnl INN_SET_LDFLAGS. dnl dnl Also provides INN_FUNC_KRB5_GET_INIT_CREDS_OPT_FREE_ARGS, which checks dnl whether krb5_get_init_creds_opt_free takes one argument or two. Defines dnl HAVE_KRB5_GET_INIT_CREDS_OPT_FREE_2_ARGS if it takes two arguments. dnl dnl Also provides INN_INCLUDES_KRB5, which are the headers to include when dnl probing the Kerberos library properties. dnl dnl The canonical version of this file is maintained in the rra-c-util dnl package, available at . dnl dnl Written by Russ Allbery dnl Copyright 2018, 2020-2021 Russ Allbery dnl Copyright 2005-2011, 2013-2014 dnl The Board of Trustees of the Leland Stanford Junior University dnl dnl This file is free software; the authors give unlimited permission to copy dnl and/or distribute it, with or without modifications, as long as this dnl notice is preserved. dnl dnl SPDX-License-Identifier: FSFULLR dnl Headers to include when probing for Kerberos library properties. AC_DEFUN([INN_INCLUDES_KRB5], [[ #if HAVE_KRB5_H # include #elif HAVE_KERBEROSV5_KRB5_H # include #else # include #endif ]]) dnl Save the current CPPFLAGS, LDFLAGS, and LIBS settings and switch to dnl versions that include the Kerberos flags. Used as a wrapper, with dnl INN_LIB_KRB5_RESTORE, around tests. AC_DEFUN([INN_LIB_KRB5_SWITCH], [inn_krb5_save_CPPFLAGS="$CPPFLAGS" inn_krb5_save_LDFLAGS="$LDFLAGS" inn_krb5_save_LIBS="$LIBS" CPPFLAGS="$KRB5_CPPFLAGS $CPPFLAGS" LDFLAGS="$KRB5_LDFLAGS $LDFLAGS" LIBS="$KRB5_LIBS $LIBS"]) dnl Restore CPPFLAGS, LDFLAGS, and LIBS to their previous values (before dnl INN_LIB_KRB5_SWITCH was called). AC_DEFUN([INN_LIB_KRB5_RESTORE], [CPPFLAGS="$inn_krb5_save_CPPFLAGS" LDFLAGS="$inn_krb5_save_LDFLAGS" LIBS="$inn_krb5_save_LIBS"]) dnl Set KRB5_CPPFLAGS and KRB5_LDFLAGS based on inn_krb5_root, dnl inn_krb5_libdir, and inn_krb5_includedir. AC_DEFUN([_INN_LIB_KRB5_PATHS], [AS_IF([test x"$inn_krb5_libdir" != x], [KRB5_LDFLAGS="-L$inn_krb5_libdir"], [AS_IF([test x"$inn_krb5_root" != x], [INN_SET_LDFLAGS([KRB5_LDFLAGS], [$inn_krb5_root])])]) AS_IF([test x"$inn_krb5_includedir" != x], [KRB5_CPPFLAGS="-I$inn_krb5_includedir"], [AS_IF([test x"$inn_krb5_root" != x], [AS_IF([test x"$inn_krb5_root" != x/usr], [KRB5_CPPFLAGS="-I${inn_krb5_root}/include"])])])]) dnl Check for a header using a file existence check rather than using dnl AC_CHECK_HEADERS. This is used if there were arguments to configure dnl specifying the Kerberos header path, since we may have one header in the dnl default include path and another under our explicitly-configured Kerberos dnl location. Sets inn_krb5_header_found to true if the header is found. AC_DEFUN([_INN_LIB_KRB5_CHECK_HEADER], [AC_MSG_CHECKING([for $1]) AS_IF([test -f "${inn_krb5_incroot}/$1"], [inn_krb5_header_found=true AC_DEFINE_UNQUOTED(AS_TR_CPP([HAVE_$1]), [1], [Define to 1 if you have the <$1> header file.]) AC_MSG_RESULT([yes])], [AC_MSG_RESULT([no])])]) dnl Check for the com_err header. Internal helper macro since we need dnl to do the same checks in multiple places. Sets inn_krb5_header_found dnl to true if one header is found. AC_DEFUN([_INN_LIB_KRB5_CHECK_HEADER_COM_ERR], [AS_IF([test x"$inn_krb5_incroot" = x], [AC_CHECK_HEADERS([et/com_err.h kerberosv5/com_err.h], [inn_krb5_header_found=true])], [_INN_LIB_KRB5_CHECK_HEADER([et/com_err.h]) _INN_LIB_KRB5_CHECK_HEADER([kerberosv5/com_err.h])])]) dnl Check for the main Kerberos header. Internal helper macro since we need dnl to do the same checks in multiple places. Sets inn_krb5_header_found dnl to true if one header is found. AC_DEFUN([_INN_LIB_KRB5_CHECK_HEADER_KRB5], [AS_IF([test x"$inn_krb5_incroot" = x], [AC_CHECK_HEADERS([krb5.h kerberosv5/krb5.h krb5/krb5.h], [inn_krb5_header_found=true])], [_INN_LIB_KRB5_CHECK_HEADER([krb5.h]) _INN_LIB_KRB5_CHECK_HEADER([kerberosv5/krb5.h]) _INN_LIB_KRB5_CHECK_HEADER([krb5/krb5.h])])]) dnl Does the appropriate library checks for reduced-dependency Kerberos dnl linkage. The single argument, if true, says to fail if Kerberos could not dnl be found. AC_DEFUN([_INN_LIB_KRB5_REDUCED], [inn_krb5_header_found=false _INN_LIB_KRB5_CHECK_HEADER_KRB5 AS_IF([test x"$inn_krb5_header_found" = xtrue], [INN_LIB_KRB5_SWITCH AC_CHECK_LIB([krb5], [krb5_init_context], [KRB5_LIBS="-lkrb5" LIBS="$KRB5_LIBS $LIBS" AC_CHECK_FUNCS([krb5_get_error_message], [AC_CHECK_FUNCS([krb5_free_error_message])], [AC_CHECK_FUNCS([krb5_get_error_string], [], [AC_CHECK_FUNCS([krb5_get_err_txt], [], [AC_CHECK_LIB([ksvc], [krb5_svc_get_msg], [KRB5_LIBS="$KRB5_LIBS -lksvc" AC_DEFINE([HAVE_KRB5_SVC_GET_MSG], [1]) AC_CHECK_HEADERS([ibm_svc/krb5_svc.h], [], [], [INN_INCLUDES_KRB5])], [inn_krb5_header_found=false _INN_LIB_KRB5_CHECK_HEADER_COM_ERR AS_IF([test x"$inn_krb5_header_found" = xtrue], [AC_CHECK_LIB([com_err], [com_err], [KRB5_LIBS="$KRB5_LIBS -lcom_err"], [AS_IF([test x"$1" = xtrue], [AC_MSG_ERROR([cannot find usable com_err library])], [KRB5_LIBS=""])])], [AS_IF([test x"$1" = xtrue], [AC_MSG_ERROR([cannot find usable com_err header])])])])])])])], [AS_IF([test x"$1" = xtrue], [AC_MSG_ERROR([cannot find usable Kerberos library])])])], [AS_IF([test x"$1" = xtrue], [AC_MSG_ERROR([cannot find usable Kerberos header])])]) INN_LIB_KRB5_RESTORE]) dnl Does the appropriate library checks for Kerberos linkage when we don't dnl have krb5-config or reduced dependencies. The single argument, if true, dnl says to fail if Kerberos could not be found. AC_DEFUN([_INN_LIB_KRB5_MANUAL], [inn_krb5_header_found=false _INN_LIB_KRB5_CHECK_HEADER_KRB5 AS_IF([test x"$inn_krb5_header_found" = xtrue], [INN_LIB_KRB5_SWITCH inn_krb5_extra= LIBS= AC_SEARCH_LIBS([res_search], [resolv], [], [AC_SEARCH_LIBS([__res_search], [resolv])]) AC_SEARCH_LIBS([gethostbyname], [nsl]) AC_SEARCH_LIBS([socket], [socket], [], [AC_CHECK_LIB([nsl], [socket], [LIBS="-lnsl -lsocket $LIBS"], [], [-lsocket])]) AC_SEARCH_LIBS([crypt], [crypt]) AC_SEARCH_LIBS([roken_concat], [roken]) inn_krb5_extra="$LIBS" LIBS="$inn_krb5_save_LIBS" AC_CHECK_LIB([krb5], [krb5_init_context], [KRB5_LIBS="-lkrb5 -lasn1 -lcom_err -lcrypto $inn_krb5_extra"], [AC_CHECK_LIB([krb5support], [krb5int_getspecific], [inn_krb5_extra="-lkrb5support $inn_krb5_extra"], [AC_CHECK_LIB([pthreads], [pthread_setspecific], [inn_krb5_pthread="-lpthreads"], [AC_CHECK_LIB([pthread], [pthread_setspecific], [inn_krb5_pthread="-lpthread"])]) AC_CHECK_LIB([krb5support], [krb5int_setspecific], [inn_krb5_extra="-lkrb5support $inn_krb5_extra $inn_krb5_pthread"], [], [$inn_krb5_pthread $inn_krb5_extra])], [$inn_krb5_extra]) AC_CHECK_LIB([com_err], [error_message], [inn_krb5_extra="-lcom_err $inn_krb5_extra"], [], [$inn_krb5_extra]) AC_CHECK_LIB([ksvc], [krb5_svc_get_msg], [inn_krb5_extra="-lksvc $inn_krb5_extra"], [], [$inn_krb5_extra]) AC_CHECK_LIB([k5crypto], [krb5int_hash_md5], [inn_krb5_extra="-lk5crypto $inn_krb5_extra"], [], [$inn_krb5_extra]) AC_CHECK_LIB([k5profile], [profile_get_values], [inn_krb5_extra="-lk5profile $inn_krb5_extra"], [], [$inn_krb5_extra]) AC_CHECK_LIB([krb5], [krb5_cc_default], [KRB5_LIBS="-lkrb5 $inn_krb5_extra"], [AS_IF([test x"$1" = xtrue], [AC_MSG_ERROR([cannot find usable Kerberos library])])], [$inn_krb5_extra])], [-lasn1 -lcom_err -lcrypto $inn_krb5_extra]) LIBS="$KRB5_LIBS $LIBS" AC_CHECK_FUNCS([krb5_get_error_message], [AC_CHECK_FUNCS([krb5_free_error_message])], [AC_CHECK_FUNCS([krb5_get_error_string], [], [AC_CHECK_FUNCS([krb5_get_err_txt], [], [AC_CHECK_FUNCS([krb5_svc_get_msg], [AC_CHECK_HEADERS([ibm_svc/krb5_svc.h], [], [], [INN_INCLUDES_KRB5])], [inn_krb5_header_found=false _INN_LIB_KRB5_CHECK_HEADER_COM_ERR AS_IF([test x"$inn_krb5_header_found" != xtrue], [AS_IF([test x"$1" = xtrue], [AC_MSG_ERROR([cannot find usable com_err header])])])])])])])], [AS_IF([test x"$1" = xtrue], [AC_MSG_ERROR([cannot find usable Kerberos header])])]) INN_LIB_KRB5_RESTORE]) dnl Sanity-check the results of krb5-config and be sure we can really link a dnl Kerberos program. If that fails, clear KRB5_CPPFLAGS and KRB5_LIBS so dnl that we know we don't have usable flags and fall back on the manual dnl check. AC_DEFUN([_INN_LIB_KRB5_CHECK], [INN_LIB_KRB5_SWITCH AC_CHECK_FUNC([krb5_init_context], [INN_LIB_KRB5_RESTORE], [INN_LIB_KRB5_RESTORE KRB5_CPPFLAGS= KRB5_LIBS= _INN_LIB_KRB5_PATHS _INN_LIB_KRB5_MANUAL([$1])])]) dnl Determine Kerberos compiler and linker flags from krb5-config. Does the dnl additional probing we need to do to uncover error handling features, and dnl falls back on the manual checks. AC_DEFUN([_INN_LIB_KRB5_CONFIG], [INN_KRB5_CONFIG([${inn_krb5_root}], [krb5], [KRB5], [inn_krb5_header_found=false _INN_LIB_KRB5_CHECK_HEADER_KRB5 AS_IF([test x"$inn_krb5_header_found" = xtrue], [_INN_LIB_KRB5_CHECK([$1]) INN_LIB_KRB5_SWITCH AC_CHECK_FUNCS([krb5_get_error_message], [AC_CHECK_FUNCS([krb5_free_error_message])], [AC_CHECK_FUNCS([krb5_get_error_string], [], [AC_CHECK_FUNCS([krb5_get_err_txt], [], [AC_CHECK_FUNCS([krb5_svc_get_msg], [AC_CHECK_HEADERS([ibm_svc/krb5_svc.h], [], [], [INN_INCLUDES_KRB5])], [inn_krb5_header_found=false _INN_LIB_KRB5_CHECK_HEADER_COM_ERR AS_IF([test x"$inn_krb5_header_found" != xtrue], [AS_IF([test x"$1" = xtrue], [AC_MSG_ERROR([cannot find usable com_err header])])])])])])]) INN_LIB_KRB5_RESTORE], [AS_IF([test x"$1" = xtrue], [AC_MSG_ERROR([cannot find usable Kerberos header])])])], [_INN_LIB_KRB5_PATHS _INN_LIB_KRB5_MANUAL([$1])])]) dnl The core of the library checking, shared between INN_LIB_KRB5 and dnl INN_LIB_KRB5_OPTIONAL. The single argument, if "true", says to fail if dnl Kerberos could not be found. Set up inn_krb5_incroot for later header dnl checking. AC_DEFUN([_INN_LIB_KRB5_INTERNAL], [AC_REQUIRE([INN_ENABLE_REDUCED_DEPENDS]) inn_krb5_incroot= AC_SUBST([KRB5_CPPFLAGS]) AC_SUBST([KRB5_CPPFLAGS_WARNINGS]) AC_SUBST([KRB5_LDFLAGS]) AC_SUBST([KRB5_LIBS]) AS_IF([test x"$inn_krb5_includedir" != x], [inn_krb5_incroot="$inn_krb5_includedir"], [AS_IF([test x"$inn_krb5_root" != x], [inn_krb5_incroot="${inn_krb5_root}/include"])]) AS_IF([test x"$inn_reduced_depends" = xtrue], [_INN_LIB_KRB5_PATHS _INN_LIB_KRB5_REDUCED([$1])], [AS_IF([test x"$inn_krb5_includedir" = x && test x"$inn_krb5_libdir" = x], [_INN_LIB_KRB5_CONFIG([$1])], [_INN_LIB_KRB5_PATHS _INN_LIB_KRB5_MANUAL([$1])])]) inn_krb5_uses_com_err=false AS_CASE([$KRB5_LIBS], [*-lcom_err*], [inn_krb5_uses_com_err=true]) AM_CONDITIONAL([KRB5_USES_COM_ERR], [test x"$inn_krb5_uses_com_err" = xtrue]) KRB5_CPPFLAGS_WARNINGS=`AS_ECHO(["$KRB5_CPPFLAGS"]) | sed -e 's/-I/-isystem /g'`]) dnl The main macro for packages with mandatory Kerberos support. AC_DEFUN([INN_LIB_KRB5], [inn_krb5_root= inn_krb5_libdir= inn_krb5_includedir= inn_use_KRB5=true AC_ARG_WITH([krb5], [AS_HELP_STRING([--with-krb5=DIR], [Location of Kerberos headers and libraries])], [AS_IF([test x"$withval" != xyes && test x"$withval" != xno], [inn_krb5_root="$withval"])]) AC_ARG_WITH([krb5-include], [AS_HELP_STRING([--with-krb5-include=DIR], [Location of Kerberos headers])], [AS_IF([test x"$withval" != xyes && test x"$withval" != xno], [inn_krb5_includedir="$withval"])]) AC_ARG_WITH([krb5-lib], [AS_HELP_STRING([--with-krb5-lib=DIR], [Location of Kerberos libraries])], [AS_IF([test x"$withval" != xyes && test x"$withval" != xno], [inn_krb5_libdir="$withval"])]) _INN_LIB_KRB5_INTERNAL([true]) AC_DEFINE([HAVE_KRB5], 1, [Define to enable Kerberos features.])]) dnl The main macro for packages with optional Kerberos support. AC_DEFUN([INN_LIB_KRB5_OPTIONAL], [inn_krb5_root= inn_krb5_libdir= inn_krb5_includedir= inn_use_KRB5= AC_ARG_WITH([krb5], [AS_HELP_STRING([--with-krb5@<:@=DIR@:>@], [Location of Kerberos headers and libraries])], [AS_IF([test x"$withval" = xno], [inn_use_KRB5=false], [AS_IF([test x"$withval" != xyes], [inn_krb5_root="$withval"]) inn_use_KRB5=true])]) AC_ARG_WITH([krb5-include], [AS_HELP_STRING([--with-krb5-include=DIR], [Location of Kerberos headers])], [AS_IF([test x"$withval" != xyes && test x"$withval" != xno], [inn_krb5_includedir="$withval"])]) AC_ARG_WITH([krb5-lib], [AS_HELP_STRING([--with-krb5-lib=DIR], [Location of Kerberos libraries])], [AS_IF([test x"$withval" != xyes && test x"$withval" != xno], [inn_krb5_libdir="$withval"])]) AS_IF([test x"$inn_use_KRB5" != xfalse], [AS_IF([test x"$inn_use_KRB5" = xtrue], [_INN_LIB_KRB5_INTERNAL([true])], [_INN_LIB_KRB5_INTERNAL([false])])], [AM_CONDITIONAL([KRB5_USES_COM_ERR], [false])]) AS_IF([test x"$KRB5_LIBS" != x], [inn_use_KRB5=true AC_DEFINE([HAVE_KRB5], 1, [Define to enable Kerberos features.])])]) dnl Source used by INN_FUNC_KRB5_GET_INIT_CREDS_OPT_FREE_ARGS. AC_DEFUN([_INN_FUNC_KRB5_OPT_FREE_ARGS_SOURCE], [INN_INCLUDES_KRB5] [[ int main(void) { krb5_get_init_creds_opt *opts; krb5_context c; krb5_get_init_creds_opt_free(c, opts); } ]]) dnl Check whether krb5_get_init_creds_opt_free takes one argument or two. dnl Early Heimdal used to take a single argument. Defines dnl HAVE_KRB5_GET_INIT_CREDS_OPT_FREE_2_ARGS if it takes two arguments. dnl dnl Should be called with INN_LIB_KRB5_SWITCH active. AC_DEFUN([INN_FUNC_KRB5_GET_INIT_CREDS_OPT_FREE_ARGS], [AC_CACHE_CHECK([if krb5_get_init_creds_opt_free takes two arguments], [inn_cv_func_krb5_get_init_creds_opt_free_args], [AC_COMPILE_IFELSE([AC_LANG_SOURCE([_INN_FUNC_KRB5_OPT_FREE_ARGS_SOURCE])], [inn_cv_func_krb5_get_init_creds_opt_free_args=yes], [inn_cv_func_krb5_get_init_creds_opt_free_args=no])]) AS_IF([test $inn_cv_func_krb5_get_init_creds_opt_free_args = yes], [AC_DEFINE([HAVE_KRB5_GET_INIT_CREDS_OPT_FREE_2_ARGS], 1, [Define if krb5_get_init_creds_opt_free takes two arguments.])])]) inn-2.6.4/m4/pam-const.m40000644000175200017520000000466314002373703014414 0ustar iuliusiuliusdnl Determine whether PAM uses const in prototypes. dnl $Id: pam-const.m4 10450 2020-12-09 21:55:08Z iulius $ dnl dnl Linux marks several PAM arguments const, including the argument to dnl pam_get_item and some arguments to conversation functions, which Solaris dnl doesn't. Mac OS X, OS X and macOS mark the first argument to pam_strerror dnl const, and other platforms don't. This test tries to determine which dnl style is in use to select whether to declare variables const and how dnl to prototype functions in order to avoid compiler warnings. dnl dnl Since this is just for compiler warnings, it's not horribly important if dnl we guess wrong. This test is ugly, but it seems to work. dnl dnl The canonical version of this file is maintained in the rra-c-util dnl package, available at . dnl dnl Written by Markus Moeller dnl Copyright 2007, 2015 Russ Allbery dnl Copyright 2007-2008 Markus Moeller dnl dnl This file is free software; the authors give unlimited permission to copy dnl and/or distribute it, with or without modifications, as long as this dnl notice is preserved. dnl dnl SPDX-License-Identifier: FSFULLR dnl Source used by INN_HEADER_PAM_CONST. AC_DEFUN([_INN_HEADER_PAM_CONST_SOURCE], [#ifdef HAVE_SECURITY_PAM_APPL_H # include #else # include #endif ]) AC_DEFUN([INN_HEADER_PAM_CONST], [AC_CACHE_CHECK([whether PAM prefers const], [inn_cv_header_pam_const], [AC_EGREP_CPP([const void \*\* *_?item], _INN_HEADER_PAM_CONST_SOURCE(), [inn_cv_header_pam_const=yes], [inn_cv_header_pam_const=no])]) AS_IF([test x"$inn_cv_header_pam_const" = xyes], [inn_header_pam_const=const], [inn_header_pam_const=]) AC_DEFINE_UNQUOTED([PAM_CONST], [$inn_header_pam_const], [Define to const if PAM uses const in pam_get_item, empty otherwise.])]) AC_DEFUN([INN_HEADER_PAM_STRERROR_CONST], [AC_CACHE_CHECK([whether pam_strerror uses const], [inn_cv_header_pam_strerror_const], [AC_EGREP_CPP([pam_strerror *\(const], _INN_HEADER_PAM_CONST_SOURCE(), [inn_cv_header_pam_strerror_const=yes], [inn_cv_header_pam_strerror_const=no])]) AS_IF([test x"$inn_cv_header_pam_strerror_const" = xyes], [inn_header_pam_strerror_const=const], [inn_header_pam_strerror_const=]) AC_DEFINE_UNQUOTED([PAM_STRERROR_CONST], [$inn_header_pam_strerror_const], [Define to const if PAM uses const in pam_strerror, empty otherwise.])]) inn-2.6.4/m4/users.m40000644000175200017520000000222714002373703013646 0ustar iuliusiuliusdnl users.m4 -- The usernames built into INN at compile time. dnl $Id: users.m4 8495 2009-05-24 12:28:19Z iulius $ dnl dnl INN allows the user and group INN will run as to be specified, as well as dnl the user to receive nightly reports and the like. dnl The settings are all fairly similar, so factor the commonality into this dnl macro. Takes the name of what we're looking for, the default, the dnl variable to set, the help string, and the comment for config.h. AC_DEFUN([_INN_ARG_USER], [AC_ARG_WITH([news-$1], [$4], [$3=$with_news_$1], [$3=$2]) AC_SUBST($3) AC_DEFINE_UNQUOTED($3, "$[$3]", [$5])]) dnl And here they are. AC_DEFUN([INN_ARG_USERS], [_INN_ARG_USER([user], [news], [RUNASUSER], [AS_HELP_STRING([--with-news-user=USER], [News user name [news]])], [The user that INN should run as.]) _INN_ARG_USER([group], [news], [RUNASGROUP], [AS_HELP_STRING([--with-news-group=GROUP], [News group name [news]])], [The group that INN should run as.]) _INN_ARG_USER([master], [usenet], [NEWSMASTER], [AS_HELP_STRING([--with-news-master=USER], [News master (address for reports) [usenet]])], [The user who gets all INN-related e-mail.])]) inn-2.6.4/m4/cc-c-o.m40000644000175200017520000000357514002373703013555 0ustar iuliusiuliusdnl cc-c-o.m4 -- Checks whether -o can be used with -c. dnl $Id: cc-c-o.m4 8407 2009-04-11 17:16:06Z iulius $ dnl dnl Used to check whether -o can be provided with -c with the chosen compiler. dnl We need this if we're not using libtool so that object files can be built dnl in subdirectories. This macro is stolen shamelessly from the libtool dnl macros. Note that we don't use the Autoconf version because it both dnl checks too much (checking cc as well as the chosen compiler) and it sets a dnl compiler #define rather than setting a variable we can use. dnl dnl $compiler_c_o is set to yes if the compiler supports this and no if not. AC_DEFUN([INN_PROG_CC_C_O], [AC_REQUIRE([AC_OBJEXT]) AC_MSG_CHECKING([if $CC supports -c -o file.$ac_objext]) AC_CACHE_VAL([inn_cv_compiler_c_o], [rm -f -r conftest 2>/dev/null mkdir conftest cd conftest echo "int some_variable = 0;" > conftest.$ac_ext mkdir out # According to Tom Tromey, Ian Lance Taylor reported there are C compilers # that will create temporary files in the current directory regardless of # the output directory. Thus, making CWD read-only will cause this test # to fail, enabling locking or at least warning the user not to do parallel # builds. chmod -w . save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -o out/conftest2.$ac_objext" compiler_c_o=no if { (eval $ac_compile) 2> out/conftest.err; } \ && test -s out/conftest2.$ac_objext; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings if test -s out/conftest.err; then inn_cv_compiler_c_o=no else inn_cv_compiler_c_o=yes fi else # Append any errors to the config.log. cat out/conftest.err 1>&AS_MESSAGE_LOG_FD inn_cv_compiler_c_o=no fi CFLAGS="$save_CFLAGS" chmod u+w . rm -f conftest* out/* rmdir out cd .. rmdir conftest rm -f -r conftest 2>/dev/null]) compiler_c_o=$inn_cv_compiler_c_o AC_MSG_RESULT([$compiler_c_o])]) inn-2.6.4/m4/ltversion.m40000644000175200017520000000127314002373703014532 0ustar iuliusiulius# ltversion.m4 -- version numbers -*- Autoconf -*- # # Copyright (C) 2004, 2011-2015 Free Software Foundation, Inc. # Written by Scott James Remnant, 2004 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # @configure_input@ # serial 4179 ltversion.m4 # This file is part of GNU Libtool m4_define([LT_PACKAGE_VERSION], [2.4.6]) m4_define([LT_PACKAGE_REVISION], [2.4.6]) AC_DEFUN([LTVERSION_VERSION], [macro_version='2.4.6' macro_revision='2.4.6' _LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?]) _LT_DECL(, macro_revision, 0) ]) inn-2.6.4/README0000644000175200017520000003426614002373703012613 0ustar iuliusiuliusWelcome to INN 2.6! This work is sponsored by Internet Systems Consortium. Please see INSTALL for installation instructions, NEWS for what's changed from the previous release, and LICENSE for the copyright, license, and distribution terms. What is INN? INN (InterNetNews), originally written by Rich Salz, is an extremely flexible and configurable Usenet / Netnews news server. For a complete description of the protocols behind Usenet and Netnews, see RFC 3977 (NNTP), RFC 4642 updated by RFC 8143 (TLS/NNTP), RFC 4643 (NNTP authentication), RFC 4644 (streaming NNTP feeds), RFC 5536 (USEFOR), RFC 5537 (USEPRO), RFC 6048 (NNTP LIST additions) and RFC 8054 (NNTP compression) or their replacements. In brief, Netnews is a set of protocols for exchanging messages between a decentralized network of news servers. News articles are organized into newsgroups, which are themselves organized into hierarchies. Each individual news server stores locally all articles it has received for a given newsgroup, making access to stored articles extremely fast. Netnews does not require any central server; instead, each news server passes along articles it receives to all of the news servers it peers with, those servers pass the articles along to their peers, and so on, resulting in "flood fill" propagation of news articles. A news server performs three basic functions: it accepts articles from other servers and stores them on disk, sends articles it has received out to other servers, and offers stored news articles to readers on demand. It additionally has to perform some periodic maintenance tasks, such as deleting older articles to make room for new ones. Originally, a news server would just store all of the news articles it had received in a file system. Users could then read news by reading the article files on disk (or more commonly using news reading software that did this efficiently). These days, news servers are almost always stand-alone systems and news reading is supported via network connections. A user who wants to read a newsgroup opens that newsgroup in their newsreader software, which opens a network connection to the news server and sends requests for articles and related information. The protocol that a newsreader uses to talk to a news server and that a news server uses to talk to another news server over TCP/IP is called NNTP (Network News Transport Protocol). INN supports accepting articles via either NNTP connections or via UUCP. innd, the heart of INN, handles NNTP feeding connections directly; UUCP newsfeeds use rnews (included in INN) to hand articles off to innd. Other parts of INN handle feeding articles out to other news servers, most commonly innfeed (for real-time outgoing feeds) or nntpsend and innxmit (used to send batches of news created by innd to a remote site via TCP/IP). INN can also handle outgoing UUCP feeds. The part of INN that handles connections from newsreaders is nnrpd. Also included in INN are a wide variety of supporting programs to handle periodic maintenance and recovery from crashes, process special control messages, maintain the list of active newsgroups, and generate and record a staggering variety of statistics and summary information on the usage and performance of the server. INN also supports an extremely powerful filtering system that allows the server administrator to reject unwanted articles (such as spam and other abuses of Usenet). INN is free software, supported by Internet Systems Consortium and volunteers around the world. See "Supporting the INN Effort" below. Prerequisites Compiling INN requires an ANSI C compiler (gcc is recommended). INN was originally written in K&R C, but supporting pre-ANSI compilers has become enough of a headache that a lot of the newer parts of INN will no longer compile with a non-ANSI compiler. gcc itself will compile with most vendor non-ANSI compilers, however, so if you're stuck with one, installing gcc is highly recommended. Not only will it let you build INN, it will make installing lots of other software much easier. You may also need GNU make (particularly if your system make is BSD-derived), although most SysV make programs should work fine. Compiling INN also currently requires a yacc implementation (bison will do fine). INN uses GNU autoconf to probe the capabilities of your system, and therefore should compile on nearly any Unix system. It does, however, make extensive use of mmap(), which can cause problems on some older operating systems. See INSTALL for a list of systems it is known to work on. If you encounter problems compiling or running INN, or if you successfully run INN on a platform that isn't listed in INSTALL, please let us know (see "Reporting Bugs" below). Perl 5.004_03 or later is required to build INN and use the embedded Perl filter support (which is highly recommended; some excellent spam filters have been written for INN). Since all versions of Perl previous to 5.004 are buggy (including security problems) and have fewer features, installing Perl 5.004_03 or later (like at least Perl 5.8.0) is recommended. If you want to enable PGP verification of control messages (highly recommended), you will need to have a PGP implementation installed. See INSTALL for more details. Getting Started A news server can be a fairly complicated piece of software to set up just because of the wide variety of pieces that have to be configured (who is authorized to read from the server, what newsgroups it carries, and how the articles are stored on disk at a bare minimum, and if the server isn't completely stand-alone -- and very few servers are -- both incoming and outgoing feeds have to be set up and tested). Be prepared to take some time to understand what's going on and how all the pieces fit together. If you have any specific suggestions for documentation, or comments about things that are unclear, please send them to the INN maintainers (see "Reporting Bugs" below). See INSTALL for step-by-step instructions for setting up and configuring a news server. INN also comes with a very complete set of man pages; there is a man page for every configuration file and program that comes with INN. (If you find one that doesn't have a man page, that's a bug. Please do report it.) When trying to figure out some specific problem, reading the man pages for all of the configuration files involved is a very good start. Reporting Bugs We're interested in all bug reports. Not just on the programs, but on the documentation too. Please send *all* such reports to inn-workers@lists.isc.org (patches are certainly welcome, see below). Even if you post to Usenet, please CC the above address. If you have general "how do I do this" questions or problems configuring your server that you don't believe are due to a bug in INN, you should post them to news.software.nntp. A lot of experienced INN users, including several of the INN maintainers, read that newsgroup regularly. Please don't send general questions to the above addresses; those addresses are specifically for INN, and the INN maintainers usually won't have time to answer general questions. Contributing Code If you have a patch or a utility that you'd like to be considered for inclusion into INN, please mail it to inn-workers@lists.isc.org in the body of the message (not as an attachment because the mailing-list might strip it), or put it on a webpage and send a link. Patches included with a bug report as described above should follow the same procedure. Have fun! Mailing Lists There are various INN-related mailing lists you can join or send messages to if you like. Some of them you must be a member of before you can send mail to them (thank the spammers for that policy), and one of them is read-only (no postings allowed). inn-announce@lists.isc.org Where announcements about INN are set (only maintainers may post). inn-workers@lists.isc.org Discussion of INN development. It is also where to send bug reports and patches for consideration for inclusion into INN (postings by members only). If you're an INN expert and have the time to help out other users, we encourage you to join this mailing list to answer questions. (You may also want to read the newsgroup news.software.nntp, which gets a lot of INN-related questions.) inn-committers@lists.isc.org Subversion commit messages for INN are sent to this list (only the automated messages are sent here, no regular posting). inn-bugs@lists.isc.org Trac tickets for INN are sent to this list (only the automated messages are sent here, no regular posting). Bug reports should be sent to the inn-workers mailing list. To join these lists, send a subscription request to the "-request" address. The addresses for the above lists are: inn-announce-request@lists.isc.org inn-workers-request@lists.isc.org inn-committers-request@lists.isc.org inn-bugs-request@lists.isc.org Who's Responsible / Who to Thank See CONTRIBUTORS for a long list of past contributors as well as people from the inn-workers mailing list who have dedicated a lot of time and effort to getting this new version together. They deserve a big round of applause. They've certainly got our thanks. This product includes software developed by UUNET Technologies, Inc. and by the University of California, Berkeley and its contributors. Last, but certainly not least, Rich Salz, the original author of INN deserves a lion's share of the credit for writing INN in the first place and making it the most popular news server software on the planet (no NNTP yet to the moon, but we plan to be there first). Related Packages INN users may also be interested in the following software packages that work with INN or are based on it. Please note that none of this software is developed or maintained by ISC; we don't support it and generally can't answer questions about it. Cleanfeed URL: (maintained by Steve Crook) Cleanfeed is an extremely powerful spam filter, probably the most widely used spam filter on Usenet currently. It catches excessive multiposting and a host of other things, and is highly configurable. Note that it requires that INN be built with Perl support (the --with-perl option to configure). Cleanfeed was originally developed by Jeremy Nixon who maintained it until 1998. Then Marco d'Itri until 2002. Steve Crook has been maintaining it since 2007. A Python-based variant of Cleanfeed, named PyClean, also exists and can be found at . GUP (Group Update Program) URL: GUP provides a way for your peers to update their newsfeeds entries as they want without having to ask you to edit the configuration file all the time. It's useful when feeding peers take limited and very specific feeds that change periodically. innduct URL: (maintained by Ian Jackson) A possible replacement for innfeed, innxmit and nntpsend that quickly and reliably streams Usenet article to a remote site. innduct is designed to be robust and not to lose any articles (when offered to peers) in case it unexpectedly dies, contrary to innfeed. It also permits a realtime feed, contrary to innxmit or nntpsend. NewsPortal URL: A PHP-based web news reader that works as a front-end to a regular news server such as INN and lets people read and post without learning a news reader. PersonalINN URL: PersonalINN is a version of INN modified for personal use and with a friendly GUI built on top of it. It is available for NEXTSTEP or OPENSTEP only, unfortunately. suck URL: suck is a separate package for downloading a news feed via a reading connection (rather than via a direct NNTP or UUCP feed) and sending outgoing local posts via POST. It's intended primarily for personal or small-organization news servers who get their news via an ISP and are too small to warrant setting up a regular news feed. Supporting the INN Effort Note that INN is supported by Internet Systems Consortium, and although it is free for use and redistribution and incorporation into vendor products and export and anything else you can think of, it costs money to produce. That money comes from ISPs, hardware and software vendors, companies who make extensive use of the software, and generally kind-hearted folk such as yourself. Internet Systems Consortium has also commissioned a DHCP server implementation and handles the official support/release of BIND. You can learn more about the ISC's goals and accomplishments from the web page at . Russ Allbery Katsuhiro Kondou $Id: readme.pod 10359 2020-03-08 21:47:11Z eagle $ inn-2.6.4/ChangeLog0000644000175200017520000004324514002373703013502 0ustar iuliusiulius2021-01-21 iulius * Time to release 2.6.4! 2021-01-20 iulius * INSTALL: a bit of clean-up, and update the list of tested OS * Update to latest upstream files control.ctl, pgpverify, Libtool, pkg-config, config.guess and config.sub * Improve NEWS and add the new year in LICENSE * Update links to external repositories * Compare space usage of our 3 overview storage methods 2021-01-17 iulius * Add support for systemd socket activation Thanks to Marco d'Itri for that new feature! * m4/krb5.m4: fix the detection of Kerberos V5 support Kerberos V5 was considered available even though C headers were not present. Now fixed that by probing both the existence of headers and libraries. * m4/python.m4: fix the detection of old Python 2.x versions The current code for probing the presence of Python only workq with Python 2.7+ and 3.1+ because the "major" attribute to sys.version_info was only added in these versions. Also, the construct 'x for y in z' is too recent and not known by Python 2.3.0, the minimum version required for INN, so I changed it to a classic map(). If two arguments were not given to the m4 macro, the script also failed. Now fixed. * Use AS_ECHO instead of echo in Autoconf macros AS_ECHO is more portable. The echo shell function may not be reliable in the calls we do, with variables containing "-" or other characters. 2021-01-15 iulius * innd: add systemd notifications for xexec and shutdown * inndf: report buffindexed usage with 2 decimals Output was truncated at the inferior number (e.g. 37.00%). 2021-01-11 iulius * Do not run the check for POD syntax if Test::POD is too old Test::POD versions prior to 1.50 may not ignore directories like .libs set in the ignore_dirs hash (due to a bug). This causes the test to fail whereas POD syntax is OK. * Improve sample init systemd script Thanks to Marco d'Itri, Debian packager of INN, for the ideas. Also enable notify type. * rc.news: start innd last when using systemd innd must be started last with exec to keep the same PID of this script. Patch from Marco d'Itri. 2021-01-05 iulius * Detail and homogenize the description of our 3 overview methods * Makefile: Remove useless flags for the linker when just compiling lib/perl.c Use condensed $(LIBLD) variable. * Add -fstack-protector-strong for linking if recognized Building innd on Solaris fails if the compiler does not have amongst its flags -fstack-protector-strong for linking. Undefined first referenced symbol in file __stack_chk_fail art.o __stack_chk_guard art.o ld: fatal: symbol referencing errors Also, if the compiler does not support -fstack-protector-strong for linking, assume it will not work, and remove that flag even for compiling (AIX typically does not have libssp_nonshared). 2021-01-04 iulius * configure: also change CC_WARNINGS when CFLAGS is changed * Fix build issue when using "make warnings" -fPIE was not present when needed when using "make warnings", causing various problems. * Move to configure.ac the logic to undefine AM_CONDITIONAL * Added preliminary support for systemd notifications Integrate necessary Autoconf macros and portability headers to use systemd. Right now, only notifications of innd startup and mode changes are notified to the unit system. Thanks to Marco d'Itri for this first systemd integration into INN. 2021-01-03 iulius * Add a comment in configure.ac and fix POD typo from previous commits * Fix build of fseeko replacement AC_FUNC_FSEEKO needs being called unconditionally out of consistency with the logic in clibrary.h (first looking for !HAVE_FSEEKO before DO_LARGEFILES, and not the contrary). * inn.conf: Mention how to disable the process of cancel messages 2020-12-31 eagle * Add detail for rejected header When nnrpd rejects a posting because of an invalid header that isn't part of the header table, include the name of the header as an aid in debugging, or the full header if no colon could be found or if the line starts with a colon. Reported by Adam Sjøgren and Lars Ingebrigtsen. 2020-12-24 eagle * Fix some subtle errors with nnrpd external auth If nnrpd saw EOF on the stderr file descriptor from an external auth program, it would ignore any further output on stdout. This was the cause of the maddeningly intermittant nnrpd/auth-ext test failures for tests 56 and 59. Sometimes the closure of stderr would be seen before the flush of output on stdout, causing the code to fail to see the username. Fix this problem with more explicit state tracking for stderr. If we see EOF or an error in the stderr file descriptor, remove it from the select set but continue processing stdout until we also see an EOF or error there. Add a new test that explicitly closes stderr. This failed consistently with the previous code and passes consistently with this code. Also close the read and error file descriptors for the external authentication program in nnrpd. Previously, we were leaking those file descriptors. * Switch nnrpd/auth-ext to the new test API Use the new test API so that failures will be reported with more detail in the hope that this will help track down the intermittant failure. * Fix GCC warnings in tests/lib/date-t.c GCC 10.2.1 rightfully complains that the snprintf invocations in this test may overflow the buffer length and truncate. Use basprintf instead to avoid having to size buffers. 2020-12-22 iulius * pgpverify: add a comment about requirements for GnuPG 1.4.20 or 2.1.0 2020-12-19 eagle * Use a fixed buffer size for QIO The buffer size for QIO is also a limit on the length of an overview line, and the previous complex approach resulted in a buffer size of 8KB on nearly all systems, which was too small in practice. Stop attempting to be clever and size according to the file system block size, which is generally small, and instead use a fixed and predictable buffer size of 32KB, which shouldn't be a problem on any modern system. 2020-12-09 iulius * INSTALL: Document the need of shared libraries or position-independent static libraries * Update new name of macOS * Typo in last commit * Mention that lines in header field bodies are separated by mere LF in Perl nnrpd filter * Update to latest rra-c-util upstream version Specific fixes for INN builds on Alpine and BSD: * In the getnameinfo replacement, handle musl libc's gethostbyaddr, which returns the string conversion of the IP address if the host doesn't resolve. This only affects the test suite, since musl libc supports IPv6 and thus doesn't need this replacement. * NetBSD prefers reallocarr to reallocarray and only prototypes the latter if _OPENBSD_SOURCE is defined, which is not one of the macros Autoconf defines by default. Work around this by checking whether reallocarray is declared, not only whether it's available, and protyping it if it's not declared. This uses the semi-hidden deprecated symbol on NetBSD. * configure.ac: use new Autoconf 2.70 syntax for AC_PROG_LEX Use 'noyywrap' for AC_PROG_LEX. Use AC_CONFIG_HEADERS instead of obsolete AC_CONFIG_HEADER. >From Autoconf 2.70 documentation: AC_PROG_LEX now takes one argument, which may be either 'yywrap' or 'noyywrap'. If it is 'noyywrap', AC_PROG_LEX will only set LEXLIB to '-lfl' or '-ll' if a scanner that defines both main and yywrap itself still needs something else from that library. On the other hand, if it is 'yywrap', AC_PROG_LEX will fail (setting LEX to ':' and LEXLIB to nothing) if it can't find a library that defines yywrap. In the absence of arguments, AC_PROG_LEX's behavior is bug-compatible with 2.69, which did neither of the above things. This mode is deprecated. Prior to Autoconf 2.70, AC_PROG_LEX did not take any arguments, and its behavior was different from either of the above possibilities: it would search for a library that defines 'yywrap', and would set 'LEXLIB' to that library if it finds one. However, if a library that defines this function could not be found, 'LEXLIB' would be left empty and 'LEX' would _not_ be reset. This behavior was due to a bug. * Improve logs when Python filters are not installed 2020-12-06 eagle * Update URL for Postfilter code.google.com is no more. This seems to be the new location on GitHub. 2020-12-01 iulius * Fix build issue in linker feature probing Thanks to Bo Lindbergh for the report. * Improve sample init systemd service unit Apply more protections. Sample shared by Russ Allbery. 2020-11-24 iulius * Fix other circular dependencies in builds 2020-11-22 iulius * Bump revision numbers in INN libraries * Add a check in configure to prevent a build with shared non-PIC libraries * Add support for hardening build flags New --enable-hardening-flags option to configure, enabled by default. It currently adds -fPIE, -fstack-protector-strong at build time, and -z relro as well as -z now at link time. More flags will eventually be added in future releases. This option can easily be disabled if the compiler or the platform does not support them well. * Update to latest control.ctl upstream file 2020-11-21 iulius * Fix spurious errors when verifying POD syntax Exclude the directory of the test suite. * Fix build with static libraries The ACTIVE parameter is no longer shared between expire.c and ov.c, so it no longer has to be exposed in ovinterface.h. Its removal fixes the naming conflict with another ACTIVE parameter in nnrpd. * Update to latest Libtool and install-sh upstream versions Libtool => use Debian-2.4.6-14 version install-sh => upstream has integrated local modifications we had carried for years in INN. Parameters have been integrated with different names, so update Makefile accordingly (-c is now -p; -B is now -S) as well as documentation * Update to latest config.guess and config.sub upstream versions * Typo fixes * Fix build with static libraries Circular dependencies were not correctly resolved by the linker. Seems to be a bug in the --preserve-dup-deps Libtool flag, that does not do what it is supposed to do. Fixed in a local modification in ltmain.sh, reported to upstream. * sm: support reading and storing wire-format articles Any number of articles can now be given in wire format to sm on its standard input when both "-s" and "-R" are used. Only native format was previously possible. This might be useful for certain types of internal migrations. Thanks to Bo Lindbergh for the patch. 2020-11-12 iulius * innd: make SIGTERM behave exactly like "ctlinnd shutdown" Patch from Marco d'Itri. * perl-nocem: document the use of gpg1 to import old PGP keys * docs/pod.t: Fix path to Perl interpreter in test suite Thanks to Bo Lindbergh for the bug report. * Add missing header files to silent gcc warning Fix build on a few systems like MacOS (warnings may make the system consider the configure test failed). Thanks to Bo Lindbergh for the bug report. * Update to latest rra-c-util and C TAP Harness upstream versions * Fix syntax in Makefile GNU make 4.3 emits the following warning: "ignoring prerequisites on suffix rule definition". In previous versions, no warning was emitted and a suffix rule was created, however all prerequisites were ignored and were not part of the suffix rule. Starting with GNU make 4.3, the behaviour is the same, and in addition a warning is generated. This commit fixes the syntax. * Fix yacc declaration for types POSIX yacc reserves %type to nonterminals. Found with new -Wyacc warning option in Bison 3.5. 2020-06-14 iulius * innreport: silent normal behaviour from rnews - Only "bad_article missing Message-ID" was skipped whereas other header fields are also checked. Change to "bad_article missing ". - Skip all "rejected 437" and "rejected 439" because responses could be different with other news servers. 2020-06-13 iulius * innreport: externalize CSS Inline styles are not allowed by a (good) Content-Security-Policy because they're vulnerable to XSS. It has become common practice to always externalize all CSS into a separate file. External CSS is also more cacheable though this isn't the primary motivation here. Patch adapted from a suggestion of Richard Kettlewell. * innreport: use INN version instead of legacy 3.1.0 version * innreport: modernize HTML No insecure external content. Remove icons for W3C XHTML and CSS validation. The reason is to avoid errors when serving innreport output via HTTPS). Thanks to Richard Kettlewell for the patch. 2020-05-24 iulius * rnews: new -d flag to log duplicates When -d is used, rnews will syslog the message-ID and the Path header value of each article rejected as a duplicate by the server. It was previously only a compile-time option (DO_RNEWS_LOG_DUPS in options.h), which I am unsure worked fine because there were several wordings in the rnews code: DONT_RNEWS_LOG_DUPS, SYSLOG_RNEWS_LOG_DUPS, FILE_RNEWS_LOG_DUPS. Remove INN_PATH_RNEWS_DUP_LOG (hard-coded to "/dev/null"). One can now parameter its syslog configuration to obtain that information, if needed. * Typo fix in a variable name Should have done a rebuild before committing! * rnews: new -a flag to configure the use of additional unpackers Added a new "-a" flag to rnews to disallow, if needed, the use of additional unpackers from "/rnews.libexec"; only "rnews" and "cunbatch" will then be recognized as valid batch commands. It was previously only a compile-time option (DO_RNEWSPROGS). * rnews: add -b flag to back up badly formatted articles This new -b flag to rnews permits saving rejected articles in the "bad" sub-directory of . Otherwise, rnews just logs and discards any articles that are rejected or cannot be parsed for some reason. This feature was previously available only via the compile-time option DO_RNEWS_SAVE_BAD. Thanks to Herbert Xu for the proposal of making it easily available. 2020-05-21 iulius * Clarify nnrpd TLS instructions Thanks to Richard Kettlewell for the suggestion. 2020-05-10 iulius * Fix build with GCC 10.1 Ensure that ser_line is at least 4-byte long. And that there is enough room in buff to copy the path. * innd: remove unused filterPath variable Variable unused since 2001 (removal forgotten in commit 4435). 2020-03-08 eagle * Change readme.pod links to https Prefer https where available for links to supporting software. 2020-01-07 eagle * Suppress (spurious) uninitialized warnings GCC 8.3 thinks that some variables in buffindexed/buffindexed.c could be used uninitialized. Initialize them to silence the compiler. 2019-10-31 eagle * Make IOV_MAX Autoconf check more cross-compile-friendly The IOV_MAX Autoconf check always compiled and ran a program and relied on the output from that program to indicate that IOV_MAX was set in limits.h, which causes problems with cross-compilation. Instead, use AC_CHECK_DECL to check for the common case that IOV_MAX is defined in limits.h, and only compile and run a program for the uncommon case that this fails. Tested only on Linux, but by changing the probe to look for something other than IOV_MAX and then for something other than UIO_MAXIOV, to make sure all the branches work. Thanks, Helmut Grohne. 2019-10-27 iulius * cnfsstat: output information about retired CNFS buffers When not in a metacycbuff, CNFS buffers still mentioned in cycbuff were not displayed. 2019-09-17 iulius * nnrpd: fix the selection of DH parameters When the parameters have already been initialized, the callback returns NULL instead of the previously loaded buffer. Fix to previous commit 10344. Thanks to Adam D. Barratt for having caught the issue. 2019-05-31 iulius * nnrpd: Adapt the length of DH parameters depending on security level Remove hard-coded 512 and 1024-bit DH parameters to only use more secure DH parameters taken from a more recent RFC 7919. When OpenSSL is configured with a security level beyond 1 (which is the case with Debian Buster for instance), shorter parameters might not be accepted. Negotiations for ciphersuites using DHE key exchange then fail. From OpenSSL documentation: "Previous versions of the callback used is_export and keylength parameters to control parameter generation for export and non-export cipher suites. Modern servers that do not support export cipher suites are advised to either use SSL_CTX_set_tmp_dh() or alternatively, use the callback but ignore keylength and is_export and simply supply at least 2048-bit parameters in the callback." Thanks to Michael Baeuerle for the bug report. 2019-05-30 iulius * Fix string operation warnings with GCC 9 Also use CNFSNASIZ when appropriate (for buffer names). * nnrpd: fix build issue with LibreSSL LibreSSL defines itself as version 2 of OpenSSL, though not implementing the same API. 2019-03-09 eagle * Update URL for suck, remove newsx suck has a new usptream on GitHub. newsx appears to be thoroughly gone and has been removed from Debian, so remove it from README. 2019-02-13 iulius * Bump revision numbers to next release inn-2.6.4/control/0000755000175200017520000000000014002373675013410 5ustar iuliusiuliusinn-2.6.4/control/signcontrol.in0000644000175200017520000005465214002373703016305 0ustar iuliusiulius#! /usr/bin/perl -w # written April 1996, (David C Lawrence) # Currently maintained by Russ Allbery # Version 1.9, 2016-10-17 # # Changes from 1.8 -> 1.9 # -- Add use strict and explicitly import LOCK_EX. # -- Fix error reporting around lock files with PGP. # -- Use https for pgpcontrol URLs. # # Changes from 1.6 -> 1.8 # -- Added support for GnuPG. # -- Replace signing code with code from PGP::Sign that generates detached # signatures instead. Otherwise, GnuPG signatures with DSA keys could # not be verified. Should still work the same as before with RSA keys. # -- Thanks to new signing code, no longer uses a temporary file. # -- Only lock when using PGP; GnuPG shouldn't need it. # # Changes from 1.5 -> 1.6 # -- eliminated subprocess use (except pgp, of course). # -- interlock against competing signing processes. # -- allow optional headers; see $use_or_add. # -- added simple comments about why particular headers are signed. # -- made error messages a tad more helpful for situations when it is hard # to know what message was trying to be signed (such as via an "at" # job). # -- set $action, $group, $moderated to "" to prevent unusued variable # warnings in the event a Control header can't be parsed. # -- moved assignment of $pgpend out of loop. # # Changes from 1.4 -> 1.5 # -- need to require Text::Tabs to get 'expand' for tabs in checkgroups. # # Changes from 1.3 -> 1.4 # -- added checkgroups checking. # -- added group name in several error messages (for help w/batch # processing). # -- disabled moderator address checking. # -- adjusted newsgroups line (ie, tabbing fixed) now correctly # substituted into control message. # # Changes from 1.2.3 -> 1.3 # -- skip minor pgp signature headers like "charset:" after "version:" # header and until the empty line that starts the base64 signature block. use strict; # CONFIGURATION # PGP variables. # # $pgp can be set to the path to GnuPG to use GnuPG instead. The program # name needs to end in gpg so that signcontrol knows GnuPG is being used. # # STORING YOUR PASSPHRASE IN A FILE IS A POTENTIAL SECURITY HOLE. # Make sure you know what you're doing if you do it. # If you don't use $pgppassfile, you can only use this script interactively. # If you DO use $pgppassfile, it is possible that someone could steal # your passphrase either by gaining access to the file or by seeing # the environment of a running pgpverify program. # # $pgplock is used because pgp does not guard itself against concurrent # read/write access to its randseed.bin file. A writable file is needed; # The default value is to use the .pgp/config.txt file in the home # directory of the user running the program. Note that this will only # work to lock against other instances of signcontrol, not all pgp uses. # $pgplock is not used if $pgp ends in 'gpg' since GnuPG doesn't need # this. my $pgpsigner = 'INSERT_YOUR_PGP_USERID'; my $pgppassfile = ''; # file with pass phrase for $pgpsigner my $pgp = "/usr/local/bin/pgp"; my $pgpheader = "X-PGP-Sig"; my $pgplock = (getpwuid($<))[7] . '/.pgp/config.txt'; # this program is strict about always wanting to be consistent about what # headers appear in the control messages. the defaults for the # @... arrays are reasonable, but you should edit the force values. # these headers are acceptable in input, but they will be overwritten with # these values. no sanity checking is done on what you put here. also, # Subject: is forced to be the Control header prepending by "cmsg". also, # Newsgroups: is forced to be just the group being added/removed. # (but is taken as-is for checkgroups) my %force; $force{'Path'} = 'bounce-back'; $force{'From'} = 'YOUR_ADDRESS_AND_NAME'; $force{'Approved'} = 'ADDRESS_FOR_Approved_HEADER'; $force{'X-Info'}='https://ftp.isc.org/pub/pgpcontrol/README.html' . "\n\t" . 'https://ftp.isc.org/pub/pgpcontrol/README'; # these headers are acceptable in input, or if not present then will be # created with the given value. None are enabled by default, because they # should not be necessary. Setting one to a null string will pass through # any instance of it found in the input, but not generate one if it is # missing. If you set any $use_or_add{} variables, you must also put it in # @orderheaders below. # # Note that Distribution nearly never works correctly, so use it only if # you are really sure the propagation of the article will be limited as # you intend. This normally means that you control all servers the # distribution will go to with an iron fist. # my %use_or_add; # $use_or_add{'Reply-To'} = 'YOUR_REPLY_ADDRESS'; # $use_or_add{'Oranization'} = 'YOUR_ORGANIZATION'; # $use_or_add{'Distribution'} = 'MESSAGE_DISTRIBUTION'; # host for message-id; this could be determined automatically based on # where it is run, but consistency is the goal here my $id_host = 'FULL_HOST_NAME'; # headers to sign. Sender is included because non-PGP authentication uses # it. The following should always be signed: # Subject -- some older news systems use it to identify the control action. # Control -- most news systems use this to determine what to do. # Message-ID -- guards against replay attacks. # Date -- guards against replay attacks. # From -- used by news systems as part of authenticating the message. # Sender -- used by news systems as part of authenticating the message. my @signheaders = ('Subject', 'Control', 'Message-ID', 'Date', 'From', 'Sender'); # headers to remove from real headers of final message. # If it is a signed header, it is signed with an empty value. # set to () if you do not want any headers removed. my @ignoreheaders = ('Sender'); # headers that will appear in final message, and their order of # appearance. all _must_ be set, either in input or via the $force{} and # $use_or_add{} variables above. # (exceptions: Date, Lines, Message-ID are computed by this program) # if header is in use_or_add with a null value, it will not appear in output. # several are required by the news article format standard; if you remove # these, your article will not propagate: # Path, From, Newsgroups, Subject, Message-ID, Date # if you take out these, your control message is not very useful: # Control, Approved # any headers in @ignoreheaders also in @orderheaders are silently dropped. # any non-null header in the input but not in @orderheaders or @ignoreheaders # is an error. # null headers are silently dropped. my @orderheaders = ('Path', 'From', 'Newsgroups', 'Subject', 'Control', 'Approved', 'Message-ID', 'Date', 'Lines', 'X-Info', $pgpheader); # this program tries to help you out by not letting you sign erroneous # names, especially ones that are so erroneous they run afoul of naming # standards. # # set to match only hierarchies you will use it on # include no '|' for a single hierarchy (eg, "$hierarchies = 'uk';"). my $hierarchies = 'HIERARCHIES'; # the draft news article format standard says: # "subsequent components SHOULD begin with a letter" # where "SHOULD" means: # means that the item is a strong recommendation: there may be # valid reasons to ignore it in unusual circumstances, but # this should be done only after careful study of the full # implications and a firm conclusion that it is necessary, # because there are serious disadvantages to doing so. # as opposed to "MUST" which means: # means that the item is an absolute requirement of the specification # MUST is preferred, but might not be acceptable if you have legacy # newsgroups that have name components that begin with a letter, like # news.announce.newgroups does with comp.sys.3b1 and 17 other groups. my $start_component_with_letter = 'MUST'; ## END CONFIGURATION use Fcntl qw(F_SETFD LOCK_EX); use FileHandle; use IPC::Open3 qw(open3); use POSIX qw(setlocale strftime LC_TIME); use Text::Tabs; # to get 'expand' for tabs in checkgroups $0 =~ s#^.*/##; die "Usage: $0 < message\n" if @ARGV > 0; my $LOCK; umask(0022); # flock needs a writable file, if we create it if ($pgp !~ /gpg$/) { open ($LOCK, '>>', $pgplock) || die "$0: open $pgplock: $!, exiting\n"; flock ($LOCK, LOCK_EX); # block until locked } my ($die, $group, $action, $grouppat, %header, $moderated, $body, @ERROR); # Initialize the $die variable here (we use it to concatenate possible # error messages during the run of the following functions). $die = ''; setgrouppat(); readhead(); readbody(); if ($die) { if ($group) { die "$0: ERROR PROCESSING ${action}group $group:\n", $die; } elsif ($action eq 'check') { die "$0: ERROR PROCESSING checkgroups:\n", $die; } elsif ($header{'Subject'}) { die "$0: ERROR PROCESSING Subject: $header{'Subject'}\n", $die; } else { die $die; } } signit(); if ($pgp !~ /gpg$/) { close ($LOCK) || warn "$0: close $pgplock: $!\n"; } exit 0; sub setgrouppat { my ($plain_component, $no_component); my ($must_start_letter, $should_start_letter); # newsgroup name checks based on RFC 1036bis (not including encodings) rules: # "component MUST contain at least one letter" # "[component] MUST not contain uppercase letters" # "[component] MUST begin with a letter or digit" # "[component] MUST not be longer than 14 characters" # "sequences 'all' and 'ctl' MUST not be used as components" # "first component MUST begin with a letter" # and enforcing "subsequent components SHOULD begin with a letter" as MUST # and enforcing at least a 2nd level group (can't use to newgroup "general") # # DO NOT COPY THIS PATTERN BLINDLY TO OTHER APPLICATIONS! # It has special construction based on the pattern it is finally used in. $plain_component = '[a-z][-+_a-z\d]{0,13}'; $no_component = '(.*\.)?(all|ctl)(\.|$)'; $must_start_letter = '(\.' . $plain_component . ')+'; $should_start_letter = '(\.(?=\d*[a-z])[a-z\d]+[-+_a-z\d]{0,13})+'; $grouppat = "(?!$no_component)($hierarchies)"; if ($start_component_with_letter eq 'SHOULD') { $grouppat .= $should_start_letter; } elsif ($start_component_with_letter eq 'MUST') { $grouppat .= $must_start_letter; } else { die "$0: unknown value configured for \$start_component_with_letter\n"; } foreach my $hierarchy (split /\|/, $hierarchies) { die "$0: hierarchy name $hierarchy not standards-compliant\n" if $hierarchy !~ /^$plain_component$/o; } eval { 'test' =~ /$grouppat/ }; die "$0: bad regexp for matching group names:\n $@" if $@; return; } sub readhead { my ($head, $label, $value); local $/ = ""; $head = ; # get the whole news header $die .= "$0: continuation lines in headers not allowed\n" if $head =~ s/\n[ \t]+/ /g; # rejoin continued lines foreach (split /\n/, $head) { if (/^(\S+): (.*)/) { $label = $1; $value = $2; $die .= "$0: duplicate header $label\n" if $header{$label}; $header{$label} = $value; $header{$label} =~ s/^\s+//; $header{$label} =~ s/\s+$//; } elsif (/^$/) { ; # the empty line separator(s) } else { $die .= "$0: non-header line:\n $_\n"; } } $header{'Message-ID'} = '<' . time . ".$$\@$id_host>"; setlocale(LC_TIME, "C"); $header{'Date'} = strftime("%a, %d %h %Y %T -0000", gmtime); for (@ignoreheaders) { $die .= "ignored header $_ also has forced value set\n" if $force{$_}; $header{$_} = ''; } for (@orderheaders) { $header{$_} = $force{$_} if defined($force{$_}); next if /^(Lines|\Q$pgpheader\E)$/; # these are set later unless ($header{$_}) { if (defined($use_or_add{$_})) { $header{$_} = $use_or_add{$_} if $use_or_add{$_} ne ''; } else { $die .= "$0: missing $_ header\n"; } } } $action = $group = $moderated = ""; if ($header{'Control'}) { if ($header{'Control'} =~ /^(new)group (\S+)( moderated)?$/o || $header{'Control'} =~ /^(rm)group (\S+)()$/o || $header{'Control'} =~ /^(check)groups()()$/o) { ($action, $group, $moderated) = ($1, $2, $3); $die .= "$0: group name $group is not standards-compliant\n" if $group !~ /^$grouppat$/ && $action eq 'new'; $die .= "$0: no group to rmgroup on Control: line\n" if ! $group && $action eq 'rm'; $header{'Subject'} = "cmsg $header{'Control'}"; $header{'Newsgroups'} = $group unless $action eq 'check'; } else { $die .= "$0: bad Control format: $header{'Control'}\n"; } } else { $die .= "$0: can't verify message content; missing Control header\n"; } return; } sub readbody { my ($status, $ngline, $fixline, $used, $desc, $mods); local $/ = undef; $body = ; # slurp the rest of the article $header{'Lines'} = $body =~ tr/\n/\n/ if $body; # the following tests are based on the structure of a # news.announce.newgroups newgroup message; even if you comment out the # "first line" test, please leave the newsgroups line and moderators # checks if ($action eq 'new') { $status = $moderated ? 'a\smoderated' : 'an\sunmoderated'; $die .= "$0: nonstandard first line in body for $group\n" if $body !~ /^\Q$group\E\sis\s$status\snewsgroup\b/; my $intro = "For your newsgroups file:\n"; $ngline = ($body =~ /^$intro\Q$group\E[ \t]+(.+)\n(\n|\Z(?!\n))/mi)[0]; if ($ngline) { $_ = $group; $desc = $1; $fixline = $_; $fixline .= "\t" x ((length) > 23 ? 1 : (4 - ((length) + 1) / 8)); $used = (length) < 24 ? 24 : (length) + (8 - (length) % 8); $used--; $desc =~ s/ \(Moderated\)//i; $desc =~ s/\s+$//; $desc =~ s/\w$/$&./; $die .= "$0: $group description too long\n" if $used + length($desc) > 80; $fixline .= $desc; $fixline .= ' (Moderated)' if $moderated; $body =~ s/^$intro(.+)/$intro$fixline/mi; } else { $die .= "$0: $group newsgroup line not formatted correctly\n"; } # moderator checks are disabled; some sites were trying to # automatically maintain aliases based on this, which is bad policy. if (0 && $moderated) { $die .= "$0: $group submission address not formatted correctly\n" if $body !~ /\nGroup submission address: ?\S+@\S+\.\S+\n/m; $mods = "( |\n[ \t]+)\\([^)]+\\)\n\n"; $die .= "$0: $group contact address not formatted correctly\n" if $body !~ /\nModerator contact address: ?\S+@\S+\.\S+$mods/m; } } # rmgroups have freeform bodies # checkgroups have structured bodies if ($action eq 'check') { for (split /\n/, $body) { my ($group, $description) = /^(\S+)\t+(.+)/; $die .= "$0: no group:\n $_\n" unless $group; $die .= "$0: no description:\n $_\n" unless $description; $die .= "$0: bad group name \"$group\"\n" if $group !~ /^$grouppat$/; $die .= "$0: tab in description\n" if $description =~ /\t/; s/ \(Moderated\)$//; $die .= "$0: $group line too long\n" if length(expand($_)) > 80; } } return; } # Create a detached signature for the given data. The first argument # should be a key id, the second argument the PGP passphrase (which may be # null, in which case PGP will prompt for it), and the third argument # should be the complete message to sign. # # In a scalar context, the signature is returned as an ASCII-armored block # with embedded newlines. In array context, a list consisting of the # signature and the PGP version number is returned. Returns undef in the # event of an error, and the error text is then stored in @ERROR. # # This function is taken almost verbatim from PGP::Sign except the PGP # style is determined from the name of the program used. sub pgp_sign { my ($keyid, $passphrase, $message) = @_; # Ignore SIGPIPE, since we're going to be talking to PGP. local $SIG{PIPE} = 'IGNORE'; # Determine the PGP style. my $pgpstyle = 'PGP2'; if ($pgp =~ /pgps$/) { $pgpstyle = 'PGP5' } elsif ($pgp =~ /gpg$/) { $pgpstyle = 'GPG' } # Figure out what command line we'll be using. PGP v6 and PGP v2 use # compatible syntaxes for what we're trying to do. PGP v5 would have, # except that the -s option isn't valid when you call pgps. *sigh* my @command; if ($pgpstyle eq 'PGP5') { @command = ($pgp, qw/-baft -u/, $keyid); } elsif ($pgpstyle eq 'GPG') { @command = ($pgp, qw/--detach-sign --armor --textmode -u/, $keyid, qw/--force-v3-sigs --pgp2/); } else { @command = ($pgp, qw/-sbaft -u/, $keyid); } # We need to send the password to PGP, but we don't want to use either # the command line or an environment variable, since both may expose us # to snoopers on the system. So we create a pipe, stick the password in # it, and then pass the file descriptor to PGP. PGP wants to know about # this in an environment variable; GPG uses a command-line flag. # 5.005_03 started setting close-on-exec on file handles > $^F, so we # need to clear that here (but ignore errors on platforms where fcntl or # F_SETFD doesn't exist, if any). # # Make sure that the file handles are created outside of the if # statement, since otherwise they leave scope at the end of the if # statement and are automatically closed by Perl. my $passfh = new FileHandle; my $writefh = new FileHandle; local $ENV{PGPPASSFD}; if ($passphrase) { pipe ($passfh, $writefh); eval { fcntl ($passfh, F_SETFD, 0) }; print $writefh $passphrase; close $writefh; if ($pgpstyle eq 'GPG') { push (@command, '--batch', '--passphrase-fd', $passfh->fileno); } else { push (@command, '+batchmode'); $ENV{PGPPASSFD} = $passfh->fileno; } } # Fork off a pgp process that we're going to be feeding data to, and tell # it to just generate a signature using the given key id and pass phrase. my $pgp = new FileHandle; my $signature = new FileHandle; my $errors = new FileHandle; my $pid = eval { open3 ($pgp, $signature, $errors, @command) }; if ($@) { @ERROR = ($@, "Execution of $command[0] failed.\n"); return undef; } # Write the message to the PGP process. Strip all trailing whitespace # for compatibility with older pgpverify and attached signature # verification. $message =~ s/[ \t]+\n/\n/g; print $pgp $message; # All done. Close the pipe to PGP, clean up, and see if we succeeded. # If not, save the error output and return undef. close $pgp; local $/ = "\n"; my @errors = <$errors>; my @signature = <$signature>; close $signature; close $errors; close $passfh if $passphrase; waitpid ($pid, 0); if ($? != 0) { @ERROR = (@errors, "$command[0] returned exit status $?\n"); return undef; } # Now, clean up the returned signature and return it, along with the # version number if desired. PGP v2 calls this a PGP MESSAGE, whereas # PGP v5 and v6 and GPG both (more correctly) call it a PGP SIGNATURE, # so accept either. while ((shift @signature) !~ /-----BEGIN PGP \S+-----\n/) { unless (@signature) { @ERROR = ("No signature from PGP (command not found?)\n"); return undef; } } my $version; while ($signature[0] ne "\n" && @signature) { $version = $1 if ((shift @signature) =~ /^Version:\s+(.*?)\s*$/); } shift @signature; pop @signature; $signature = join '', @signature; chomp $signature; undef @ERROR; return wantarray ? ($signature, $version) : $signature; } sub signit { my ($head, $signheaders); # Form the message to be signed. $signheaders = join ",", @signheaders; $head = "X-Signed-Headers: $signheaders\n"; foreach my $header (@signheaders) { $head .= "$header: $header{$header}\n"; } my $message = "$head\n$body"; # Get the passphrase if available. my $passphrase; if ($pgppassfile && -f $pgppassfile) { $pgppassfile =~ s%^(\s)%./$1%; if (open my $PGPPASS, '<', $pgppassfile) { $passphrase = <$PGPPASS>; close $PGPPASS; chomp $passphrase; } } # Sign the message, getting the signature and PGP version number. my ($signature, $version) = pgp_sign($pgpsigner, $passphrase, $message); unless ($signature) { die "@ERROR\n$0: could not generate signature\n"; } # GnuPG has version numbers containing spaces, which breaks our header # format. Find just some portion that contains a digit. ($version) = ($version =~ /(\S*\d\S*)/); # Put the signature into the headers. $signature =~ s/^/\t/mg; $header{$pgpheader} = "$version $signheaders\n$signature"; for (@ignoreheaders) { delete $header{$_} if defined $header{$_}; } $head = ''; foreach my $header (@orderheaders) { $head .= "$header: $header{$header}\n" if $header{$header}; delete $header{$header}; } foreach my $header (keys %header) { die "$0: unexpected header $header left in header array\n"; } print STDOUT $head; print STDOUT "\n"; print STDOUT $body; return; } # Our lawyer told me to include the following. The upshot of it is that # you can use the software for free as much as you like. # Copyright (c) 1996 UUNET Technologies, Inc. # 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 UUNET Technologies, Inc. # 4. The name of UUNET Technologies ("UUNET") may not be used to endorse or # promote products derived from this software without specific prior # written permission. # # THIS SOFTWARE IS PROVIDED BY UUNET ``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 UUNET 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. # Local variables: # cperl-indent-level: 2 # fill-column: 74 # End: inn-2.6.4/control/controlbatch.in0000644000175200017520000000503014002373703016410 0ustar iuliusiulius#! /bin/sh # fixscript will replace this line with code to load innshellvars ######################################################################## # controlbatch - Run controlchan against a batch file. # # Command usage: controlbatch [feedsite batchfile] # Defaults are feedsite: controlchan!, batchfile: ${BATCH}/controlchan! ######################################################################## # # This script will run controlchan against a batch file. You can use # it to clear occasional backlogs while running controls from a # channel, or even skip the channel and run control messages as a file # feed. # ######################################################################## # # If you're doing the channel thing, you might want to put something # like this in your crontab to do a cleanup in the wee hours: # # 00 04 * * * /controlbatch # ######################################################################## # # If you would rather skip the channel and just process controls each # hour in a batch, use this newsfeeds entry instead of the "stock" # version: # # controlchan!\ # :!*,control,control.*,!control.cancel\ # :Tf,Wnsm: # # And, a crontab entry something like this: # # 30 * * * * /controlbatch # ######################################################################## batchlock="${LOCKS}/LOCK.controlbatch" mypid=$$ # A concession to INN 1.x if [ me${PATHBIN}ow = meow ] ; then PATHBIN=${NEWSBIN} export PATHBIN fi # See if we have no arguments and should use the defaults. If there are # arguments, make sure we have enough to attempt something useful. if [ me${1}ow != meow ] ; then if [ me${2}ow = meow ] ; then echo "Usage: ${0} [feedsite batchfile]" >&2 exit 0 else feedsite=${1} batchfile=${2} fi else feedsite=controlchan\! batchfile=controlchan\! fi # Check if any other copies of controlbatch are running. If we are not # alone, give up here and now. ${PATHBIN}/shlock -p $mypid -f ${batchlock} || exit 0 cd ${BATCH} if [ -s ${batchfile}.work ] ; then cat ${batchfile}.work >>${batchfile}.doit rm -f ${batchfile}.work fi if [ -s ${batchfile} ] ; then mv ${batchfile} ${batchfile}.work if ${PATHBIN}/ctlinnd -s -t30 flush ${feedsite} ; then cat ${batchfile}.work >>${batchfile}.doit rm -f ${batchfile}.work fi fi if [ -s ${batchfile}.doit ] ; then ${PATHBIN}/controlchan \ < ${batchfile}.doit >> ${MOST_LOGS}/controlbatch.log 2>&1 # if you want extra assurance that nothing gets lost... # cat ${batchfile}.doit >> ${batchfile}.done rm -f ${batchfile}.doit fi rm -f ${batchlock} inn-2.6.4/control/Makefile0000644000175200017520000000230714002373703015042 0ustar iuliusiulius## $Id: Makefile 8247 2008-12-21 22:28:19Z iulius $ include ../Makefile.global top = .. ALL = controlbatch controlchan docheckgroups perl-nocem \ pgpverify signcontrol MAN = ../doc/man/perl-nocem.8 ../doc/man/pgpverify.1 all: $(ALL) $(MAN) install: all for F in $(ALL) ; do \ $(CP_XPUB) $$F $D$(PATHBIN)/$$F ; \ done for M in modules/*.pl ; do \ $(CP_RPUB) $$M $D$(PATHCONTROL)/`basename $$M` ; \ done bootstrap: $(MAN) clean clobber distclean: rm -f $(ALL) maintclean: distclean rm -f $(MAN) profiled: all depend: $(FIXSCRIPT): @echo Run configure before running make. See INSTALL for details. @exit 1 ## Build rules. FIX = $(FIXSCRIPT) controlbatch: controlbatch.in $(FIX) ; $(FIX) controlbatch.in controlchan: controlchan.in $(FIX) ; $(FIX) controlchan.in docheckgroups: docheckgroups.in $(FIX) ; $(FIX) docheckgroups.in perl-nocem: perl-nocem.in $(FIX) ; $(FIX) perl-nocem.in pgpverify: pgpverify.in $(FIX) ; $(FIX) pgpverify.in signcontrol: signcontrol.in $(FIX) ; $(FIX) -i signcontrol.in ../doc/man/perl-nocem.8: perl-nocem.in $(POD2MAN) -s 8 -n "PERL-NOCEM" $? > $@ ../doc/man/pgpverify.1: pgpverify.in $(POD2MAN) -s 1 -n "PGPVERIFY" $? > $@ inn-2.6.4/control/pgpverify.in0000644000175200017520000010447314002373703015754 0ustar iuliusiulius#! /usr/bin/perl -w # use lib '@LIBPERLDIR@'; use INN::Config; # If running inside INN, uncomment the above and point to INN::Config. # # Written April 1996, (David C Lawrence) # Currently maintained by Russ Allbery # Version 1.30, 2018-01-21 # # NOTICE TO INN MAINTAINERS: The version that is shipped with INN is the # same as the version that I make available to the rest of the world # (including non-INN sites), so please make all changes through me. # # This program requires Perl 5, probably at least about Perl 5.003 since # that's when FileHandle was introduced. If you want to use this program # and your Perl is too old, please contact me (eagle@eyrie.org) and tell # me about it; I want to know what old versions of Perl are still used in # practice. # # Changes from 1.29 -> 1.30 # -- Support for GnuPG's gpg binary (in addition to gpgv). gpg (from # GnuPG 1.x before 1.4.20, and GnuPG 2.0.x) still validates signatures # made with weak digest algorithms like MD5 whereas current versions # of gpgv no longer do. # -- This new release of pgpverify requires at least GnuPG 1.4.20 or 2.1.0. # If you're using an older version of GnuPG, you have to keep using # pgpverify 1.29. # # Changes from 1.28 -> 1.29 # -- Disambiguate numbered lists from description lists in POD to silent # a pod2man warning. # -- Add a --findid= flag to explicitly search for in the # output from PGP's analysis of the message. In case the signature is # valid but does not contain , pgpverify exits with the new # exit status 4. # # Changes from 1.27 -> 1.28 # -- Use the INN::Config Perl module instead of innshellvars.pl to # accommodate the new build process of INN 2.5. # # Changes from 1.26 -> 1.27 # -- Default to pubring.gpg when trustedkeys.gpg is not found in the # default key location, for backward compatibility. # # Changes from 1.25 -> 1.26 # -- Return the correct status code when the message isn't verified # instead of always returning 255. # # Changes from 1.24 -> 1.25 # -- Fix the -test switch to actually do something. # -- Improve date generation when logging to standard output. # # Changes from 1.23 -> 1.24 # -- Fix bug in the recognition of wire-format articles. # # Changes from 1.15 -> 1.23 # -- Bump version number to match CVS revision number. # -- Replaced all signature verification code with code that uses detached # signatures. Signatures generated by GnuPG couldn't be verified using # attached signatures without adding a Hash: header, and this was the # path of least resistance plus avoids munging problems in the future. # Code taken from PGP::Sign. # # Changes from 1.14 -> 1.15 # -- Added POD documentation. # -- Fixed the -test switch so that it works again. # -- Dropped Perl 4 compatibility and reformatted. Now passes use strict. # # Changes from 1.13.1 -> 1.14 # -- Native support for GnuPG without the pgpgpg wrapper, using GnuPG's # program interface by Marco d'Itri. # -- Always use Sys::Syslog without any setlogsock call for Perl 5.6.0 or # later, since Sys::Syslog in those versions of Perl uses the C library # interface and is now portable. # -- Default to expecting the key ring in $inn'newsetc/pgp if it exists. # -- Fix a portability problem for Perl 4 introduced in 1.12. # # Changes from 1.13 -> 1.13.1 # -- Nothing functional, just moved the innshellvars.pl line to the head of # the script, to accommodate the build process of INN. # # Changes from 1.12 -> 1.13 # -- Use INN's syslog_facility if available. # # Changes from 1.11 -> 1.12 # -- Support for GnuPG. # -- Use /usr/ucb/logger, if present, instead of /usr/bin/logger (the latter # of which, on Solaris at least, is some sort of brain damaged POSIX.2 # command which doesn't use syslog). # -- Made syslog work for dec_osf (version 4, at least). # -- Fixed up priority of '.' operator vs bitwise operators. # # Changes from 1.10 -> 1.11 # -- Code to log error messages to syslog. # See $syslog and $syslog_method configurable variables. # -- Configurably allow date stamp on stderr error messages. # -- Added locking for multiple concurrent pgp instances. # -- More clear error message if pgp exits abnormally. # -- Identify PGP 5 "BAD signature" string. # -- Minor diddling for INN (path to innshellvars.pl changed). # # Changes from 1.9 -> 1.10 # -- Minor diddling for INN 2.0: use $inn'pathtmp if it exists, and # work with the new subst method to find innshellvars.pl. # -- Do not truncate the tmp file when opening, in case it is really # linked to another file. # # Changes from 1.8 -> 1.9 # -- Match 'Bad signature' pgp output to return exit status 3 by removing # '^' in regexp matched on multiline string. # # Changes from 1.7 -> 1.8 # -- Ignore final dot-CRLF if article is in NNTP format. # # Changes from 1.6 -> 1.7 # -- Parse PGP 5.0 'good signature' lines. # -- Allow -test switch; prints pgp input and output. # -- Look for pgp in INN's innshellvars.pl. # -- Changed regexp delimiters for stripping $0 to be compatible with old # Perl. # # Changes from 1.5 -> 1.6 # -- Handle articles encoded in NNTP format ('.' starting line is doubled, # \r\n at line end) by stripping NNTP encoding. # -- Exit 255 with pointer to $HOME or $PGPPATH if pgp can't find key # ring. (It probably doesn't match the necessary error message with # ViaCrypt PGP.) # -- Failures also report Message-ID so the article can be looked up to # retry. # # Changes from 1.4 -> 1.5 # -- Force English language for 'Good signature from user' by passing # +language=en on pgp command line, rather than setting the # environment variable LANGUAGE to 'en'. # # Changes from 1.3 -> 1.4 # -- Now handles wrapped headers that have been unfolded. # (Though I do believe news software oughtn't be unfolding them.) # -- Checks to ensure that the temporary file is really a file, and # not a link or some other weirdness. # Path to the GnuPG gpg binary, if you have GnuPG and don't want to use # gpgv. This will be used in preference to gpgv and PGP. If you have INN # and the script is able to successfully include your INN::Config module, # the value of $INN::Config::gpg will override this. On a recent Debian # variant, use /usr/bin/gpg1 (from the gnupg1 package) if you want to # support old signatures with MD5 digest algorithms. # $gpg = '/usr/local/bin/gpg'; # Path to the GnuPG gpgv binary, if you have GnuPG. If you do, this will # be used in preference to PGP. For most current control messages, you # need a version of GnuPG that can handle RSA signatures. If you have INN # and the script is able to successfully include your INN::Config module, # the value of $INN::Config::gpgv will override this. # $gpgv = '/usr/local/bin/gpgv'; # Path to pgp binary; for PGP 5.0, set the path to the pgpv binary. If # you have INN and the script is able to successfully include your # INN::Config module, the value of $INN::Config::pgp will override this. $pgp = '/usr/local/bin/pgp'; # If you keep your keyring somewhere that is not the default used by pgp, # uncomment the next line and set appropriately. If you have INN and the # script is able to successfully include your INN::Config module, this # will be set to $INN::Config::newsetc/pgp if that directory exists unless # you set it explicitly. GnuPG will use a file named pubring.gpg in this # directory. # $keyring = '/path/to/your/pgp/config'; # If you have INN and the script is able to successfully include your # INN::Config module, the value of $INN::Config::pathtmp and # $INN::Config::locks will override these. $tmpdir = "/tmp"; $lockdir = $tmpdir; # How should syslog be accessed? # # As it turns out, syslogging is very hard to do portably in versions of # Perl prior to 5.6.0. Sys::Syslog should work without difficulty in # 5.6.0 or later and will be used automatically for those versions of Perl # (unless $syslog_method is ''). For earlier versions of Perl, 'inet' is # all that's available up to version 5.004_03. If your syslog does not # accept UDP log packets, such as when syslogd runs with the -l flag, # 'inet' will not work. A value of 'unix' will try to contact syslogd # directly over a Unix domain socket built entirely in Perl code (no # subprocesses). If that is not working for you, and you have the # 'logger' program on your system, set this variable to its full path name # to have a subprocess contact syslogd. If the method is just "logger", # the script will search some known directories for that program. If it # can't be found & used, everything falls back on stderr logging. # # You can test the script's syslogging by running "pgpverify < # /some/text/file" on a file that is not a valid news article. The # "non-header at line #" error should be syslogged. # # $syslog_method = 'unix'; # Unix doman socket, Perl 5.004_03 or higher. # $syslog_method = 'inet'; # UDP to port 514 of localhost. # $syslog_method = ''; # Don't ever try to do syslogging. $syslog_method = 'logger'; # Search for the logger program. # The next two variables are the values to be used for syslog's facility # and level to use, as would be found in syslog.conf. For various # reasons, it is impossible to economically have the script figure out how # to do syslogging correctly on the machine. If you have INN and the # script is able to successfully include you INN::Config module, then # the value of $INN::Config::syslog_facility will override this value of # $syslog_facility; $syslog_level is unaffected. $syslog_facility = 'news'; $syslog_level = 'err'; # Prepend the error message with a timestamp? This is only relevant if # not syslogging, when errors go to stderr. # # $log_date = 0; # Zero means don't do it. # $log_date = 1; # Non-zero means do it. $log_date = -t STDOUT; # Do it if STDOUT is to a terminal. # End of configuration section. require 5; use strict; use vars qw($gpg $gpgv $pgp $keyring $tmp $tmpdir $lockdir $syslog_method $syslog_facility $syslog_level $log_date $findid $test $messageid); use Fcntl qw(O_WRONLY O_CREAT O_EXCL); use FileHandle; use IPC::Open3 qw(open3); use POSIX qw(strftime); use Getopt::Long; # Check the arguments passed to pgpverify. # If a syntax error occurs, do not syslog it: such an error is almost # certainly from someone running the script manually. Getopt::Long::Configure('bundling_override'); GetOptions( 'test' => sub { $test = 1 }, 'findid=s' => \$findid ) or die "Usage: $0 [--findid='string'] [--test] < message\n"; # Grab various defaults from INN::Config if running inside INN. $pgp = $INN::Config::pgp if $INN::Config::pgp && $INN::Config::pgp ne "no-pgp-found-during-configure"; $gpgv = $INN::Config::gpgv if $INN::Config::gpgv; $gpg = $INN::Config::gpg if $INN::Config::gpg; $tmp = ($INN::Config::pathtmp ? $INN::Config::pathtmp : $tmpdir) . "/pgp$$"; $lockdir = $INN::Config::locks if $INN::Config::locks; $syslog_facility = $INN::Config::syslog_facility if $INN::Config::syslog_facility; if (! $keyring && $INN::Config::newsetc) { $keyring = $INN::Config::newsetc . '/pgp' if -d $INN::Config::newsetc . '/pgp'; } # Trim /path/to/prog to prog for error messages. $0 =~ s%^.*/%%; # Make sure that the signature verification program can be executed. if ($gpg) { if (! -x $gpg) { &fail("$0: $gpg: " . (-e _ ? "cannot execute" : "no such file") . "\n"); } } elsif ($gpgv) { if (! -x $gpgv) { &fail("$0: $gpgv: " . (-e _ ? "cannot execute" : "no such file") . "\n"); } } elsif (! -x $pgp) { &fail("$0: $pgp: " . (-e _ ? "cannot execute" : "no such file") . "\n"); } # Parse the article headers and generate the PGP message. my ($nntp_format, $header, $dup) = &parse_header(); exit 1 unless $$header{'X-PGP-Sig'}; my ($message, $signature, $version) = &generate_message($nntp_format, $header, $dup); if ($test) { print "-----MESSAGE-----\n$message\n-----END MESSAGE-----\n\n"; print "-----SIGNATURE-----\n$signature\n-----SIGNATURE-----\n\n"; } # The call to pgp needs to be locked because it tries to both read and # write a file named randseed.bin but doesn't do its own locking as it # should, and the consequences of a multiprocess conflict is failure to # verify. my $lock; unless ($gpg or $gpgv) { $lock = "$lockdir/LOCK.$0"; until (&shlock($lock) > 0) { sleep(2); } } # Verify the message. my ($ok, $signer) = pgp_verify($signature, $version, $message); unless ($gpg or $gpgv) { unlink ($lock) or &errmsg("$0: unlink $lock: $!\n"); } print "$signer\n" if $signer; unless ($ok == 0) { &errmsg("$0: verification failed\n"); } exit $ok; # Parse the article headers and return a flag saying whether the message # is in NNTP format and then two references to hashes. The first hash # contains all the header/value pairs, and the second contains entries for # every header that's duplicated. This is, by design, case-sensitive with # regards to the headers it checks. It's also insistent about the # colon-space rule. sub parse_header { my (%header, %dup, $label, $value, $nntp_format); while (<>) { # If the first header line ends with \r\n, this article is in the # encoding it would be in during an NNTP session. Some article # storage managers keep them this way for efficiency. $nntp_format = /\r\n$/ if $. == 1; s/\r?\n$//; last if /^$/; if (/^(\S+):[ \t](.+)/) { ($label, $value) = ($1, $2); $dup{$label} = 1 if $header{$label}; $header{$label} = $value; } elsif (/^\s/) { &fail("$0: non-header at line $.: $_\n") unless $label; $header{$label} .= "\n$_"; } else { &fail("$0: non-header at line $.: $_\n"); } } $messageid = $header{'Message-ID'}; return ($nntp_format, \%header, \%dup); } # Generate the PGP message to verify. Takes a flag indicating wire # format, the hash of headers and header duplicates returned by # parse_header and returns a list of three elements. The first is the # message to verify, the second is the signature, and the third is the # version number. sub generate_message { my ($nntp_format, $header, $dup) = @_; # The regexp below might be too strict about the structure of PGP # signature lines. # The $sep value means the separator between the radix64 signature lines # can have any amount of spaces or tabs, but must have at least one # space or tab; if there is a newline then the space or tab has to # follow the newline. Any number of newlines can appear as long as each # is followed by at least one space or tab. *phew* my $sep = "[ \t]*(\n?[ \t]+)+"; # Match all of the characters in a radix64 string. my $r64 = '[a-zA-Z0-9+/]'; local $_ = $$header{'X-PGP-Sig'}; &fail("$0: X-PGP-Sig not in expected format\n") unless /^(\S+)$sep(\S+)(($sep$r64{64})+$sep$r64+=?=?$sep=$r64{4})$/; my ($version, $signed_headers, $signature) = ($1, $3, $4); $signature =~ s/$sep/\n/g; $signature =~ s/^\s+//; my $message = "X-Signed-Headers: $signed_headers\n"; my $label; foreach $label (split(",", $signed_headers)) { &fail("$0: duplicate signed $label header, can't verify\n") if $$dup{$label}; $message .= "$label: "; $message .= "$$header{$label}" if $$header{$label}; $message .= "\n"; } $message .= "\n"; # end of headers while (<>) { # read body lines if ($nntp_format) { # Check for end of article; some news servers (eg, Highwind's # "Breeze") include the dot-CRLF of the NNTP protocol in the article # data passed to this script. last if $_ eq ".\r\n"; # Remove NNTP encoding. s/^\.\./\./; s/\r\n$/\n/; } $message .= $_; } # Strip off all trailing whitespaces for compatibility with the way that # pgpverify used to work, using attached signatures. $message =~ s/[ \t]+\n/\n/g; return ($message, $signature, $version); } # Check a detached signature for given data. Takes a signature block (in # the form of an ASCII-armored string with embedded newlines), a version # number (which may be undef), and the message. We return an exit status # and the key id if the signature is verified. 0 means good signature, 1 # means bad data, 2 means an unknown signer, 3 means a bad signature, and # 4 means good signature without having found the argument given to the # --findid flag. # In the event of an error, we report with errmsg. # # This code is taken almost verbatim from PGP::Sign except for the code to # figure out the PGP style. sub pgp_verify { my ($signature, $version, $message) = @_; chomp $signature; # Ignore SIGPIPE, since we're going to be talking to PGP. local $SIG{PIPE} = 'IGNORE'; # Set the PGP style based on whether $gpg or $gpgv is set. my $pgpstyle = ($gpg || $gpgv ? 'GPG' : 'PGP2'); # Because this is a detached signature, we actually need to save both # the signature and the data to files and then run PGP on the signature # file to make it verify the signature. Because this is a detached # signature, though, we don't have to do any data mangling, which makes # our lives much easier. It would be nice to do this without having to # use temporary files, but I don't see any way to do so without running # into mangling problems. # # PGP v5 *requires* there be some subheader or another. *sigh*. So we # supply one if Version isn't given. :) my $umask = umask 077; my $filename = $tmpdir . '/pgp' . time . '.' . $$; my $sigfile = new FileHandle "$filename.asc", O_WRONLY|O_EXCL|O_CREAT; unless ($sigfile) { &errmsg ("Unable to open temp file $filename.asc: $!\n"); return (255, undef); } if ($pgpstyle eq 'PGP2') { print $sigfile "-----BEGIN PGP MESSAGE-----\n"; } else { print $sigfile "-----BEGIN PGP SIGNATURE-----\n"; } if (defined $version) { print $sigfile "Version: $version\n"; } elsif ($pgpstyle ne 'GPG') { print $sigfile "Comment: Use GnuPG; it's better :)\n"; } print $sigfile "\n", $signature; if ($pgpstyle eq 'PGP2') { print $sigfile "\n-----END PGP MESSAGE-----\n"; } else { print $sigfile "\n-----END PGP SIGNATURE-----\n"; } close $sigfile; # Signature saved. Now save the actual message. my $datafile = new FileHandle "$filename", O_WRONLY|O_EXCL|O_CREAT; unless ($datafile) { &errmsg ("Unable to open temp file $filename: $!\n"); unlink "$filename.asc"; return (255, undef); } print $datafile $message; close $datafile; # Figure out what command line we'll be using. my @command; if ($pgpstyle eq 'GPG') { if ($gpg) { @command = ($gpg, qw/--verify --allow-weak-digest-algos/); push (@command, qw/--quiet --status-fd=1 --logger-fd=1/); } else { @command = ($gpgv, qw/--quiet --status-fd=1 --logger-fd=1/); } } else { @command = ($pgp, '+batchmode', '+language=en'); } # Now, call PGP to check the signature. Because we've written # everything out to a file, this is actually fairly simple; all we need # to do is grab stdout. PGP prints its banner information to stderr, so # just ignore stderr. Set PGPPATH if desired. # # For GnuPG, use pubring.gpg if an explicit keyring was configured or # found. Otherwise, use trustedkeys.gpg in the default keyring location # if found and non-zero, or fall back on pubring.gpg. This is # definitely not the logic that I would use if writing this from # scratch, but it has the most backward compatibility. local $ENV{PGPPATH} = $keyring if ($keyring && $pgpstyle ne 'GPG'); if ($pgpstyle eq 'GPG') { if ($keyring) { push (@command, "--keyring=$keyring/pubring.gpg"); } else { my $home = $ENV{GNUPGHOME} || $ENV{HOME}; $home .= '/.gnupg' if $home; if ($home && ! -s "$home/trustedkeys.gpg" && -f "$home/pubring.gpg") { push (@command, "--keyring=pubring.gpg"); } } } push (@command, "$filename.asc"); push (@command, $filename); my $input = new FileHandle; my $output = new FileHandle; my $pid = eval { open3 ($input, $output, $output, @command) }; if ($@) { &errmsg ($@); &errmsg ("Execution of $command[0] failed.\n"); unlink ($filename, "$filename.asc"); return (255, undef); } close $input; # Check for the message that gives us the key status and return the # appropriate thing to our caller. This part is a zoo due to all of the # different formats used. GPG has finally done the right thing and # implemented a separate status stream with parseable data. # # MIT PGP 2.6.2 and PGP 6.5.2: # Good signature from user "Russ Allbery ". # ViaCrypt PGP 4.0: # Good signature from user: Russ Allbery # PGP 5.0: # Good signature made 1999-02-10 03:29 GMT by key: # 1024 bits, Key ID 0AFC7476, Created 1999-02-10 # "Russ Allbery " # # Also, PGP v2 prints out "Bad signature" while PGP v5 uses "BAD # signature", and PGP v6 reverts back to "Bad signature". local $_; local $/ = ''; my $signer; my $ok = 255; while (<$output>) { print if $test; if ($pgpstyle eq 'GPG') { if (/\[GNUPG:\]\s+GOODSIG\s+\S+\s+(\S+)/) { $ok = 0; $signer = $1; } elsif (/\[GNUPG:\]\s+NODATA/ || /\[GNUPG:\]\s+UNEXPECTED/) { $ok = 1; last; } elsif (/\[GNUPG:\]\s+NO_PUBKEY/) { $ok = 2; last; } elsif (/\[GNUPG:\]\s+BADSIG\s+/) { $ok = 3; last; } } else { if (/^Good signature from user(?::\s+(.*)|\s+\"(.*)\"\.)$/m) { $signer = $+; $ok = 0; } elsif (/^Good signature made .* by key:\n.+\n\s+\"(.*)\"/m) { $signer = $1; $ok = 0; } elsif (/^\S+: Good signature from \"(.*)\"/m) { $signer = $1; $ok = 0; } elsif (/^(?:\S+: )?Bad signature /im) { $ok = 3; last; } } # If the --findid flag is used, and the signature is good, # override the value of the signer with the string specified in # the --findid flag. if (defined ($findid) and $ok eq 0) { $signer = $findid if (/$findid/); } } close $input; waitpid ($pid, 0); unlink ($filename, "$filename.asc"); umask $umask; if (defined ($findid) and $ok eq 0 and $signer ne $findid) { $ok = 4; } return ($ok, $signer || ''); } # Log an error message, attempting syslog first based on $syslog_method # and falling back on stderr. sub errmsg { my ($message) = @_; $message =~ s/\n$//; my $date = ''; if ($log_date) { $date = strftime ('%Y-%m-%d %T ', localtime); } if ($syslog_method && $] >= 5.006) { eval "use Sys::Syslog"; $syslog_method = 'internal'; } if ($syslog_method eq "logger") { my @loggers = ('/usr/ucb/logger', '/usr/bin/logger', '/usr/local/bin/logger'); my $try; foreach $try (@loggers) { if (-x $try) { $syslog_method = $try; last; } } $syslog_method = '' if $syslog_method eq 'logger'; } if ($syslog_method ne '' && $syslog_method !~ m%/logger$%) { eval "use Sys::Syslog"; } if ($@ || $syslog_method eq '') { warn $date, "$0: trying to use Perl's syslog: $@\n" if $@; warn $date, $message, "\n"; warn $date, "... while processing $messageid\n" if $messageid; } else { $message .= " processing $messageid" if $messageid; if ($syslog_method =~ m%/logger$%) { unless (system($syslog_method, "-i", "-p", "$syslog_facility.$syslog_level", $message) == 0) { if ($? >> 8) { warn $date, "$0: $syslog_method exited status ", $? >> 8, "\n"; } else { warn $date, "$0: $syslog_method died on signal ", $? & 255, "\n"; } $syslog_method = ''; &errmsg($message); } } else { # setlogsock arrived in Perl 5.004_03 to enable Sys::Syslog to use a # Unix domain socket to talk to syslogd, which is the only way to do # it when syslog runs with the -l switch. if ($syslog_method eq "unix") { if ($^O eq "dec_osf" && $] >= 5) { eval 'sub Sys::Syslog::_PATH_LOG { "/dev/log" }'; } if ($] <= 5.00403 || ! eval "setlogsock('unix')") { warn $date, "$0: cannot use syslog_method 'unix' on this system\n"; $syslog_method = ''; &errmsg($message); return; } } # Unfortunately, there is no way to definitively know in this # program if the message was logged. I wish there were a way to # send a message to stderr if and only if the syslog attempt failed. &openlog($0, 'pid', $syslog_facility); &syslog($syslog_level, $_[0]); &closelog(); } } } sub fail { &errmsg($_[0]); exit 255; } # Get a lock in essentially the same fashion as INN's shlock. return 1 on # success, 0 for normal failure, -1 for abnormal failure. "normal # failure" is that a lock is apparently in use by someone else. sub shlock { my ($file) = @_; my ($ltmp, $pid); unless (defined(&ENOENT)) { eval "require POSIX qw(:errno_h)"; if ($@) { # values taken from BSD/OS 3.1 sub ENOENT { 2 } sub ESRCH { 3 } sub EEXIST { 17 } } } $ltmp = ($file =~ m%(.*/)%)[0] . "shlock$$"; # This should really attempt to use another temp name. -e $ltmp && (unlink($ltmp) || return -1); open(LTMP, ">$ltmp") || return -1; print LTMP "$$\n" || (unlink($ltmp), return -1); close(LTMP) || (unlink($ltmp), return -1); if (!link($ltmp, $file)) { if ($! == &EEXIST) { if (open(LOCK, "<$file")) { $pid = ; if ($pid =~ /^\d+$/ && (kill(0, $pid) == 1 || $! != &ESRCH)) { unlink($ltmp); return 0; } # OK, the pid in the lockfile is not a number or no longer exists. close(LOCK); # silent failure is ok here # Unlink failed. if (unlink($file) != 1 && $! != &ENOENT) { unlink($ltmp); return 0; } # Check if open failed for reason other than file no longer present. } elsif ($! != &ENOENT) { unlink($ltmp); return -1; } # Either this process unlinked the lockfile because it was bogus, or # between this process's link() and open() the other process holding # the lock unlinked it. This process can now try to acquire. if (! link($ltmp, $file)) { unlink($ltmp); return $! == &EEXIST ? 0 : -1; # Maybe another proc grabbed the lock. } } else { # First attempt to link failed. unlink($ltmp); return 0; } } unlink($ltmp); return 1; } =head1 NAME pgpverify - Cryptographically verify Usenet control messages =head1 SYNOPSIS B [B<--findid>=I] [B<--test>] < I =head1 DESCRIPTION The B program reads (on standard input) a Usenet control message that has been cryptographically signed using the B program (or some other program that produces a compatible format). B then uses a PGP implementation to determine who signed the control message. If the control message has a valid signature, B prints (to stdout) the user ID of the key that signed the message. Otherwise, it exits with a non-zero exit status. If B is installed as part of INN, it uses INN's configuration to determine what signature verification program to use, how to log errors, what temporary directory to use, and what keyring to use. Otherwise, all of those parameters can be set by editing the beginning of this script. By default, when running as part of INN, B expects the PGP key ring to be found in I/pgp (as either F or F depending on whether PGP or GnuPG is used to verify signatures). If that directory doesn't exist, it will fall back on using the default key ring, which is in a F<.pgp> or F<.gnupg> subdirectory of the running user's home directory. INN, when using GnuPG, configures B to use B or B, which by default expects keys to be in a keyring named F, since it doesn't implement trust checking directly. B uses that file if present but falls back to F if it's not found. This bypasses the trust model for checking keys, but is compatible with the way that B used to behave. Of course, if a keyring is found in I/pgp or configured at the top of the script, that overrides all of this behavior. =head1 OPTIONS =over 4 =item B<--findid>=I The B<--findid> flag causes B to explicitly search for I in the output from PGP's analysis of the message. This option is useful when several UIDs are defined on a single PGP key, and the caller to B needs checking whether a given one is defined on this key. In case the signature is valid but does not contain I, B exits with exit status 4. =item B<--test> The B<--test> flag causes B to print out the input that it is passing to PGP (which is a reconstructed version of the input that supposedly created the control message) as well as the output from PGP's analysis of the message. =back =head1 EXIT STATUS B may exit with the following statuses: =over 4 =item 0Z<> The control message had a good PGP signature. =item 1Z<> The control message had no PGP signature. =item 2Z<> The control message had an unknown PGP signature. =item 3Z<> The control message had a bad PGP signature. =item 4Z<> The control message had a good PGP signature but the argument given to the B<--findid> flag had non been found in the output from PGP's analysis of the message. =item 255Z<> A problem occurred not directly related to PGP analysis of signature. =back =head1 ENVIRONMENT B does not modify or otherwise alter the environment before invoking the B, B or B program. It is the responsibility of the person who installs B to ensure that when B, B or B runs, it has the ability to locate and read a PGP key file that contains the PGP public keys for the appropriate Usenet hierarchy administrators. B can be pointed to an appropriate key ring by editing variables at the beginning of this script. =head1 NOTES Historically, Usenet news server administrators have configured their news servers to automatically honor Usenet control messages based on the originator of the control messages and the hierarchies for which the control messages applied. For example, in the past, David Lawrence always issued control messages for the S<"Big 8"> hierarchies (comp, humanities, misc, news, rec, sci, soc, talk). Usenet news administrators would configure their news server software to automatically honor newgroup and rmgroup control messages that originated from David Lawrence and applied to any of the S hierarchies. Unfortunately, Usenet news articles (including control messages) are notoriously easy to forge. Soon, malicious users realized they could create or remove (at least temporarily) any S newsgroup they wanted by simply forging an appropriate control message in David Lawrence's name. As Usenet became more widely used, forgeries became more common. The B program was designed to allow Usenet news administrators to configure their servers to cryptographically verify control messages before automatically acting on them. Under the B system, a Usenet hierarchy maintainer creates a PGP public/private key pair and disseminates the public key. Whenever the hierarchy maintainer issues a control message, he uses the B program to sign the control message with the PGP private key. Usenet news administrators configure their news servers to run the B program on the appropriate control messages, and take action based on the PGP key User ID that signed the control message, not the name and address that appear in the control message's From: or Sender: headers. Thus, appropriate use of the B and B programs essentially eliminates the possibility of malicious users forging Usenet control messages that sites will act upon, as such users would have to obtain the PGP private key in order to forge a control message that would pass the cryptographic verification step. If the hierarchy administrators properly protect their PGP private keys, the only way a malicious user could forge a validly-signed control message would be by breaking the public key encryption algorithm, which (at least at this time) is believed to be prohibitively difficult for PGP keys of a sufficient bit length. =head1 HISTORY B was written by David C Lawrence . Manual page provided by James Ralston. It is currently maintained by Russ Allbery . =head1 COPYRIGHT AND LICENSE David Lawrence wrote: "Our lawyer told me to include the following. The upshot of it is that you can use the software for free as much as you like." Copyright (c) 1996 UUNET Technologies, Inc. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: =over 4 =item 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. =item 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. =item 3. All advertising materials mentioning features or use of this software must display the following acknowledgement: This product includes software developed by UUNET Technologies, Inc. =item 4. The name of UUNET Technologies ("UUNET") may not be used to endorse or promote products derived from this software without specific prior written permission. =back THIS SOFTWARE IS PROVIDED BY UUNET "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 UUNET 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. =head1 SEE ALSO gpg(1), gpgv(1), pgp(1). L is where the most recent versions of B and B live, along with PGP public keys used for hierarchy administration. =cut # Local variables: # cperl-indent-level: 2 # fill-column: 74 # End: inn-2.6.4/control/modules/0000755000175200017520000000000014002373675015060 5ustar iuliusiuliusinn-2.6.4/control/modules/sendme.pl0000644000175200017520000000371014002373703016661 0ustar iuliusiulius## $Id: sendme.pl 8281 2009-01-10 11:52:16Z iulius $ ## ## sendme control message handler. ## ## Copyright 2001 by Marco d'Itri ## ## 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. use strict; sub control_sendme { my ($par, $sender, $replyto, $site, $action, $log, $approved, $article) = @_; my @body = split(/\r?\n/, $article->stringify_body); if ($action eq 'mail') { my $mail = sendmail("sendme by $sender"); print $mail map { s/^~/~~/; "$_\n" } @body; close $mail or logdie('Cannot send mail: ' . $!); } elsif ($action eq 'log') { if ($log) { logger($log, "sendme $sender", $article); } else { logmsg("sendme from $sender"); } } elsif ($action eq 'doit') { my $tempfile = "$INN::Config::tmpdir/sendme.$$"; open(GREPHIST, "| $INN::Config::newsbin/grephistory -s > $tempfile") or logdie("Cannot run grephistory: $!"); foreach (@body) { print GREPHIST "$_\n"; } close GREPHIST or logdie("Cannot run grephistory: $!"); if (-s $tempfile and $site =~ /^[a-zA-Z0-9.-_]+$/) { open(TEMPFILE, $tempfile) or logdie("Cannot open $tempfile: $!"); open(BATCH, ">>$INN::Config::batch/$site.work") or logdie("Cannot open $INN::Config::batch/$site.work: $!"); print BATCH $_ while ; close BATCH; close TEMPFILE; } unlink $tempfile; } } 1; inn-2.6.4/control/modules/senduuname.pl0000644000175200017520000000432514002373703017555 0ustar iuliusiulius## $Id: senduuname.pl 8281 2009-01-10 11:52:16Z iulius $ ## ## senduuname control message handler. ## ## Copyright 2001 by Marco d'Itri ## ## 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. use strict; sub control_senduuname { my ($par, $sender, $replyto, $site, $action, $log, $approved, $article) = @_; my ($where) = @$par; my $head = $article->head; my @headers = split(/\r?\n/, $head->stringify); my @body = split(/\r?\n/, $article->stringify_body); if ($action eq 'mail') { my $mail = sendmail("senduuname $sender"); print $mail <; close UUNAME or logdie("Cannot run uuname: $!"); close $mail or logdie("Cannot send mail: $!"); logger($log, "senduuname $sender to $replyto", $article) if $log; } } 1; inn-2.6.4/control/modules/newgroup.pl0000644000175200017520000002453514002373703017264 0ustar iuliusiulius## $Id: newgroup.pl 9303 2011-08-04 22:09:57Z iulius $ ## ## newgroup control message handler. ## ## Copyright 2001 by Marco d'Itri ## ## 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. use strict; sub control_newgroup { my ($par, $sender, $replyto, $site, $action, $log, $approved, $article, $charset_from, $charset_to) = @_; my ($groupname, $modflag) = @$par; my $head = $article->head; my @headers = split(/\r?\n/, $head->stringify); my @fullbody = split(/\r?\n/, $article->stringify_body); my (@body, $part, $part_head); my $mimegroupinfo = 0; my $charset_message; if (defined $head->mime_attr('Content-Type.charset')) { $charset_message = $head->mime_attr('Content-Type.charset'); } # Check if it is a multipart message. The body is restricted to # the application/news-groupinfo part, if any. if ($article->parts > 0) { foreach $part ($article->parts) { $part_head = $part->head; if ($part_head->mime_type eq 'application/news-groupinfo') { @body = split(/\r?\n/, $part->stringify_body); if (defined $part_head->mime_attr('Content-Type.charset')) { $charset_message = $part_head->mime_attr('Content-Type.charset'); } $mimegroupinfo = 1; } } } # The newgroup control message can be an application/news-groupinfo # entity itself. if ($head->mime_type eq 'application/news-groupinfo') { @body = @fullbody; $mimegroupinfo = 1; } @body = @fullbody if not $mimegroupinfo; # Find the right charset if absent or forced by control.ctl. foreach (@$charset_from) { my ($group, $charset) = split /:/; if ($groupname =~ /$group/) { if (not defined $charset_message or $charset =~ /=force/) { $charset_message = $charset; $charset_message =~ s/\^(.+)\$/$1/; $charset_message =~ s/\\//g; $charset_message =~ s/=force//; } last; } } if (not defined $charset_message or not defined Encode::find_encoding($charset_message)) { $charset_message = "cp1252"; # Default charset, when undefined. } $modflag ||= ''; my $modcmd = $modflag eq 'moderated' ? 'm' : 'y'; # Scan active to see what sort of change we are making. open(ACTIVE, $INN::Config::active) or logdie("Cannot open $INN::Config::active: $!"); my @oldgroup; while () { next unless /^(\Q$groupname\E)\s\d+\s\d+\s(\w)/; @oldgroup = split /\s+/; last; } close ACTIVE; my $status; my $ngdesc = ''; my $olddesc = ''; my $ngname = $groupname; # If there is a tag line, search whether the description has changed. my $found = 0; my $ngline = ''; foreach (@body) { $found = 1 if (($mimegroupinfo) and ($_ !~ /^For your newsgroups file:\s*$/)); if ($found) { # It is the line which contains the description. $ngline = $_; last; } $found = 1 if $_ =~ /^For your newsgroups file:\s*$/; } if ($found) { ($ngname, $ngdesc) = split(/\s+/, $ngline, 2); # Scan newsgroups to see the previous description, if any. open(NEWSGROUPS, $INN::Config::newsgroups) or logdie("Cannot open $INN::Config::newsgroups: $!"); while () { if (/^\Q$groupname\E\s+(.*)/) { $olddesc = $1; last; } } close NEWSGROUPS; } # Properly encode the newsgroup description. Encode::from_to($ngdesc, $charset_message, $charset_to); if (@oldgroup) { if ($oldgroup[3] eq 'm' and $modflag ne 'moderated') { $status = 'be made unmoderated'; } elsif ($oldgroup[3] ne 'm' and $modflag eq 'moderated') { $status = 'be made moderated'; } else { if ($ngdesc eq $olddesc) { $status = 'not change'; } else { $status = 'have a new description'; } } } elsif (not $approved) { $status = 'be unapproved'; } else { $status = 'be created'; } # Check whether the group name and the description are not junk. my $errmsg; if (defined &local_checkgroupname) { $errmsg = local_checkgroupname($groupname); } else { $errmsg = checkgroupname($groupname); } if (! $errmsg) { if (defined &local_checkdescription) { $errmsg = local_checkdescription($ngdesc, $modcmd); } else { $errmsg = checkdescription($ngdesc, $modcmd); } } if ($errmsg) { if ($log) { logger($log, "skipping newgroup $groupname $modcmd" . " $sender (would $status): $errmsg", $article); } else { logmsg("skipping newgroup $groupname $modcmd $sender" . " (would $status): $errmsg"); } return; } if ($action eq 'mail' and $status !~ /(not change|be unapproved)/) { my $mail = sendmail("newgroup $groupname $modcmd $sender"); print $mail <$tempfile") or logdie("Cannot open $tempfile: $!"); while () { next if (/^\Q$name\E\s+(.*)/); print TEMPFILE $_; } # We now write a pretty line for the description. if (length $name < 8) { print TEMPFILE "$name\t\t\t$desc\n"; } elsif (length $name < 16) { print TEMPFILE "$name\t\t$desc\n"; } else { print TEMPFILE "$name\t$desc\n"; } close TEMPFILE; close NEWSGROUPS; rename($tempfile, $INN::Config::newsgroups) or logdie("Cannot rename $tempfile: $!"); unlink($tempfile); # Unlock. INN::Utils::Shlock::unlock($lockfile); } # Check the group name. This is partially derived from C News. # Some checks are commented out if I think they're too strict or # language-dependent. Your mileage may vary. sub checkgroupname { local $_ = shift; # Whole-name checking. return 'Empty group name' if (! $_); return 'Whitespace in group name' if /\s/; # return 'Unsafe group name' if /[\`\/:;]/; return 'Bad dots in group name' if /^\./ or /\.$/ or /\.\./; # return 'Group name does not begin/end with alphanumeric' # if (/^[a-zA-Z0-9].+[a-zA-Z0-9]$/; return 'Group name begins in control., example. or to.' if /^(?:control|example|to)\./; return 'Group name is control, example, junk, poster or to' if /^(?:control|example|junk|poster|to)$/; # return 'Group name too long' if length $_ > 128; my @components = split(/\./); # Prevent alt.a.b.c.d.e.f.g.w.x.y.z... return 'Too many components' if $#components > 9; # Per-component checking. for (my $i = 0; $i <= $#components; $i++) { local $_ = $components[$i]; return 'All-numeric name component' if /^[0-9]+$/; # return 'Name component starts with non-alphanumeric' if /^[a-zA-Z0-9]/; # return 'Name component does not contain letter' if not /[a-zA-Z]/; return "`all' or `ctl' used as name component" if /^(?:all|ctl)$/; # return 'Name component longer than 30 characters' if length $_ > 30; return 'Uppercase letter(s) in name' if /[A-Z]/; # return 'Illegal character(s) in name' if /[^a-z0-9+_\-]/; # Sigh, c++ etc. must be allowed. # return 'Repeated punctuation in name' if /--|__|\+\+./; # return 'Repeated component(s) in name' if ($i + 2 <= $#components # and $_ eq $components[$i + 1] and $_ eq $components[$i + 2]); } return ''; } # Check the description. sub checkdescription { my ($desc, $flag) = @_; # Whole-name checking. return 'Empty description' if (! $desc); return 'Moderation status mismatch' if ($desc =~ / \(Moderated\)$/) and $flag eq 'y'; return 'Moderation status mismatch' if ($desc !~ / \(Moderated\)$/) and $flag eq 'm'; return 'Reserved "(Moderated)" substring used' if ($desc =~ /\(Moderated\).+$/); return ''; } 1; inn-2.6.4/control/modules/checkgroups.pl0000644000175200017520000001607214002373703017730 0ustar iuliusiulius## $Id: checkgroups.pl 8550 2009-07-18 13:07:05Z iulius $ ## ## checkgroups control message handler. ## ## Copyright 2001 by Marco d'Itri ## ## 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. use strict; sub control_checkgroups { my ($par, $sender, $replyto, $site, $action, $log, $approved, $article, $charset_from, $charset_to, $exclusionpats, $droppats, $maxchanges) = @_; my ($newsgrouppats) = @$par; my $head = $article->head; my @headers = split(/\r?\n/, $head->stringify); my @body = split(/\r?\n/, $article->stringify_body); my @newbody; my $charset_message; if (defined $head->mime_attr('Content-Type.charset')) { $charset_message = $head->mime_attr('Content-Type.charset'); } foreach (@body) { my ($ngname, $ngdesc) = split(/\s+/, $_, 2); my $charset_newsgroup = $charset_message; next if ($ngname !~ /$newsgrouppats/); next if ($exclusionpats and $ngname =~ /$exclusionpats/); next if ($droppats and $ngname =~ /$droppats/); # Find the right charset if absent or forced by control.ctl. foreach (@$charset_from) { my ($group, $charset) = split /:/; if ($ngname =~ /$group/) { if (not defined $charset_newsgroup or $charset =~ /=force/) { $charset_newsgroup = $charset; $charset_newsgroup =~ s/\^(.+)\$/$1/; $charset_newsgroup =~ s/\\//g; $charset_newsgroup =~ s/=force//; } last; } } if (not defined $charset_newsgroup or not defined Encode::find_encoding($charset_newsgroup)) { $charset_newsgroup = "cp1252"; # Default charset, when undefined. } # Properly encode the newsgroup description. Encode::from_to($ngdesc, $charset_newsgroup, $charset_to); push(@newbody, $ngname."\t".$ngdesc); } # We do not go on if there is no changes to do. return if ($#newbody < 0); if ($action eq 'mail') { my $mail = sendmail("checkgroups by $sender"); print $mail "$sender posted the following checkgroups message:\n\n"; print $mail map { s/^~/~~/; "$_\n" } @headers; print $mail <$tempfile.art") or logdie("Cannot open $tempfile.art: $!"); print TEMPART map { s/^~/~~/; "$_\n" } @$body; close TEMPART; open(OLDIN, '<&STDIN') or die $!; open(OLDOUT, '>&STDOUT') or die $!; open(STDIN, "$tempfile.art") or die $!; open(STDOUT, ">$tempfile") or die $!; my $st = system("$INN::Config::pathbin/docheckgroups", "-u", $newsgrouppats, $exclusionpats); logdie('Cannot run docheckgroups: ' . $!) if $st == -1; logdie('docheckgroups returned status ' . ($st & 255)) if $st > 0; close(STDIN); close(STDOUT); open(STDIN, '<&OLDIN') or die $!; open(STDOUT, '>&OLDOUT') or die $!; open(TEMPFILE, $tempfile) or logdie("Cannot open $tempfile: $!"); my @output = ; chop @output; # There is no need to send an empty mail. if ($#output > 0) { my $dochanges = 1; my @newmaxchanges = @$maxchanges; foreach my $line (@output) { last if !$dochanges; if ($line =~ /^\s*\S*ctlinnd \S+ (\S+)/) { my $ngname = $1; foreach my $i (0..$#newmaxchanges) { my ($group, $value) = split (/:/, $newmaxchanges[$i]); if ($ngname =~ /$group/) { $value--; if ($value < 0) { $dochanges = 0; } $newmaxchanges[$i] = "$group:$value"; last; } } } } if ($dochanges) { open(OLDIN, '<&STDIN') or die $!; open(OLDOUT, '>&STDOUT') or die $!; open(STDIN, "$tempfile") or die $!; open(STDOUT, ">$tempfile.modact") or die $!; my $st = system("$INN::Config::pathbin/mod-active"); logdie('Cannot run mod-active: ' . $!) if $st == -1; logdie('mod-active returned status ' . ($st & 255)) if $st > 0; close(STDIN); close(STDOUT); open(STDIN, '<&OLDIN') or die $!; open(STDOUT, '>&OLDOUT') or die $!; if ($log) { unshift(@output, ''); unshift(@output, '######################################################################'); unshift(@output, '# This script has already been successfully executed by controlchan. #'); unshift(@output, '######################################################################'); logger($log, "checkgroups by $sender processed (changes applied)", \@output); } } else { unshift(@output, ''); unshift(@output, '################################################'); unshift(@output, '# This script was NOT executed by controlchan. #'); unshift(@output, '################################################'); logger($log || 'mail', "checkgroups by $sender *not* processed (too many changes)", \@output); } } else { logmsg("checkgroups by $sender processed (no change)"); } close TEMPFILE; unlink($tempfile, "$tempfile.art", "$tempfile.modact"); } 1; inn-2.6.4/control/modules/version.pl0000644000175200017520000000413714002373703017077 0ustar iuliusiulius## $Id: version.pl 8281 2009-01-10 11:52:16Z iulius $ ## ## version control message handler. ## ## Copyright 2001 by Marco d'Itri ## ## 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. use strict; sub control_version { my ($par, $sender, $replyto, $site, $action, $log, $approved, $article) = @_; my ($where) = @$par; my $head = $article->head; my @headers = split(/\r?\n/, $head->stringify); my @body = split(/\r?\n/, $article->stringify_body); my $version = $INN::Config::version || '(unknown version)'; if ($action eq 'mail') { my $mail = sendmail("version $sender"); print $mail < ## ## 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. use strict; sub control_sendsys { my ($par, $sender, $replyto, $site, $action, $log, $approved, $article) = @_; my ($where) = @$par; my $head = $article->head; my @headers = split(/\r?\n/, $head->stringify); my @body = split(/\r?\n/, $article->stringify_body); if ($action eq 'mail') { my $mail = sendmail("sendsys $sender"); print $mail <; print $mail "\n"; close NEWSFEEDS; close $mail or logdie("Cannot send mail: $!"); logger($log, "sendsys $sender to $replyto", $article) if $log; } } 1; inn-2.6.4/control/modules/ihave.pl0000644000175200017520000000403014002373703016476 0ustar iuliusiulius## $Id: ihave.pl 8285 2009-01-11 12:06:55Z iulius $ ## ## ihave control message handler. ## ## Copyright 2001 by Marco d'Itri ## ## 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. use strict; sub control_ihave { my ($par, $sender, $replyto, $site, $action, $log, $approved, $article) = @_; my @body = split(/\r?\n/, $article->stringify_body); if ($action eq 'mail') { my $mail = sendmail("ihave by $sender"); print $mail map { s/^~/~~/; "$_\n" } @body; close $mail or logdie('Cannot send mail: ' . $!); } elsif ($action eq 'log') { if ($log) { logger($log, "ihave $sender", $article); } else { logmsg("ihave $sender"); } } elsif ($action eq 'doit') { my $tempfile = "$INN::Config::tmpdir/ihave.$$"; open(GREPHIST, "| $INN::Config::newsbin/grephistory -i > $tempfile") or logdie('Cannot run grephistory: ' . $!); foreach (@body) { print GREPHIST "$_\n"; } close GREPHIST; if (-s $tempfile) { open(INEWS, "| $INN::Config::inews -h") or logdie('Cannot run inews: ' . $!); print INEWS "Newsgroups: to.$site\n" . "Subject: cmsg sendme $INN::Config::pathhost\n" . "Control: sendme $INN::Config::pathhost\n\n"; open(TEMPFILE, $tempfile) or logdie("Cannot open $tempfile: $!"); print INEWS $_ while ; close INEWS or die $!; close TEMPFILE; } unlink $tempfile; } } 1; inn-2.6.4/control/modules/rmgroup.pl0000644000175200017520000000651614002373703017110 0ustar iuliusiulius## $Id: rmgroup.pl 9303 2011-08-04 22:09:57Z iulius $ ## ## rmgroup control message handler. ## ## Copyright 2001 by Marco d'Itri ## ## 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. use strict; sub control_rmgroup { my ($par, $sender, $replyto, $site, $action, $log, $approved, $article) = @_; my ($groupname) = @$par; my $head = $article->head; my @headers = split(/\r?\n/, $head->stringify); my @body = split(/\r?\n/, $article->stringify_body); # Scan active to see what sort of change we are making. open(ACTIVE, $INN::Config::active) or logdie("Cannot open $INN::Config::active: $!"); my @oldgroup; while () { next unless /^(\Q$groupname\E)\s\d+\s\d+\s(\w)/; @oldgroup = split /\s+/; last; } close ACTIVE; my $status; if (not @oldgroup) { $status = 'not change'; } elsif (not $approved) { $status = 'be unapproved'; } else { $status = 'be removed'; } if ($action eq 'mail' and $status !~ /(not change|be unapproved)/) { my $mail = sendmail("rmgroup $groupname $sender"); print $mail <$tempfile") or logdie("Cannot open $tempfile: $!"); while () { print TEMPFILE $_ if not /^\Q$groupname\E\s/; } close TEMPFILE; close NEWSGROUPS; rename($tempfile, $INN::Config::newsgroups) or logdie("Cannot rename $tempfile: $!"); unlink $tempfile; # Unlock. INN::Utils::Shlock::unlock($lockfile); logger($log, "rmgroup $groupname $status $sender", $article) if $log; } } 1; inn-2.6.4/control/docheckgroups.in0000644000175200017520000002040614002373703016572 0ustar iuliusiulius#! /bin/sh # fixscript will replace this line with code to load innshellvars ## $Id: docheckgroups.in 9343 2011-08-16 14:28:07Z iulius $ ## Script to execute checkgroups text; results to stdout. ## ## Usage: docheckgroups [-u] [include-pattern [exclude-pattern]] < message ## ## If the -u flag is given, the newsgroups descriptions are automatically ## updated. T=${TMPDIR} UPDATEDESC=false cat /dev/null >${T}/$$out ## Parse arguments. if [ $# -gt 0 ]; then case $1 in -u) shift; UPDATEDESC=true;; esac fi ## Copy the message without excluded newsgroups and append local newsgroups. cat | ${PERL} -e 'while () { my @fields = split(); print $_ if ((scalar(@fields) > 0) && ($fields[0] !~ /'${2:-^#}'/) && ($fields[0] !~ /^#/)); }' > ${T}/$$msg test -f ${LOCALGROUPS} && cat ${LOCALGROUPS} | ${EGREP} -v "^#" >> ${T}/$$msg ## Exit if there is no matching newsgroup (otherwise docheckgroups is eager ## to delete everything). test -s ${T}/$$msg || { rm -f ${T}/$$* exit 0 } ## Make sure we do not have duplicates in the resulting concatenation of ## the checkgroups and the localgroups file. ${SORT} -u ${T}/$$msg > ${T}/$$msg2 mv -f ${T}/$$msg2 ${T}/$$msg ## Get the top-level newsgroup names from the message and turn it into ## a regexp. PATS=`${SED} <${T}/$$msg \ -e 's/[ ].*//' -e 's/\..*//' \ -e 's/^!//' -e '/^$/d' \ -e 's/^/^/' -e 's/$/[\.\w]/' \ | ${SORT} -u \ | (tr '\012' '|' ; echo '' ) \ | ${SED} -e 's/|$//'` ## Check for missing and obsolete newsgroups in active. cat ${ACTIVE} | ${PERL} -e 'while () { my @fields = split(); print $fields[0]."\n" if ((scalar(@fields) > 0) && ($fields[0] =~ /'${1:-.}'/) && ($fields[0] =~ /'${PATS}'/)); }' | ${SORT} > ${T}/$$active cat ${T}/$$msg | ${PERL} -e 'while () { my @fields = split(); print $fields[0]."\n" if ((scalar(@fields) > 0) && ($fields[0] =~ /'${1:-.}'/) && ($fields[0] =~ /'${PATS}'/)); }' | ${SORT} > ${T}/$$newsgrps comm -13 ${T}/$$active ${T}/$$newsgrps >${T}/$$missing comm -23 ${T}/$$active ${T}/$$newsgrps >${T}/$$remove ## Check for proper moderation flags in active (we need to be careful ## when dealing with wire-formatted articles manually fed from the spool). cat ${ACTIVE} | ${PERL} -e 'while () { my @fields = split(); print $fields[0]."\n" if ((scalar(@fields) > 0) && ($fields[0] =~ /'${1:-.}'/) && ($fields[0] =~ /'${PATS}'/) && ($_ =~ / m$/)); }' | ${SORT} > ${T}/$$amod.all cat ${T}/$$msg | ${PERL} -e 'while () { my @fields = split(); print $fields[0]."\n" if ((scalar(@fields) > 0) && ($fields[0] =~ /'${1:-.}'/) && ($fields[0] =~ /'${PATS}'/) && ($_ =~ / \(Moderated\)\r?$/)); }' \ | ${SORT} > ${T}/$$ng.mod comm -12 ${T}/$$missing ${T}/$$ng.mod >${T}/$$add.mod comm -23 ${T}/$$missing ${T}/$$ng.mod >${T}/$$add.unmod cat ${T}/$$add.mod ${T}/$$add.unmod >>${T}/$$add comm -23 ${T}/$$amod.all ${T}/$$remove >${T}/$$amod comm -13 ${T}/$$ng.mod ${T}/$$amod >${T}/$$ismod comm -23 ${T}/$$ng.mod ${T}/$$amod >${T}/$$nm.all comm -23 ${T}/$$nm.all ${T}/$$add >${T}/$$notmod ## Check for missing and obsolete newsgroups descriptions (possibly ## in wire format). A few sed implementations do not recognize ## "[ ]\+", so we use " [ ]*" instead. cat ${NEWSGROUPS} | ${PERL} -e 'while () { my @fields = split(); print $_ if ((scalar(@fields) > 0) && ($fields[0] =~ /'${1:-.}'/) && ($fields[0] =~ /'${PATS}'/)); }' \ | ${SED} 's/ [ ]*/ /' | ${SORT} > ${T}/$$localdesc cat ${T}/$$msg | ${PERL} -e 'while () { my @fields = split(); print $_ if ((scalar(@fields) > 0) && ($fields[0] =~ /'${1:-.}'/) && ($fields[0] =~ /'${PATS}'/)); }' \ | ${SED} 's/\r\?$//' \ | ${SED} 's/ [ ]*/ /' | ${SORT} > ${T}/$$newdesc comm -13 ${T}/$$localdesc ${T}/$$newdesc >${T}/$$missingdesc comm -23 ${T}/$$localdesc ${T}/$$newdesc >${T}/$$removedesc ## If the -u flag is given, update the newsgroups descriptions. if [ "${UPDATEDESC}" = "true" ] ; then cat ${NEWSGROUPS} | ${PERL} -e 'while () { my @fields = split(); print $_ if ((scalar(@fields) > 0) && ($fields[0] !~ /'${PATS}'/)); }' \ > ${T}/$$updatednewsgroups cat ${NEWSGROUPS} | ${PERL} -e 'while () { my @fields = split(); print $_ if ((scalar(@fields) > 0) && ($fields[0] !~ /'${1:-.}'/) && ($fields[0] =~ /'${PATS}'/)); }' \ >> ${T}/$$updatednewsgroups cat ${T}/$$newdesc >>${T}/$$updatednewsgroups mv -f ${NEWSGROUPS} ${NEWSGROUPS}.old ${SORT} ${T}/$$updatednewsgroups | ${SED} 's/ [ ]*/ /' \ | ${PERL} -e 'while () { my @fields = split("\t", $_, 2); next if (scalar(@fields) == 0); my $length = length("$fields[0]"); my $desc; if (scalar(@fields) == 2) { $desc = "$fields[1]"; } else { $desc = ""; } if ($length < 8) { print $fields[0]."\t\t\t".$desc; } elsif ($length < 16) { print $fields[0]."\t\t".$desc; } else { print $fields[0]."\t".$desc; } }' > ${NEWSGROUPS} chmod 0664 ${NEWSGROUPS} ${NEWSGROUPS}.old fi ## Display information on newsgroups which need to be removed/added/changed. if [ -s ${T}/$$remove ] ; then ( echo "# The following newsgroups are non-standard and should be removed:" echo "#" ${SED} "s/^/# /" ${T}/$$remove echo "#" echo "# You can remove them by executing the command(s):" echo "" for i in `cat ${T}/$$remove` ; do echo " ${PATHBIN}/ctlinnd rmgroup $i" done echo "" ) >>${T}/$$out fi if [ -s ${T}/$$add ] ; then ( echo "# The following newsgroups are missing and should be added:" echo "#" ${SED} "s/^/# /" ${T}/$$add echo "#" echo "# You can add them by executing the command(s):" echo "" for i in `cat ${T}/$$add.unmod` ; do echo " ${PATHBIN}/ctlinnd newgroup $i y ${FROM}" done for i in `cat ${T}/$$add.mod` ; do echo " ${PATHBIN}/ctlinnd newgroup $i m ${FROM}" done echo "" ) >>${T}/$$out fi if [ -s ${T}/$$ismod ] ; then ( echo "# The following newsgroups are incorrectly marked as moderated" echo "# and should have their status changed:" echo "#" ${SED} "s/^/# /" ${T}/$$ismod echo "#" echo "# You can correct this by executing the command(s):" echo "" for i in `cat ${T}/$$ismod` ; do echo " ${PATHBIN}/ctlinnd changegroup $i y" done echo "" ) >>${T}/$$out fi if [ -s ${T}/$$notmod ] ; then ( echo "# The following newsgroups are incorrectly marked as unmoderated" echo "# and should have their status changed:" echo "#" ${SED} "s/^/# /" ${T}/$$notmod echo "#" echo "# You can correct this by executing the command(s):" echo "" for i in `cat ${T}/$$notmod` ; do echo " ${PATHBIN}/ctlinnd changegroup $i m" done echo "" ) >>${T}/$$out fi ## Display information on descriptions which need to be removed/added. if [ -s ${T}/$$removedesc ] ; then ( echo "# The following newsgroups descriptions are obsolete and should be removed:" echo "#" ${SED} "s/^/# /" ${T}/$$removedesc echo "#" if [ "${UPDATEDESC}" = "true" ] ; then echo "# The file ${NEWSGROUPS} has just been updated accordingly." else echo "# You can remove them by editing ${NEWSGROUPS}" echo "# or by using the -u flag with docheckgroups." fi echo "" ) >>${T}/$$out fi if [ -s ${T}/$$missingdesc ] ; then ( echo "# The following newsgroups descriptions are missing and should be added:" echo "#" ${SED} "s/^/# /" ${T}/$$missingdesc echo "#" if [ "${UPDATEDESC}" = "true" ] ; then echo "# The file ${NEWSGROUPS} has just been updated accordingly." else echo "# You can add them by editing ${NEWSGROUPS}" echo "# or by using the -u flag with docheckgroups." fi echo "" ) >>${T}/$$out fi ## We're done. test -s ${T}/$$out && { cat ${T}/$$out echo "exit # so you can feed this message into the shell (as well as mod-active)." echo "" } rm -f ${T}/$$* inn-2.6.4/control/controlchan.in0000644000175200017520000004727414002373703016260 0ustar iuliusiulius#! /usr/bin/perl -w # fixscript will replace this line with code to load INN::Config ## $Id: controlchan.in 10076 2016-10-08 20:37:36Z iulius $ ## ## Channel feed program to route control messages to an appropriate handler. ## ## Copyright 2001 by Marco d'Itri ## ## 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. ## ## Give this program its own newsfeed. Make sure that you've created ## the newsgroup control.cancel so that you don't have to scan through ## cancels, which this program won't process anyway. ## ## Make a newsfeeds entry like this: ## ## controlchan!\ ## :!*,control,control.*,!control.cancel\ ## :AC,Tc,Wnsm\ ## :/controlchan require 5.004_03; use Encode; use Getopt::Std; use MIME::Parser; use INN::Utils::Shlock; use strict; delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'}; $0 =~ s!.*/!!; # globals my ($cachedctl, $curmsgid); my $lastctl = 0; my $use_syslog = 0; my $debug = 0; END { # In case we bail out, while holding a lock. INN::Utils::Shlock::releaselocks(); } my $usage = "usage: $0 [-ch]\n\n" . "Reads stdin for file names or tokens.\n\n" . " -c Disables cutoff on dates.\n" . " -h Giveis this usage information.\n"; my %opt; getopts("ch", \%opt) || die $usage; die $usage if defined $opt{'h'}; # setup logging ########################################################### # do not log to syslog if stderr is connected to a console if (not -t 2) { eval { require INN::Syslog; import INN::Syslog; $use_syslog = 1; }; eval { require Sys::Syslog; import Sys::Syslog; $use_syslog = 1; } unless $use_syslog; } if ($use_syslog) { if ($Sys::Syslog::VERSION lt 0.15) { eval "sub Sys::Syslog::_PATH_LOG { '/dev/log' }" if $^O eq 'dec_osf'; Sys::Syslog::setlogsock('unix') if $^O =~ /linux|dec_osf|freebsd|darwin/; } openlog('controlchan', 'pid', $INN::Config::syslog_facility); } logmsg('starting'); # load modules from the control directory ################################# opendir(CTL, $INN::Config::controlprogs) or logdie("Cannot open $INN::Config::controlprogs: $!", 'crit'); foreach (readdir CTL) { next if not /^([a-z\.]+\.pl)$/ or not -f "$INN::Config::controlprogs/$_"; eval { require "$INN::Config::controlprogs/$1" }; if ($@) { $@ =~ s/\n/ /g; logdie($@, 'crit'); } logmsg("loaded $INN::Config::controlprogs/$1", 'debug'); } closedir CTL; # main loop ############################################################### while () { chop; my ($token, $sitepath, $msgid) = split(/\s+/, $_); next if not defined $token; $sitepath ||= ''; $curmsgid = $msgid || ''; my $artfh = open_article($token); next if not defined $artfh; my $article_string = ''; while (<$artfh>) { $article_string .= $_; } close $artfh or logdie('sm died with status ' . ($? >> 8)); my %hdr; my $parser = new MIME::Parser; $parser->output_dir("$INN::Config::pathtmp"); my $article = $parser->parse_data($article_string); if (not parse_article($article, \%hdr)) { $parser->filer->purge; next; } if (not $hdr{'control'}) { $parser->filer->purge; next; } if (not defined $opt{'c'}) { # Make sure old control articles are not replayed. my ($postingdate, $injectiondate); # Parse date header fields. We will take the oldest date. if ($hdr{'date'}) { $postingdate = int(convdate('-n', "$hdr{'date'}")); } else { logmsg('Missing Date: header field'); $parser->filer->purge; next; } if ($hdr{'injection-date'}) { $injectiondate = int(convdate('-n', "$hdr{'injection-date'}")); } else { $injectiondate = $postingdate; } my $articledate = ($postingdate < $injectiondate) ? $postingdate : $injectiondate; # Compute the allowed interval of time: # artcutoff days in the past, one day in the future. my $currentdate = int(convdate('-n')); my $mindate = $currentdate - $INN::Config::artcutoff * 86400; my $maxdate = $currentdate + 86400; if ($articledate > $maxdate) { logmsg('Control article injected or posted in the future (' . convdate('-d', '-c', "$articledate") . ')'); $parser->filer->purge; next; } if ($INN::Config::artcutoff > 0 && $articledate < $mindate) { logmsg('Control article too old (' . convdate('-d', '-c', "$articledate") . '), artcutoff set to ' . $INN::Config::artcutoff . ' days'); $parser->filer->purge; next; } } $curmsgid = $hdr{'message-id'}; my $sender = cleanaddr($hdr{'sender'} || $hdr{'from'}); my $replyto = cleanaddr($hdr{'reply-to'} || $hdr{'from'}); my (@progparams, $progname); if ($hdr{'control'} =~ /\s/) { $hdr{'control'} =~ /^(\S+)\s+(.+)?/; $progname = lc $1; # Newsgroups names are case-sensitive. @progparams = split(/\s+/, $2) if $2; if ($progname eq 'newgroup' and defined $progparams[1]) { $progparams[1] = lc $progparams[1]; } } else { $progname = lc $hdr{'control'}; } if ($progname eq 'cancel') { $parser->filer->purge; next; } if ($progname !~ /^([a-z]+)$/) { logmsg("Naughty control in article $curmsgid ($progname)"); $parser->filer->purge; next; } $progname = $1; # Do we want to process the message? Let's check the permissions. my (@charset_from, @maxchanges, @matches); my $exclusionpats = ''; my $droppats = ''; my $charset_to = ctlperm($progname, $sender, $progparams[0], $token, $article, \@charset_from, \@maxchanges, \@matches); foreach my $i (0..$#matches) { my $action = $matches[$i][0] if $matches[$i][0]; my $logname = $matches[$i][1] if $matches[$i][1]; $progparams[0] = $matches[$i][2] if $matches[$i][2]; if ($action eq '_pgpfail') { my $type = ''; if ($progname and $progname eq 'newgroup') { if ($progparams[1] and $progparams[1] eq 'moderated') { $type = 'm '; } else { $type = 'y '; } } logmsg("skipping $progname $type$sender" . " (pgpverify failed) in $curmsgid"); next; } # Find the appropriate module and call it. my $subname = "control_$progname"; my $subfind = \&$subname; if (not defined &$subfind) { if ($logname) { logger($logname, "Unknown control message by $sender", $article); } else { logmsg("Unknown \"$progname\" control by $sender"); } next; } # Count a control article only once. my $approved = $hdr{'approved'} ? 1 : 0; $approved = -1 if $i > 0; logmsg("$subname, " . join(' ', @progparams) . " $sender $replyto $token, $exclusionpats, $droppats," . " $charset_to, $sitepath, $action" . ($logname ? "=$logname" : '') .", $approved"); if ($action ne 'drop') { &$subfind(\@progparams, $sender, $replyto, $sitepath, $action, $logname, $approved, $article, \@charset_from, $charset_to, $exclusionpats, $droppats, \@maxchanges); $exclusionpats .= '|' if $exclusionpats; $exclusionpats .= $progparams[0]; } else { $droppats .= '|' if $droppats; $droppats .= $progparams[0]; } } $parser->filer->purge; } closelog() if $use_syslog; exit 0; # misc functions ########################################################## sub parse_article { my ($article, $hdr) = @_; my ($h, $buffer); my %uniquehdr = map { $_ => 1 } qw(approved control date followup-to from injection-date message-id newsgroups path reply-to sender subject); my $head = $article->head; foreach $h (%uniquehdr) { $hdr->{$h} = ''; $buffer = $head->get($h); if ($buffer) { $buffer =~ s/\r?\n$//; $buffer =~ s/\r?\n\s+/ /g; $hdr->{$h} = $buffer; } if ($head->count($h) > 1) { logmsg("Multiple $h headers in article $curmsgid"); return 0; } } # Article is empty or does not exist. return 0 if not $head->stringify; return 1; } # Strip a mail address, innd-style. sub cleanaddr { local $_ = shift; s/(\s+)?\(.*\)(\s+)?//g; s/.*<(.*)>.*/$1/; s/[^-a-zA-Z0-9+_.@%]/_/g; # protect MTA s/^-/_/; # protect MTA return $_; } # Read and cache control.ctl and control.ctl.local. sub readctlfile { if (! -e $INN::Config::ctlfile) { logdie("Cannot open $INN::Config::ctlfile: $!", 'crit'); } my $localfile = (-e $INN::Config::ctlfile . '.local'); my @files = ($INN::Config::ctlfile); my $mtime = (stat($INN::Config::ctlfile))[9]; if ($localfile) { push(@files, $INN::Config::ctlfile . '.local'); my $mtimelocalfile = (stat($INN::Config::ctlfile . '.local'))[9]; if ($mtimelocalfile > $mtime) { $mtime = $mtimelocalfile; } } return $cachedctl if $lastctl == $mtime; # mtime has not changed. $lastctl = $mtime; my @ctllist; foreach my $file (@files) { open(CTLFILE, $file) or logdie("Cannot open $file: $!", 'crit'); while () { chop; # Not a comment or blank? Convert wildmat to regex. next if not /^(\s+)?[^\#]/ or /^$/; if (not /^\/(?:local)?encoding\/:/ and not /^\/maxdocheckgroups\/:/ and not /:(?:doit|doifarg|drop|log|mail|verify-.*)(?:=.*)?$/) { s/.*://; logmsg("$_ is not a valid action for control.ctl", 'err'); next; } # Convert to a ':'-separated list of regexps. s/^all:/*:/i; s/([\$\+\.])/\\$1/g; s/\*/.*/g; s/\?/./g; s/(.*)/^$1\$/; s/:/\$:^/g; s/\|/\$|^/g; s/\//\\\//g; push(@ctllist, $_); } close(CTLFILE); } logmsg('warning: control.ctl is empty!', 'err') if not @ctllist; return $cachedctl = [ reverse @ctllist ]; } # Parse a control message's permissions. sub ctlperm { my ($type, $sender, $newsgroup, $token, $article, $charset_from, $maxchanges, $matches) = @_; my %keyresults = (); my ($action, $maxdocheckgroups, $logname, $charset_to); # newgroup and rmgroup require newsgroup names; check explicitly for that # here and return drop if the newsgroup is missing (to avoid a bunch of # warnings from undefined values later on in permission checking). if ($type eq 'newgroup' or $type eq 'rmgroup') { unless ($newsgroup) { push (@$matches, [ 'drop', undef, undef ]); return ('UTF-8'); } } my $ctllist = readctlfile(); my $matchedaction = 0; my $matchedencoding = 0; foreach (@$ctllist) { my @ctlline = split /:/; # 0: type 1: from@addr 2: group.* 3: action if ($type =~ /$ctlline[0]/ and $sender =~ /$ctlline[1]/i and ($type !~ /(?:new|rm)group/ or $newsgroup =~ /$ctlline[2]/)) { if (not $matchedaction) { $action = $ctlline[3]; $action =~ s/\^(.+)\$/$1/; $action =~ s/\\//g; ($action, $logname) = split(/=/, $action); if ($type eq 'checkgroups') { push (@$matches, [ $action, $logname, $ctlline[2] ]); } else { push (@$matches, [ $action, $logname, undef ]); # @ctllist is a reversed list so the first match is the last # one in control.ctl followed by control.ctl.local. $matchedaction = 1; } } } # 0: /localencoding/ 1: encoding if ($ctlline[0] eq '^\/localencoding\/$') { if (not $matchedencoding) { $charset_to = $ctlline[1]; $charset_to =~ s/\^(.+)\$/$1/; $charset_to =~ s/\\//g; $matchedencoding = 1; } } # 0: /encoding/ 1: from@addr 2: group.* 3: encoding[=force] if ($ctlline[0] eq '^\/encoding\/$') { if ($sender =~ /$ctlline[1]/i) { push (@$charset_from, $ctlline[2].':'.$ctlline[3]); } } # 0: /maxdocheckgroups/ 1: from@addr 2: group.* 3: number if ($ctlline[0] eq '^\/maxdocheckgroups\/$') { if ($sender =~ /$ctlline[1]/i) { $maxdocheckgroups = $ctlline[3]; $maxdocheckgroups =~ s/\^(.+)\$/$1/; push (@$maxchanges, $ctlline[2].':'.$maxdocheckgroups); } } } if (not defined $charset_to or not defined Encode::find_encoding($charset_to)) { $charset_to = 'UTF-8'; # Default local encoding. } # Default value when nothing matches the control article. if ($#$matches < 0) { push (@$matches, [ 'drop', undef, undef ]); } # Default value appended to the end of @maxchanges. push (@$maxchanges, '^.*$:10'); foreach my $i (0..$#$matches) { if ($$matches[$i][0] =~ /^verify-(.+)/) { my $keyowner = $1; if (!exists($keyresults{$keyowner})) { if ($INN::Config::pgpverify and $INN::Config::pgpverify =~ /^(?:true|on|yes)$/i) { my $pgpresult = defined &local_pgpverify ? local_pgpverify($token, $article, $keyowner) : pgpverify($token, $keyowner); if ($keyowner eq $pgpresult) { $keyresults{$keyowner} = 'doit'; } else { $keyresults{$keyowner} = '_pgpfail'; } } else { $keyresults{$keyowner} = 'mail'; } } $$matches[$i][0] = $keyresults{$keyowner}; } } return ($charset_to); } # Write stuff to a log or send mail to the news admin. sub logger { my ($logfile, $message, $article) = @_; my (@headers, @body); if (ref $article eq 'ARRAY') { @headers = @$article; } else { my $head = $article->head; @headers = split(/\r?\n/, $head->stringify); @body = split(/\r?\n/, $article->stringify_body); } if ($logfile eq 'mail') { my $mail = sendmail($message); print $mail map { s/^~/~~/; "$_\n" } @headers; print $mail "\n" . join ('', map { s/^~/~~/; "$_\n" } @body) if @body; close $mail or logdie("Cannot send mail: $!"); return; } if ($logfile =~ /^([^.\/].*)/) { $logfile = $1; } else { logmsg("Invalid log file: $logfile", 'err'); $logfile = 'control'; } $logfile = "$INN::Config::most_logs/$logfile.log" unless $logfile =~ /^\//; my $lockfile = $logfile; $lockfile =~ s#.*/##; $lockfile = "$INN::Config::locks/LOCK.$lockfile"; # Acquire a lock. INN::Utils::Shlock::lock($lockfile, 60) or logdie("Cannot create lockfile $lockfile"); open(LOGFILE, ">>$logfile") or logdie("Cannot open $logfile: $!"); print LOGFILE "$message\n"; foreach (@headers, '', @body, '') { print LOGFILE " $_\n"; } close LOGFILE; # Unlock. INN::Utils::Shlock::unlock($lockfile); } # write to syslog or errlog sub logmsg { my ($msg, $lvl) = @_; return if $lvl and $lvl eq 'debug' and not $debug; if ($use_syslog) { syslog($lvl || 'notice', '%s', $msg); } else { print STDERR (scalar localtime) . ": $msg\n"; } } # log a message and then die sub logdie { my ($msg, $lvl) = @_; $msg .= " ($curmsgid)" if $curmsgid; logmsg($msg, $lvl || 'err'); exit 1; } # wrappers executing external programs #################################### # Open an article appropriately to our storage method (or lack thereof). sub open_article { my $token = shift; if ($token =~ /^\@.+\@$/) { my $pid = open(ART, '-|'); logdie('Cannot fork: ' . $!) if $pid < 0; if ($pid == 0) { exec("$INN::Config::newsbin/sm", '-q', $token) or logdie("Cannot exec sm: $!"); } return *ART; } else { return *ART if open(ART, $token); logmsg("Cannot open article $token: $!"); } return undef; } sub pgpverify { my $token = shift; my $keyid = shift; if ($token =~ /^\@.+\@$/) { open(PGPCHECK, "$INN::Config::newsbin/sm -q $token " . "| $INN::Config::newsbin/pgpverify --findid='$keyid' |") or goto ERROR; } else { open(PGPCHECK, "$INN::Config::newsbin/pgpverify --findid='$keyid' < $token |") or goto ERROR; } my $pgpresult = ; close PGPCHECK or goto ERROR; $pgpresult ||= ''; chop $pgpresult; return $pgpresult; ERROR: logmsg("pgpverify failed: $!", 'debug'); return ''; } sub ctlinnd { my ($cmd, @args) = @_; my $st = system("$INN::Config::newsbin/ctlinnd", '-s', $cmd, @args); logdie('Cannot run ctlinnd: ' . $!) if $st == -1; logdie('ctlinnd returned status ' . ($st & 255)) if $st > 0; } # Run convdate on the given arguments. # The result can be numeric (with -n) or a string (with -d). sub convdate { my (@args) = @_; my $result = 0; my $pid = open(my $CONVDATE, '-|'); logdie("Cannot fork: $!") if $pid < 0; if ($pid == 0) { # exec() properly escapes its arguments to prevent shell injection. exec("$INN::Config::pathbin/convdate", @args) or logdie("Cannot exec convdate: $!"); } else { $result = <$CONVDATE>; close($CONVDATE); } $result = 0 if not $result; chomp $result; return $result; } # If $body is not defined, returns a file handle which must be closed. # Don't forget checking the return value of close(). # $addresses may be a scalar or a reference to a list of addresses. # If not defined, $INN::Config::newsmaster is the default. # parts of this code stolen from innmail.pl sub sendmail { my ($subject, $addresses, $body) = @_; $addresses = [ $addresses || $INN::Config::newsmaster ] if not ref $addresses; $subject ||= '(no subject)'; # fix up all addresses my @addrs = map { s#[^-a-zA-Z0-9+_.@%]##g; $_ } @$addresses; my $sm = $INN::Config::mta; if ($sm =~ /%s/) { $sm = sprintf($sm, join(' ', @addrs)); } else { $sm .= ' ' . join(' ', @addrs); } # fork and spawn the MTA without using the shell my $pid = open(MTA, '|-'); logdie('Cannot fork: ' . $!) if $pid < 0; if ($pid == 0) { exec(split(/\s+/, $sm)) or logdie("Cannot exec $sm: $!"); } print MTA 'To: ' . join(",\n\t", @addrs) . "\nSubject: $subject\n\n"; return *MTA if not defined $body; $body = join("\n", @$body) if ref $body eq 'ARRAY'; print MTA $body . "\n"; close MTA or logdie("Execution of $sm failed: $!"); return 1; } inn-2.6.4/control/perl-nocem.in0000644000175200017520000004527014002373703016001 0ustar iuliusiulius#! /usr/bin/perl -w # fixscript will replace this line with code to load INN::Config ############################################################################## # perl-nocem - a NoCeM-on-spool implementation for INN 2.x. # Copyright 2000 by Miquel van Smoorenburg # Copyright 2001 by Marco d'Itri # This program is licensed under the terms of the GNU General Public License. # # List of changes: # # 2002: Patch by Steven M. Christey for untrusted printf input. # 2007: Patch by Christoph Biedl for checking a timeout. # Documentation improved by Jeffrey M. Vinocur (2002), Russ Allbery (2006) # and Julien Elie (2007). # ############################################################################## require 5.00403; use strict; # XXX FIXME I haven't been able to load it only when installed. # If nobody can't fix it just ship the program with this line commented. #use Time::HiRes qw(time); my $keyring = $INN::Config::pathetc . '/pgp/ncmring.gpg'; # XXX To be moved to a config file. #sub local_want_cancel_id { # my ($group, $hdrs) = @_; # ## Hippo has too many false positives to be useful outside of pr0n groups # if ($hdrs->{issuer} =~ /(?:Ultra|Spam)Hippo/) { # foreach (split(/,/, $group)) { # return 1 if /^alt\.(?:binar|sex)/; # } # return 0; # } # return 1; #} # no user serviceable parts below this line ################################### # global variables my ($working, $got_sighup, $got_sigterm, @ncmperm, $cancel); my $use_syslog = 0; my $log_open = 0; my $nntp_open = 0; my $last_cancel = 0; my $socket_timeout = $INN::Config::peertimeout - 100; my $logfile = $INN::Config::pathlog . '/perl-nocem.log'; # initialization and main loop ############################################### eval { require Sys::Syslog; import Sys::Syslog; $use_syslog = 1; }; if ($use_syslog) { if ($Sys::Syslog::VERSION lt 0.15) { eval "sub Sys::Syslog::_PATH_LOG { '/dev/log' }" if $^O eq 'dec_osf'; Sys::Syslog::setlogsock('unix') if $^O =~ /linux|dec_osf|freebsd|darwin/; } openlog('nocem', '', $INN::Config::syslog_facility); } if (not $INN::Config::gpgv and not $INN::Config::gpg) { logmsg('cannot find the gpgv or gpg binary', 'err'); sleep 5; exit 1; } if ($INN::Config::version and not $INN::Config::version =~ /^INN 2\.[0123]\./) { $cancel = \&cancel_nntp; } else { $cancel = \&cancel_ctlinnd; } $SIG{HUP} = \&hup_handler; $SIG{INT} = \&term_handler; $SIG{TERM} = \&term_handler; $SIG{PIPE} = \&term_handler; logmsg('starting up'); unless (read_ctlfile()) { sleep 5; exit 1; } while () { chop; $working = 1; do_nocem($_); $working = 0; term_handler() if $got_sigterm; hup_handler() if $got_sighup; } logmsg('exiting because of EOF', 'debug'); exit 0; ############################################################################## # Process one NoCeM notice. sub do_nocem { my $token = shift; my $start = time; # open the article and verify the notice my $artfh = open_article($token); return if not defined $artfh; my ($msgid, $nid, $issuer, $nocems) = read_nocem($artfh); close $artfh; return unless $nocems; &$cancel($nocems); logmsg("Articles cancelled: " . join(' ', @$nocems), 'debug'); my $diff = (time - $start) || 0.01; my $nr = scalar @$nocems; logmsg(sprintf("processed notice %s by %s (%d ids, %.5f s, %.1f/s)", $nid, $issuer, $nr, $diff, $nr / $diff)); } # - Check if it is a PGP signed NoCeM notice # - See if we want it # - Then check PGP signature sub read_nocem { my $artfh = shift; # Examine the first 200 lines to see if it is a PGP signed NoCeM. my $ispgp = 0; my $isncm = 0; my $inhdr = 1; my $i = 0; my $body = ''; my $from = ''; my $msgid = '<>'; while (<$artfh>) { last if $i++ > 200; s/\r\n$/\n/; if ($inhdr) { if (/^$/) { $inhdr = 0; } elsif (/^From:\s+(.*)\s*$/i) { $from = $1; } elsif (/^Message-ID:\s+(<.*>)/i) { $msgid = $1; } } else { $body .= $_; $ispgp = 1 if /^-----BEGIN PGP SIGNED MESSAGE-----/; if (/^\@\@BEGIN NCM HEADERS/) { $isncm = 1; last; } } } # must be a PGP signed NoCeM. if (not $ispgp) { logmsg("Article $msgid: not PGP signed", 'debug'); return; } if (not $isncm) { logmsg("Article $msgid: not a NoCeM", 'debug'); return; } # read the headers of this NoCeM, and check if it's supported. my %hdrs; while (<$artfh>) { s/\r\n/\n/; $body .= $_; last if /^\@\@BEGIN NCM BODY/; my ($key, $val) = /^([^:]+)\s*:\s*(.*)$/; $hdrs{lc $key} = $val; } foreach (qw(action issuer notice-id type version)) { next if $hdrs{$_}; logmsg("Article $msgid: missing $_ pseudo header", 'debug'); return; } return if not supported_nocem($msgid, \%hdrs); # decide if we want it. if (not want_nocem(\%hdrs)) { logmsg("Article $msgid: unwanted ($hdrs{issuer}/$hdrs{type})", 'debug'); return; } # XXX want_hier() not implemented # if ($hdrs{hierarchies} and not want_hier($hdrs{hierarchies})) { # logmsg("Article $msgid: unwanted hierarchy ($hdrs{hierarchies})", # 'debug'); # return; # } # We do want it, so read the entire article. Also copy it to # a temp file so that we can check the PGP signature when done. my $tmpfile = "$INN::Config::pathtmp/nocem.$$"; if (not open(OFD, ">$tmpfile")) { logmsg("cannot open temp file $tmpfile: $!", 'err'); return; } print OFD $body; undef $body; # process NoCeM body. my $inbody = 1; my @nocems; my ($lastid, $lastgrp); while (<$artfh>) { s/\r\n$/\n/; print OFD; $inbody = 0 if /^\@\@END NCM BODY/; next if not $inbody or /^#/; my ($id, $grp) = /^(\S*)\s+(\S+)/; next if not $grp; if ($id) { push @nocems, $lastid if $lastid and want_cancel_id($lastgrp, \%hdrs); $lastid = $id; $lastgrp = $grp; } else { $lastgrp .= ',' . $grp; } } push @nocems, $lastid if $lastid and want_cancel_id($lastgrp, \%hdrs); close OFD; # at this point we need to verify the PGP signature. return if not @nocems; my $e = pgp_check($hdrs{issuer}, $msgid, $tmpfile); unlink $tmpfile; return if not $e; return ($msgid, $hdrs{'notice-id'}, $hdrs{issuer}, \@nocems); } # XXX not implemented: code to discard notices for groups we don't carry sub want_cancel_id { my ($group, $hdrs) = @_; return local_want_cancel_id(@_) if defined &local_want_cancel_id; 1; } # Do we actually want this NoCeM? sub want_nocem { my $hdrs = shift; foreach (@ncmperm) { my ($issuer, $type) = split(/\001/); if ($hdrs->{issuer} =~ /$issuer/i) { return 1 if '*' eq $type or lc $hdrs->{type} eq $type; } } return 0; } sub supported_nocem { my ($msgid, $hdrs) = @_; if ($hdrs->{version} !~ /^0\.9[0-9]?$/) { logmsg("Article $msgid: version $hdrs->{version} not supported", 'debug'); return 0; } if ($hdrs->{action} ne 'hide') { logmsg("Article $msgid: action $hdrs->{action} not supported", 'debug'); return 0; } return 1; } # Check the PGP signature on an article. sub pgp_check { my ($issuer, $msgid, $art) = @_; # fork and spawn a child my $pid = open(PFD, '-|'); if (not defined $pid) { logmsg("pgp_check: cannot fork: $!", 'err'); return 0; } if ($pid == 0) { open(STDERR, '>&STDOUT'); if ($INN::Config::gpg) { exec($INN::Config::gpg, '--status-fd=1', '--verify', '--allow-weak-digest-algos', $keyring ? '--keyring=' . $keyring : '', $art); } else { exec($INN::Config::gpgv, '--status-fd=1', $keyring ? '--keyring=' . $keyring : '', $art); } exit 126; } # Read the result and check status code. local $_ = join('', ); my $status = 0; if (not close PFD) { if ($? >> 8) { $status = $? >> 8; } else { if ($INN::Config::gpg) { logmsg("Article $msgid: $INN::Config::gpg killed by signal " . ($? & 255)); } else { logmsg("Article $msgid: $INN::Config::gpgv killed by signal " . ($? & 255)); } return 0; } } # logmsg("Command line was: $INN::Config::gpgv --status-fd=1" # . ($keyring ? ' --keyring=' . $keyring : '') . " $art", 'debug'); # logmsg("Full PGP output: >>>$_<<<", 'debug'); if (/^\[GNUPG:\]\s+GOODSIG\s+\S+\s+(.*)/m) { return 1 if $1 =~ /\Q$issuer\E/; logmsg("Article $msgid: signed by $1 instead of $issuer"); } elsif (/^\[GNUPG:\]\s+NO_PUBKEY\s+(\S+)/m) { logmsg("Article $msgid: $issuer (ID $1) not in keyring"); } elsif (/^\[GNUPG:\]\s+BADSIG\s+\S+\s+(.*)/m) { logmsg("Article $msgid: bad signature from $1"); } elsif (/^\[GNUPG:\]\s+BADARMOR/m or /^\[GNUPG:\]\s+UNEXPECTED/m) { logmsg("Article $msgid: malformed signature"); } elsif (/^\[GNUPG:\]\s+ERRSIG\s+(\S+)/m) { # safety net: we get there if we don't know about some token logmsg("Article $msgid: unknown error (ID $1)"); } else { # some other error we don't know about happened. # 126 is returned by the child if exec fails. s/ at \S+ line \d+\.\n$//; s/\n/_/; if ($INN::Config::gpg) { logmsg("Article $msgid: $INN::Config::gpg exited " . (($status == 126) ? "($_)" : "with status $status"), 'err'); } else { logmsg("Article $msgid: $INN::Config::gpgv exited " . (($status == 126) ? "($_)" : "with status $status"), 'err'); } } return 0; } # Read article. sub open_article { my $token = shift; if ($token =~ /^\@.+\@$/) { my $pid = open(ART, '-|'); if ($pid < 0) { logmsg('Cannot fork: ' . $!, 'err'); return undef; } if ($pid == 0) { exec("$INN::Config::newsbin/sm", '-q', $token) or logmsg("Cannot exec sm: $!", 'err'); return undef; } return *ART; } else { return *ART if open(ART, $token); logmsg("Cannot open article $token: $!", 'err'); } return undef; } # Cancel a number of Message-IDs. We use ctlinnd to do this, # and we run up to 15 of them at the same time (10 usually). sub cancel_ctlinnd { my @ids = @{$_[0]}; while (@ids > 0) { my $max = @ids <= 15 ? @ids : 10; for (my $i = 1; $i <= $max; $i++) { my $msgid = shift @ids; my $pid; sleep 5 until (defined ($pid = fork)); if ($pid == 0) { exec "$INN::Config::pathbin/ctlinnd", '-s', '-t', '180', 'cancel', $msgid; exit 126; } # logmsg("cancelled: $msgid [$i/$max]", 'debug'); } # Now wait for all children. while ((my $pid = wait) > 0) { next unless $?; if ($? >> 8) { logmsg("Child $pid died with status " . ($? >> 8), 'err'); } else { logmsg("Child $pid killed by signal " . ($? & 255), 'err'); } } } } sub cancel_nntp { my $ids = shift; my $r; if ($nntp_open and time - $socket_timeout > $last_cancel) { logmsg('Close socket for timeout'); close (NNTP); $nntp_open = 0; } if (not $nntp_open) { use Socket; if (not socket(NNTP, PF_UNIX, SOCK_STREAM, 0)) { logmsg("socket: $!", 'err'); goto ERR; } if (not connect(NNTP, sockaddr_un($INN::Config::pathrun . '/nntpin'))) { logmsg("connect: $!", 'err'); goto ERR; } if (($r = ) !~ /^200 /) { $r =~ s/\r\n$//; logmsg("bad reply from server: $r", 'err'); goto ERR; } select NNTP; $| = 1; select STDOUT; print NNTP "MODE CANCEL\r\n"; if (($r = ) !~ /^284 /) { $r =~ s/\r\n$//; logmsg("MODE CANCEL not supported: $r", 'err'); goto ERR; } $nntp_open = 1; } foreach (@$ids) { print NNTP "$_\r\n"; if (($r = ) !~ /^289/) { $r =~ s/\r\n$//; logmsg("cannot cancel $_: $r", 'err'); goto ERR; } } $last_cancel = time; return; ERR: # discard unusable socket close (NNTP); logmsg('Switching to ctlinnd...', 'err'); cancel_ctlinnd($ids); $cancel = \&cancel_ctlinnd; } sub read_ctlfile { my $permfile = $INN::Config::pathetc . '/nocem.ctl'; unless (open(CTLFILE, $permfile)) { logmsg("Cannot open $permfile: $!", 'err'); return 0; } while () { chop; s/^\s+//; s/\s+$//; next if /^#/ or /^$/; my ($issuer, $type) = split(/:/, lc $_); if (not (defined($issuer) and defined($type))) { logmsg("Cannot parse nocem.ctl line <<$_>>; syntax is <>.", 'err'); next; } $type =~ s/\s//g; foreach (split(/,/, $type)) { push(@ncmperm, "$issuer\001$_"); } } close CTLFILE; return 1; } sub logmsg { my ($msg, $lvl) = @_; if (not $use_syslog) { if ($log_open == 0) { open(LOG, ">>$logfile") or die "Cannot open log: $!"; $log_open = 1; select LOG; $| = 1; select STDOUT; } $lvl ||= 'notice'; print LOG "$lvl: $msg\n"; return; } syslog($lvl || 'notice', '%s', $msg); } sub hup_handler { $got_sighup = 1; return if $working; close LOG; $log_open = 0; } sub term_handler { $got_sigterm = 1; return if $working; logmsg('exiting because of signal'); exit 1; } __END__ =head1 NAME perl-nocem - A NoCeM-on-spool implementation for S =head1 SYNOPSIS perl-nocem =head1 DESCRIPTION NoCeM, which is pronounced I, is a protocol enabling authenticated third-parties to issue notices which can be used to cancel unwanted articles (like spam and articles in moderated newsgroups which were not approved by their moderators). It can also be used by readers as a I. It is intended to eventually replace the protocol for third-party cancel messages. B processes third-party, PGP-signed article cancellation notices. It is possible not to honour all NoCeM notices but only those which are sent by people whom you trust (that is to say if you trust the PGP key they use to sign their NoCeM notices). Indeed, it is up to you to decide whether you wish to honour their notices, depending on the criteria they use. Processing NoCeM notices is easy to set up: =over 4 =item 1. Import the keys of the NoCeM issuers you trust in order to check the authenticity of their notices. You can do: gpg1 --no-default-keyring --primary-keyring /pgp/ncmring.gpg \ --no-options --allow-non-selfsigned-uid --no-permission-warning \ --batch --import chmod 644 /pgp/ncmring.gpg where is the value of the I parameter set in F and the file containing the key(s) to import. The keyring must be located in /pgp/ncmring.gpg; you only have to create the directory /pgp before using B (it will automatically generate the F file) and make sure the news user can read this file, once generated. As a few NoCeM issuers are still using old PGP-generated keys, you may have to use B with various legacy options in command-line (like in the example above) instead of more recent versions of B that no longer accept such keys. The keys of NoCeM issuers can be found in the web site of I: L. You can even download there a unique file which contains all the keys. =item 2. Create a F config file in I indicating the NoCeM issuers and notices you want to follow. This permission file contains lines like: bleachbot@httrack.com:spam,site pgpmoose@killfile.org:pgpmoose-forged-moderation This will remove all articles for which the issuer (first part of the line, before the colon C<:>) has issued NoCeM notices corresponding to the criteria specified after the colon. You will also find information about that on the web site of I. =item 3. Add to the F file an entry like this one in order to feed B the NoCeM notices posted to alt.nocem.misc and news.lists.filters: nocem!\ :!*,alt.nocem.misc,news.lists.filters\ :Tc,Wf,Ap:/perl-nocem with the correct path to B, located in . Then, reload the F file (C). Note that you should at least carry news.lists.filters on your news server (or other newsgroups where NoCeM notices are sent) if you wish to process them. =item 4. Everything should now work. However, do not hesitate to manually test B with a NoCeM notice, using: grephistory '' | perl-nocem Indeed, B expects tokens on its standard input, and B can easily give it the token of a known article, thanks to its Message-ID. =back When you have verified that everything works, you can eventually turn off regular spam cancels, if you want, not processing any longer cancels containing C in the Path: header (see the I parameter in F). =head1 FILES =over 4 =item I/perl-nocem The Perl script itself used to process NoCeM notices. =item I/nocem.ctl The configuration file which specifies the NoCeM notices to be processed. =item I/pgp/ncmring.gpg The keyring which contains the public keys of trusted NoCeM issuers. =back =head1 BUGS The Subject: header is not checked for the @@NCM string and there is no check for the presence of the References: header. The Newsgroups: pseudo header is not checked, but this can be done in local_want_cancel_id(). The Hierarchies: header is ignored. =head1 HISTORY Copyright 2000 by Miquel van Smoorenburg . Copyright 2001 by Marco d'Itri . $Id: perl-nocem.in 10399 2020-11-12 20:24:35Z iulius $ =head1 SEE ALSO gpg(1), gpgv(1), grephistory(1), inn.conf(5), newsfeeds(5), pgp(1). =cut inn-2.6.4/samples/0000755000175200017520000000000014002373701013362 5ustar iuliusiuliusinn-2.6.4/samples/nnrpd_auth_wrapper.pl.in0000644000175200017520000000251014002373703020226 0ustar iuliusiulius#! /usr/bin/perl -w # fixscript will replace this line with code to load INN::Config # Example wrapper nnrpd_auth.pl for support of old perl authentication # scripts, by Erik Klavon. # This file contains a sample perl script which can be used to # duplicate the behavior of the old nnrpperlauth functionality. This # script only supports authentication. # How to use this wrapper: # - append your old script to this file with two changes: # - rename the old "auth_init" sub to "old_auth_init" # - rename the old "authenticate" sub to "old_authenticate" use vars qw(%attributes); # auth_init # This sub simply calls old_auth_init # Comment this out if you don't need auth_init sub auth_init { old_auth_init(); } # authenticate # This sub modifies the global hash attributes so that it has all the # entries required in the old way of doing things, calls # old_authenticate, and transforms the return array into the new # format. sub authenticate { $attributes{type} = "authenticate"; my @auth_array = old_authenticate(); my @return_array; # copy return code $return_array[0] = $auth_array[0]; # simple error report if ($auth_array[0] != 281) { $return_array[1] = "Perl authentication error!"; return @return_array; } else { $return_array[1] = ""; } return @return_array; } inn-2.6.4/samples/startup_innd.pl0000644000175200017520000000245614002373703016442 0ustar iuliusiulius# # RCSId: $Id: startup_innd.pl 42 1997-08-04 04:03:43Z gpalmer $ # Description: Sample startup code for Perl hooks in INN. This file, after # it's installed in the right spot, will be loaded when # innd starts up. The following functions should be defined # by it (they don't have to be, in fact this file can be # empty, but it must exist if you've compiled in Perl support). # # sub filter_before_reload { ... } # Called before the filter definition file filter_innd.pl # is loaded (every time). # sub filter_after_reload { ... } # Called after the filter definition file filter_innd.pl # is loaded (every time). # # See the sample file filter_innd.pl for details on what it does. my $before_count = 1 ; # Gets no arguments, and its caller expects no return value. sub filter_before_reload { if ($before_count == 1) { # Do one thing # print "First time (before)\n" ; $before_count++ ; } else { # Do something else # print "Time number $before_count (before)\n" ; $before_count++ ; } } my $after_count = 1 ; # Gets no arguments, and its caller expects no return value. sub filter_after_reload { if ($after_count == 1) { # Do one thing # print "First time (after)\n" ; $after_count++ ; } else { # Do another # print "Time number $after_count (after)\n" ; $after_count++ ; } } inn-2.6.4/samples/cycbuff.conf0000644000175200017520000000350614002373703015660 0ustar iuliusiulius## $Id: cycbuff.conf 7651 2007-08-20 10:28:34Z iulius $ ## ## Configuration file for INN CNFS storage method. ## ## This file defines the cyclical buffers that make up the storage pools ## for CNFS (Cyclic News File System). For information about how to ## configure INN to use CNFS, see the storage.conf man page; and for ## information about how to create the CNFS buffers, see the cycbuff.conf ## man page. ## ## The order of lines in this file is not important among the same item. ## But all cycbuff item should be presented before any metacycbuff item. ## Number of articles written before the cycbuff header is ## written back to disk to (25 by default). cycbuffupdate:25 ## Interval (in seconds) between re-reads of the cycbuff (30 by default). refreshinterval:30 ## 1. Cyclic buffers ## Format: ## "cycbuff" (literally) : symbolic buffer name (less than 7 characters) : ## path to buffer file : length of symbolic buffer in kilobytes in decimal ## (1KB = 1024 bytes) ## ## If you're trying to stay under 2 GB, keep your sizes below 2097152. cycbuff:ONE:/export/cycbuffs/one:512000 cycbuff:TWO:/export/cycbuffs/two:512000 cycbuff:THREE:/export/cycbuffs/three:512000 ## 2. Meta-cyclic buffers ## Format: ## "metacycbuff" (literally) : symbolic meta-cyclic buffer name (less than ## 8 characters) : comma separated list of cyclic buffer symbolic names ## [:INTERLEAVE|SEQUENTIAL] ## ## With the default INTERLEAVE mode, articles are stored in each cycbuff ## in a round-robin fashion, one article per cycbuff in the order listed. ## With the SEQUENTIAL mode, each cycbuff is written in turn until that ## cycbuff is full and then moves on to the next one. ## ## Symbolic meta-cyclic buffer names are used in storage.conf in the ## options: field. metacycbuff:BIG:ONE,TWO:SEQUENTIAL metacycbuff:SMALL:THREE inn-2.6.4/samples/innshellvars.local0000755000175200017520000000070314002373703017113 0ustar iuliusiulius## $Id: innshellvars.local 10283 2018-05-14 12:43:05Z iulius $ ## ## Sample innshellvars.local script. ## ## It permits adding or overriding variables defined by ## the innshellvars shell script. ## This script has to be executable in order to be included ## during the run of innshellvars. ## Defining or redefining VARIABLE will allow using ## $VARIABLE with the corresponding value in a script ## calling innshellvars. #VARIABLE = 'test' inn-2.6.4/samples/nnrpd_auth_wrapper.py0000644000175200017520000000455114002373703017645 0ustar iuliusiulius## $Id: nnrpd_auth_wrapper.py 10282 2018-05-14 12:42:14Z iulius $ ## ## Example wrapper for support of old Python authentication scripts, ## by Erik Klavon. ## ## This file contains a sample Python script which can be used to ## duplicate the behaviour of the old nnrppythonauth functionality. ## This script only supports authentication. ## ## How to use this wrapper: ## - insert your authentication class into this file; ## - rename your authentication class OLDAUTH. ## ## See the INN Python Filtering and Authentication Hooks documentation ## for more information. ## The use of this file is *discouraged*. ## Old AUTH class. ## Insert your old auth class here. ## Do not include the code which sets the hook. ## Wrapper AUTH class. It creates an instance of the old class and ## calls its methods. Arguments and return values are munged as ## needed to fit the new way of doing things. class MYAUTH: """Provide auth callbacks to nnrpd.""" def authen_init(self): self.old = OLDAUTH() def authenticate(self, attributes): # Python 3.x uses memoryview(b'authinfo') because buffers # do not exist any longer. Note that the argument is # a bytes object. # attributes['type'] = memoryview(b'authinfo') # perm = (self.old).authenticate(attributes) # whereas in Python 2.x: # attributes['type'] = buffer('authinfo') # perm = (self.old).authenticate(attributes) response = 281 err_str = "No error" # if perm[0] == 481: # response = perm[0] # err_str = "Python authentication error!" return (response, err_str) def authen_close(self): (self.old).close() ## The rest is used to hook up the auth module on nnrpd. It is unlikely ## you will ever need to modify this. ## Import functions exposed by nnrpd. This import must succeed, or nothing ## will work! from nnrpd import * ## Create a class instance. myauth = MYAUTH() ## ...and try to hook up on nnrpd. This would make auth object methods visible ## to nnrpd. import sys try: set_auth_hook(myauth) syslog('notice', "authentication module successfully hooked into nnrpd") except Exception: # Syntax valid in both Python 2.x and 3.x. e = sys.exc_info()[1] syslog('error', "Cannot obtain nnrpd hook for authentication method: %s" % e.args[0]) inn-2.6.4/samples/send-uucp.cf0000644000175200017520000000222314002373703015600 0ustar iuliusiulius## $Id: send-uucp.cf 7650 2007-08-20 10:08:33Z iulius $ ## ## Configuration file for send-uucp(8). ## ## It specifies to which remote UUCP sites news batches from the outgoing ## files should be sent. ## ## Format: ## site[:host[:funnel]] [compressor [maxsize [batchtime]]] ## ## compressor, maxsize and batchtime can be left out and will then use the ## default values. You can't leave out the second field (compressor) and ## still use the third (maxsize) or the fourth (batchtime). So if you want ## to set a maxsize, you HAVE to add a compression method. ## ## compressor values can be one of: "bzip2", "compress", "gzip", "none". ## ## You can use flags with your compressor, just add them with a '_' character ## instead of a space. For example, "compress_-b13" for 13 bits compression. ## ## Remember that the size you set is the size *before* compression! ## ## See the send-uucp man page for more information. #zoetermeer gzip 1048576 5,18,22 #hoofddorp gzip 1048576 5,18,22 #pa3ebv gzip 1048576 5,18,22 #drinkel bzip2 1048576 5,6,18,20,22,0,2 #manhole compress 1048576 5,18,22 #owl compress 1048576 #able #pern::MYFUNNEL! inn-2.6.4/samples/distributions0000644000175200017520000000060014002373703016205 0ustar iuliusiulius## $Id: distributions 9028 2010-03-21 20:10:46Z iulius $ ## ## Sample distributions configuration file. ## ## It contains recommended values for the Distribution: header. ## It is encoded in UTF-8. ## See the distributions man page for more information. #fr Local to France. #local Local to this news server. #nj Local to New Jersey. #usa Local to the United States of America. inn-2.6.4/samples/actsync.ign0000644000175200017520000000111514002373703015525 0ustar iuliusiulius## $Id: actsync.ign 7664 2007-09-02 12:58:07Z iulius $ ## ## Sample actsync ignore file. ## ## It defines synchronization rules (which newsgroups will be ## checked and which will be ignored). ## See the actsync man page for more information. ## For now by default do not sync. i * ## Sync on the 8 majors. c comp.* c humanities.* c misc.* c news.* c rec.* c sci.* c soc.* c talk.* ## Sync only moderated gnu.* groups. #c gnu.* m ## Don't compare to.* groups as they will differ. i to.* ## We always want our special top level groups. i control i general i junk i test i to inn-2.6.4/samples/nnrpd_access.py0000644000175200017520000001037214002373703016403 0ustar iuliusiulius## $Id: nnrpd_access.py 10282 2018-05-14 12:42:14Z iulius $ ## ## This is a sample access module for the Python nnrpd hook. ## ## See the INN Python Filtering and Authentication Hooks documentation ## for more information. ## The python_access: parameter in readers.conf is used to load this script. ## ## An instance of ACCESS class is passed to nnrpd via the set_auth_hook() ## function imported from nnrpd. The following methods of that class ## are known to nnrpd: ## ## __init__() - Use this method to initialize your ## general variables or open a common ## database connection. May be omitted. ## access_init() - Init function specific to access ## control. May be omitted. ## access(attributes) - Called when a python_access ## statement is reached in the ## processing of readers.conf. Returns ## a dictionary of values representing ## statements to be included in an ## access group. ## access_close() - Called on nnrpd termination. Save ## your state variables or close a ## database connection. May be omitted. ## ## If there is a problem with return codes from any of these methods, ## then nnrpd will die and syslog the exact reason. ## ## There are also a few Python functions defined in nnrpd: ## ## set_auth_hook() - Called by nnrpd as this module is loaded. ## It is used to pass a reference to an ## instance of authentication class to nnrpd. ## syslog() - An equivalent replacement for regular syslog. ## One consideration for using it is to ## uniform nnrpd logging. ## Sample access class. It defines all access methods known to nnrpd. class ACCESS: """Provide access callbacks to nnrpd.""" def __init__(self): """This is a good place to initialize variables or open a database connection.""" syslog('notice', 'nnrpd access class instance created') def access_init(self): """Called when this script is initialized.""" pass def access(self, attributes): """Called when python_access: is encountered in readers.conf.""" # Just for debugging purposes (in Python 3.x syntax). # syslog('notice', 'n_a access() invoked: hostname %s, ipaddress %s, port %lu, interface %s, intipaddr %s, intport %lu, user %s' % ( \ # attributes['hostname'].tobytes(), \ # attributes['ipaddress'].tobytes(), \ # attributes['port'], \ # attributes['interface'].tobytes(), \ # attributes['intipaddr'].tobytes(), \ # attributes['intport'], \ # (attributes['user'].tobytes() if attributes['user'] else "-"))) # Allow newsreading from specific host only. # Python 2.x syntax: # if '127.0.0.1' == str(attributes['ipaddress']): # Python 3.x syntax: # if b'127.0.0.1' == attributes['ipaddress'].tobytes(): # syslog('notice', 'authentication access by IP address succeeded') # return {'read':'*', 'post':'*'} syslog('notice', 'authentication access by IP address failed') return {'read':'!*', 'post':'!*'} def access_close(self): """Called on nnrpd termination.""" pass ## The rest is used to hook up the access module on nnrpd. It is unlikely ## you will ever need to modify this. ## Import functions exposed by nnrpd. This import must succeed, or nothing ## will work! from nnrpd import * ## Create a class instance. myaccess = ACCESS() ## ...and try to hook up on nnrpd. This would make auth object methods visible ## to nnrpd. import sys try: set_auth_hook(myaccess) syslog('notice', "access module successfully hooked into nnrpd") except Exception: # Syntax valid in both Python 2.x and 3.x. e = sys.exc_info()[1] syslog('error', "Cannot obtain nnrpd hook for access method: %s" % e.args[0]) inn-2.6.4/samples/innshellvars.pl.local0000755000175200017520000000100514002373703017521 0ustar iuliusiulius## $Id: innshellvars.pl.local 10283 2018-05-14 12:43:05Z iulius $ ## ## Sample innshellvars.pl.local script. ## ## It permits adding or overriding variables defined by ## the INN::Config Perl module (or the legacy innshellvars.pl ## Perl script). ## This script has to be executable in order to be included ## during the run of INN::Config. ## Defining or redefining $variable will allow using ## $INN::Config::variable with the corresponding value ## in a script calling INN::Config. #$variable = 'test'; inn-2.6.4/samples/filter_innd.py0000644000175200017520000003130114002373703016231 0ustar iuliusiulius## $Id: filter_innd.py 10282 2018-05-14 12:42:14Z iulius $ ## ## This is a sample filter for the Python innd hook. ## ## See the INN Python Filtering and Authentication Hooks documentation ## for more information. ## ## You have access to the following methods from the module INN: ## - addhist(message-id) ## - article(message-id) ## - cancel(message-id) ## - havehist(message-id) ## - hashstring(string) ## - head(message-id) ## - newsgroup(groupname) ## - set_filter_hook(instance) ## - syslog(level, message) import re from string import * import sys ## The built-in intern() method has been in the sys module ## since Python 3.0. if sys.version_info[0] >= 3: def intern(headerName): return sys.intern(headerName) ## This looks weird, but creating and interning these strings should ## let us get faster access to header keys (which innd also interns) by ## losing some strcmps under the covers. Also_Control = intern("Also-Control") Approved = intern("Approved") Archive = intern("Archive") Archived_At = intern("Archived-At") Bytes = intern("Bytes") Cancel_Key = intern("Cancel-Key") Cancel_Lock = intern("Cancel-Lock") Comments = intern("Comments") Content_Base = intern("Content-Base") Content_Disposition = intern("Content-Disposition") Content_Transfer_Encoding = intern("Content-Transfer-Encoding") Content_Type = intern("Content-Type") Control = intern("Control") Date = intern("Date") Date_Received = intern("Date-Received") Distribution = intern("Distribution") Expires = intern("Expires") Face = intern("Face") Followup_To = intern("Followup-To") From = intern("From") In_Reply_To = intern("In-Reply-To") Injection_Date = intern("Injection-Date") Injection_Info = intern("Injection-Info") Jabber_ID = intern("Jabber-ID") Keywords = intern("Keywords") Lines = intern("Lines") List_ID = intern("List-ID") Message_ID = intern("Message-ID") MIME_Version = intern("MIME-Version") Newsgroups = intern("Newsgroups") NNTP_Posting_Date = intern("NNTP-Posting-Date") NNTP_Posting_Host = intern("NNTP-Posting-Host") NNTP_Posting_Path = intern("NNTP-Posting-Path") Organization = intern("Organization") Original_Sender = intern("Original-Sender") Originator = intern("Originator") Path = intern("Path") Posted = intern("Posted") Posting_Version = intern("Posting-Version") Received = intern("Received") References = intern("References") Relay_Version = intern("Relay-Version") Reply_To = intern("Reply-To") Sender = intern("Sender") Subject = intern("Subject") Summary = intern("Summary") Supersedes = intern("Supersedes") User_Agent = intern("User-Agent") X_Auth = intern("X-Auth") X_Auth_Sender = intern("X-Auth-Sender") X_Canceled_By = intern("X-Canceled-By") X_Cancelled_By = intern("X-Cancelled-By") X_Complaints_To = intern("X-Complaints-To") X_Face = intern("X-Face") X_HTTP_UserAgent = intern("X-HTTP-UserAgent") X_HTTP_Via = intern("X-HTTP-Via") X_Mailer = intern("X-Mailer") X_Modbot = intern("X-Modbot") X_Modtrace = intern("X-Modtrace") X_Newsposter = intern("X-Newsposter") X_Newsreader = intern("X-Newsreader") X_No_Archive = intern("X-No-Archive") X_Original_Message_ID = intern("X-Original-Message-ID") X_Original_NNTP_Posting_Host = intern("X-Original-NNTP-Posting-Host") X_Original_Trace = intern("X-Original-Trace") X_Originating_IP = intern("X-Originating-IP") X_PGP_Key = intern("X-PGP-Key") X_PGP_Sig = intern("X-PGP-Sig") X_Poster_Trace = intern("X-Poster-Trace") X_Postfilter = intern("X-Postfilter") X_Proxy_User = intern("X-Proxy-User") X_Submissions_To = intern("X-Submissions-To") X_Trace = intern("X-Trace") X_Usenet_Provider = intern("X-Usenet-Provider") X_User_ID = intern("X-User-ID") Xref = intern("Xref") __BODY__ = intern("__BODY__") __LINES__ = intern("__LINES__") class InndFilter: """Provide filtering callbacks to innd.""" def __init__(self): """This runs every time the filter is loaded or reloaded. This is a good place to initialize variables and precompile regular expressions, or maybe reload stats from disk. """ self.re_newrmgroup = re.compile('(?:new|rm)group\s') self.re_obsctl = re.compile('(?:sendsys|version|uuname)') # Message-ID pattern from a once-common spambot. self.re_none44 = re.compile('none\d+\.yet>') # There is a mad newgrouper who likes to meow. self.re_meow = re.compile("^Meow\!", re.M) # One of my silly addresses. self.re_fluffymorph = re.compile("andruQ@myremarQ.coM", re.I) def filter_before_reload(self): """Runs just before the filter gets reloaded. You can use this method to save state information to be restored by the __init__() method or down in the main module. """ syslog('notice', "filter_before_reload executing...") def filter_close(self): """Runs when innd exits. You can use this method to save state information to be restored by the __init__() method or down in the main module. """ syslog('notice', "filter_close running, bye!") def filter_messageid(self, msgid): """Filter articles just by their Message-IDs. This method interacts with the CHECK, IHAVE and TAKETHIS NNTP commands. If you return a non-empty string here, the offered article will be refused before you ever have to waste any bandwidth looking at it (unless TAKETHIS is used before an earlier CHECK). Make sure that such a message is properly encoded in UTF-8 so as to comply with the NNTP protocol. """ return "" # Deactivate the samples. syslog('notice', "just seen %s" % msgid) if self.re_none44.search(msgid): return "But I don't like spam!" if msgid[0:8] == ': ## Where: ## Wildcard name or IP address ## String to be displayed in the logs ## ## By adding a host to this file, it will be tracked using the ## nnrpd tracking system if enabled in inn.conf(5). Each read/post ## will have an entry logged with the in the log message ## # nasty.foo.com:nasty@foo.com # *.bar.com:VeryNastyClient inn-2.6.4/samples/newsfeeds.in0000644000175200017520000001355014002373703015703 0ustar iuliusiulius## $Id: newsfeeds.in 9501 2013-07-01 17:32:45Z iulius $ ## ## newsfeeds - determine where Usenet articles get sent ## ## Format: ## site[/exclude,exclude...]\ ## :pattern,pattern...[/distrib,distrib...]\ ## :flag,flag...\ ## :param ## ## This file is complicated -- see newsfeeds(5) for full details. ## The ME feed entry is special magic. ## ## "/exclude" entries for this feed entry will cause INN to reject all ## articles that have passed through those listed sites (by matching ## Path: entries). There are some "pseudo-sites" in general use that can ## be listed as exclusions to reject specific types of 3rd-party cancel ## messages (see the "Cancel FAQ" in news.admin.net-abuse.usenet): ## ## cyberspam Cancels for spam, munged articles, binaries ## spewcancel Cancels for munged articles and runaway gateways ## bincancel Cancels for binary postings to non-binary groups ## udpcancel Cancels to force sites to enforce antispam policies ## ## The "pattern" field for this feed entry gives the initial subscription ## list for all other feeds specified in this file. These patterns are ## *prepended* to all other feed patterns. Using this feature is ## confusing and mildly discouraged; make sure you understand the man ## page before using it. ## ## "/distrib" for this feed entry specifies what distributions the server ## will accept. If any distributions are listed there, the server will ## accept only articles with those distributions and articles that do not ## have a Distribution: header field. If all the distributions listed are ## negated (starting with "!"), then the server will only accept articles ## without those distributions and articles that do not have a Distribution: ## header field. ## ## For the ME line (and the ME line *only*), patterns affect *outgoing* ## feeds and distributions affect *incoming* feeds (including local posts). # Empty default subscription list, reject all incoming articles (including # locally posted articles) with a distribution of "local" or # "collabra-internal", accept all others (including articles that do not # have a Distribution: header field). ME:!*/!local,!collabra-internal:: # The same as the above, but would reject all posts that have # news.example.com in the path (posts passing through that site). #ME/news.example.com:!*/!local,!collabra-internal:: # An empty ME entry is possible, in which case no exclusion patterns # will be defined. #ME::: # The special feed that handles all newsgroup control messages. Only # disable this if you want to ignore all newsgroup control messages; INN # no longer handles any control messages except cancel internally. controlchan!\ :!*,control,control.*,!control.cancel\ :AC,Tc,Wnsm:@bindir@/controlchan ## Uncomment if you're using innfeed. This feed tells INN how to run ## innfeed, and then every site you're feeding with innfeed has a ## flag of Tm and an argument of "innfeed!" to funnel into this feed. ## The feed pattern for innfeed should *always* be "!*"; don't ever ## feed articles directly into innfeed. ## ## Add "-y" as an option to innfeed to use the name of each feed as the ## name of the host to feed articles to; without "-y" an innfeed.conf ## file is needed. # innfeed funnel master. #innfeed!\ # :!*\ # :Tc,Wnm*:@bindir@/innfeed ## Only uncomment this feed if both enableoverview and useoverchan are ## set to true in inn.conf. By default, innd will write out overview ## internally and doesn't need or want this feed, but useoverchan can ## optionally be set to true and this feed uncommented to move those ## operations out of innd's main loop. # News overview. #overview!:*:Tc,WnteO:@bindir@/overchan ## OUTGOING NORMAL FEED EXAMPLES # A real-time feed through innfeed. Don't send articles with a distribution # of "foo", since those articles are internal. # Note that control messages will be sent even though "!control,!control.*" # is specified. It is useful not to forget that pattern since control # messages for local.* would still be sent with "*,@local.*" only. #news.uu.net/uunet\ # :*,!junk,!control,!control.*/!foo\ # :Tm:innfeed! # Create a batch file in @SPOOLDIR@/outgoing for all articles # that haven't already passed through nic.near.net. The batch file will # be named nic.near.net, the default file name, and either nntpsend or # send-nntp can send articles from that spool file. #nic.near.net\ # :*,!junk,!control,!control.*/!foo\ # :Tf,Wnm: # A UUCP feed, where we try to keep the "batching" between 4 KB and 1 KB. # You can use send-uucp(8) to process these batch files. #ihnp4\ # :*,!junk,!control,!control.*/!foo\ # :Tf,Wnb,B4096/1024: ## OUTGOING SPECIAL FEED EXAMPLES # Accumulate Path: header statistics. See ninpaths(8) for more details on # how to set this up. #inpaths!:*:Tc,WP:@bindir@/ninpaths -p -d @LOGDIR@/path/inpaths.%d # Feed all moderated source postings to an archiver. #source-archive!:!*,*sources*,!*wanted*,!*.d\ # :Tc,Wn:@bindir@/archive -f -i @SPOOLDIR@/archive/INDEX # Feed NoCeM notices to perl-nocem in order to process third-party, # PGP-signed article cancellation notices. See perl-nocem(8) for more # details on how to set this up. #nocem!:!*,alt.nocem.misc,news.lists.filters\ # :Tc,Wf,Ap:@bindir@/perl-nocem # News to mail gateway. Similar to innfeed, this uses a master feed and # then individual feeds for every separate address that news is being # gated to. This sends all posts to rec.pets.red-ants to the address # listed in @sysconfdir@/news2mail.cf for list-big-red-ants. # Posts from the domain list owner are excluded (path for that example: # lists.ucsd.edu). #news2mail!:!*:Ac,Tc,Wn*:@bindir@/news2mail #list-big-red-ants/lists.ucsd.edu:!*,rec.pets.red-ants:Ap,Tm:news2mail! # Capture all local postings (with a distribution of "foo" and no more # than two sites in the Path: header) using a local program (that doesn't # come with INN). #capture!\ # :*/foo\ # :Tp,H2:/usr/local/bin/capture %s inn-2.6.4/samples/active.minimal0000644000175200017520000000034114002373703016205 0ustar iuliusiuliuscontrol 0000000000 0000000001 n control.cancel 0000000000 0000000001 n control.checkgroups 0000000000 0000000001 n control.newgroup 0000000000 0000000001 n control.rmgroup 0000000000 0000000001 n junk 0000000000 0000000001 n inn-2.6.4/samples/nnrpd_dynamic_wrapper.py0000644000175200017520000000356514002373703020334 0ustar iuliusiulius## $Id: nnrpd_dynamic_wrapper.py 10282 2018-05-14 12:42:14Z iulius $ ## ## Example wrapper for support of old Python authentication scripts, ## by Erik Klavon. ## ## This file contains a sample Python script which can be used to ## duplicate the behaviour of the old nnrppythonauth functionality. ## This script only supports dynamic access control by group. ## ## How to use this wrapper: ## - insert your authentication class into this file; ## - rename your authentication class OLDAUTH. ## ## See the INN Python Filtering and Authentication Hooks documentation ## for more information. ## The use of this file is *discouraged*. ## Old AUTH class. ## Insert your old auth class here. ## Do not include the code which sets the hook. ## Wrapper DYNACCESS class. It creates an instance of the old class and ## calls its methods. Arguments and return values are munged as ## needed to fit the new way of doing things. class MYDYNACCESS: """Provide dynamic access callbacks to nnrpd.""" def dynamic_init(self): self.old = OLDAUTH() def dynamic(self, attributes): return (self.old).authorize(attributes) def dynamic_close(self): (self.old).close() ## The rest is used to hook up the dynamic access module on nnrpd. ## It is unlikely you will ever need to modify this. ## Import functions exposed by nnrpd. This import must succeed, or nothing ## will work! from nnrpd import * ## Create a class instance. mydynaccess = MYDYNACCESS() ## ...and try to hook up on nnrpd. This would make auth object methods visible ## to nnrpd. import sys try: set_auth_hook(mydynaccess) syslog('notice', "dynamic access module successfully hooked into nnrpd") except Exception: # Syntax valid in both Python 2.x and 3.x. e = sys.exc_info()[1] syslog('error', "Cannot obtain nnrpd hook for dynamic access method: %s" % e.args[0]) inn-2.6.4/samples/inn.conf.in0000644000175200017520000001416614002373703015434 0ustar iuliusiulius## $Id: inn.conf.in 10301 2018-11-11 14:42:17Z iulius $ ## ## inn.conf -- INN configuration data ## ## Format: ## : ## ## Blank values are allowed for certain parameters. ## ## See the inn.conf(5) man page for a full description of each of these ## options. This sample file is divided into two sections; first, there ## are the parameters that must be set (or should be set in nearly all ## cases), and then all parameters are given with their defaults for ## reference in the same order and with the same organization as the ## inn.conf(5) documentation. # The following parameters are most likely to need setting, although the # defaults generated by configure may be reasonable. mta: "@SENDMAIL@ -oi -oem %s" organization: "A poorly-installed InterNetNews site" ovmethod: tradindexed hismethod: hisv6 pathhost: @HOSTNAME@ pathnews: @prefix@ #runasuser: #runasgroup: # General Settings #domain: #innflags: mailcmd: @bindir@/innmail #server: #syntaxchecks: [ no-laxmid ] # Feed Configuration artcutoff: 10 #bindaddress: #bindaddress6: dontrejectfiltered: false hiscachesize: 256 ignorenewsgroups: false immediatecancel: false linecountfuzz: 0 maxartsize: 1000000 maxconnections: 50 #pathalias: #pathcluster: pgpverify: @DO_PGPVERIFY@ port: 119 refusecybercancels: false remembertrash: true #sourceaddress: #sourceaddress6: verifycancels: false verifygroups: false wanttrash: false wipcheck: 5 wipexpire: 10 # Article Storage cnfscheckfudgesize: 0 enableoverview: true extraoverviewadvertised: [ ] extraoverviewhidden: [ ] groupbaseexpiry: true mergetogroups: false nfswriter: false overcachesize: 128 #ovgrouppat: storeonxref: true useoverchan: false wireformat: true xrefslave: false # Reading allownewnews: true articlemmap: true clienttimeout: 1800 initialtimeout: 10 msgidcachesize: 64000 nfsreader: false nfsreaderdelay: 60 nnrpdcheckart: true nnrpdflags: "" nnrpdloadlimit: 16 noreader: false readerswhenstopped: false readertrack: false tradindexedmmap: true # Reading -- Keyword Support # # You should add "keywords" to extraoverviewadvertised or extraoverviewhidden # if you enable this feature. You must have compiled this support in too # with --enable-keywords at configure time. keywords: false keyartlimit: 100000 keylimit: 512 keymaxwords: 250 # Posting addinjectiondate: true addinjectionpostingaccount: false addinjectionpostinghost: true checkincludedtext: false #complaints: #fromhost: localmaxartsize: 1000000 #moderatormailer: nnrpdauthsender: false #nnrpdposthost: nnrpdpostport: 119 spoolfirst: false strippostcc: false # Posting -- Exponential Backoff backoffauth: false #backoffdb: backoffk: 1 backoffpostfast: 0 backoffpostslow: 1 backofftrigger: 10000 # Reading and Posting -- TLS/SSL Support # # The OpenSSL SSL and crypto libraries must have been found # at configure time to have this support, or you must have # compiled this support in with --with-openssl at configure time. #tlscafile: #tlscapath: @sysconfdir@ #tlscertfile: @sysconfdir@/cert.pem #tlskeyfile: @sysconfdir@/key.pem #tlsciphers: #tlsciphers13: #tlscompression: false #tlseccurve: #tlspreferserverciphers: true #tlsprotocols: [ TLSv1 TLSv1.1 TLSv1.2 TLSv1.3 ] # Monitoring doinnwatch: true innwatchbatchspace: 4000 innwatchlibspace: 25000 innwatchloload: 1000 innwatchhiload: 2000 innwatchpauseload: 1500 innwatchsleeptime: 600 innwatchspoolnodes: 200 innwatchspoolspace: 25000 # Logging docnfsstat: false htmlstatus: true incominglogfrequency: 200 logartsize: true logcancelcomm: false logcycles: 3 logipaddr: true logsitename: true logstatus: true logtrash: true nnrpdoverstats: true nntplinklog: false #stathist: status: 600 timer: 600 # System Tuning badiocount: 5 blockbackoff: 120 chaninacttime: 600 chanretrytime: 300 datamovethreshold: 16384 icdsynccount: 10 keepmmappedthreshold: 1024 #maxcmdreadsize: maxforks: 10 nicekids: 4 nicenewnews: 0 nicennrpd: 0 pauseretrytime: 300 peertimeout: 3600 rlimitnofile: -1 # Paths patharchive: @SPOOLDIR@/archive patharticles: @SPOOLDIR@/articles pathbin: @bindir@ pathcontrol: @CONTROLDIR@ pathdb: @DBDIR@ pathetc: @sysconfdir@ pathfilter: @FILTERDIR@ pathhttp: @HTTPDIR@ pathincoming: @SPOOLDIR@/incoming pathlog: @LOGDIR@ pathoutgoing: @SPOOLDIR@/outgoing pathoverview: @SPOOLDIR@/overview pathrun: @RUNDIR@ pathspool: @SPOOLDIR@ pathtmp: @tmpdir@ inn-2.6.4/samples/incoming.conf0000644000175200017520000001401414002373703016036 0ustar iuliusiulius## $Id: incoming.conf 10179 2017-09-18 20:13:48Z iulius $ ## ## incoming.conf -- Configuration of incoming news feeds ## ## This file consists of three types of entries: key/value, peer and group. ## Comments are taken from the hash character "#" to the end of the line. ## Blank lines are ignored. ## ## Key/value entries are a keyword immediately followed by a colon, at least ## one blank and a value. For example: ## ## max-connections: 10 ## ## A legal key contains neither blanks, nor colon, nor "#". ## There are three different types of values: integers, booleans, and strings. ## Integers are as to be expected. A boolean value is either "true" or ## "false" (case is significant). A string value is any other sequence of ## characters. If the string needs to contain whitespace, then it must be ## quoted with double quotes. ## ## Peer entries look like: ## ## peer { ## # body ## } ## ## The word "peer" is required. is a label for this peer. It is ## any string valid as a key. The body of a peer entry contains some number ## of key/value entries. ## ## Group entries look like: ## ## group { ## # body ## } ## ## The word "group" is required. is any string valid as a key. ## The body of a group entry contains any number of the three types of ## entries. So key/value pairs can be defined inside a group, and peers can ## be nested inside a group, and other groups can be nested inside a group. ## ## Key/value entries that are defined outside of all peer and group entries ## are said to be at "global scope". Global key/value entries act as ## defaults for peers. When innd looks for a specific value in a peer entry ## (for example, the maximum number of connections to allow), if the value ## is not defined in the peer entry, then the enclosing groups are examined ## for the entry (starting at the closest enclosing group). If there are no ## enclosing groups, or the enclosing groups don't define the key/value, ## then the value at global scope is used. ## ## A small example could be: ## ## # Global value applied to all peers that have no value of their own. ## max-connections: 5 ## ## # A peer definition. ## peer uunet { ## hostname: usenet1.uu.net ## } ## ## peer vixie { ## hostname: gw.home.vix.com ## max-connections: 10 # Override global value. ## } ## ## # A group of two peers which can open more connections than normal. ## group fast-sites { ## max-connections: 15 ## ## # Another peer. The max-connections: value from the ## # fast-sites group scope is used. ## peer data.ramona.vix.com { ## hostname: data.ramona.vix.com ## } ## ## peer bb.home.vix.com { ## hostname: bb.home.vix.com ## max-connections: 20 # He can really cook. ## } ## } ## ## Given the above configuration file, the defined peers would have the ## following values for the max-connections: key. ## ## uunet 5 ## vixie 10 ## data.ramona.vix.com 15 ## bb.home.vix.com 20 ## ## The following keys are allowed: ## ## hostname: ## This key is mandatory in a peer block. The value is a string representing ## a list of hostnames separated by a comma. A hostname is either a FQDN ## that resolves to the IPv4 or IPv6 address of the peer, or the dotted-quad ## IP address of the peer for IPv4, or the colon-separated IP address of ## the peer for IPv6. ## ## streaming: ## This key requires a boolean value. It defines whether streaming commands ## are allowed from this peer. (default=true) ## ## max-connections: ## This key requires a positive integer value. It defines the maximum number ## of connections allowed. A value of zero specifies an unlimited number ## of maximum connections ("unlimited" or "none" can be used as synonyms). ## (default=0) ## ## hold-time: ## This key requires a positive integer value. It defines the hold time before ## close, if the connection is over the max-connections: value. A value of zero ## specifies immediate close. (default=0) ## ## identd: ## This key requires a string value. It is used if you wish to require a ## peer's user name retrieved through identd match the specified string. ## (unset by default, that is to say no identd) ## ## password: ## This key requires a string value. It is used if you wish to require a peer ## to supply a password. (unset by default, that is to say no password) ## ## patterns: ## This key requires a string value. It is a list of newsfeeds(5)-style list ## of newsgroups which are to be accepted from this host. (default="*") ## ## email: ## This key requires a string value. Reserved for future use. (empty by default) ## ## comment: ## This key requires a string value. Reserved for future use. (empty by default) ## ## skip: ## This key requires a boolean value. Setting this entry causes this peer ## to be skipped. (default=false) ## ## ignore: ## This key requires a boolean value. Setting this entry causes innd to ## refuse every article sent via CHECK or IHAVE by this peer. (default=false) ## ## noresendid: ## This key requires a boolean value. It defines whether innd should send ## "431" (response to CHECK, in streaming mode) or "436" (response to IHAVE ## in non-streaming mode) responses instead of "438" (response to CHECK) ## or "435" (response to IHAVE) if a message is offered that is already ## received from another peer. This can be useful for peers that resend ## messages right away, as innfeed does. (default=false) ## ## nolist: ## This key requires a boolean value. It defines whether a peer is allowed ## to issue list command. (default=false, that is to say it can) ## streaming: true # Streaming allowed by default. max-connections: 8 # Per feed. peer ME { hostname: "localhost, 127.0.0.1, ::1" } inn-2.6.4/samples/localgroups0000644000175200017520000000131214002373703015636 0ustar iuliusiulius## $Id: localgroups 8441 2009-05-03 22:12:50Z iulius $ ## ## Put your local newsgroups, along with their descriptions, ## in this file (formatted like the newsgroups file) if you want ## them to be recognized by docheckgroups. They would otherwise ## be mentioned for removal. ## ## There is no need to put here local newsgroups of hierarchies ## for which no checkgroups control messages are sent (unless ## you manually process checkgroups texts for them). ## ## Lines beginning with a hash sign (#) are not taken into account. ## ## See the docheckgroups man page for more information. #comp.group.to.add An additional local newsgroup in comp.*. #comp.other.group Another local newsgroup in comp.*. inn-2.6.4/samples/nnrpd_access_wrapper.pl.in0000644000175200017520000000267214002373703020537 0ustar iuliusiulius#! /usr/bin/perl -w # fixscript will replace this line with code to load INN::Config # Example wrapper nnrpd_access.pl for support of old perl authentication # scripts, by Erik Klavon. # This file contains a sample perl script which can be used to # duplicate the behavior of the old nnrpperlauth functionality. This # script only supports access control. # How to use this wrapper: # - append your old script to this file with two changes: # - rename the old "auth_init" sub to "old_auth_init" # - rename the old "authenticate" sub to "old_authenticate" use vars qw(%attributes); # access # This sub modifies the global hash attributes so that it has all the # entries required in the old way of doing things, calls # old_authenticate, and creates a return hash with the right attributes. sub access { # Comment this out if you don't need auth_init. old_auth_init(); $attributes{type} = "connect"; my @connect_array = old_authenticate(); my %hash; # handle max rate if ($connect_array[4]) { # Force perl to make a C string out of this integer, # or else bad things will happen. Sigh. $hash{"max_rate"} = $connect_array[4] . "\0"; } # handle read boolean, set to wildmat if ($connect_array[1]) { $hash{"read"} = $connect_array[3]; } # handle post boolean, set to wildmat if ($connect_array[2]) { $hash{"post"} = $connect_array[3]; } return %hash; } inn-2.6.4/samples/inn-radius.conf0000644000175200017520000000340214002373703016303 0ustar iuliusiulius# $Id: inn-radius.conf 9940 2015-09-04 12:58:15Z iulius $ # # Sample RADIUS configuration file for the RADIUS readers.conf # authenticator. If you're not using that authenticator, this file is not # used. server radius { # Hostname of the RADIUS server. #radhost: radius-server.example.com # Port to query on the RADIUS server. radport: 1645 # Local hostname or IP address making the request. # # The RADIUS server expects an IP address; a hostname will be translated # into an IP address with gethostbyname(). If not given, this information # is not included in the request (not all RADIUS setups need this information). #lochost: news.example.com # Local port of connection. # # The port the client being authenticated is connecting to. If not # given, defaults to 119. This doesn't need to be set unless readers are # connecting to a non-standard port. #locport: 119 # Shared secret with the RADIUS server. # # If your secret includes spaces, tabs, or #, be sure to include it # in double quotes. #secret: SECRET-WORD # Prefix for username. # # Before being given to the RADIUS server, usernames will be rewritten by # prepending the prefix, if given, and then appending the suffix, if # given. #prefix: news- # Suffix for username. #suffix: @example.com # Whether to ignore bad reply IP. # # If set to false, the RADIUS authenticator will check to ensure that the # response it receives is from the same IP address as it sent the request # to (for some added security). If set to true, it will skip this # verification check (if your RADIUS server has multiple IP addresses or # if other odd things are going on, it may be perfectly normal for the # response to come from a different IP address). ignore-source: false } inn-2.6.4/samples/INN.py0000644000175200017520000000202714002373703014363 0ustar iuliusiulius## $Id: INN.py 8250 2008-12-23 12:00:46Z iulius $ ## ## This module supplies stub Python functions corresponding to the ones ## provided by innd. It is not used by the server; it is only here so ## that you can test your filter scripts before loading. ## See the INN Python Filtering and Authentication Hooks documentation ## for more information. from types import * def set_filter_hook(anObject): print("** set_filter_hook for " + repr(anObject)) def addhist(messageid): print("** addhist Message-ID: " + messageid) def havehist(messageid): print("** havehist Message-ID: " + messageid) def cancel(messageid): print("** cancel Message-ID: " + messageid) def newsgroup(groupname): print("** newsgroup: " + groupname) def head(messageid): print("** head Message-ID: " + messageid) def article(messageid): print("** article Message-ID: " + messageid) def hashstring(mystring): print("** hash: " + mystring) def syslog(level, message): print("-- syslog level: %s message: %s" % (level, message)) inn-2.6.4/samples/Makefile0000644000175200017520000000277614002373703015040 0ustar iuliusiulius## $Id: Makefile 7650 2007-08-20 10:08:33Z iulius $ ## ## All the actual installation work of any files in the samples directory ## is done via the site directory, so that one can maintain one's news ## configuration in the site directory and use make commands to update the ## server automatically. All this Makefile does is run fixconfig or ## fixscript on a few files that need configure results (and remove them on ## make clean). include ../Makefile.global top = .. ALL = buffindexed.conf inn.conf innreport.conf newsfeeds \ nnrpd_auth.pl nnrpd_access.pl nnrpd_auth_wrapper.pl \ nnrpd_access_wrapper.pl all: $(ALL) install: bootstrap: clean clobber distclean maintclean: rm -f $(ALL) depend: profiled: all $(FIXCONFIG) $(FIXSCRIPT): @echo Run configure before running make. See INSTALL for details. @exit 1 ## Build rules. FIXC = $(FIXCONFIG) FIXS = $(FIXSCRIPT) buffindexed.conf: buffindexed.conf.in $(FIXC) ; $(FIXC) $@.in inn.conf: inn.conf.in $(FIXC) ; $(FIXC) $@.in innreport.conf: innreport.conf.in $(FIXC) ; $(FIXC) $@.in newsfeeds: newsfeeds.in $(FIXC) ; $(FIXC) $@.in nnrpd_auth.pl: nnrpd_auth.pl.in $(FIXS) ; $(FIXS) $@.in nnrpd_access.pl: nnrpd_access.pl.in $(FIXS) ; $(FIXS) $@.in nnrpd_auth_wrapper.pl: nnrpd_auth_wrapper.pl.in $(FIXS) ; $(FIXS) $@.in nnrpd_access_wrapper.pl: nnrpd_access_wrapper.pl.in $(FIXS) ; $(FIXS) $@.in inn-2.6.4/samples/storage.conf0000644000175200017520000000276014002373703015704 0ustar iuliusiulius## $Id: storage.conf 7651 2007-08-20 10:28:34Z iulius $ ## ## Rules for where INN should store incoming articles. ## ## This file is used to determine which storage method articles are sent ## to be stored and which storage class they are stored as. Each ## method is described as follows: ## ## method { ## newsgroups: ## class: ## size: [,] ## expires: [,] ## options: ## exactmatch: ## } ## ## See the storage.conf man page for more information. ## ## Only newsgroups, class, and (for CNFS, to specify the metacycbuff) ## options are required; the other keys are optional. If any CNFS ## methods are configured, you will also need to set up cycbuff.conf. ## By default, store everything in tradspool. method tradspool { newsgroups: * class: 0 } ## Here are some samples for a CNFS configuration. This assumes that you ## have two metacycbuffs configured, one for text newsgroups and one for ## binaries. Cancel messages, which tend to be very high-volume, are ## stored in the binary metacycbuff as well. This assumes storeonxref is ## set to true in inn.conf. ## Pick off the binary newsgroups first. #method cnfs { # newsgroups: *.bina*,control.cancel # class: 1 # options: BINARY #} ## Put the remaining (text) groups in the other cycbuff. #method cnfs { # newsgroups: * # class: 2 # options: TEXT #} inn-2.6.4/samples/nnrpd.py0000644000175200017520000000105214002373703015055 0ustar iuliusiulius## $Id: nnrpd.py 8250 2008-12-23 12:00:46Z iulius $ ## ## This module supplies stub Python functions corresponding to the ones ## provided by nnrpd. It is not used by the server; it is only here so ## that you can test your filter scripts before loading. ## See the INN Python Filtering and Authentication Hooks documentation ## for more information. from types import * def set_auth_hook(anObject): print("** set_auth_hook for " + repr(anObject)) def syslog(level, message): print("-- syslog level: %s message: %s" % (level, message)) inn-2.6.4/samples/innshellvars.tcl.local0000755000175200017520000000072114002373703017674 0ustar iuliusiulius## $Id: innshellvars.tcl.local 10283 2018-05-14 12:43:05Z iulius $ ## ## Sample innshellvars.tcl.local script. ## ## It permits adding or overriding variables defined by ## the innshellvars.tcl script. ## This script has to be executable in order to be included ## during the run of innshellvars.tcl. ## Defining or redefining variable will allow using ## $variable with the corresponding value during the run ## of innshellvars.tcl. #set variable "test" inn-2.6.4/samples/newsgroups.minimal0000644000175200017520000000051514002373703017151 0ustar iuliusiuliuscontrol Various control messages (no posting). control.cancel Cancel messages (no posting). control.checkgroups Hierarchy check control messages (no posting). control.newgroup Newsgroup creation control messages (no posting). control.rmgroup Newsgroup removal control messages (no posting). junk Unfiled articles (no posting). inn-2.6.4/samples/readers.conf0000644000175200017520000001121314002373703015656 0ustar iuliusiulius## $Id: readers.conf 7828 2008-05-07 07:58:22Z iulius $ ## ## readers.conf - Access control and configuration for nnrpd ## ## Format: ## auth "" { ## hosts: "" ## auth: "" ## res: "" ## default: "" ## default-domain: "" ## } ## access "" { ## users: "" ## newsgroups: "" ## read: "" ## post: "" ## access: "" ## } ## ## Other parameters are possible. See readers.conf(5) for all the ## details. Only one of newsgroups or read/post may be used in a single ## access group. ## ## If the connecting host is not matched by any hosts: parameter of any ## auth group, it will be denied access. auth groups assign an identity ## string to connections, access groups grant privileges to identity ## strings matched by their users: parameters. ## ## In all cases, the last match found is used, so put defaults first. ## ## For a news server that allows connections from anyone within a ## particular domain or IP address range, just uncomment the "local" auth ## group and the "local" access group below and adjust the hosts: and ## default: parameters of the auth group and the users: parameter of the ## access group for your local network and domain name. That's all there ## is to it. ## ## For more complicated configurations, read the comments on the examples ## and also see the examples and explanations in readers.conf(5). The ## examples in readers.conf(5) include setups that require the user to ## log in with a username and password (the example in this file only ## uses simple host-based authentication). ## ## NOTE: Unlike in previous versions of INN, nnrpd will now refuse any ## post from anyone to a moderated newsgroup that contains an Approved: ## header unless their access block has an access: key containing the ## "A" flag. This is to prevent abuse of moderated groups, but it means ## that if you support any newsgroup moderators, you need to make sure ## to add such a line to the access group that affects them. See the ## access group for localhost below for an example. # The only groups enabled by default (the rest of this file is # commented-out examples). This assigns the identity of to # the local machine auth "localhost" { hosts: "localhost, 127.0.0.1, ::1, stdin" default: "" } # Grant that specific identity access to read and post to any newsgroup # and allow it to post articles with Approved: headers to moderated # groups. access "localhost" { users: "" newsgroups: "*" access: RPA } # This auth group matches all connections from example.com or machines in # the example.com domain and gives them the identity @example.com. # Instead of using wildmat patterns to match machine names, you could also # put a wildmat pattern matching IP addresses or an IP range specified # using CIDR notation (like 10.10.10.0/24) here. #auth "local" { # hosts: "*.example.com, example.com" # default: "@example.com" #} # This auth group matches a subset of machines and assigns connections # from there an identity of "@example.com"; these systems should # only have read access, no posting privileges. #auth "read-only" { # hosts: "*.newuser.example.com" # default: "@example.com" #} # This auth group matches the systems at a guest institution that should # be allowed to read the example.events.* hierarchy but nothing else. #auth "events-only" { # hosts: "*.example.org" # default: "@example.org" #} # Finally, this auth group matches some particular systems which have been # abusing the server. Note that it doesn't assign them an identity at # all; the "empty" identity created in this fashion won't match any users: # parameters. Note also that it's last, so anything matching this entry # will take precedent over everything above it. #auth "abusers" { # hosts: "badguy-dsl.example.com, kiosk.public-access.example.com" #} # Now for the access groups. All of our access groups should have users: # parameters so there are no access groups that match connections without # an identity (such as are generated by the "abusers" entry above). # First, the default case of local users, who get to read and post to # everything. #access "local" { # users: "@example.com" # newsgroups: "*" #} # Now, the read-only folks, who only get to read everything. #access "read-only" { # users: "@example.com" # read: "*" #} # Finally, the events-only people who get to read and post but only to a # specific hierarchy. #access "events-only" { # users: "@example.org" # newsgroups: "example.events.*" #} inn-2.6.4/samples/buffindexed.conf.in0000644000175200017520000000116314002373703017124 0ustar iuliusiulius## $Id: buffindexed.conf.in 7651 2007-08-20 10:28:34Z iulius $ ## ## Configuration for the buffindexed overview method. ## ## It specifies the buffers that the buffindexed overview method ## should use. It is required if the server uses buffindexed (as ## configured by the ovmethod: parameter in inn.conf). ## See the buffindexed.conf man page for more information. ## ## The order of lines in this file is not important. ## Format: ## index(0-65535) : path to buffer file : ## length of buffer in kilobytes in decimal (1KB = 1024 bytes) 0:@SPOOLDIR@/overview/OV1:1536000 1:@SPOOLDIR@/overview/OV2:1536000 inn-2.6.4/samples/nnrpd_access.pl.in0000644000175200017520000001016414002373703016772 0ustar iuliusiulius#! /usr/bin/perl -w # fixscript will replace this line with code to load INN::Config ## ## Sample code for the nnrpd Perl access hooks. ## This file is loaded when a perl_access: parameter is reached in ## readers.conf. If it defines a sub named access, which will be ## called during processing of a perl_access: parameter. Attributes ## about the connection are passed to the program in the %attributes ## global variable. It should return a hash containing ## parameter-value pairs for the access group. If there is a problem, ## nnrpd will die and syslog the exact error. ## The default behavior of the following code is to look for nnrp.access ## in INN's configuration file directory and to attempt to implement about ## the same host-based access control as the previous nnrp.access code in ## earlier versions of INN. This may be useful for backward compatibility. ## This file cannot be run as a standalone script, although it would be ## worthwhile to add some code so that it could so that one could test the ## results of various authentication and connection queries from the ## command line. The #! line at the top is just so that fixscript will ## work. # This function is called when perl_access: is reached in readers.conf. # For details on all the information passed to it, see # ~news/doc/hook-perl. sub access { &loadnnrp($INN::Config::newsetc . '/nnrp.access'); return &checkhost($attributes{hostname}, $attributes{ipaddress}); } # Called at startup, this loads the nnrp.access file and converts it into a # convenient internal format for later queries. sub loadnnrp { my $file = shift; my ($block, $perm, $user, $pass); open (ACCESS, $file) or die "Could not open $file: $!\n"; local $_; while () { my %tmp; chomp; s/\#.*//; ($block, $perm, $user, $pass, $tmp{groups}) = split /:/; next unless (defined $tmp{groups}); # We don't support username/password entries, so be safe. next if ($user || $pass); # Change the wildmat pattern to a regex (this isn't thorough, as # some ranges won't be converted properly, but it should be good # enough for this purpose). if ($block !~ m%^(?:\d+\.){3}\d+/\d+$%) { $block =~ s/\./\\./g; $block =~ s/\?/./g; $block =~ s/\*/.*/g; } $tmp{block} = $block; $tmp{canread} = ($perm =~ /r/i); $tmp{canpost} = ($perm =~ /p/i); unshift(@hosts, { %tmp }); } close ACCESS; } # Given the hostname and IP address of a connecting host, use our @hosts # array constructed from nnrp.access and see what permissions that host has. sub checkhost { my ($host, $ip) = @_; my %return_hash; my $key; for $key (@hosts) { my ($read, $post) = ($key->{canread}, $key->{canpost}); # First check for CIDR-style blocks. if ($key->{block} =~ m%^(\d+\.\d+\.\d+\.\d+)/(\d+)$%) { my $block = unpack('N', pack('C4', split(/\./, $1))); my $mask = (0xffffffff << (32 - $2)) & 0xffffffff; $block = $block & $mask; my $packedip = unpack('N', pack('C4', split(/\./, $ip))); if (($packedip & $mask) == $block) { if ($read) { $return_hash{"read"} = $key->{groups}; } if ($post) { $return_hash{"post"} = $key->{groups}; } return %return_hash; } } if ($ip =~ /^$key->{block}$/) { if ($read) { $return_hash{"read"} = $key->{groups}; } if ($post) { $return_hash{"post"} = $key->{groups}; } return %return_hash; } if ($host =~ /^$key->{block}$/) { if ($read) { $return_hash{"read"} = $key->{groups}; } if ($post) { $return_hash{"post"} = $key->{groups}; } return %return_hash; } } # If we fell through to here, nothing matched, so we should deny # permissions. return %return_hash; } inn-2.6.4/samples/subscriptions0000644000175200017520000000016214002373703016215 0ustar iuliusiuliusnews.announce.newusers news.newusers.questions misc.test misc.test.moderated news.announce.newgroups news.answers inn-2.6.4/samples/innwatch.ctl0000644000175200017520000000430114002373703015701 0ustar iuliusiulius## $Id: innwatch.ctl 10305 2018-12-02 14:21:56Z iulius $ ## ## Sample control file for innwatch. ## ## Indicates what to run to test the state of the news system, and what ## to do about it. Format: ## !state!when!condition!test!limit!command!reason/comment ## where ## Delimiter; pick from [!,:@;?]. ## State to enter if true. ## States we must be in to match. ## Command to run to test condition. ## Operator to use in test(1) condition. ## Value to test against. ## Command for innwatch to perform; use exit, ## flush, go, pause, shutdown, skip, or throttle. ## Used in ctlinnd command (if needed). ## ## See the innwatch.ctl man page for more information. ## First, just exit innwatch if innd has gone away. !!! test -f ${LOCKS}/innd.pid && echo 0 || echo 1 ! eq ! 1 ! exit ! innd dead ## If another innwatch has started, exit. !!! cat ${LOCKS}/LOCK.${PROGNAME} ! ne ! $$ ! exit ! innwatch replaced ## Next test the load average. Above first threshold pause, above higher ## threshold throttle, below restart limit undo whatever was done. !load!load hiload! uptime | tr -d ,. | awk '{ print $(NF - 2) }' ! lt ! ${INNWATCHLOLOAD} ! go ! loadav !hiload!+ load! uptime | tr -d ,. | awk '{ print $(NF - 2) }' ! gt ! ${INNWATCHHILOAD} ! throttle ! loadav !load!+! uptime | tr -d ,. | awk '{ print $(NF - 2) }' ! gt ! ${INNWATCHPAUSELOAD} ! pause ! loadav ## Uncomment these to keep overchan backlog in check. Assumes your overchan ## feed is named 'overview!'. #::overblog:ctlinnd feedinfo overview!|awk 'NR==1{print $7}':lt:100000:go:overviewbacklog #:overblog:+:ctlinnd feedinfo overview!|awk 'NR==1{print $7}':gt:400000:throttle:overviewbacklog ## If load is OK, check space (and inodes) on various filesystems !!! ${INNDF} . ! lt ! ${INNWATCHSPOOLSPACE} ! throttle ! No space (spool) !!! ${INNDF} ${BATCH} ! lt ! ${INNWATCHBATCHSPACE} ! throttle ! No space (newsq) !!! ${INNDF} ${PATHDB} ! lt ! ${INNWATCHLIBSPACE} ! throttle ! No space (newslib) !!! ${INNDF} -i . ! lt ! ${INNWATCHSPOOLNODES} ! throttle ! No space (spool inodes) !!! test -d ${OVERVIEWDIR} && ${INNDF} ${OVERVIEWDIR} ! lt ! ${INNWATCHSPOOLSPACE} ! throttle ! No space (overview) inn-2.6.4/samples/innfeed.conf0000644000175200017520000001002314002373703015637 0ustar iuliusiulius## $Id: innfeed.conf 9923 2015-07-14 16:48:11Z iulius $ ## ## innfeed.conf - Configuration file for innfeed ## ## Format: ## key: value ## ## Values may be an integer, a floating-point number, ## C-style single-quoted characters, boolean, and strings. ## ## If a string value contains whitespace, or embedded quotes, ## or the comment character ("#"), then the whole string must ## be quoted with double quotes. Inside the quotes, standard ## C-escape sequences can be used (\t, \n, \r, \f, \v, \", \'). ## ## Blank lines are ignored. Everything after a '#' is ignored too. ## ## ## See the innfeed.conf(5) man page for a full description ## of the format. ## Global values. Not specific to any peer. These are optional, ## but if used, will override the compiled-in values. #news-spool: # Default is . #input-file: # Default is unset (channel mode). #pid-file: innfeed.pid # Relative to . #debug-level: 0 #debug-shrinking: false #fast-exit: false #use-mmap: true #log-file: innfeed.log # Relative to . #stdio-fdmax: 0 #log-time-format: "%a %b %d %H:%M:%S %Y" ## Uncomment the next line to include the contents ## of "testfile" at this point. #$INCLUDE testfile ## Other global parameters. #backlog-directory: innfeed # Relative to . #backlog-highwater: 5 #backlog-rotate-period: 60 #backlog-ckpt-period: 30 #backlog-newfile-period: 600 #dns-retry: 900 #dns-expire: 86400 #close-period: 86400 #gen-html: false # If true, status-file is relative to ; #status-file: innfeed.status # otherwise, it is relative to . #connection-stats: false #host-queue-highwater: 10 #stats-period: 600 #stats-reset: 43200 #initial-sleep: 2 #initial-reconnect-time: 30 #max-reconnect-time: 3600 ## Defaults for all peers. These all exist at ## global scope. Any of them can be redefined ## inside a peer or group definition. #article-timeout: 600 #response-timeout: 300 #initial-connections: 1 #max-connections: 2 #max-queue-size: 20 #streaming: true #no-check-high: 95.0 #no-check-low: 90.0 #no-check-filter: 50.0 #bindaddress: #bindaddress6: #port-number: 119 #force-ipv4: false #drop-deferred: false #min-queue-connection: false #backlog-limit: 0 #backlog-factor: 1.10 #backlog-limit-highwater: 0 #dynamic-method: 3 #dynamic-backlog-filter: 0.7 #dynamic-backlog-low: 20.0 #dynamic-backlog-high: 50.0 #no-backlog: false #backlog-feed-first: false ## Peers. #peer decwrl { # ip-name: news1.pa.dec.com #} #peer uunet { # ip-name: news.uunet.uu.net # max-connections: 10 #} ## Group peers together to give second level defaults. #group fast-sites { # max-connections: 7 # # peer data.ramona.vix.com { # # ip-name defaults to "data.ramona.vix.com". # streaming: false # } # # peer bb.home.vix.com { # ip-name: 192.5.5.33 # username: john # password: myPassword # } #} ## For imapfeed. # If imapfeed is used, the following parameters can # be set at global scope: # deliver-authname, deliver-password, deliver-username, # deliver-realm, deliver-rcpt-to, deliver-to-header. inn-2.6.4/samples/moderators0000644000175200017520000000241414002373703015467 0ustar iuliusiulius## $Id: moderators 8211 2008-12-06 12:56:46Z iulius $ ## ## moderators - Mailing addresses for moderators. ## ## Whenever possible, the master moderator database at moderators.isc.org ## should be used rather than adding specific entries to this file. The ## master database will list any publically propagated moderated group; ## changes should be sent to . ## ## Exceptions listed in this file are mostly hierarchies for which the ## master database isn't accurate or updated quickly enough. Local ## moderated newsgroups can also be added to this file. ## ## Format: ## : ## ## Shell-style newsgroup pattern or specific newsgroup. ## Mail address, "%s" becomes newgroup name with dots ## changed to dashes. ## ## The first matching entry is used. ## Public hierarchies with exceptions. aioe.*:%s-newsgroup@aioe.org fido7.*:%s@fido7.ru ffm.*:%s@moderators.arcornews.de fj.*:%s@moderators.fj-news.org medlux.*:%s@news.medlux.ru nl.*:%s@nl.news-admin.org perl.*:news-moderator-%s@perl.org relcom.*:%s@moderators.relcom.ru si.*:%s@arnes.si ukr.*:%s@sita.kiev.ua ## Direct all other public hierarchies to the master moderator database. *:%s@moderators.isc.org inn-2.6.4/samples/nnrpd_dynamic.py0000644000175200017520000001147514002373703016573 0ustar iuliusiulius## $Id: nnrpd_dynamic.py 10282 2018-05-14 12:42:14Z iulius $ ## ## This is a sample dynamic access module for the Python nnrpd hook. ## ## See the INN Python Filtering and Authentication Hooks documentation ## for more information. ## The python_dynamic: parameter in readers.conf is used to load this script. ## ## An instance of DYNACCESS class is passed to nnrpd via the set_auth_hook() ## function imported from nnrpd. The following methods of that class ## are known to nnrpd: ## ## __init__() - Use this method to initialize your ## general variables or open a common ## database connection. May be omitted. ## dynamic_init() - Init function specific to ## authentication. May be omitted. ## dynamic(attributes) - Called whenever a reader requests either ## read or post access to a ## newsgroup. Returns None to grant ## access, or a non-empty string (which ## will be reported back to reader) ## encoded in UTF-8 otherwise. ## dynamic_close() - Called on nnrpd termination. Save ## your state variables or close a database ## connection. May be omitted. ## ## If there is a problem with return codes from any of these methods, ## then nnrpd will die and syslog the exact reason. ## ## There are also a few Python functions defined in nnrpd: ## ## set_auth_hook() - Called by nnrpd as this module is loaded. ## It is used to pass a reference to an ## instance of authentication class to nnrpd. ## syslog() - An equivalent replacement for regular syslog. ## One consideration for using it is to ## uniform nnrpd logging. ## Sample dynamic access class. It defines all dynamic access methods known ## to nnrpd. class DYNACCESS: """Provide dynamic access callbacks to nnrpd.""" def __init__(self): """This is a good place to initialize variables or open a database connection.""" syslog('notice', 'nnrpd dynamic access class instance created') def dynamic_init(self): """Called when this script is initialized.""" pass def dynamic(self, attributes): """Called when python_dynamic: is reached in the processing of readers.conf and a reader requests either read or post permission for particular newsgroup.""" # Just for debugging purposes (in Python 3.x syntax). # syslog('notice', 'n_a dynamic() invoked: type %s, newsgroup %s, hostname %s, ipaddress %s, port %lu, interface %s, intipaddr %s, intport %lu, user %s' % ( \ # attributes['type'].tobytes(), \ # attributes['newsgroup'].tobytes(), \ # attributes['hostname'].tobytes(), \ # attributes['ipaddress'].tobytes(), \ # attributes['port'], \ # attributes['interface'].tobytes(), \ # attributes['intipaddr'].tobytes(), \ # attributes['intport'], \ # (attributes['user'].tobytes() if attributes['user'] else "-"))) # Allow reading of any newsgroup but not posting. # Python 2.x syntax: # if 'post' == str(attributes['type']): # Python 3.x syntax: # if b'post' == attributes['type'].tobytes(): # syslog('notice', 'dynamic authorization access for post access denied') # return "no posting for you" # elif 'read' == str(attributes['type']): # syslog('notice', 'dynamic authorization access for read access granted') # return None # else: # syslog('notice', 'dynamic authorization access type is not known: %s' % attributes['type']) # return "Internal error"; return None def dynamic_close(self): """Called on nnrpd termination.""" pass ## The rest is used to hook up the dynamic access module on nnrpd. ## It is unlikely you will ever need to modify this. ## Import functions exposed by nnrpd. This import must succeed, or nothing ## will work! from nnrpd import * ## Create a class instance. mydynaccess = DYNACCESS() ## ...and try to hook up on nnrpd. This would make auth object methods visible ## to nnrpd. import sys try: set_auth_hook(mydynaccess) syslog('notice', "dynamic access module successfully hooked into nnrpd") except Exception: # Syntax valid in both Python 2.x and 3.x. e = sys.exc_info()[1] syslog('error', "Cannot obtain nnrpd hook for dynamic access method: %s" % e.args[0]) inn-2.6.4/samples/news2mail.cf0000644000175200017520000000203114002373703015573 0ustar iuliusiulius## $Id: news2mail.cf 8198 2008-11-30 12:37:18Z iulius $ ## ## Sample news2mail configuration file. ## ## Format is: ## ## Newsfeeds-name List-to-address [List-sender-address] ## ## Newsfeeds-name: Name used in the newsfeeds file for the gateway feed ## (required). ## List-to-address: List address to send articles to (required). ## List-sender-address: Envelope-from address to use (a list member's ## address; optional). ## ## In newsfeeds, put an entry like: ## ## news2mail!:!*:Ac,Tc,Wn*:/news2mail ## ## and for each mailing-list, have an entry list like: ## ## list-big-red-ants/lists.ucsd.edu:!*,rec.pets.red-ants:Ap,Tm:news2mail! ## ## The site name used in the newfeeds entry for a mailing-list (above ## "list-big-red-ants") must be the same as the first field in an entry in ## this file. ## ## See the news2mail man page for more information. #list-big-red-ants big-red-ants@lists.ucsd.edu news+big-red-ants@local.news.server.org inn-2.6.4/samples/nnrpd_access_wrapper.py0000644000175200017520000000451714002373703020147 0ustar iuliusiulius## $Id: nnrpd_access_wrapper.py 10282 2018-05-14 12:42:14Z iulius $ ## ## Example wrapper for support of old Python authentication scripts, ## by Erik Klavon. ## ## This file contains a sample Python script which can be used to ## duplicate the behaviour of the old nnrppythonauth functionality. ## This script only supports access control. ## ## How to use this wrapper: ## - insert your authentication class into this file; ## - rename your authentication class OLDAUTH. ## ## See the INN Python Filtering and Authentication Hooks documentation ## for more information. ## The use of this file is *discouraged*. ## Old AUTH class. ## Insert your old auth class here. ## Do not include the code which sets the hook. ## Wrapper ACCESS class. It creates an instance of the old class and ## calls its methods. Arguments and return values are munged as ## needed to fit the new way of doing things. class MYACCESS: """Provide access callbacks to nnrpd.""" def access_init(self): self.old = OLDAUTH() def access(self, attributes): # Python 3.x uses memoryview(b'connect') because buffers # do not exist any longer. Note that the argument is # a bytes object. # attributes['type'] = memoryview(b'connect') # perm = (self.old).authenticate(attributes) # whereas in Python 2.x: # attributes['type'] = buffer('connect') # perm = (self.old).authenticate(attributes) result = dict({'users': '*'}) #if perm[1] == 1: # result['read'] = perm[3] #if perm[2] == 1: # result['post'] = perm[3] return result def access_close(self): (self.old).close() ## The rest is used to hook up the access module on nnrpd. It is unlikely ## you will ever need to modify this. ## Import functions exposed by nnrpd. This import must succeed, or nothing ## will work! from nnrpd import * ## Create a class instance. myaccess = MYACCESS() ## ...and try to hook up on nnrpd. This would make access object methods ## visible to nnrpd. import sys try: set_auth_hook(myaccess) syslog('notice', "access module successfully hooked into nnrpd") except Exception: # Syntax valid in both Python 2.x and 3.x. e = sys.exc_info()[1] syslog('error', "Cannot obtain nnrpd hook for access method: %s" % e.args[0]) inn-2.6.4/samples/nnrpd_auth.py0000644000175200017520000001200414002373703016075 0ustar iuliusiulius## $Id: nnrpd_auth.py 10282 2018-05-14 12:42:14Z iulius $ ## ## This is a sample authentication module for the Python nnrpd hook. ## ## See the INN Python Filtering and Authentication Hooks documentation ## for more information. ## The python_auth: parameter in readers.conf is used to load this script. ## ## An instance of AUTH class is passed to nnrpd via the set_auth_hook() ## function imported from nnrpd. The following methods of that class ## are known to nnrpd: ## ## __init__() - Use this method to initialize your ## general variables or open a common ## database connection. May be omitted. ## authen_init() - Init function specific to ## authentication. May be omitted. ## authenticate(attributes) - Called when a python_auth statement ## is reached in the processing of ## readers.conf. Returns a response ## code, an error string and an ## optional string to appear in the ## logs as the username (make sure that ## such a message is properly encoded ## in UTF-8 so as to comply with the ## NNTP protocol). ## authen_close() - Called on nnrpd termination. Save ## your state variables or close a database ## connection. May be omitted. ## ## If there is a problem with return codes from any of these methods, ## then nnrpd will die and syslog the exact reason. ## ## There are also a few Python functions defined in nnrpd: ## ## set_auth_hook() - Called by nnrpd as this module is loaded. ## It is used to pass a reference to an ## instance of authentication class to nnrpd. ## syslog() - An equivalent replacement for regular syslog. ## One consideration for using it is to ## uniform nnrpd logging. ## Sample authentication class. It defines all auth methods known to nnrpd. class AUTH: """Provide authentication callbacks to nnrpd.""" def __init__(self): """This is a good place to initialize variables or open a database connection.""" # Create a list of NNTP codes to respond on authentication. self.authcodes = { 'ALLOWED': 281, 'DENIED': 481, 'ERROR': 403 } syslog('notice', 'nnrpd authentication class instance created') def authen_init(self): """Called when this script is initialized.""" pass def authenticate(self, attributes): """Called when python_auth: is encountered in readers.conf.""" # Just for debugging purposes (in Python 3.x syntax). # By default, do not log passwords (available in attributes['pass']). # syslog('notice', 'n_a authenticate() invoked: hostname %s, ipaddress %s, port %lu, interface %s, intipaddr %s, intport %lu, user %s' % ( \ # attributes['hostname'].tobytes(), \ # attributes['ipaddress'].tobytes(), \ # attributes['port'], \ # attributes['interface'].tobytes(), \ # attributes['intipaddr'].tobytes(), \ # attributes['intport'], \ # (attributes['user'].tobytes() if attributes['user'] else "-"))) # Do username password authentication. # Python 2.x syntax: # if attributes['user'] and attributes['pass'] \ # and 'foo' == str(attributes['user']) \ # and 'foo' == str(attributes['pass']): # Python 3.x syntax: # if attributes['user'] and attributes['pass'] \ # and b'foo' == attributes['user'].tobytes() \ # and b'foo' == attributes['pass'].tobytes(): # syslog('notice', 'authentication by username succeeded') # return (self.authcodes['ALLOWED'], 'No error', 'default_user') syslog('notice', 'authentication by username failed') return (self.authcodes['DENIED'], 'Access Denied!') def authen_close(self): """Called on nnrpd termination.""" pass ## The rest is used to hook up the auth module on nnrpd. It is unlikely ## you will ever need to modify this. ## Import functions exposed by nnrpd. This import must succeed, or nothing ## will work! from nnrpd import * ## Create a class instance. myauth = AUTH() ## ...and try to hook up on nnrpd. This would make auth object methods visible ## to nnrpd. import sys try: set_auth_hook(myauth) syslog('notice', "authentication module successfully hooked into nnrpd") except Exception: # Syntax valid in both Python 2.x and 3.x. e = sys.exc_info()[1] syslog('error', "Cannot obtain nnrpd hook for authentication method: %s" % e.args[0]) inn-2.6.4/samples/nocem.ctl0000644000175200017520000000152314002373703015172 0ustar iuliusiulius## $Id: nocem.ctl 9513 2013-07-26 20:30:29Z iulius $ ## ## Configuration file for perl-nocem(8). ## This file specifies the NoCeM issuers and notices you want to follow. ## ## Based on Rosalind Hengeveld's NoCeM Registry: ## ## ## ## Format: ## issuer:notice1,notice2 ## ## You also have to properly configure your newsfeeds file and ## your keyring situated in /pgp/ncmring.gpg. ## You may wish to review and change the policy below. ## ## See the perl-nocem man page for more information. alba-nocem@albasani.net:spam,Content-Based.Detlef-B,Content-Based.Selzer-M bleachbot@httrack.com:spam,site news@uni-berlin.de:Admincancel nl-cancel@a3.xs4all.nl:spam,mmf,binary nocem@aioe.org:aioe-spam nocem@arcor.de:spam pgpmoose@killfile.org:pgpmoose-forged-moderation inn-2.6.4/samples/motd.nnrpd0000644000175200017520000000323314002373703015373 0ustar iuliusiuliusHere are a few suggestions of messages to display to news readers accessing the server. The contents of this file is displayed in reply to the LIST MOTD command from readers. Just rename this file to "motd.nnrpd" and adjust its contents to whatever message of the day (encoded in UTF-8) you want to communicate. It is not an error if this file does not exist nor if it is empty. For more information, please have a look at the generic motd.news man page. Example 1 --------- Attention all users, This server will be down for scheduled upgrades on February 1st. It should be back up by 8:00 a.m. February 2nd. Any questions should be e-mailed to . Apologies for the disturbance. Example 2 --------- Dear customers, We are pleased to announce the creation of a support newsgroup, named "our.company.support". It was created on February 1st and is intended to receive your questions about the use of our services. Our support team will usually be responding within a couple of days. Please use this new newsgroup as the preferable means to contact us. Example 3 --------- This news server now supports TLS connections. Please configure your news reader to use TLS when connecting or authenticating. A tutorial is available in the "our.company.tutorials" newsgroup to help you do the change. Do not hesitate to ask for help in the "our.company.support" newsgroup if you encounter issues during the change. Starting from February 1st, unencrypted authentications (that is to say not using TLS) will be rejected. Example 4 --------- Support for a new SASL mechanism has been added: OPENID20 can now be used to authenticate. Feel free to use it! inn-2.6.4/samples/control.ctl0000644000175200017520000032142614002373703015560 0ustar iuliusiulius## control.ctl - Access control for control messages. ## Last modified: 2020-12-24 ## ## Based on rone's unified control.ctl file. ## ## For a web presentation of the information recorded here, as well as ## other useful information about Usenet hierarchies, please see: ## ## ## ## Please copy usenet-config@isc.org on any updates to this file so that ## it can be updated in the INN Subversion repository and on ftp.isc.org. ## For changes to a public hierarchy, please also post the changes to ## news.admin.hierarchies. ## ## The canonical version of this file can be found in the latest INN ## release and at ; these ## two files will be kept in sync. Please refer to the latest version of ## this file for the most up-to-date hierarchy control information and ## please use the latest version if you intend to carry all hierarchies. ## ## You may wish to review and change the policy for alt.*, free.*, ## it-alt.*, and oesterreich.* below before using this file on your ## server. ## ## Format: ## ::: ## ## Control message or "all" if it applies to all control ## messages. ## Pattern that must match the From line. ## Pattern that must match the newsgroup being newgroup'd ## or rmgroup'd (ignored for other messages). ## What to do: ## doit Perform action ## drop Ignore message ## log One line to error log ## mail Send mail to admin ## verify-pgp_userid Do PGP verification on user. ## All actions except drop and mail can be given a log ## location by following the action with an = and the ## log ("mail" says to mail the admin, an empty location ## tosses the log information, and a relative path xxx ## logs to $LOG/xxx.log). ## ## The *last* matching entry is used. See the expire.ctl(5) man page for ## complete information. ## ## This file follows the following policies: ## ## * Most unknown or invalid control messages no longer result in mail. ## This is due to the proliferation of forged control messages filling ## up mailboxes. Some news servers even get overwhelmed with trying to ## log failure, so unsigned control messages for hierarchies that use ## PGP are simply dropped. ## ## * The assumption is that you now have PGP on your system. If you ## don't, you should get it to help protect yourself against all the ## control message forgeries. See . ## PGP control message verification comes with all versions of INN since ## 1.5, but you will need to install either PGP or GnuPG; see the ## installation instructions for your news server. ## ## If for some reason you can't use PGP, search for the *PGP* comments ## and modify the control lines to change "verify-..." in the action ## field to "mail" or "doit=mail" or "doit=" or whatever you ## prefer (replacing with the name of an appropriate log ## file). ## ## * A number of hierarchies are for local use only but have leaked out ## into the general stream. In this config file, they are set so that ## the groups will be easy to remove, and are marked with a comment of ## *LOCAL* (for use by that organization only, not generally ## distributed), *DEFUNCT* (a hierarchy that's no longer used), or ## *PRIVATE* (should only be carried after making arrangements with the ## given contact address). Please delete all groups in those ## hierarchies from your server if you carry them, unless you've ## contacted the listed contact address and arranged a feed. ## ## If you have permission to carry any of the hierarchies so listed in ## this file, you should change the entries for those hierarchies ## below. ## ## * Some hierarchies are marked as *HISTORIC*. These hierarchies ## aren't entirely defunct, but they are very low-traffic, not widely ## read or carried, and may not be worth carrying. If you don't intend ## to carry them, comment out their entries. ## ## * Some hierarchies are marked as *RESERVED*. These are used for ## special purposes by news software and should not be managed by ## control messages. This config file drops all control messages for ## those hierarchies. ## ## The comments of this file aren't in any formal or well-defined syntax, ## but they are meant to use a consistent syntax to allow eventual parsing ## by scripts into a better database format. Please follow the syntax of ## existing entries when providing new ones. The recognized "fields" are ## Contact (contact e-mail address), Admin group (the administrative group ## for the hierarchy), URL, Key URL (URL for PGP key), Key fingerprint, Key ## mail (address to mail for PGP key), and Syncable server (for actsync or ## a similar tool). ## ## Names used in this file that cannot be encoded in 7bit ASCII are in ## UTF-8. The only non-7bit-ASCII content is in comments. ## ## Information in this file has been contributed by many different people ## and has been based on numerous historical revisions of this file. A ## full, detailed history of contributions and copyright holders probably ## does not exist. So far as the current maintainers are aware, copying ## and distribution of this file, with or without modification, are ## permitted in any medium without royalty. This file is offered as-is, ## without any warranty. ## ------------------------------------------------------------------------- ## DEFAULT ## ------------------------------------------------------------------------- # Default to dropping control messages that aren't recognized to allow # people to experiment without inadvertently mailbombing news admins. all:*:*:drop ## ------------------------------------------------------------------------- ## CHECKGROUPS MESSAGES ## ------------------------------------------------------------------------- # Default to mailing all checkgroups messages to the administrator. checkgroups:*:*:mail ## ------------------------------------------------------------------------- ## MISCELLANEOUS CONTROL MESSAGES ## ------------------------------------------------------------------------- # Mostly only used for UUCP feeds, very rarely used these days. ihave:*:*:drop sendme:*:*:drop # Request to send a copy of the newsfeeds file, intended for mapping # projects. Almost never used for anything other than mailbombing now. sendsys:*:*:log=sendsys # Request to send the server's path entry. Not particularly useful. senduuname:*:*:log=senduuname # Request to send the server's version number. version:*:*:log=version ## ------------------------------------------------------------------------- ## NEWGROUP/RMGROUP MESSAGES ## ------------------------------------------------------------------------- ## Default (for any group) newgroup:*:*:mail rmgroup:*:*:mail ## Special reserved groups newgroup:*:control|general|junk|test|to:drop rmgroup:*:control|general|junk|test|to:drop ## A.BSU (*DEFUNCT* -- Ball State University, USA) # This hierarchy is defunct. Please remove it. newgroup:*:a.bsu.*:mail rmgroup:*:a.bsu.*:doit ## ACS & OSU (*LOCAL* -- Ohio State University, USA) # Contact: Albert J. School # Contact: Harpal Chohan # For local use only, contact the above address for information. newgroup:*:acs.*|osu.*:mail rmgroup:*:acs.*|osu.*:doit ## ADASS (Astronomical Data Analysis Software and Systems) # URL: http://iraf.noao.edu/iraf/web/adass_news.html checkgroups:news@iraf.noao.edu:adass.*:doit newgroup:news@iraf.noao.edu:adass.*:doit rmgroup:news@iraf.noao.edu:adass.*:doit ## AHN (Athens-Clarke County, Georgia, USA) checkgroups:greg@*.ucns.uga.edu:ahn.*:doit newgroup:greg@*.ucns.uga.edu:ahn.*:doit rmgroup:greg@*.ucns.uga.edu:ahn.*:doit ## AIOE (Aioe.org) # Contact: usenet@aioe.org # URL: http://news.aioe.org/hierarchy/ # Admin group: aioe.system # Key URL: http://news.aioe.org/hierarchy/aioe.txt # Key fingerprint: 2203 1AAC 51E7 C7FD 664F 1D80 90DF 6C71 2322 A7F8 # Syncable server: nntp.aioe.org # *PGP* See comment at top of file. newgroup:*:aioe.*:drop rmgroup:*:aioe.*:drop checkgroups:usenet@aioe.org:aioe.*:verify-usenet@aioe.org newgroup:usenet@aioe.org:aioe.*:verify-usenet@aioe.org rmgroup:usenet@aioe.org:aioe.*:verify-usenet@aioe.org ## AIR (*DEFUNCT* -- Stanford University, USA) # Contact: news@news.stanford.edu # This hierarchy is defunct. Please remove it. newgroup:*:air.*:mail rmgroup:*:air.*:doit ## AKR (Akron, Ohio, USA) checkgroups:red@redpoll.mrfs.oh.us:akr.*:doit newgroup:red@redpoll.mrfs.oh.us:akr.*:doit rmgroup:red@redpoll.mrfs.oh.us:akr.*:doit ## ALABAMA & HSV (Huntsville, Alabama, USA) # Contact: jpc@suespammers.org # Admin group: alabama.config # *PGP* See comment at top of file. newgroup:*:alabama.*|hsv.*:drop rmgroup:*:alabama.*|hsv.*:drop checkgroups:jpc@suespammers.org:alabama.*|hsv.*:verify-alabama-group-admin newgroup:jpc@suespammers.org:alabama.*|hsv.*:verify-alabama-group-admin rmgroup:jpc@suespammers.org:alabama.*|hsv.*:verify-alabama-group-admin ## ALIVE (*DEFUNCT* -- ?) # Contact: thijs@kink.xs4all.nl # This hierarchy is defunct. Please remove it. newgroup:*:alive.*:mail rmgroup:*:alive.*:doit ## ALT # # Accept all newgroups (except ones forged from Big 8 newgroup issuers, # who never issue alt.* control messages) and silently ignore all # rmgroups. # # What policy to use for alt.* groups varies widely from site to site. # For a small site, it is strongly recommended that this policy be changed # to drop all newgroups and rmgroups for alt.*. The local news admin can # then add new alt.* groups only on user request. Tons of alt.* newgroups # are sent out regularly with the intent more to create nonsense entries # in active files than to actually create a useable newsgroup. The admin # may still want to check the control message archive, as described below. # # Quality, user-desirable new groups can often be discovered by a quick # perusal of recent alt.* newgroup messages after discarding obvious junk # groups. One good initial filter is to check the archive of control # messages for a requested group to see if a syntactically valid newgroup # message was issued. Many of the junk control messages are invalid and # won't be archived, and many sites will only add alt.* groups with valid # control messages. To check the archive, see if: # # ftp://ftp.isc.org/pub/usenet/control/alt/.gz # # exists (replacing with the name of the group) and read the # first and last few control messages to see if the newsgroup should be # moderated. (Some alt.* groups that should be moderated are created # unmoderated by hijackers to try to damage the newsgroup.) # # Be aware that there is no official, generally accepted alt.* policy and # all information about alt.* groups available is essentially someone's # opinion, including these comments. There are nearly as many different # policies with regard to alt.* groups as there are Usenet sites. # newgroup:*:alt.*:doit newgroup:group-admin@isc.org:alt.*:drop newgroup:tale@*uu.net:alt.*:drop rmgroup:*:alt.*:drop ## AR (Argentina) checkgroups:jorge_f@nodens.fisica.unlp.edu.ar:ar.*:doit newgroup:jorge_f@nodens.fisica.unlp.edu.ar:ar.*:doit rmgroup:jorge_f@nodens.fisica.unlp.edu.ar:ar.*:doit ## ARC (*LOCAL* -- NASA Ames Research Center, USA) # Contact: news@arc.nasa.gov # For local use only, contact the above address for information. newgroup:*:arc.*:mail rmgroup:*:arc.*:doit ## ARKANE (Arkane Systems, UK) # Contact: newsbastard@arkane.demon.co.uk checkgroups:newsbastard@arkane.demon.co.uk:arkane.*:doit newgroup:newsbastard@arkane.demon.co.uk:arkane.*:doit rmgroup:newsbastard@arkane.demon.co.uk:arkane.*:doit ## AT (Austria) # URL: http://www.usenet.at/ # Admin group: at.usenet.gruppen # Key URL: http://www.usenet.at/pgpkey.asc # *PGP* See comment at top of file. newgroup:*:at.*:drop rmgroup:*:at.*:drop checkgroups:control@usenet.backbone.at:at.*:verify-control@usenet.backbone.at newgroup:control@usenet.backbone.at:at.*:verify-control@usenet.backbone.at rmgroup:control@usenet.backbone.at:at.*:verify-control@usenet.backbone.at ## AUS (Australia) # Contact: ausadmin@aus.news-admin.org # URL: http://aus.news-admin.org/ # Admin group: aus.net.news # Key URL: http://aus.news-admin.org/ausadmin.asc # *PGP* See comment at top of file. newgroup:*:aus.*:drop rmgroup:*:aus.*:drop checkgroups:ausadmin@aus.news-admin.org:aus.*:verify-ausadmin@aus.news-admin.org newgroup:ausadmin@aus.news-admin.org:aus.*:verify-ausadmin@aus.news-admin.org rmgroup:ausadmin@aus.news-admin.org:aus.*:verify-ausadmin@aus.news-admin.org ## AUSTIN (Austin, Texas, USA) # URL: http://frenzy.austin.tx.us/austin/ # Admin group: austin.usenet.config checkgroups:chip@unicom.com:austin.*:doit checkgroups:fletcher@cs.utexas.edu:austin.*:doit checkgroups:pug@pug.net:austin.*:doit newgroup:chip@unicom.com:austin.*:doit newgroup:fletcher@cs.utexas.edu:austin.*:doit newgroup:pug@pug.net:austin.*:doit rmgroup:chip@unicom.com:austin.*:doit rmgroup:fletcher@cs.utexas.edu:austin.*:doit rmgroup:pug@pug.net:austin.*:doit ## AZ (Arizona, USA) checkgroups:system@asuvax.eas.asu.edu:az.*:doit newgroup:system@asuvax.eas.asu.edu:az.*:doit rmgroup:system@asuvax.eas.asu.edu:az.*:doit ## BA (San Francisco Bay Area, USA) # Contact: ba-mod@panix.com # URL: http://www.panix.com/~babm/ba/ # Admin group: ba.config # Key URL: http://www.panix.com/~babm/ba/ba-mod.asc # Key fingerprint: 3C B6 7A 3B 34 53 C0 58 D2 FB 65 E8 E9 6F CD 46 # *PGP* See comment at top of file. newgroup:*:ba.*:drop rmgroup:*:ba.*:drop checkgroups:ba-mod@panix.com:ba.*:verify-ba.config newgroup:ba-mod@panix.com:ba.*:verify-ba.config rmgroup:ba-mod@panix.com:ba.*:verify-ba.config ## BACKBONE (*LOCAL* -- ruhr.de/ruhrgebiet.individual.net in Germany) # Contact: admin@ruhr.de # For local use only, contact the above address for information. newgroup:*:backbone.*:mail rmgroup:*:backbone.*:doit ## BC (British Columbia, Canada) checkgroups:bc_van_usenet@fastmail.ca:bc.*:doit newgroup:bc_van_usenet@fastmail.ca:bc.*:doit rmgroup:bc_van_usenet@fastmail.ca:bc.*:doit ## BDA (German groups?) checkgroups:news@*netuse.de:bda.*:doit newgroup:news@*netuse.de:bda.*:doit rmgroup:news@*netuse.de:bda.*:doit ## BE (Belgique/Belgie/Belgien/Belgium) # Contact: be-hierarchy-admin@usenet.be # URL: http://usenet.be/ # Admin group: be.announce # Key URL: http://usenet.be/be.announce.newgroups.asc # Key fingerprint: 30 2A 45 94 70 DE 1F D5 81 8C 58 64 D2 F7 08 71 # *PGP* See comment at top of file. newgroup:*:be.*:drop rmgroup:*:be.*:drop checkgroups:group-admin@usenet.be:be.*:verify-be.announce.newgroups newgroup:group-admin@usenet.be:be.*:verify-be.announce.newgroups rmgroup:group-admin@usenet.be:be.*:verify-be.announce.newgroups ## BELWUE (Landeshochschulnetz Baden-Wuerttemberg, Germany) # Contact: news@belwue.de # URL: http://www.belwue.de/produkte/dienste/dienste-usenet1.html # Admin group: belwue.infos # Key URL: http://www.belwue.de/fileadmin/belwue/Dokumente/Newsserver/belwue-hir-control.asc # Key fingerprint: 2E FF 2B 8A 89 1F E5 AA 6F 89 67 24 50 B5 42 D9 # *PGP* See comment at top of file. newgroup:*:belwue.*:drop rmgroup:*:belwue.*:drop checkgroups:news@news.belwue.de:belwue.*:verify-belwue-hir-control newgroup:news@news.belwue.de:belwue.*:verify-belwue-hir-control rmgroup:news@news.belwue.de:belwue.*:verify-belwue-hir-control ## BERMUDA (Bermuda) checkgroups:news@*ibl.bm:bermuda.*:doit newgroup:news@*ibl.bm:bermuda.*:doit rmgroup:news@*ibl.bm:bermuda.*:doit ## BEST (*LOCAL* -- Best Internet Communications, Inc.) # Contact: news@best.net # For local use only, contact the above address for information. newgroup:*:best.*:mail rmgroup:*:best.*:doit ## BIONET (Biology Network) # URL: http://www.bio.net/ # Admin group: bionet.general # Key fingerprint: EB C0 F1 BA 26 0B C6 D6 FB 8D ED C4 AE 5D 10 54 # *PGP* See comment at top of file. newgroup:*:bionet.*:drop rmgroup:*:bionet.*:drop checkgroups:Biosci-control-key@net.bio.net:bionet.*:verify-Biosci-control-key@net.bio.net newgroup:Biosci-control-key@net.bio.net:bionet.*:verify-Biosci-control-key@net.bio.net rmgroup:Biosci-control-key@net.bio.net:bionet.*:verify-Biosci-control-key@net.bio.net ## BIRK (*LOCAL* -- University of Oslo, Norway) # Contact: birk-admin@ping.uio.no # For local use only, contact the above address for information. newgroup:*:birk.*:mail rmgroup:*:birk.*:doit ## BIT (Gatewayed Mailing lists) # URL: http://www.newsadmin.com/bit/bit.htm # Admin group: bit.admin # *PGP* See comment at top of file. newgroup:*:bit.*:drop rmgroup:*:bit.*:drop checkgroups:bit@newsadmin.com:bit.*:verify-bit@newsadmin.com newgroup:bit@newsadmin.com:bit.*:verify-bit@newsadmin.com rmgroup:bit@newsadmin.com:bit.*:verify-bit@newsadmin.com ## BIZ (Business Groups) checkgroups:edhew@xenitec.on.ca:biz.*:doit newgroup:edhew@xenitec.on.ca:biz.*:doit rmgroup:edhew@xenitec.on.ca:biz.*:doit ## BLGTN (Bloomington, In, USA) checkgroups:control@news.bloomington.in.us:blgtn.*:doit newgroup:control@news.bloomington.in.us:blgtn.*:doit rmgroup:control@news.bloomington.in.us:blgtn.*:doit ## BLN (Berlin, Germany) # Contact: news@fu-berlin.de # URL: ftp://ftp.fu-berlin.de/doc/news/bln/bln # Admin group: bln.net.news checkgroups:news@*fu-berlin.de:bln.*:doit newgroup:news@*fu-berlin.de:bln.*:doit rmgroup:news@*fu-berlin.de:bln.*:doit ## BNE (Brisbane, Australia) # Contact: ausadmin@aus.news-admin.org # URL: http://bne.news-admin.org/ # Key URL: http://aus.news-admin.org/ausadmin.asc # *PGP* See comment at top of file. newgroup:*:bne.*:drop rmgroup:*:bne.*:drop checkgroups:ausadmin@aus.news-admin.org:bne.*:verify-ausadmin@aus.news-admin.org newgroup:ausadmin@aus.news-admin.org:bne.*:verify-ausadmin@aus.news-admin.org rmgroup:ausadmin@aus.news-admin.org:bne.*:verify-ausadmin@aus.news-admin.org ## BOFH (*PRIVATE* -- Bastard Operator From Hell) # Contact: bofh-control@lists.killfile.org # Key fingerprint: 40B5 8A56 1E00 6152 083E 38B3 CEF5 6980 7DC1 A266 # For private use only, contact the above address for information. # *PGP* See comment at top of file. newgroup:*:bofh.*:drop rmgroup:*:bofh.*:drop # The following three lines are only for authorized bofh.* sites. #checkgroups:bofh-control@killfile.org:bofh.*:verify-bofh-control@lists.killfile.org #newgroup:bofh-control@killfile.org:bofh.*:verify-bofh-control@lists.killfile.org #rmgroup:bofh-control@killfile.org:bofh.*:verify-bofh-control@lists.killfile.org ## CA (California, USA) # Contact: ikluft@thunder.sbay.org # URL: http://www.sbay.org/ca/ checkgroups:ikluft@thunder.sbay.org:ca.*:doit newgroup:ikluft@thunder.sbay.org:ca.*:doit rmgroup:ikluft@thunder.sbay.org:ca.*:doit ## CAIS (*LOCAL* -- Capital Area Internet Services) # Contact: news@cais.com # For local use only, contact the above address for information. newgroup:*:cais.*:mail rmgroup:*:cais.*:doit ## CALSTATE (California State University) checkgroups:*@*calstate.edu:calstate.*:doit newgroup:*@*calstate.edu:calstate.*:doit rmgroup:*@*calstate.edu:calstate.*:doit ## CANB (Canberra, Australia) # Contact: ausadmin@aus.news-admin.org # URL: http://canb.news-admin.org/ # Key URL: http://aus.news-admin.org/ausadmin.asc # *PGP* See comment at top of file. newgroup:*:canb.*:drop rmgroup:*:canb.*:drop checkgroups:ausadmin@aus.news-admin.org:canb.*:verify-ausadmin@aus.news-admin.org newgroup:ausadmin@aus.news-admin.org:canb.*:verify-ausadmin@aus.news-admin.org rmgroup:ausadmin@aus.news-admin.org:canb.*:verify-ausadmin@aus.news-admin.org ## CAPDIST (Albany, The Capital District, New York, USA) checkgroups:danorton@albany.net:capdist.*:doit newgroup:danorton@albany.net:capdist.*:doit rmgroup:danorton@albany.net:capdist.*:doit ## CARLETON (Carleton University, Canada) newgroup:news@cunews.carleton.ca:carleton.*:doit newgroup:news@cunews.carleton.ca:carleton*class.*:mail rmgroup:news@cunews.carleton.ca:carleton.*:doit ## CD-ONLINE (*LOCAL* -- ?) # Contact: newsmaster@worldonline.nl # For local use only, contact the above address for information. newgroup:*:cd-online.*:mail rmgroup:*:cd-online.*:doit ## CENTRAL (*LOCAL* -- The Internet Company of New Zealand, Wellington, NZ) # Contact: usenet@iconz.co.nz # For local use only, contact the above address for information. newgroup:*:central.*:mail rmgroup:*:central.*:doit ## CERN (*PRIVATE* -- CERN European Laboratory for Particle Physics) # Contact: Dietrich Wiegandt # For private use only, contact the above address for information. newgroup:News.Support@cern.ch:cern.*:mail rmgroup:News.Support@cern.ch:cern.*:doit ## CH (Switzerland) # Contact: ch-news-admin@use-net.ch # URL: http://www.use-net.ch/Usenet/ # Key URL: http://www.use-net.ch/Usenet/adminkey.html # Key fingerprint: 71 80 D6 8C A7 DE 2C 70 62 4A 48 6E D9 96 02 DF # *PGP* See comment at top of file. newgroup:*:ch.*:drop rmgroup:*:ch.*:drop checkgroups:felix.rauch@nice.ch:ch.*:verify-ch-news-admin@use-net.ch newgroup:felix.rauch@nice.ch:ch.*:verify-ch-news-admin@use-net.ch rmgroup:felix.rauch@nice.ch:ch.*:verify-ch-news-admin@use-net.ch ## CHAVEN (*LOCAL* -- Celestian Haven ISP, Midwest, USA) # Contact: news@chaven.com # For local use only, contact the above address for information. newgroup:*:chaven.*:mail rmgroup:*:chaven.*:doit ## CHI (Chicago, USA) # URL: http://lull.org/pub/chi-newsgroup-faq checkgroups:lisbon@*chi.il.us:chi.*:doit newgroup:lisbon@*chi.il.us:chi.*:doit rmgroup:lisbon@*chi.il.us:chi.*:doit ## CHILE (Chile and Chilean affairs) # Contact: mod-cga@usenet.cl # URL: http://www.usenet.cl/ # Admin group: chile.grupos.anuncios checkgroups:mod-cga@*usenet.cl:chile.*:doit checkgroups:mod-cga@*farah.cl:chile.*:doit newgroup:mod-cga@*usenet.cl:chile.*:doit newgroup:mod-cga@*farah.cl:chile.*:doit rmgroup:mod-cga@*usenet.cl:chile.*:doit rmgroup:mod-cga@*farah.cl:chile.*:doit ## CHINESE (China and Chinese language groups) checkgroups:pinghua@stat.berkeley.edu:chinese.*:doit newgroup:pinghua@stat.berkeley.edu:chinese.*:doit rmgroup:pinghua@stat.berkeley.edu:chinese.*:doit ## CHRISTNET (Christian Discussion) checkgroups:news@fdma.com:christnet.*:doit newgroup:news@fdma.com:christnet.*:doit rmgroup:news@fdma.com:christnet.*:doit ## CL (*PRIVATE* -- CL-Netz, German) # Contact: koordination@cl-netz.de # URL: http://www.cl-netz.de/ # Key URL: http://www.cl-netz.de/control.txt # For private use only, contact above address for questions. # *PGP* See comment at top of file. newgroup:*:cl.*:drop rmgroup:*:cl.*:doit # The following three lines are only for authorized cl.* sites. #checkgroups:koordination@cl-netz.de:cl.*:verify-cl.netz.infos #newgroup:koordination@cl-netz.de:cl.*:verify-cl.netz.infos #rmgroup:koordination@cl-netz.de:cl.*:verify-cl.netz.infos ## CLARI (*PRIVATE* -- Features and News, available on a commercial basis) # Contact: support@clari.net # Admin group: clari.net.admin # Key URL: http://www.clari.net/tech/clarikey.txt # For private use only, contact the above address for information. # *PGP* See comment at top of file. newgroup:*:clari.*:drop rmgroup:*:clari.*:drop newgroup:cl*@clarinet.com:clari.*:mail rmgroup:cl*@clarinet.com:clari.*:verify-ClariNet.Group ## CMI (*LOCAL* -- Champaign County, IL, USA) # Contact: news@ks.uiuc.edu # For local use only, contact the above address for information. newgroup:*:cmi.*:mail rmgroup:*:cmi.*:doit ## CMU (*LOCAL* -- Carnegie-Mellon University, Pennsylvania, USA) # Contact: Daniel Edward Lovinger # For local use only, contact the above address for information. newgroup:*:cmu.*:mail rmgroup:*:cmu.*:doit ## CN (China) # URL: http://news.yaako.com/ # Admin group: cn.announce # Key fingerprint: 62 97 EE 33 F7 16 25 C1 A4 9E 47 BA C5 3E 5E 9E # *PGP* See comment at top of file. newgroup:*:cn.*:drop rmgroup:*:cn.*:drop checkgroups:control@bentium.com:cn.*:verify-cn.admin.news.announce newgroup:control@bentium.com:cn.*:verify-cn.admin.news.announce rmgroup:control@bentium.com:cn.*:verify-cn.admin.news.announce ## CN.BBS (China) # URL: http://bbs.cn.news-admin.org/ # Admin group: cn.bbs.admin.announce # *PGP* See comment at top of file. newgroup:*:cn.bbs.*:drop rmgroup:*:cn.bbs.*:drop checkgroups:control@cn-bbs.org:cn.bbs.*:verify-cn.bbs.admin.announce newgroup:control@cn-bbs.org:cn.bbs.*:verify-cn.bbs.admin.announce rmgroup:control@cn-bbs.org:cn.bbs.*:verify-cn.bbs.admin.announce ## CO (Colorado, USA) # Contact: coadmin@boyznoyz.com (Bill of Denver) checkgroups:coadmin@boyznoyz.com:co.*:doit newgroup:coadmin@boyznoyz.com:co.*:doit rmgroup:coadmin@boyznoyz.com:co.*:doit ## CODEWARRIOR (CodeWarrior discussion) checkgroups:news@supernews.net:codewarrior.*:doit newgroup:news@supernews.net:codewarrior.*:doit rmgroup:news@supernews.net:codewarrior.*:doit ## COMP, HUMANITIES, MISC, NEWS, REC, SCI, SOC, TALK (The Big Eight) # Contact: board@big-8.org # URL: http://www.big-8.org/ # Admin group: news.announce.newgroups # Key fingerprint: F5 35 58 D3 55 64 10 14 07 C6 95 53 13 6F D4 07 # *PGP* See comment at top of file. newgroup:*:comp.*|humanities.*|misc.*|news.*|rec.*|sci.*|soc.*|talk.*:drop rmgroup:*:comp.*|humanities.*|misc.*|news.*|rec.*|sci.*|soc.*|talk.*:drop checkgroups:group-admin@isc.org:comp.*|humanities.*|misc.*|news.*|rec.*|sci.*|soc.*|talk.*:verify-news.announce.newgroups newgroup:group-admin@isc.org:comp.*|humanities.*|misc.*|news.*|rec.*|sci.*|soc.*|talk.*:verify-news.announce.newgroups rmgroup:group-admin@isc.org:comp.*|humanities.*|misc.*|news.*|rec.*|sci.*|soc.*|talk.*:verify-news.announce.newgroups ## COMPUTER42 (Computer 42, Germany) # Contact: Dirk Schmitt checkgroups:news@computer42.org:computer42.*:doit newgroup:news@computer42.org:computer42.*:doit rmgroup:news@computer42.org:computer42.*:doit ## CONCORDIA (Concordia University, Montreal, Canada) # Contact: newsmaster@concordia.ca # URL: General University info at http://www.concordia.ca/ checkgroups:news@newsflash.concordia.ca:concordia.*:doit newgroup:news@newsflash.concordia.ca:concordia.*:doit rmgroup:news@newsflash.concordia.ca:concordia.*:doit ## CONTROL (*RESERVED* -- Special hierarchy for control messages) # # The control.* hierarchy is reserved by RFC 5536 and MUST NOT be used # for regular newsgroups. It is used by some news implementations, such # as INN, as a local, special hierarchy that shows all control messages # posted to any group. # checkgroups:*:control.*:drop newgroup:*:control.*:drop rmgroup:*:control.*:drop ## COURTS (*DEFUNCT* -- Court discussion) # Contact: trier@ins.cwru.edu # This hierarchy is defunct. Please remove it. newgroup:*:courts.*:mail rmgroup:*:courts.*:doit ## CPCUIIA (Chartered Prop. Casulty Underwriter/Insurance Institute of America) # Contact: miller@cpcuiia.org # URL: http://www.aicpcu.org/ checkgroups:miller@cpcuiia.org:cpcuiia.*:doit newgroup:miller@cpcuiia.org:cpcuiia.*:doit rmgroup:miller@cpcuiia.org:cpcuiia.*:doit ## CU (*LOCAL* -- University of Colorado) # Contact: Doreen Petersen # For local use only, contact the above address for information. newgroup:*:cu.*:mail rmgroup:*:cu.*:doit ## CUHK (*LOCAL* -- Chinese University of Hong Kong) # Contact: shlam@ie.cuhk.edu.hk (Alan S H Lam) # For local use only, contact the above address for information. newgroup:*:cuhk.*:mail rmgroup:*:cuhk.*:doit ## CZ (Czech Republic) # URL: ftp://ftp.vslib.cz/pub/news/config/cz/newsgroups (text) checkgroups:petr.kolar@vslib.cz:cz.*:doit newgroup:petr.kolar@vslib.cz:cz.*:doit rmgroup:petr.kolar@vslib.cz:cz.*:doit ## DC (Washington, D.C., USA) checkgroups:news@mattress.atww.org:dc.*:doit newgroup:news@mattress.atww.org:dc.*:doit rmgroup:news@mattress.atww.org:dc.*:doit ## DE (German language) # Contact: moderator@dana.de # URL: http://www.dana.de/ # Admin group: de.admin.news.announce # Key URL: http://www.dana.de/pgp/dana.txt # Key fingerprint: 5B B0 52 88 BF 55 19 4F 66 7D C2 AE 16 26 28 25 # *PGP* See comment at top of file. newgroup:*:de.*:drop rmgroup:*:de.*:drop checkgroups:moderator@dana.de:de.*:verify-de.admin.news.announce newgroup:moderator@dana.de:de.*:verify-de.admin.news.announce rmgroup:moderator@dana.de:de.*:verify-de.admin.news.announce ## DE.ALT (German language alternative hierarchy) # *PGP* See comment at top of file. newgroup:*:de.alt.*:doit rmgroup:moderator@dana.de:de.alt.*:verify-de.admin.news.announce ## DEMON (Demon Internet, UK) # Contact: newsmaster@demon.net # Admin group: demon.news # Key URL: ftp://ftp.demon.co.uk/pub/news/doc/demon.news.txt # *PGP* See comment at top of file. newgroup:*:demon.*:drop rmgroup:*:demon.*:drop checkgroups:newsmaster@demon.net:demon.*:verify-demon.news newgroup:newsmaster@demon.net:demon.*:verify-demon.news rmgroup:newsmaster@demon.net:demon.*:verify-demon.news ## DFW (Dallas/Fort Worth, Texas, USA) # URL: http://www.cirr.com/dfw/ # Admin group: dfw.usenet.config checkgroups:eric@*cirr.com:dfw.*:doit newgroup:eric@*cirr.com:dfw.*:doit rmgroup:eric@*cirr.com:dfw.*:doit ## DK (Denmark) # URL: http://www.usenet.dk/dk-admin/ # Key URL: http://www.usenet.dk/dk-admin/pubkey.html # Key fingerprint: 7C B2 C7 50 F3 7D 5D 73 8C EE 2E 3F 55 80 72 FF # *PGP* See comment at top of file. newgroup:*:dk.*:drop rmgroup:*:dk.*:drop checkgroups:news@news.dknet.dk:dk.*:verify-news@news.dknet.dk newgroup:news@news.dknet.dk:dk.*:verify-news@news.dknet.dk rmgroup:news@news.dknet.dk:dk.*:verify-news@news.dknet.dk ## DUKE (*LOCAL* -- Duke University, USA) # Contact: news@newsgate.duke.edu # For local use only, contact the above address for information. newgroup:*:duke.*:mail rmgroup:*:duke.*:doit ## EASYNET (*HISTORIC* -- Easynet PLC, UK) # # This hierarchy is not entirely defunct, but it receives very little # traffic and is included primarily for the sake of completeness. # # Contact: Christiaan Keet # Admin group: easynet.support # *PGP* See comment at top of file. newgroup:*:easynet.*:drop rmgroup:*:easynet.*:drop checkgroups:newsmaster@easynet.net:easynet.*:verify-easynet.news newgroup:newsmaster@easynet.net:easynet.*:verify-easynet.news rmgroup:newsmaster@easynet.net:easynet.*:verify-easynet.news ## EE (Estonia) # Contact: usenet@news.ut.ee # URL: http://news.ut.ee/ # Key URL: http://news.ut.ee/pubkey.asc # *PGP* See comment at top of file. newgroup:*:ee.*:drop rmgroup:*:ee.*:drop checkgroups:news@news.ut.ee:ee.*:verify-ee.news newgroup:news@news.ut.ee:ee.*:verify-ee.news rmgroup:news@news.ut.ee:ee.*:verify-ee.news ## EFN & EUG (*HISTORIC* -- Eugene Free Computer Network, Eugene/Springfield, Oregon, USA) # # This hierarchy is not entirely defunct, but it receives very little # traffic and is included primarily for the sake of completeness. # # Admin group: eug.config # *PGP* See comment at top of file. newgroup:*:efn.*|eug.*:drop rmgroup:*:efn.*|eug.*:drop checkgroups:newsadmin@efn.org:efn.*|eug.*:verify-eug.config newgroup:newsadmin@efn.org:efn.*|eug.*:verify-eug.config rmgroup:newsadmin@efn.org:efn.*|eug.*:verify-eug.config ## EHIME-U (? University, Japan ?) checkgroups:news@cc.nias.ac.jp:ehime-u.*:doit checkgroups:news@doc.dpc.ehime-u.ac.jp:ehime-u.*:doit newgroup:news@cc.nias.ac.jp:ehime-u.*:doit newgroup:news@doc.dpc.ehime-u.ac.jp:ehime-u.*:doit rmgroup:news@cc.nias.ac.jp:ehime-u.*:doit rmgroup:news@doc.dpc.ehime-u.ac.jp:ehime-u.*:doit ## ENGLAND (England) # Contact: admin@england.news-admin.org # Admin group: england.news.policy # Key fingerprint: DA 3E C2 01 46 E5 61 CB A2 43 09 CA 13 6D 31 1F # *PGP* See comment at top of file. newgroup:*:england.*:drop rmgroup:*:england.*:drop checkgroups:admin@england.news-admin.org:england.*:verify-england-usenet newgroup:admin@england.news-admin.org:england.*:verify-england-usenet rmgroup:admin@england.news-admin.org:england.*:verify-england-usenet ## ES (Spain) # Contact: moderador@corus-es.org # URL: http://www.corus-es.org/docs/es_newsadmins_faq.txt # Admin group: es.news.anuncios # Key URL: http://www.corus-es.org/docs/esnews.asc # *PGP* See comment at top of file. newgroup:*:es.*:drop rmgroup:*:es.*:drop checkgroups:moderador@corus-es.org:es.*:verify-es.news newgroup:moderador@corus-es.org:es.*:verify-es.news rmgroup:moderador@corus-es.org:es.*:verify-es.news ## ESP (Spanish-language newsgroups) # Contact: # URL: http://ennui.org/esp/ # Key URL: http://ennui.org/esp/mod-ena.asc # *PGP* See comment at top of file. newgroup:*:esp.*:drop rmgroup:*:esp.*:drop checkgroups:mod-ena@ennui.org:esp.*:verify-esp.news.administracion newgroup:mod-ena@ennui.org:esp.*:verify-esp.news.administracion rmgroup:mod-ena@ennui.org:esp.*:verify-esp.news.administracion ## ETERNAL-SEPTEMBER (Eternal-September Project) # Contact: news@eternal-september.org # URL: http://www.eternal-september.org/ # Key URL: http://www.eternal-september.org/control/pgpkey.txt # Key fingerprint: B7 9A 2B C6 7D 5A FF 79 18 E2 AC 91 4B C1 25 F1 # *PGP* See comment at top of file. newgroup:*:eternal-september.*:drop rmgroup:*:eternal-september.*:drop checkgroups:news@eternal-september.org:eternal-september.*:verify-news@eternal-september.org newgroup:news@eternal-september.org:eternal-september.*:verify-news@eternal-september.org rmgroup:news@eternal-september.org:eternal-september.*:verify-news@eternal-september.org ## EUNET (Europe) checkgroups:news@noc.eu.net:eunet.*:doit newgroup:news@noc.eu.net:eunet.*:doit rmgroup:news@noc.eu.net:eunet.*:doit ## EUROPA (Europe) # URL: http://www.europa.usenet.eu.org/ # Admin group: europa.usenet.admin # Key URL: http://www.europa.usenet.eu.org/pgp/index.html # Key fingerprint: 3A 05 A8 49 FB 16 29 25 75 E3 DE BB 69 E0 1D B4 # *PGP* See comment at top of file. newgroup:*:europa.*:drop rmgroup:*:europa.*:drop checkgroups:group-admin@usenet.eu.org:europa.*:verify-group-admin@usenet.eu.org newgroup:group-admin@usenet.eu.org:europa.*:verify-group-admin@usenet.eu.org rmgroup:group-admin@usenet.eu.org:europa.*:verify-group-admin@usenet.eu.org ## EXAMPLE (*RESERVED* -- For use in examples) # # The example.* hierarchy is reserved by RFC 5536 and MUST NOT be used # for regular newsgroups. It is intended for use in examples, standards # documents, and similar places to avoid clashes with real newsgroup # names. # checkgroups:*:example.*:drop newgroup:*:example.*:drop rmgroup:*:example.*:drop ## FA (Gated mailing lists) # # This hierarchy was removed in the Great Renaming of 1988. # # A site in Norway is currently (as of 2002) gatewaying various mailing # lists into fa.* newsgroups, but that site does not appear to be issuing # any control messages for those groups. # # This hierarchy is still in use, but it has no active maintainer. # Control messages for this hierarchy should not be honored without # confirming that the sender is the new hierarchy maintainer. ## FFM (Frankfurt/M., Germany) # URL: http://ffm.arcornews.de/ # Admin group: ffm.admin # Key URL: ftp://ftp.arcor-online.net/pub/news/PGPKEY.FFM # Key fingerprint: 53 A0 82 62 6F C7 81 C9 CF 53 AB 00 A3 F8 C2 11 # *PGP* See comment at top of file. newgroup:*:ffm.*:drop rmgroup:*:ffm.*:drop checkgroups:ffm.admin@arcor.de:ffm.*:verify-ffm.admin newgroup:ffm.admin@arcor.de:ffm.*:verify-ffm.admin rmgroup:ffm.admin@arcor.de:ffm.*:verify-ffm.admin ## FIDO (FidoNet) # # This hierarchy is still in use, but it has no active maintainer. # Control messages for this hierarchy should not be honored without # confirming that the sender is the new hierarchy maintainer. ## FIDO.BELG (Belgian FidoNet) # Admin group: fido.belg.news # *PGP* See comment at top of file. newgroup:*:fido.belg.*:drop rmgroup:*:fido.belg.*:drop checkgroups:fidobelg@mail.z2.fidonet.org:fido.belg.*:verify-fido.belg.news newgroup:fidobelg@mail.z2.fidonet.org:fido.belg.*:verify-fido.belg.news rmgroup:fidobelg@mail.z2.fidonet.org:fido.belg.*:verify-fido.belg.news ## FIDO.GER (German FIDO Net Echos) # URL: ftp://ftp.fu-berlin.de/doc/news/fido.ger/fido.ger-info.english # Key URL: ftp://ftp.fu-berlin.de/doc/news/fido.ger/PGP-Key # *PGP* See comment at top of file. newgroup:*:fido.ger.*:drop rmgroup:*:fido.ger.*:drop checkgroups:fido.ger@news.fu-berlin.de:fido.ger.*:verify-fido.ger@news.fu-berlin.de newgroup:fido.ger@news.fu-berlin.de:fido.ger.*:verify-fido.ger@news.fu-berlin.de rmgroup:fido.ger@news.fu-berlin.de:fido.ger.*:verify-fido.ger@news.fu-berlin.de ## FIDO7 (Russian FidoNet) # URL: http://www.fido7.ru/ # Admin group: fido7.postmasters # Key URL: http://www.fido7.ru/pgpcontrol.html # *PGP* See comment at top of file. newgroup:*:fido7.*:drop rmgroup:*:fido7.*:drop checkgroups:newgroups-request@fido7.ru:fido7.*:verify-fido7.announce.newgroups newgroup:newgroups-request@fido7.ru:fido7.*:verify-fido7.announce.newgroups rmgroup:newgroups-request@fido7.ru:fido7.*:verify-fido7.announce.newgroups ## FINET (Finland and Finnish language alternative newsgroups) checkgroups:*@*.fi:finet.*:doit newgroup:*@*.fi:finet.*:doit rmgroup:*@*.fi:finet.*:doit ## FJ (Japan and Japanese language) # Contact: committee@fj-news.org # URL: http://www.fj-news.org/index.html.en # Admin group: fj.news.announce # Key URL: http://www.is.tsukuba.ac.jp/~yas/fj/fj.asc # *PGP* See comment at top of file. newgroup:*:fj.*:drop rmgroup:*:fj.*:drop checkgroups:committee@fj-news.org:fj.*:verify-fj.news.announce newgroup:committee@fj-news.org:fj.*:verify-fj.news.announce rmgroup:committee@fj-news.org:fj.*:verify-fj.news.announce ## FL (Florida, USA) checkgroups:hgoldste@news1.mpcs.com:fl.*:doit checkgroups:scheidell@fdma.fdma.com:fl.*:doit newgroup:hgoldste@news1.mpcs.com:fl.*:doit newgroup:scheidell@fdma.fdma.com:fl.*:doit rmgroup:hgoldste@news1.mpcs.com:fl.*:doit rmgroup:scheidell@fdma.fdma.com:fl.*:doit ## FLORA (FLORA Community WEB, Canada) # Contact: russell@flora.org # Admin group: flora.general # *PGP* See comment at top of file. newgroup:*:flora.*:drop rmgroup:*:flora.*:drop checkgroups:news@flora.ottawa.on.ca:flora.*:verify-flora-news newgroup:news@flora.ottawa.on.ca:flora.*:verify-flora-news rmgroup:news@flora.ottawa.on.ca:flora.*:verify-flora-news ## FR (French language) # URL: https://www.usenet-fr.net/ # Admin group: fr.usenet.forums.annonces # Key URL: https://www.usenet-fr.net/pgp-fr-2020.txt # Key fingerprint: D5F3 69B2 9757 3622 0153 54E7 FA42 3E89 970E B10B # *PGP* See comment at top of file. newgroup:*:fr.*:drop rmgroup:*:fr.*:drop checkgroups:control@usenet-fr.news.eu.org:fr.*:verify-control@usenet-fr.news.eu.org newgroup:control@usenet-fr.news.eu.org:fr.*:verify-control@usenet-fr.news.eu.org rmgroup:control@usenet-fr.news.eu.org:fr.*:verify-control@usenet-fr.news.eu.org ## FRANCE (France) # Contact: control@usenet-france.news.eu.org # Admin group: france.admin.evolutions # *PGP* See comment at top of file. newgroup:*:france.*:drop rmgroup:*:france.*:drop checkgroups:control@usenet-france.news.eu.org:france.*:verify-control@usenet-france.news.eu.org newgroup:control@usenet-france.news.eu.org:france.*:verify-control@usenet-france.news.eu.org rmgroup:control@usenet-france.news.eu.org:france.*:verify-control@usenet-france.news.eu.org ## FREE (Open Hierarchy where anyone can create a group) newgroup:*:free.*:doit newgroup:group-admin@isc.org:free.*:drop newgroup:tale@*uu.net:free.*:drop rmgroup:*:free.*:drop ## FUDAI (Japanese ?) checkgroups:news@picard.cs.osakafu-u.ac.jp:fudai.*:doit newgroup:news@picard.cs.osakafu-u.ac.jp:fudai.*:doit rmgroup:news@picard.cs.osakafu-u.ac.jp:fudai.*:doit ## FUR (*PRIVATE* -- furrynet) # Contact: fur-config@news.furry.net # For private use only, contact the above address for information. newgroup:*:fur.*:mail rmgroup:*:fur.*:doit ## GENERAL (*RESERVED* -- Sometimes used as a local catch-all) # # There is some history of using a newsgroup named general as a local # catch-all discussion group. That newsgroup name and hierarchy should # be avoided on production servers since it may occur at many # disconnected sites. # checkgroups:*:general.*:drop newgroup:*:general.*:drop rmgroup:*:general.*:drop ## GER & HANNOVER & HANNET & HILDESHEIM & HISS (Hannover, Germany) checkgroups:fifi@hiss.han.de:ger.*|hannover.*|hannet.*|hildesheim.*|hiss.*:doit newgroup:fifi@hiss.han.de:ger.*|hannover.*|hannet.*|hildesheim.*|hiss.*:doit rmgroup:fifi@hiss.han.de:ger.*|hannover.*|hannet.*|hildesheim.*|hiss.*:doit ## GIT (Georgia Institute of Technology, USA) newgroup:news@news.gatech.edu:git.*:doit newgroup:news@news.gatech.edu:git*class.*:mail rmgroup:news@news.gatech.edu:git.*:doit ## GNU (Free Software Foundation) # URL: http://www.gnu.org/usenet/usenet.html # Admin group: gnu.gnusenet.config # Key URL: http://www.gnu.org/usenet/usenet-pgp-key.txt # *PGP* See comment at top of file. newgroup:*:gnu.*:drop rmgroup:*:gnu.*:drop checkgroups:usenet@gnu.org:gnu.*:verify-usenet@gnu.org newgroup:usenet@gnu.org:gnu.*:verify-usenet@gnu.org rmgroup:usenet@gnu.org:gnu.*:verify-usenet@gnu.org ## GNUU (*PRIVATE* -- GNUU e.V., Oberursel, Germany) # URL: http://www.gnuu.de/ # Key URL: http://www.gnuu.de/config/PGPKEY.GNUU # For private use only. # *PGP* See comment at top of file. newgroup:*:gnuu.*:drop rmgroup:*:gnuu.*:drop newgroup:news@gnuu.de:gnuu.*:mail rmgroup:news@gnuu.de:gnuu.*:verify-news@gnuu.de ## GRISBI (Grisbi Personal Finance Manager software) # Contact: newsmaster@grisbi.org # URL: http://news.grisbi.org/ # Admin group: grisbi.admin # Key URL: http://news.grisbi.org/public-key.asc # Key fingerprint: EB35 0C03 0080 BD2A 7E0C A4C9 F2C6 2A3D C86C C6E1 # *PGP* See comment at top of file. newgroup:*:grisbi.*:drop rmgroup:*:grisbi.*:drop checkgroups:grisbi-control@grisbi.org:grisbi.*:verify-grisbi-control@grisbi.org newgroup:grisbi-control@grisbi.org:grisbi.*:verify-grisbi-control@grisbi.org rmgroup:grisbi-control@grisbi.org:grisbi.*:verify-grisbi-control@grisbi.org ## GWU (George Washington University, Washington, DC) # Contact: Sweth Chandramouli checkgroups:news@nit.gwu.edu:gwu.*:doit newgroup:news@nit.gwu.edu:gwu.*:doit rmgroup:news@nit.gwu.edu:gwu.*:doit ## HACKTIC (*HISTORIC* -- XS4ALL, Netherlands) # # This hierarchy is not entirely defunct, but it receives very little # traffic and is included primarily for the sake of completeness. # # *PGP* See comment at top of file. newgroup:*:hacktic.*:drop rmgroup:*:hacktic.*:drop checkgroups:news@zhaum.xs4all.nl:hacktic.*:verify-news@zhaum.xs4all.nl newgroup:news@zhaum.xs4all.nl:hacktic.*:verify-news@zhaum.xs4all.nl rmgroup:news@zhaum.xs4all.nl:hacktic.*:verify-news@zhaum.xs4all.nl ## HAMBURG (City of Hamburg, Germany) # Contact: hamburg@steering-group.net # URL: http://www.steering-group.net/hamburg/ # Admin group: hamburg.koordination # Key URL: http://www.steering-group.net/hamburg/hamburg.koordination.txt # Key fingerprint: 3E E7 0C BB 6E 01 94 EE 45 6F C5 57 F4 B9 54 8E # *PGP* See comment at top of file. newgroup:*:hamburg.*:drop rmgroup:*:hamburg.*:drop checkgroups:hamburg@steering-group.net:hamburg.*:verify-hamburg.koordination newgroup:hamburg@steering-group.net:hamburg.*:verify-hamburg.koordination rmgroup:hamburg@steering-group.net:hamburg.*:verify-hamburg.koordination ## HAMILTON (Canadian) checkgroups:news@*dcss.mcmaster.ca:hamilton.*:doit newgroup:news@*dcss.mcmaster.ca:hamilton.*:doit rmgroup:news@*dcss.mcmaster.ca:hamilton.*:doit ## HAMSTER (Hamster, a Win32 news and mail proxy server) # Contact: hamster-contact@snafu.de # Admin group: hamster.de.config # Key fingerprint: 12 75 A9 42 8A D6 1F 77 6A CF B4 0C 79 15 5F 93 # *PGP* See comment at top of file. newgroup:*:hamster.*:drop rmgroup:*:hamster.*:drop checkgroups:hamster-control@snafu.de:hamster.*:verify-hamster-control@snafu.de newgroup:hamster-control@snafu.de:hamster.*:verify-hamster-control@snafu.de rmgroup:hamster-control@snafu.de:hamster.*:verify-hamster-control@snafu.de ## HAN (Korean Hangul) # Contact: newgroups-request@usenet.or.kr # Admin group: han.news.admin # Key URL: ftp://ftp.usenet.or.kr/pub/korea/usenet/pgp/PGPKEY.han # *PGP* See comment at top of file. newgroup:*:han.*:drop rmgroup:*:han.*:drop checkgroups:newgroups-request@usenet.or.kr:han.*:verify-han.news.admin newgroup:newgroups-request@usenet.or.kr:han.*:verify-han.news.admin rmgroup:newgroups-request@usenet.or.kr:han.*:verify-han.news.admin ## HARVARD (*LOCAL* -- Harvard University, Cambridge, MA) # For local use only. newgroup:*@*.harvard.edu:harvard.*:mail rmgroup:*@*.harvard.edu:harvard.*:doit ## HAWAII (Hawaii, USA) checkgroups:news@lava.net:hawaii.*:doit newgroup:news@lava.net:hawaii.*:doit rmgroup:news@lava.net:hawaii.*:doit ## HFX (Halifax, Nova Scotia) checkgroups:stevemackie@gmail.com:hfx.*:doit newgroup:stevemackie@gmail.com:hfx.*:doit rmgroup:stevemackie@gmail.com:hfx.*:doit ## HIV (HIVNET Foundation, for HIV+/AIDS information) # Contact: news@hivnet.org # Admin group: hiv.config # Key fingerprint: 5D D6 0E DC 1E 2D EA 0B B0 56 4D D6 52 53 D7 A4 # *PGP* See comment at top of file. newgroup:*:hiv.*:drop rmgroup:*:hiv.*:drop checkgroups:news@hivnet.org:hiv.*:verify-news@hivnet.org newgroup:news@hivnet.org:hiv.*:verify-news@hivnet.org rmgroup:news@hivnet.org:hiv.*:verify-news@hivnet.org ## HK (Hong Kong) checkgroups:hknews@comp.hkbu.edu.hk:hk.*:doit newgroup:hknews@comp.hkbu.edu.hk:hk.*:doit rmgroup:hknews@comp.hkbu.edu.hk:hk.*:doit ## HOUSTON (Houston, Texas, USA) # Admin group: houston.usenet.config # *PGP* See comment at top of file. newgroup:*:houston.*:drop rmgroup:*:houston.*:drop checkgroups:news@academ.com:houston.*:verify-houston.usenet.config newgroup:news@academ.com:houston.*:verify-houston.usenet.config rmgroup:news@academ.com:houston.*:verify-houston.usenet.config ## HR (Croatian language) # Contact: newsmaster@carnet.hr # URL: http://newsfeed.carnet.hr/control/ # Admin group: hr.news.admin # Key URL: http://newsfeed.carnet.hr/control/key.txt # Key fingerprint: 0EE5 74FB 1C40 7ADB 0AAC A52F 7192 1BA3 ED63 AD9A # Syncable server: news.carnet.hr # *PGP* See comment at top of file. newgroup:*:hr.*:drop rmgroup:*:hr.*:drop checkgroups:newsmaster@carnet.hr:hr.*:verify-newsmaster@carnet.hr newgroup:newsmaster@carnet.hr:hr.*:verify-newsmaster@carnet.hr rmgroup:newsmaster@carnet.hr:hr.*:verify-newsmaster@carnet.hr ## HUMANITYQUEST (*HISTORIC* -- Humanities discussion) # # This hierarchy is not entirely defunct, but it receives very little # traffic and is included primarily for the sake of completeness. # # Contact: news-admin@humanityquest.com # URL: http://www.humanityquest.com/projects/newsgroups/ # Key URL: http://www.humanityquest.com/projects/newsgroups/PGP.htm # Key fingerprint: BA3D B306 B6F5 52AA BA8F 32F0 8C4F 5040 16F9 C046 # *PGP* See comment at top of file. newgroup:*:humanityquest.*:drop rmgroup:*:humanityquest.*:drop checkgroups:news-admin@humanityquest.com:humanityquest.*:verify-humanityquest.admin.config newgroup:news-admin@humanityquest.com:humanityquest.*:verify-humanityquest.admin.config rmgroup:news-admin@humanityquest.com:humanityquest.*:verify-humanityquest.admin.config ## HUN (Hungary) # URL: http://gatling.ikk.sztaki.hu/~kissg/news/ # Admin group: hun.admin.news # Key URL: http://gatling.ikk.sztaki.hu/~kissg/news/hun.admin.news.asc # *PGP* See comment at top of file. newgroup:*:hun.*:drop rmgroup:*:hun.*:drop checkgroups:hun-mnt@news.sztaki.hu:hun.*:verify-hun.admin.news newgroup:hun-mnt@news.sztaki.hu:hun.*:verify-hun.admin.news rmgroup:hun-mnt@news.sztaki.hu:hun.*:verify-hun.admin.news ## IA (Iowa, USA) checkgroups:skunz@iastate.edu:ia.*:doit newgroup:skunz@iastate.edu:ia.*:doit rmgroup:skunz@iastate.edu:ia.*:doit ## IBMNET (*LOCAL* -- ?) # Contact: news@ibm.net # For local use only, contact the above address for information. newgroup:*:ibmnet.*:mail rmgroup:*:ibmnet.*:doit ## ICONZ (*LOCAL* -- The Internet Company of New Zealand, New Zealand) # Contact: usenet@iconz.co.nz # For local use only, contact the above address for information. newgroup:*:iconz.*:mail rmgroup:*:iconz.*:doit ## IDOCTRA (Idoctra Translation Software, Translation Discussion) # Contact: support@idoctra.com checkgroups:support@idoctra.com:idoctra.*:doit newgroup:support@idoctra.com:idoctra.*:doit rmgroup:support@idoctra.com:idoctra.*:doit ## IE (Ireland) # Contact: control@usenet.ie # Admin group: ie.news.group # *PGP* See comment at top of file. newgroup:*:ie.*:drop rmgroup:*:ie.*:drop checkgroups:control@usenet.ie:ie.*:verify-control@usenet.ie newgroup:control@usenet.ie:ie.*:verify-control@usenet.ie rmgroup:control@usenet.ie:ie.*:verify-control@usenet.ie ## IEEE (*DEFUNCT* -- Institute of Electrical and Electronic Engineers) # Contact: postoffice@ieee.org # This hierarchy is defunct. Please remove it. newgroup:*:ieee.*:mail rmgroup:*:ieee.*:doit ## INFO (*DEFUNCT* -- Gatewayed mailing lists) # This hierarchy is defunct. Please remove it. newgroup:rjoyner@uiuc.edu:info.*:mail rmgroup:rjoyner@uiuc.edu:info.*:doit ## IS (Iceland) # Contact: IS Group Admins # URL: http://www.usenet.is/ # Admin group: is.isnet # Key URL: http://www.usenet.is/group-admin.asc # Key fingerprint: 33 32 8D 46 1E 5E 1C 7F 48 60 8E 72 E5 3E CA EA # *PGP* See comment at top of file. newgroup:*:is.*:drop rmgroup:*:is.*:drop checkgroups:group-admin@usenet.is:is.*:verify-group-admin@usenet.is newgroup:group-admin@usenet.is:is.*:verify-group-admin@usenet.is rmgroup:group-admin@usenet.is:is.*:verify-group-admin@usenet.is ## ISC (Japanese ?) checkgroups:news@sally.isc.chubu.ac.jp:isc.*:doit newgroup:news@sally.isc.chubu.ac.jp:isc.*:doit rmgroup:news@sally.isc.chubu.ac.jp:isc.*:doit ## ISRAEL & IL (Israel) newgroup:news@news.biu.ac.il:israel.*:doit rmgroup:news@news.biu.ac.il:israel.*|il.*:doit ## ISU (I-Shou University, Taiwan) # Contact: news@news.isu.edu.tw # URL: http://news.isu.edu.tw/ # Admin group: isu.newgroups # Key URL: http://news.isu.edu.tw/isu.asc # *PGP* See comment at top of file. newgroup:*:isu.*:drop rmgroup:*:isu.*:drop checkgroups:news@news.isu.edu.tw:isu.*:verify-news@news.isu.edu.tw newgroup:news@news.isu.edu.tw:isu.*:verify-news@news.isu.edu.tw rmgroup:news@news.isu.edu.tw:isu.*:verify-news@news.isu.edu.tw ## IT (Italian) # Contact: gcn@news.nic.it # URL: http://www.news.nic.it/ # Admin group: it.news.annunci # Key URL: http://www.news.nic.it/pgp.txt # Key fingerprint: 94 A4 F7 B5 46 96 D6 C7 A6 73 F2 98 C4 8C D0 E0 # *PGP* See comment at top of file. newgroup:*:it.*:drop rmgroup:*:it.*:drop checkgroups:gcn@news.nic.it:it.*:verify-gcn@news.nic.it newgroup:gcn@news.nic.it:it.*:verify-gcn@news.nic.it rmgroup:gcn@news.nic.it:it.*:verify-gcn@news.nic.it ## IT-ALT (Alternate Italian) # # There is no one official control message issuer for the it-alt.* # hierarchy, so this file doesn't choose any particular one. Several # different people issue control messages for this hierarchy, which may # or may not agree, and sites carrying this hierarchy are encouraged to # pick one and add it below. # # Newgroup and removal requests are to be posted to it-alt.config. A list # of people issuing PGP/GPG signed control messages is available in a # periodic posting to news.admin.hierarchies and it-alt.config. # newgroup:*:it-alt.*:drop rmgroup:*:it-alt.*:drop ## ITALIA (Italy) # Contact: news@news.cineca.it # URL: http://news.cineca.it/italia/ # Admin group: italia.announce.newgroups # Key URL: http://news.cineca.it/italia/italia-pgp.txt # Key fingerprint: 0F BB 71 62 DA 5D 5D B8 D5 86 FC 28 02 67 1A 6B # *PGP* See comment at top of file. newgroup:*:italia.*:drop rmgroup:*:italia.*:drop checkgroups:news@news.cineca.it:italia.*:verify-italia.announce.newgroups newgroup:news@news.cineca.it:italia.*:verify-italia.announce.newgroups rmgroup:news@news.cineca.it:italia.*:verify-italia.announce.newgroups ## IU (Indiana University) newgroup:news@usenet.ucs.indiana.edu:iu.*:doit newgroup:root@usenet.ucs.indiana.edu:iu.*:doit newgroup:*@usenet.ucs.indiana.edu:iu*class.*:mail rmgroup:news@usenet.ucs.indiana.edu:iu.*:doit rmgroup:root@usenet.ucs.indiana.edu:iu.*:doit ## JAPAN (Japan) # Contact: Tsuneo Tanaka # URL: http://www.asahi-net.or.jp/~AE5T-KSN/japan-e.html # Admin group: japan.admin.announce # Key URL: http://grex.cyberspace.org/~tt/japan.admin.announce.asc # Key fingerprint: 6A FA 19 47 69 1B 10 74 38 53 4B 1B D8 BA 3E 85 # *PGP* See comment at top of file. newgroup:*:japan.*:drop rmgroup:*:japan.*:drop checkgroups:japan.admin.announce@news.efnet.com:japan.*:verify-japan.admin.announce@news.efnet.com newgroup:japan.admin.announce@news.efnet.com:japan.*:verify-japan.admin.announce@news.efnet.com rmgroup:japan.admin.announce@news.efnet.com:japan.*:verify-japan.admin.announce@news.efnet.com ## JLUG (Japan Linux Users Group) # Contact: news@linux.or.jp # URL: http://www.linux.or.jp/community/news/index.html # Admin group: jlug.config # Key URL: http://www.linux.or.jp/pgpkey/news # *PGP* See comment at top of file. newgroup:*:jlug.*:drop rmgroup:*:jlug.*:drop checkgroups:news@linux.or.jp:jlug.*:verify-news@linux.or.jp newgroup:news@linux.or.jp:jlug.*:verify-news@linux.or.jp rmgroup:news@linux.or.jp:jlug.*:verify-news@linux.or.jp ## JUNK (*RESERVED* -- Used for unwanted newsgroups) # # The junk newsgroup is reserved by RFC 5536 and MUST NOT be used. It is # used by some implementations to store messages to unwanted newsgroups. # The junk.* hierarchy is not reserved by RFC 5536, but it's marked # reserved here because, given the special meaning of the junk group, # using it for any other purpose would be confusing and might trigger # implementation bugs. # checkgroups:*:junk.*:drop newgroup:*:junk.*:drop rmgroup:*:junk.*:drop ## K12 (US Educational Network) # URL: http://www.k12groups.org/ checkgroups:braultr@*csmanoirs.qc.ca:k12.*:doit newgroup:braultr@*csmanoirs.qc.ca:k12.*:doit rmgroup:braultr@*csmanoirs.qc.ca:k12.*:doit ## KA (*PRIVATE* -- Karlsruhe, Germany) # Contact: usenet@karlsruhe.org # URL: http://www.karlsruhe.org/ # Admin group: ka.admin # Key URL: http://www.karlsruhe.org/pubkey-news.karlsruhe.org.asc # Key fingerprint: DE 19 BB 25 76 19 81 17 F0 67 D2 23 E8 C8 7C 90 # For private use only, contact the above address for information. # *PGP* See comment at top of file. newgroup:*:ka.*:drop rmgroup:*:ka.*:drop # The following three lines are only for authorized ka.* sites. #checkgroups:usenet@karlsruhe.org:ka.*:verify-usenet@karlsruhe.org #newgroup:usenet@karlsruhe.org:ka.*:verify-usenet@karlsruhe.org #rmgroup:usenet@karlsruhe.org:ka.*:verify-usenet@karlsruhe.org ## KANTO (?) # *PGP* See comment at top of file. rmgroup:*:kanto.*:drop checkgroups:ty@kamoi.imasy.or.jp:kanto.*:verify-kanto.news.network # NOTE: newgroups aren't verified... newgroup:*@*.jp:kanto.*:doit rmgroup:ty@kamoi.imasy.or.jp:kanto.*:verify-kanto.news.network ## KASSEL (Kassel, Germany) # Admin group: kassel.admin # *PGP* See comment at top of file. newgroup:*:kassel.*:drop rmgroup:*:kassel.*:drop checkgroups:dirk.meyer@dinoex.sub.org:kassel.*:verify-kassel-admin newgroup:dirk.meyer@dinoex.sub.org:kassel.*:verify-kassel-admin rmgroup:dirk.meyer@dinoex.sub.org:kassel.*:verify-kassel-admin ## KC (Kansas City, Kansas/Missouri, USA) checkgroups:dan@sky.net:kc.*:doit newgroup:dan@sky.net:kc.*:doit rmgroup:dan@sky.net:kc.*:doit ## KGK (Administered by KGK, Japan) # Contact: Keiji KOSAKA # URL: http://film.rlss.okayama-u.ac.jp/~kgk/kgk/index.html # Admin group: kgk.admin checkgroups:usenet@film.rlss.okayama-u.ac.jp:kgk.*:doit newgroup:usenet@film.rlss.okayama-u.ac.jp:kgk.*:doit rmgroup:usenet@film.rlss.okayama-u.ac.jp:kgk.*:doit ## KIEL (Kiel, Germany) # # This hierarchy is still in use, but it has no active maintainer. # Control messages for this hierarchy should not be honored without # confirming that the sender is the new hierarchy maintainer. # # Admin group: kiel.sysop ## KRST (*LOCAL* -- University of Oslo, Norway) # Contact: jani@ifi.uio.no # For local use only, contact the above address for information. newgroup:*:krst.*:mail rmgroup:*:krst.*:doit ## KWNET (*LOCAL* -- Kitchener-Waterloo?) # Contact: Ed Hew # For local use only, contact the above address for information. newgroup:*:kwnet.*:mail rmgroup:*:kwnet.*:doit ## LAW (?) # Contact: Jim Burke checkgroups:*@*.kentlaw.edu:law.*:doit checkgroups:*@*.law.vill.edu:law.*:doit newgroup:*@*.kentlaw.edu:law.*:doit newgroup:*@*.law.vill.edu:law.*:doit rmgroup:*@*.kentlaw.edu:law.*:doit rmgroup:*@*.law.vill.edu:law.*:doit ## LINUX (Gated Linux mailing lists) # Contact: Marco d'Itri # Admin group: linux.admin.news # Key fingerprint: 81 B3 27 99 4F CE 32 D1 1B C9 01 0D BB B3 2E 41 # *PGP* See comment at top of file. newgroup:*:linux.*:drop rmgroup:*:linux.*:drop checkgroups:linux-admin@bofh.it:linux.*:verify-linux-admin@bofh.it newgroup:linux-admin@bofh.it:linux.*:verify-linux-admin@bofh.it rmgroup:linux-admin@bofh.it:linux.*:verify-linux-admin@bofh.it ## LOCAL (*RESERVED* -- Local-only groups) # # Historically reserved for local groups and occasionally configured for # such groups in news software. It is not really a good idea for sites # to use this hierarchy for local groups, since they may occur on many # unconnected sites and may confuse news readers that read at multiple # sites. # checkgroups:*:local.*:drop newgroup:*:local.*:drop rmgroup:*:local.*:drop ## LUEBECK (Luebeck, Germany) # Contact: usenet@zybrkat.org # Admin group: luebeck.admin checkgroups:usenet@zybrkat.org:luebeck.*:doit newgroup:usenet@zybrkat.org:luebeck.*:doit rmgroup:usenet@zybrkat.org:luebeck.*:doit ## MALTA (Nation of Malta) # Contact: cmeli@cis.um.edu.mt # URL: http://www.malta.news-admin.org/ # Admin group: malta.config # Key URL: http://www.cis.um.edu.mt/news-malta/PGP.PUBLICKEY # Key fingerprint: 20 17 01 5C F0 D0 1A 42 E4 13 30 58 0B 14 48 A6 # *PGP* See comment at top of file. newgroup:*:malta.*:drop rmgroup:*:malta.*:drop checkgroups:cmeli@cis.um.edu.mt:malta.*:verify-malta.config newgroup:cmeli@cis.um.edu.mt:malta.*:verify-malta.config rmgroup:cmeli@cis.um.edu.mt:malta.*:verify-malta.config ## MANAWATU (*LOCAL* -- Manawatu district, New Zealand) # Contact: alan@manawatu.gen.nz or news@manawatu.gen.nz # For local use only, contact the above address for information. newgroup:*:manawatu.*:mail rmgroup:*:manawatu.*:doit ## MAUS (MausNet, Germany) # Admin group: maus.info # Key fingerprint: 82 52 C7 70 26 B9 72 A1 37 98 55 98 3F 26 62 3E # *PGP* See comment at top of file. newgroup:*:maus.*:drop rmgroup:*:maus.*:drop checkgroups:guenter@gst0hb.hb.provi.de:maus.*:verify-maus-info checkgroups:guenter@gst0hb.north.de:maus.*:verify-maus-info newgroup:guenter@gst0hb.hb.provi.de:maus.*:verify-maus-info newgroup:guenter@gst0hb.north.de:maus.*:verify-maus-info rmgroup:guenter@gst0hb.hb.provi.de:maus.*:verify-maus-info rmgroup:guenter@gst0hb.north.de:maus.*:verify-maus-info ## MCMASTER (*LOCAL* -- McMaster University, Ontario) # Contact: Brian Beckberger # For local use only, contact the above address for information. newgroup:*:mcmaster.*:mail rmgroup:*:mcmaster.*:doit ## MCOM (*LOCAL* -- Netscape Inc, USA) # For local use only. newgroup:*:mcom.*:mail rmgroup:*:mcom.*:doit ## ME (Maine, USA) checkgroups:kerry@maine.maine.edu:me.*:doit newgroup:kerry@maine.maine.edu:me.*:doit rmgroup:kerry@maine.maine.edu:me.*:doit ## MEDLUX (All-Russia medical teleconferences) # URL: ftp://ftp.medlux.ru/pub/news/medlux.grp checkgroups:neil@new*.medlux.ru:medlux.*:doit newgroup:neil@new*.medlux.ru:medlux.*:doit rmgroup:neil@new*.medlux.ru:medlux.*:doit ## MELB (Melbourne, Australia) # Contact: ausadmin@aus.news-admin.org # URL: http://melb.news-admin.org/ # Key URL: http://aus.news-admin.org/ausadmin.asc # *PGP* See comment at top of file. newgroup:*:melb.*:drop rmgroup:*:melb.*:drop checkgroups:ausadmin@aus.news-admin.org:melb.*:verify-ausadmin@aus.news-admin.org newgroup:ausadmin@aus.news-admin.org:melb.*:verify-ausadmin@aus.news-admin.org rmgroup:ausadmin@aus.news-admin.org:melb.*:verify-ausadmin@aus.news-admin.org ## MENSA (The Mensa Organisation) # Contact: usenet@newsgate.mensa.org # Admin group: mensa.config # Key fingerprint: 52B9 3963 85D9 0806 8E19 7344 973C 5005 DC7D B7A7 # *PGP* See comment at top of file. newgroup:*:mensa.*:drop rmgroup:*:mensa.*:drop checkgroups:usenet@newsgate.mensa.org:mensa.*:verify-mensa.config newgroup:usenet@newsgate.mensa.org:mensa.*:verify-mensa.config rmgroup:usenet@newsgate.mensa.org:mensa.*:verify-mensa.config ## METOCEAN (ISP in Japan) checkgroups:fwataru@*.metocean.co.jp:metocean.*:doit newgroup:fwataru@*.metocean.co.jp:metocean.*:doit rmgroup:fwataru@*.metocean.co.jp:metocean.*:doit ## METROPOLIS (*LOCAL* -- ?) # Contact: newsmaster@worldonline.nl # For local use only, contact the above address for information. newgroup:*:metropolis.*:mail rmgroup:*:metropolis.*:doit ## MI (Michigan, USA) # Contact: Steve Simmons checkgroups:scs@lokkur.dexter.mi.us:mi.*:doit newgroup:scs@lokkur.dexter.mi.us:mi.*:doit rmgroup:scs@lokkur.dexter.mi.us:mi.*:doit ## MICROSOFT (Microsoft Corporation, USA) # # Control articles for that hierarchy are not issued by Microsoft itself # but by a Usenet active participant in order to improve the quality of # the propagation of Microsoft newsgroups. Their official URL is: # http://www.microsoft.com/communities/newsgroups/list/en-us/default.aspx # # Contact: control-microsoft@trigofacile.com # URL: http://www.trigofacile.com/divers/usenet/clefs/index.htm # Admin group: microsoft.public.news.server # Key URL: http://www.trigofacile.com/divers/usenet/clefs/pgpkey-microsoft.asc # Key fingerprint: DF70 5FC9 F615 D52E 02DB A3CB 63A9 8D13 E60E 2FAA # Syncable server: msnews.microsoft.com # *PGP* See comment at top of file. newgroup:*:microsoft.*:drop rmgroup:*:microsoft.*:drop checkgroups:control-microsoft@trigofacile.com:microsoft.*:verify-control-microsoft@trigofacile.com newgroup:control-microsoft@trigofacile.com:microsoft.*:verify-control-microsoft@trigofacile.com rmgroup:control-microsoft@trigofacile.com:microsoft.*:verify-control-microsoft@trigofacile.com ## MILW (Milwaukee, Wisconsin, USA) # Contact: milw@usenet.mil.wi.us # URL: http://usenet.mil.wi.us/ # Admin group: milw.config # Key URL: http://usenet.mil.wi.us/pgpkey # Key fingerprint: 6E 9B 9F 70 98 AB 9C E5 C3 C0 05 82 21 5B F4 9E # *PGP* See comment at top of file. newgroup:*:milw.*:drop rmgroup:*:milw.*:drop checkgroups:milw@usenet.mil.wi.us:milw.*:verify-milw.config newgroup:milw@usenet.mil.wi.us:milw.*:verify-milw.config rmgroup:milw@usenet.mil.wi.us:milw.*:verify-milw.config ## MOD (*DEFUNCT* -- Original top level moderated hierarchy) # This hierarchy is defunct. Please remove it. newgroup:*:mod.*:mail rmgroup:*:mod.*:doit ## MUC (Munchen [Munich], Germany) # Admin group: muc.admin # Key URL: http://home.arcor.de/andreas-barth/muc-admin.html # Key fingerprint: 43 C7 0E 7C 45 C7 06 E0 BD 6F 76 CE 07 39 5E 66 # *PGP* See comment at top of file. newgroup:*:muc.*:drop rmgroup:*:muc.*:drop checkgroups:muc-cmsg@muenchen.pro-bahn.org:muc.*:verify-muc.admin newgroup:muc-cmsg@muenchen.pro-bahn.org:muc.*:verify-muc.admin rmgroup:muc-cmsg@muenchen.pro-bahn.org:muc.*:verify-muc.admin ## NAGASAKI-U (Nagasaki University, Japan ?) checkgroups:root@*nagasaki-u.ac.jp:nagasaki-u.*:doit newgroup:root@*nagasaki-u.ac.jp:nagasaki-u.*:doit rmgroup:root@*nagasaki-u.ac.jp:nagasaki-u.*:doit ## NAS (*LOCAL* -- NAS, NASA Ames Research Center, USA) # Contact: news@nas.nasa.gov # For local use only, contact the above address for information. newgroup:*:nas.*:mail rmgroup:*:nas.*:doit ## NASA (*LOCAL* -- National Aeronautics and Space Administration, USA) # Contact: news@nas.nasa.gov # For local use only, contact the above address for information. newgroup:*:nasa.*:mail rmgroup:*:nasa.*:doit ## NC (North Carolina, USA) # # This hierarchy is still in use, but it has no active maintainer. # Control messages for this hierarchy should not be honored without # confirming that the sender is the new hierarchy maintainer. ## NCF (*LOCAL* -- National Capital Freenet, Ottawa, Ontario, Canada) # Contact: news@freenet.carleton.ca # For local use only, contact the above address for information. newgroup:*:ncf.*:mail rmgroup:*:ncf.*:doit ## NCTU (Taiwan) checkgroups:chen@cc.nctu.edu.tw:nctu.*:doit newgroup:chen@cc.nctu.edu.tw:nctu.*:doit rmgroup:chen@cc.nctu.edu.tw:nctu.*:doit ## NCU (*LOCAL* -- National Central University, Taiwan) # Contact: Ying-Hao Chang # Contact: # For local use only, contact the above address for information. newgroup:*:ncu.*:mail rmgroup:*:ncu.*:doit ## NERSC (National Energy Research Scientific Computing Center) # # This hierarchy is still in use, but it has no active maintainer. # Control messages for this hierarchy should not be honored without # confirming that the sender is the new hierarchy maintainer. # # Contact: usenet@nersc.gov ## NET (*HISTORIC* -- Usenet 2) # # This was a failed experiment in a different newsgroup creation policy and # administrative policy which has now been almost entirely abandoned. The # information is retained here for the few sites still using it, but sites # not already carrying the groups probably won't be interested. # # (This was also the original unmoderated Usenet hierarchy from before the # Great Renaming. The groups that used to be in net.* in the 1980s are now # in the Big Eight hierarchies.) # # URL: http://www.usenet2.org # Admin group: net.config # Key URL: http://www.usenet2.org/control@usenet2.org.asc # Key fingerprint: D7 D3 5C DB 18 6A 29 79 BF 74 D4 58 A3 78 9D 22 # *PGP* See comment at top of file. newgroup:*:net.*:drop rmgroup:*:net.*:drop #checkgroups:control@usenet2.org:net.*:verify-control@usenet2.org #newgroup:control@usenet2.org:net.*:verify-control@usenet2.org #rmgroup:control@usenet2.org:net.*:verify-control@usenet2.org ## NETINS (*LOCAL* -- netINS, Inc) # Contact: news@netins.net # For local use only, contact the above address for information. newgroup:*:netins.*:mail rmgroup:*:netins.*:doit ## NETSCAPE (Netscape Communications Corp) # Contact: news@netscape.com # URL: http://www.mozilla.org/community.html # Admin group: netscape.public.admin # Key fingerprint: B7 80 55 12 1F 9C 17 0B 86 66 AD 3B DB 68 35 EC # *PGP* See comment at top of file. newgroup:*:netscape.*:drop rmgroup:*:netscape.*:drop checkgroups:news@netscape.com:netscape.*:verify-netscape.public.admin newgroup:news@netscape.com:netscape.*:verify-netscape.public.admin rmgroup:news@netscape.com:netscape.*:verify-netscape.public.admin ## NEWS4US (*LOCAL* -- NEWS4US dot NL, Netherlands) # Contact: info@news4us.nl # For local use only, contact the above address for information. newgroup:*:news4us.*:mail rmgroup:*:news4us.*:doit ## NF (Newfoundland and Labrador, Canada) # Contact: randy@mun.ca checkgroups:randy@mun.ca:nf.*:doit newgroup:randy@mun.ca:nf.*:doit rmgroup:randy@mun.ca:nf.*:doit ## NIAGARA (Niagara Peninsula, USA/Canada) checkgroups:news@niagara.com:niagara.*:doit newgroup:news@niagara.com:niagara.*:doit rmgroup:news@niagara.com:niagara.*:doit ## NIAS (Japanese ?) checkgroups:news@cc.nias.ac.jp:nias.*:doit newgroup:news@cc.nias.ac.jp:nias.*:doit rmgroup:news@cc.nias.ac.jp:nias.*:doit ## NIGERIA (Nigeria) checkgroups:news@easnet.net:nigeria.*:doit newgroup:news@easnet.net:nigeria.*:doit rmgroup:news@easnet.net:nigeria.*:doit ## NIHON (Japan) checkgroups:ktomita@jade.dti.ne.jp:nihon.*:doit newgroup:ktomita@jade.dti.ne.jp:nihon.*:doit rmgroup:ktomita@jade.dti.ne.jp:nihon.*:doit ## NIPPON (*PRIVATE* -- Japan) # URL: http://www.gcd.org/news/nippon/ # Admin group: nippon.news.group # Key URL: http://www.gcd.org/news/nippon/ # Key fingerprint: BC CF 15 CD B1 3C DF B3 C3 DE 35 6F 2F F7 46 DB # For private use only. # *PGP* See comment at top of file. newgroup:*:nippon.*:drop rmgroup:*:nippon.*:drop newgroup:news@gcd.org:nippon.*:mail rmgroup:news@gcd.org:nippon.*:verify-nippon.news.group ## NJ (New Jersey, USA) # Contact: nj-admin@gunslinger.net # URL: http://www.exit109.com/~jeremy/nj/ checkgroups:nj-admin@gunslinger.net:nj.*:doit newgroup:nj-admin@gunslinger.net:nj.*:doit rmgroup:nj-admin@gunslinger.net:nj.*:doit ## NL (Netherlands) # Contact: nl-admin@nic.surfnet.nl # URL: http://nl.news-admin.org/info/nladmin.html # Admin group: nl.newsgroups # Key fingerprint: 45 20 0B D5 A1 21 EA 7C EF B2 95 6C 25 75 4D 27 # *PGP* See comment at top of file. newgroup:*:nl.*:drop rmgroup:*:nl.*:drop checkgroups:nl-admin@nic.surfnet.nl:nl.*:verify-nl.newsgroups newgroup:nl-admin@nic.surfnet.nl:nl.*:verify-nl.newsgroups rmgroup:nl-admin@nic.surfnet.nl:nl.*:verify-nl.newsgroups ## NL-ALT (Alternative Netherlands groups) # Key fingerprint: 6B 62 EB 53 4D 5D 2F 96 35 D9 C8 9C B0 65 0E 4C # *PGP* See comment at top of file. checkgroups:nl-alt-janitor@surfer.xs4all.nl:nl-alt.*:verify-nl-alt.config.admin newgroup:*:nl-alt.*:doit rmgroup:nl-alt-janitor@surfer.xs4all.nl:nl-alt.*:verify-nl-alt.config.admin rmgroup:news@kink.xs4all.nl:nl-alt.*:verify-nl-alt.config.admin ## NLO (Open Source / Free Software, hosted by nl.linux.org) # URL: http://mail.nl.linux.org/ # Key fingerprint: 63 DC B2 51 0A F3 DD 72 C2 BD C6 FD C1 C5 44 CF # Syncable server: news.nl.linux.org # *PGP* See comment at top of file. newgroup:*:nlo.*:drop rmgroup:*:nlo.*:drop checkgroups:news@nl.linux.org:nlo.*:verify-nlo.newsgroups newgroup:news@nl.linux.org:nlo.*:verify-nlo.newsgroups rmgroup:news@nl.linux.org:nlo.*:verify-nlo.newsgroups ## NM (New Mexico, USA) checkgroups:news@tesuque.cs.sandia.gov:nm.*:doit newgroup:news@tesuque.cs.sandia.gov:nm.*:doit rmgroup:news@tesuque.cs.sandia.gov:nm.*:doit ## NNTPWORLD (General discussion) # Contact: usenet@nntpworld.net # URL: http://www.nntpworld.net/ # Admin group: nntpworld.config # Key URL: http://www.nntpworld.net/nntpworld.asc # Key fingerprint: C7 BB E0 56 7A 8A 5A 86 09 B5 E3 29 E1 BB 8C E1 # *PGP* See comment at top of file. newgroup:*:nntpworld.*:drop rmgroup:*:nntpworld.*:drop checkgroups:usenet@nntpworld.net:nntpworld.*:verify-usenet@nntpworld.net newgroup:usenet@nntpworld.net:nntpworld.*:verify-usenet@nntpworld.net rmgroup:usenet@nntpworld.net:nntpworld.*:verify-usenet@nntpworld.net ## NO (Norway) # URL: http://www.usenet.no/ # Admin group: no.usenet.admin # Key URL: http://www.usenet.no/pgp-key.txt # *PGP* See comment at top of file. newgroup:*:no.*:drop rmgroup:*:no.*:drop checkgroups:control@usenet.no:no.*:verify-no-hir-control newgroup:control@usenet.no:no.*:verify-no-hir-control rmgroup:control@usenet.no:no.*:verify-no-hir-control ## NO.ALT (Norway alternative hierarchy) # *PGP* See comment at top of file. newgroup:*:no.alt.*:drop rmgroup:*:no.alt.*:drop newgroup:*@*.no:no.alt.*:doit rmgroup:control@usenet.no:no.alt.*:verify-no-hir-control ## NORD (Northern Germany) # # This hierarchy is still in use, but it has no active maintainer. # Control messages for this hierarchy should not be honored without # confirming that the sender is the new hierarchy maintainer. ## NRW (Northrine-Westfalia, Germany) # Contact: moderator@nrw.usenetverwaltung.de # URL: http://nrw.usenetverwaltung.de/ # Admin group: nrw.admin.announce # Key URL: http://nrw.usenetverwaltung.de/pgp/nrw.asc # Key fingerprint: 13 4A 80 FE D6 34 B4 64 AF 32 08 3F 62 0E B1 E2 # *PGP* See comment at top of file. newgroup:*:nrw.*:drop rmgroup:*:nrw.*:drop checkgroups:moderator@nrw.usenetverwaltung.de:nrw.*:verify-moderator@nrw.usenetverwaltung.de newgroup:moderator@nrw.usenetverwaltung.de:nrw.*:verify-moderator@nrw.usenetverwaltung.de rmgroup:moderator@nrw.usenetverwaltung.de:nrw.*:verify-moderator@nrw.usenetverwaltung.de ## NV (Nevada) checkgroups:cshapiro@netcom.com:nv.*:doit checkgroups:doctor@netcom.com:nv.*:doit newgroup:cshapiro@netcom.com:nv.*:doit newgroup:doctor@netcom.com:nv.*:doit rmgroup:cshapiro@netcom.com:nv.*:doit rmgroup:doctor@netcom.com:nv.*:doit ## NY (New York State, USA) checkgroups:root@ny.psca.com:ny.*:doit newgroup:root@ny.psca.com:ny.*:doit rmgroup:root@ny.psca.com:ny.*:doit ## NYC (New York City) # Contact: Perry E. Metzger checkgroups:perry@piermont.com:nyc.*:doit newgroup:perry@piermont.com:nyc.*:doit rmgroup:perry@piermont.com:nyc.*:doit ## NZ (New Zealand) # Contact: root@usenet.net.nz # URL: http://www.faqs.org/faqs/usenet/nz-news-hierarchy # Admin group: nz.net.announce # Key fingerprint: 07 DF 48 AA D0 ED AA 88 16 70 C5 91 65 3D 1A 28 # *PGP* See comment at top of file. newgroup:*:nz.*:drop rmgroup:*:nz.*:drop checkgroups:root@usenet.net.nz:nz.*:verify-nz-hir-control newgroup:root@usenet.net.nz:nz.*:verify-nz-hir-control rmgroup:root@usenet.net.nz:nz.*:verify-nz-hir-control ## OC (Orange County, California, USA) checkgroups:bob@tsunami.sugarland.unocal.com:oc.*:doit newgroup:bob@tsunami.sugarland.unocal.com:oc.*:doit rmgroup:bob@tsunami.sugarland.unocal.com:oc.*:doit ## OESTERREICH (Free Austria) # # This is apparently another alt.* or free.* but specific to Austria. # Currently, the ftp.isc.org list doesn't honor newgroup messages in the # hierarchy due to lack of requests, but here is the information in case # any news admin wishes to carry it. # # URL: http://www.tahina.priv.at/~cm/oe/index.en.html #newgroup:*:oesterreich.*:doit #newgroup:group-admin@isc.org:oesterreich.*:drop #newgroup:tale@*uu.net:oesterreich.*:drop #rmgroup:*:oesterreich.*:drop ## OH (Ohio, USA) checkgroups:trier@ins.cwru.edu:oh.*:doit newgroup:trier@ins.cwru.edu:oh.*:doit rmgroup:trier@ins.cwru.edu:oh.*:doit ## OK (Oklahoma, USA) checkgroups:quentin@*qns.com:ok.*:doit newgroup:quentin@*qns.com:ok.*:doit rmgroup:quentin@*qns.com:ok.*:doit ## OKINAWA (Okinawa, Japan) checkgroups:news@opus.or.jp:okinawa.*:doit newgroup:news@opus.or.jp:okinawa.*:doit rmgroup:news@opus.or.jp:okinawa.*:doit ## ONT (Ontario, Canada) checkgroups:pkern@gpu.utcc.utoronto.ca:ont.*:doit newgroup:pkern@gpu.utcc.utoronto.ca:ont.*:doit rmgroup:pkern@gpu.utcc.utoronto.ca:ont.*:doit ## OPENNEWS (Open News Network) # URL: http://www.open-news-network.org/ # *PGP* See comment at top of file. newgroup:*:opennews.*:drop rmgroup:*:opennews.*:drop checkgroups:news@news2.open-news-network.org:opennews.*:verify-news@news2.open-news-network.org newgroup:news@news2.open-news-network.org:opennews.*:verify-news@news2.open-news-network.org rmgroup:news@news2.open-news-network.org:opennews.*:verify-news@news2.open-news-network.org ## OPENWATCOM (Open Watcom compilers) # Contact: admin@openwatcom.news-admin.org # URL: http://www.openwatcom.org/ # Admin group: openwatcom.contributors # Key URL: http://cmeerw.org/files/openwatcom/pgp-openwatcom.asc # Syncable server: news.openwatcom.org # *PGP* See comment at top of file. newgroup:*:openwatcom.*:drop rmgroup:*:openwatcom.*:drop checkgroups:admin@openwatcom.news-admin.org:openwatcom.*:verify-admin@openwatcom.news-admin.org newgroup:admin@openwatcom.news-admin.org:openwatcom.*:verify-admin@openwatcom.news-admin.org rmgroup:admin@openwatcom.news-admin.org:openwatcom.*:verify-admin@openwatcom.news-admin.org ## OPERA (Opera Software, Oslo, Norway) # Contact: usenet@opera.com # Syncable server: news.opera.com # *PGP* See comment at top of file. newgroup:*:opera.*:drop rmgroup:*:opera.*:drop checkgroups:*@opera.com:opera.*:verify-opera-group-admin newgroup:*@opera.com:opera.*:verify-opera-group-admin rmgroup:*@opera.com:opera.*:verify-opera-group-admin ## OTT (Ottawa, Ontario, Canada) # Contact: onag@pinetree.org # URL: http://www.pinetree.org/ONAG/ checkgroups:clewis@ferret.ocunix.on.ca:ott.*:doit checkgroups:dave@revcan.ca:ott.*:doit checkgroups:gordon@*pinetree.org:ott.*:doit checkgroups:news@*pinetree.org:ott.*:doit checkgroups:news@bnr.ca:ott.*:doit checkgroups:news@ferret.ocunix.on.ca:ott.*:doit checkgroups:news@nortel.ca:ott.*:doit newgroup:clewis@ferret.ocunix.on.ca:ott.*:doit newgroup:dave@revcan.ca:ott.*:doit newgroup:gordon@*pinetree.org:ott.*:doit newgroup:news@*pinetree.org:ott.*:doit newgroup:news@bnr.ca:ott.*:doit newgroup:news@ferret.ocunix.on.ca:ott.*:doit newgroup:news@nortel.ca:ott.*:doit rmgroup:clewis@ferret.ocunix.on.ca:ott.*:doit rmgroup:dave@revcan.ca:ott.*:doit rmgroup:gordon@*pinetree.org:ott.*:doit rmgroup:news@*pinetree.org:ott.*:doit rmgroup:news@bnr.ca:ott.*:doit rmgroup:news@ferret.ocunix.on.ca:ott.*:doit rmgroup:news@nortel.ca:ott.*:doit ## OWL (Ostwestfalen-Lippe, Germany) # # This hierarchy is still in use, but it has no active maintainer. # Control messages for this hierarchy should not be honored without # confirming that the sender is the new hierarchy maintainer. # # Contact: news@owl.de # Syncable server: news.owl.de ## PA (Pennsylvania, USA) # URL: http://www.netcom.com/~rb1000/pa_hierarchy/ checkgroups:fxp@epix.net:pa.*:doit newgroup:fxp@epix.net:pa.*:doit rmgroup:fxp@epix.net:pa.*:doit ## PBINFO (Paderborn, Germany) # Contact: news@uni-paderborn.de # *PGP* See comment at top of file. newgroup:*:pbinfo.*:drop rmgroup:*:pbinfo.*:drop checkgroups:postmaster@upb.de:pbinfo.*:verify-news@uni-paderborn.de newgroup:postmaster@upb.de:pbinfo.*:verify-news@uni-paderborn.de rmgroup:postmaster@upb.de:pbinfo.*:verify-news@uni-paderborn.de ## PERL (Perl Programming Language) # Contact: newsadmin@perl.org # URL: http://www.nntp.perl.org/about/ # Key URL: http://www.nntp.perl.org/about/newsadmin@perl.org.pgp # Key fingerprint: 438F D1BA 4DCC 3B1A BED8 2BCC 3298 8A7D 8B2A CFBB # *PGP* See comment at top of file. newgroup:*:perl.*:drop rmgroup:*:perl.*:drop checkgroups:newsadmin@perl.org:perl.*:verify-newsadmin@perl.org newgroup:newsadmin@perl.org:perl.*:verify-newsadmin@perl.org rmgroup:newsadmin@perl.org:perl.*:verify-newsadmin@perl.org ## PGH (Pittsburgh, Pennsylvania, USA) # Admin group: pgh.config # *PGP* See comment at top of file. newgroup:*:pgh.*:drop rmgroup:*:pgh.*:drop checkgroups:pgh-config@psc.edu:pgh.*:verify-pgh.config newgroup:pgh-config@psc.edu:pgh.*:verify-pgh.config rmgroup:pgh-config@psc.edu:pgh.*:verify-pgh.config ## PGSQL (Gated PostgreSQL mailing lists) # Contact: news@postgresql.org # URL: http://news.hub.org/gpg_public_keys.html # Key URL: http://news.hub.org/gpg_public_keys.html # *PGP* See comment at top of file. newgroup:*:pgsql.*:drop rmgroup:*:pgsql.*:drop checkgroups:news@postgresql.org:pgsql.*:verify-news@postgresql.org newgroup:news@postgresql.org:pgsql.*:verify-news@postgresql.org rmgroup:news@postgresql.org:pgsql.*:verify-news@postgresql.org ## PHL (Philadelphia, Pennsylvania, USA) checkgroups:news@vfl.paramax.com:phl.*:doit newgroup:news@vfl.paramax.com:phl.*:doit rmgroup:news@vfl.paramax.com:phl.*:doit ## PIN (Personal Internauts' NetNews) checkgroups:pin-admin@forus.or.jp:pin.*:doit newgroup:pin-admin@forus.or.jp:pin.*:doit rmgroup:pin-admin@forus.or.jp:pin.*:doit ## PIPEX (UUNET WorldCom UK) # Contact: Russell Vincent checkgroups:news-control@ops.pipex.net:pipex.*:doit newgroup:news-control@ops.pipex.net:pipex.*:doit rmgroup:news-control@ops.pipex.net:pipex.*:doit ## PITT (University of Pittsburgh, PA) checkgroups:news+@pitt.edu:pitt.*:doit checkgroups:news@toads.pgh.pa.us:pitt.*:doit newgroup:news+@pitt.edu:pitt.*:doit newgroup:news@toads.pgh.pa.us:pitt.*:doit rmgroup:news+@pitt.edu:pitt.*:doit rmgroup:news@toads.pgh.pa.us:pitt.*:doit ## PL (Poland and Polish language) # URL: http://www.usenet.pl/doc/news-pl-new-site-faq.html # Admin group: pl.news.admin # Key URL: http://www.usenet.pl/doc/news-pl-new-site-faq.html#pgp # *PGP* See comment at top of file. newgroup:*:pl.*:drop rmgroup:*:pl.*:drop checkgroups:michalj@*fuw.edu.pl:pl.*:verify-pl.announce.newgroups checkgroups:newgroup@usenet.pl:pl.*:verify-pl.announce.newgroups newgroup:michalj@*fuw.edu.pl:pl.*:verify-pl.announce.newgroups newgroup:newgroup@usenet.pl:pl.*:verify-pl.announce.newgroups rmgroup:michalj@*fuw.edu.pl:pl.*:verify-pl.announce.newgroups rmgroup:newgroup@usenet.pl:pl.*:verify-pl.announce.newgroups ## PLANET (*LOCAL* -- PlaNet FreeNZ co-operative, New Zealand) # Contact: office@pl.net # For local use only, contact the above address for information. newgroup:*:planet.*:mail rmgroup:*:planet.*:doit ## PRIMA (*LOCAL* -- prima.ruhr.de/Prima e.V. in Germany) # Contact: admin@prima.ruhr.de # For local use only, contact the above address for information. newgroup:*:prima.*:mail rmgroup:*:prima.*:doit ## PRIVATE (*RESERVED* -- Server-local newsgroups) # # Sometimes used for groups intended to be private to a specific server. # It is not a good idea to use this hierarchy name on any production # server since they may occur on many unconnected sites. # checkgroups:*:private.*:drop newgroup:*:private.*:drop rmgroup:*:private.*:drop ## PSU (*LOCAL* -- Penn State University, USA) # Contact: Dave Barr (barr@math.psu.edu) # For local use only, contact the above address for information. newgroup:*:psu.*:mail rmgroup:*:psu.*:doit ## PT (Portugal and Portuguese language) # URL: http://www.usenet-pt.org/ # Admin group: pt.internet.usenet # Key URL: http://www.usenet-pt.org/control@usenet-pt.org.asc # *PGP* See comment at top of file. newgroup:*:pt.*:drop rmgroup:*:pt.*:drop checkgroups:pmelo@*.inescc.pt:pt.*:verify-control@usenet-pt.org newgroup:pmelo@*.inescc.pt:pt.*:verify-control@usenet-pt.org rmgroup:pmelo@*.inescc.pt:pt.*:verify-control@usenet-pt.org ## PUBNET (*DEFUNCT* -- ?) # URL: ftp://ftp.isc.org/pub/usenet/control/pubnet/pubnet.config.gz # This hierarchy is defunct. Please remove it. newgroup:*:pubnet.*:mail rmgroup:*:pubnet.*:doit ## RELCOM (Commonwealth of Independent States) # URL: ftp://ftp.relcom.ru/pub/relcom/netinfo/ # Admin group: relcom.netnews # Key URL: ftp://ftp.relcom.ru/pub/relcom/netinfo/coordpubkey.txt # *PGP* See comment at top of file. newgroup:*:relcom.*:drop rmgroup:*:relcom.*:drop checkgroups:coord@*.relcom.ru:relcom.*:verify-relcom.newsgroups newgroup:coord@*.relcom.ru:relcom.*:verify-relcom.newsgroups rmgroup:coord@*.relcom.ru:relcom.*:verify-relcom.newsgroups ## ROCKSOLID (Rocksolid network - novabbs.com) # Contact: usenet@novabbs.com # URL: http://news.novabbs.com/hierarchy/ # Admin group: rocksolid.shared.rocksolid # Key URL: http://news.novabbs.com/hierarchy/rocksolid.txt # Key fingerprint: FF84 6D73 0B72 CC0C B69B 6480 2A1C 655B F6D1 0B13 # *PGP* See comment at top of file. newgroup:*:rocksolid.*:drop rmgroup:*:rocksolid.*:drop checkgroups:usenet@novabbs.com:rocksolid.*:verify-usenet@novabbs.com newgroup:usenet@novabbs.com:rocksolid.*:verify-usenet@novabbs.com rmgroup:usenet@novabbs.com:rocksolid.*:verify-usenet@novabbs.com ## RPI (*LOCAL* -- Rensselaer Polytechnic Institute, Troy, NY, USA) # Contact: sofkam@rpi.edu # For local use only, contact the above address for information. newgroup:*:rpi.*:mail rmgroup:*:rpi.*:doit ## SAAR (Saarland Region, Germany) # URL: http://www.saar-admin-news.de/ # Admin group: saar.admin.news # Key URL: http://www.saar-admin-news.de/saar-control.asc # *PGP* See comment at top of file. newgroup:*:saar.*:drop rmgroup:*:saar.*:drop checkgroups:control@saar-admin-news.de:saar.*:verify-saar-control newgroup:control@saar-admin-news.de:saar.*:verify-saar-control rmgroup:control@saar-admin-news.de:saar.*:verify-saar-control ## SACHSNET (Sachsen [Saxony], Germany) checkgroups:root@lusatia.de:sachsnet.*:doit newgroup:root@lusatia.de:sachsnet.*:doit rmgroup:root@lusatia.de:sachsnet.*:doit ## SAT (San Antonio, Texas, USA) # Contact: satgroup@endicor.com # Admin group: sat.usenet.config # *PGP* See comment at top of file. newgroup:*:sat.*:drop rmgroup:*:sat.*:drop checkgroups:satgroup@endicor.com:sat.*:verify-satgroup@endicor.com newgroup:satgroup@endicor.com:sat.*:verify-satgroup@endicor.com rmgroup:satgroup@endicor.com:sat.*:verify-satgroup@endicor.com ## SBAY (South Bay/Silicon Valley, California) # URL: http://www.sbay.org/sbay-newsgroups.html checkgroups:ikluft@thunder.sbay.org:sbay.*:doit checkgroups:steveh@grafex.sbay.org:sbay.*:doit newgroup:ikluft@thunder.sbay.org:sbay.*:doit newgroup:steveh@grafex.sbay.org:sbay.*:doit rmgroup:ikluft@thunder.sbay.org:sbay.*:doit rmgroup:steveh@grafex.sbay.org:sbay.*:doit ## SCHULE (?) # Contact: schule-admin@roxel.ms.sub.org # URL: http://home.pages.de/~schule-admin/ # Admin group: schule.admin # Key URL: http://www.afaik.de/usenet/admin/schule/control/schule.asc # Key fingerprint: 64 06 F0 AE E1 46 85 0C BD CA 0E 53 8B 1E 73 D2 # *PGP* See comment at top of file. newgroup:*:schule.*:drop rmgroup:*:schule.*:drop checkgroups:newsctrl@schule.de:schule.*:verify-schule.konfig newgroup:newsctrl@schule.de:schule.*:verify-schule.konfig rmgroup:newsctrl@schule.de:schule.*:verify-schule.konfig ## SCOT (Scotland) # URL: http://scot.news-admin.org/ # Admin group: scot.newsgroups.discuss # Key URL: http://scot.news-admin.org/signature.html # *PGP* See comment at top of file. newgroup:*:scot.*:drop rmgroup:*:scot.*:drop checkgroups:control@scot.news-admin.org:scot.*:verify-control@scot.news-admin.org newgroup:control@scot.news-admin.org:scot.*:verify-control@scot.news-admin.org rmgroup:control@scot.news-admin.org:scot.*:verify-control@scot.news-admin.org ## SCOUT (Scouts and guides) # URL: http://news.scoutnet.org/ # Admin group: scout.admin # Key URL: http://news.scoutnet.org/scout-pgpkey.asc # *PGP* See comment at top of file. newgroup:*:scout.*:drop rmgroup:*:scout.*:drop checkgroups:control@news.scoutnet.org:scout.*:verify-control@news.scoutnet.org newgroup:control@news.scoutnet.org:scout.*:verify-control@news.scoutnet.org rmgroup:control@news.scoutnet.org:scout.*:verify-control@news.scoutnet.org ## SDSU (*LOCAL* -- San Diego State University, CA) # Contact: Craig R. Sadler # For local use only, contact the above address for information. newgroup:*:sdsu.*:mail rmgroup:*:sdsu.*:doit ## SE (Sweden) # Contact: usenet@usenet-se.net # Admin group: se.internet.news.meddelanden # Key fingerprint: 68 03 F0 FD 0C C3 4E 69 6F 0D 0C 60 3C 58 63 96 # *PGP* See comment at top of file. newgroup:*:se.*:drop rmgroup:*:se.*:drop checkgroups:usenet@usenet-se.net:se.*:verify-usenet-se newgroup:usenet@usenet-se.net:se.*:verify-usenet-se rmgroup:usenet@usenet-se.net:se.*:verify-usenet-se ## SEATTLE (Seattle, Washington, USA) checkgroups:billmcc@akita.com:seattle.*:doit checkgroups:graham@ee.washington.edu:seattle.*:doit newgroup:billmcc@akita.com:seattle.*:doit newgroup:graham@ee.washington.edu:seattle.*:doit rmgroup:billmcc@akita.com:seattle.*:doit rmgroup:graham@ee.washington.edu:seattle.*:doit ## SFNET (Finland) # Contact: sfnet@cs.tut.fi # URL: http://www.cs.tut.fi/sfnet/ # Admin group: sfnet.ryhmat+listat # Key fingerprint: DE79 33C2 D359 D128 44E5 6A0C B6E3 0E53 6933 A636 # *PGP* See comment at top of file. newgroup:*:sfnet.*:drop rmgroup:*:sfnet.*:drop checkgroups:sfnet@*cs.tut.fi:sfnet.*:verify-sfnet@cs.tut.fi newgroup:sfnet@*cs.tut.fi:sfnet.*:verify-sfnet@cs.tut.fi rmgroup:sfnet@*cs.tut.fi:sfnet.*:verify-sfnet@cs.tut.fi ## SHAMASH (Jewish) checkgroups:archives@israel.nysernet.org:shamash.*:doit newgroup:archives@israel.nysernet.org:shamash.*:doit rmgroup:archives@israel.nysernet.org:shamash.*:doit ## SI (The Republic of Slovenia) # URL: http://www.arnes.si/news/config/ # Admin group: si.news.announce.newsgroups # Key URL: http://www.arnes.si/news/config/ # *PGP* See comment at top of file. newgroup:*:si.*:drop rmgroup:*:si.*:drop checkgroups:news-admin@arnes.si:si.*:verify-si.news.announce.newsgroups newgroup:news-admin@arnes.si:si.*:verify-si.news.announce.newsgroups rmgroup:news-admin@arnes.si:si.*:verify-si.news.announce.newsgroups ## SJ (St. John's, Newfoundland and Labrador, Canada) # Contact: randy@mun.ca checkgroups:randy@mun.ca:sj.*:doit newgroup:randy@mun.ca:sj.*:doit rmgroup:randy@mun.ca:sj.*:doit ## SK (Slovakia) checkgroups:uhlar@ccnews.ke.sanet.sk:sk.*:doit newgroup:uhlar@ccnews.ke.sanet.sk:sk.*:doit rmgroup:uhlar@ccnews.ke.sanet.sk:sk.*:doit ## SLO (San Luis Obispo, CA) checkgroups:news@punk.net:slo.*:doit newgroup:news@punk.net:slo.*:doit rmgroup:news@punk.net:slo.*:doit ## SOLENT (Solent region, England) checkgroups:news@tcp.co.uk:solent.*:doit newgroup:news@tcp.co.uk:solent.*:doit rmgroup:news@tcp.co.uk:solent.*:doit ## SPOKANE (Spokane, Washington, USA) checkgroups:usenet@news.spokane.wa.us:spokane.*:doit newgroup:usenet@news.spokane.wa.us:spokane.*:doit rmgroup:usenet@news.spokane.wa.us:spokane.*:doit ## SSLUG (*PRIVATE* -- SkÃ¥ne Sjælland Linux User Group) # URL: http://en.sslug.dk/ # For private use only. newgroup:sparre@sslug.se:sslug.*:mail rmgroup:sparre@sslug.se:sslug.*:doit ## STAROFFICE (StarOffice business suite, Sun Microsystems, Inc.) # Contact: news@starnews.sun.com # Admin group: staroffice.admin # Key fingerprint: C6 3E 81 6F 2A 19 D3 84 72 51 F9 1B E3 B9 B2 C9 # Syncable server: starnews.sun.com # *PGP* See comment at top of file. newgroup:*:staroffice.*:drop rmgroup:*:staroffice.*:drop checkgroups:news@stardivision.de:staroffice.*:verify-staroffice.admin newgroup:news@stardivision.de:staroffice.*:verify-staroffice.admin rmgroup:news@stardivision.de:staroffice.*:verify-staroffice.admin ## STGT (Stuttgart, Germany) # Contact: news@news.uni-stuttgart.de # URL: http://news.uni-stuttgart.de/hierarchie/stgt/ # Admin group: stgt.net # Key URL: http://news.uni-stuttgart.de/hierarchie/stgt/stgt-control.txt # Key fingerprint: BA A4 0A 54 8F F5 F5 1E 72 48 51 AE 09 51 DE 44 # *PGP* See comment at top of file. newgroup:*:stgt.*:drop rmgroup:*:stgt.*:drop checkgroups:stgt-control@news.uni-stuttgart.de:stgt.*:verify-stgt-control newgroup:stgt-control@news.uni-stuttgart.de:stgt.*:verify-stgt-control rmgroup:stgt-control@news.uni-stuttgart.de:stgt.*:verify-stgt-control ## STL (Saint Louis, Missouri, USA) checkgroups:news@icon-stl.net:stl.*:doit newgroup:news@icon-stl.net:stl.*:doit rmgroup:news@icon-stl.net:stl.*:doit ## SU (*LOCAL* -- Stanford University, USA) # Contact: news@news.stanford.edu # For local use only, contact the above address for information. newgroup:*:su.*:mail rmgroup:*:su.*:doit ## SUNET (Swedish University Network) checkgroups:ber@*.sunet.se:sunet.*:doit newgroup:ber@*.sunet.se:sunet.*:doit rmgroup:ber@*.sunet.se:sunet.*:doit ## SURFNET (Dutch Universities network) checkgroups:news@info.nic.surfnet.nl:surfnet.*:doit newgroup:news@info.nic.surfnet.nl:surfnet.*:doit rmgroup:news@info.nic.surfnet.nl:surfnet.*:doit ## SWNET (Sverige, Sweden) checkgroups:ber@sunic.sunet.se:swnet.*:doit newgroup:ber@sunic.sunet.se:swnet.*:doit rmgroup:ber@sunic.sunet.se:swnet.*:doit ## SYD (Sydney, Australia) # Contact: ausadmin@aus.news-admin.org # URL: http://syd.news-admin.org/ # Key URL: http://aus.news-admin.org/ausadmin.asc # *PGP* See comment at top of file. newgroup:*:syd.*:drop rmgroup:*:syd.*:drop checkgroups:ausadmin@aus.news-admin.org:syd.*:verify-ausadmin@aus.news-admin.org newgroup:ausadmin@aus.news-admin.org:syd.*:verify-ausadmin@aus.news-admin.org rmgroup:ausadmin@aus.news-admin.org:syd.*:verify-ausadmin@aus.news-admin.org ## SZAF (*PRIVATE* -- Szafe im Netz) # Contact: hirtenrat@szaf.org # Admin group: szaf.admin # Key URL: http://news.szaf.org/szaf/szaf-key.txt # For private use only, contact the above address for information. # *PGP* See comment at top of file. newgroup:*:szaf.*:drop rmgroup:*:szaf.*:drop newgroup:hirtenrat@szaf.org:szaf.*:mail rmgroup:hirtenrat@szaf.org:szaf.*:verify-Hirtenrat ## T-NETZ (*DEFUNCT* -- Germany) # This hierarchy is defunct. Please remove it. newgroup:*:t-netz.*:mail rmgroup:*:t-netz.*:doit ## TAMU (Texas A&M University) # Contact: Philip Kizer checkgroups:news@tamsun.tamu.edu:tamu.*:doit newgroup:news@tamsun.tamu.edu:tamu.*:doit rmgroup:news@tamsun.tamu.edu:tamu.*:doit ## TAOS (Taos, New Mexico, USA) # Contact: Chris Gunn checkgroups:cgunn@laplaza.org:taos.*:doit newgroup:cgunn@laplaza.org:taos.*:doit rmgroup:cgunn@laplaza.org:taos.*:doit ## TCFN (Toronto Free Community Network, Canada) checkgroups:news@t-fcn.net:tcfn.*:doit newgroup:news@t-fcn.net:tcfn.*:doit rmgroup:news@t-fcn.net:tcfn.*:doit ## TELE (*LOCAL* -- Tele Danmark Internet) # Contact: usenet@tdk.net # For local use only, contact the above address for information. newgroup:*:tele.*:mail rmgroup:*:tele.*:doit ## TERMVAKT (*LOCAL* -- University of Oslo, Norway) # Contact: jani@ifi.uio.no # For local use only, contact the above address for information. newgroup:*:termvakt.*:mail rmgroup:*:termvakt.*:doit ## TEST (*RESERVED* -- Local test hierarchy) # # Historically used as a local test hierarchy. It is not a good idea to # use this hierarchy name on any production server since they may occur # on many unconnected sites. # checkgroups:*:test.*:drop newgroup:*:test.*:drop rmgroup:*:test.*:drop ## THUR (Thuringia, Germany) # Contact: usenet@thur.de # URL: http://www.thur.de/thurnet/old/thurnews.html # Admin group: thur.net.news.groups # Key fingerprint: 7E 3D 73 13 93 D4 CA 78 39 DE 3C E7 37 EE 22 F1 # Syncable server: news.thur.de # *PGP* See comment at top of file. newgroup:*:thur.*:drop rmgroup:*:thur.*:drop checkgroups:usenet@thur.de:thur.*:verify-thur.net.news.groups newgroup:usenet@thur.de:thur.*:verify-thur.net.news.groups rmgroup:usenet@thur.de:thur.*:verify-thur.net.news.groups ## TNN (*DEFUNCT* -- The Network News, Japan) # This hierarchy is defunct. Please remove it. newgroup:netnews@news.iij.ad.jp:tnn.*:mail newgroup:tnn@iij-mc.co.jp:tnn.*:mail rmgroup:netnews@news.iij.ad.jp:tnn.*:doit rmgroup:tnn@iij-mc.co.jp:tnn.*:doit ## TO (*RESERVED* -- Special hierarchy for UUCP point-to-point messages) # # Historically, the to.* hierarchy was used with UUCP to send special # control messages to a particular peer. This usage is very obsolete, # but the hierarchy is still special-cased in some news software and # should not be used. # checkgroups:*:to.*:drop newgroup:*:to.*:drop rmgroup:*:to.*:drop ## TRIANGLE (Research Triangle, Central North Carolina, USA) checkgroups:jfurr@acpub.duke.edu:triangle.*:doit checkgroups:news@news.duke.edu:triangle.*:doit checkgroups:tas@concert.net:triangle.*:doit newgroup:jfurr@acpub.duke.edu:triangle.*:doit newgroup:news@news.duke.edu:triangle.*:doit newgroup:tas@concert.net:triangle.*:doit rmgroup:jfurr@acpub.duke.edu:triangle.*:doit rmgroup:news@news.duke.edu:triangle.*:doit rmgroup:tas@concert.net:triangle.*:doit ## TUM (Technische Universitaet Muenchen) checkgroups:news@informatik.tu-muenchen.de:tum.*:doit newgroup:news@informatik.tu-muenchen.de:tum.*:doit rmgroup:news@informatik.tu-muenchen.de:tum.*:doit ## TW (Taiwan) checkgroups:ltc@news.cc.nctu.edu.tw:tw.*:doit newgroup:ltc@news.cc.nctu.edu.tw:tw.*:doit rmgroup:ltc@news.cc.nctu.edu.tw:tw.*:doit ## TW.K-12 (Taiwan K-12 Discussion) checkgroups:k-12@news.nchu.edu.tw:tw.k-12.*:doit newgroup:k-12@news.nchu.edu.tw:tw.k-12.*:doit rmgroup:k-12@news.nchu.edu.tw:tw.k-12.*:doit ## TX (Texas, USA) checkgroups:eric@cirr.com:tx.*:doit checkgroups:fletcher@cs.utexas.edu:tx.*:doit checkgroups:usenet@academ.com:tx.*:doit newgroup:eric@cirr.com:tx.*:doit newgroup:fletcher@cs.utexas.edu:tx.*:doit newgroup:usenet@academ.com:tx.*:doit rmgroup:eric@cirr.com:tx.*:doit rmgroup:fletcher@cs.utexas.edu:tx.*:doit rmgroup:usenet@academ.com:tx.*:doit ## UCB (University of California Berkeley, USA) # Contact: Chris van den Berg # URL: http://www.net.berkeley.edu/usenet/ # Key URL: http://www.net.berkeley.edu/usenet/usenet.asc # Key fingerprint: 96 B8 8E 9A 98 09 37 7D 0E EC 81 88 DB 90 29 BF # *PGP* See comment at top of file. newgroup:*:ucb.*:drop rmgroup:*:ucb.*:drop checkgroups:usenet@agate.berkeley.edu:ucb.*:verify-ucb.news newgroup:usenet@agate.berkeley.edu:ucb.*:verify-ucb.news rmgroup:usenet@agate.berkeley.edu:ucb.*:verify-ucb.news ## UCD (University of California Davis, USA) checkgroups:usenet@mark.ucdavis.edu:ucd.*:doit checkgroups:usenet@rocky.ucdavis.edu:ucd.*:doit newgroup:usenet@mark.ucdavis.edu:ucd.*:doit newgroup:usenet@rocky.ucdavis.edu:ucd.*:doit rmgroup:usenet@mark.ucdavis.edu:ucd.*:doit rmgroup:usenet@rocky.ucdavis.edu:ucd.*:doit ## UFRA (Unterfranken, Deutschland) # # This hierarchy is still in use, but it has no active maintainer. # Control messages for this hierarchy should not be honored without # confirming that the sender is the new hierarchy maintainer. # # Admin group: ufra.admin # Key fingerprint: F7 AD 96 D8 7A 3F 7E 84 02 0C 83 9A DB 8F EB B8 # *PGP* See comment at top of file. newgroup:*:ufra.*:drop rmgroup:*:ufra.*:drop ## UIUC (*DEFUNCT* -- University of Illinois at Urbana-Champaign, USA) # Contact: news@ks.uiuc.edu # This hierarchy is defunct. Please remove it. newgroup:*:uiuc.*:mail rmgroup:*:uiuc.*:doit ## UK (United Kingdom of Great Britain and Northern Ireland) # URL: http://www.usenet.org.uk/ # Admin group: uk.net.news.announce # Key URL: http://www.usenet.org.uk/newsadmins.html # *PGP* See comment at top of file. newgroup:*:uk.*:drop rmgroup:*:uk.*:drop checkgroups:control@usenet.org.uk:uk.*:verify-uk.net.news.announce newgroup:control@usenet.org.uk:uk.*:verify-uk.net.news.announce rmgroup:control@usenet.org.uk:uk.*:verify-uk.net.news.announce ## UKR (Ukraine) checkgroups:ay@sita.kiev.ua:ukr.*:doit newgroup:ay@sita.kiev.ua:ukr.*:doit rmgroup:ay@sita.kiev.ua:ukr.*:doit ## ULM (*PRIVATE* -- Ulm, Germany) # Admin group: ulm.misc # Syncable server: news.in-ulm.de # For private use only. newgroup:*:ulm.*:mail rmgroup:*:ulm.*:doit ## UMICH (University of Michigan, USA) checkgroups:*@*.umich.edu:umich.*:doit newgroup:*@*.umich.edu:umich.*:doit rmgroup:*@*.umich.edu:umich.*:doit ## UMN (University of Minnesota, USA) newgroup:edh@*.tc.umn.edu:umn.*:doit newgroup:news@*.tc.umn.edu:umn.*:doit newgroup:Michael.E.Hedman-1@umn.edu:umn.*:doit newgroup:edh@*.tc.umn.edu:umn*class.*:mail newgroup:news@*.tc.umn.edu:umn*class.*:mail newgroup:Michael.E.Hedman-1@umn.edu:umn*class.*:mail rmgroup:news@*.tc.umn.edu:umn.*:doit rmgroup:edh@*.tc.umn.edu:umn.*:doit rmgroup:Michael.E.Hedman-1@umn.edu:umn.*:doit ## UN (*HISTORIC* -- The United Nations) # # This hierarchy is not entirely defunct, but it receives very little # traffic and is included primarily for the sake of completeness. # # Admin group: un.public.usenet.admin # *PGP* See comment at top of file. newgroup:*:un.*:drop rmgroup:*:un.*:drop checkgroups:news@news.itu.int:un.*:verify-ungroups@news.itu.int newgroup:news@news.itu.int:un.*:verify-ungroups@news.itu.int rmgroup:news@news.itu.int:un.*:verify-ungroups@news.itu.int ## UO (University of Oregon, Eugene, Oregon, USA) checkgroups:newsadmin@news.uoregon.edu:uo.*:doit newgroup:newsadmin@news.uoregon.edu:uo.*:doit rmgroup:newsadmin@news.uoregon.edu:uo.*:doit ## US (United States of America) # Contact: us-control@lists.killfile.org # Admin group: us.config # Key fingerprint: BB96 EB2C CFD0 75C8 E9DE C2C2 1DA2 9D87 B73C AF1B # *PGP* See comment at top of file. newgroup:*:us.*:drop rmgroup:*:us.*:drop checkgroups:us-control@lists.killfile.org:us.*:verify-us-control@lists.killfile.org newgroup:us-control@lists.killfile.org:us.*:verify-us-control@lists.killfile.org rmgroup:us-control@lists.killfile.org:us.*:verify-us-control@lists.killfile.org ## UT (*LOCAL* -- University of Toronto, Canada) # URL: http://www.utoronto.ca/ns/utornews/ #newgroup:news@ecf.toronto.edu:ut.*:doit #newgroup:news@ecf.toronto.edu:ut.class.*:mail #rmgroup:news@ecf.toronto.edu:ut.*:doit ## UTA (Finnish) checkgroups:news@news.cc.tut.fi:uta.*:doit newgroup:news@news.cc.tut.fi:uta.*:doit rmgroup:news@news.cc.tut.fi:uta.*:doit ## UTEXAS (*LOCAL* -- University of Texas, USA) # URL: http://www.utexas.edu/its/usenet/index.php newgroup:fletcher@cs.utexas.edu:utexas.*:doit newgroup:news@geraldo.cc.utexas.edu:utexas.*:doit newgroup:fletcher@cs.utexas.edu:utexas*class.*:mail newgroup:news@geraldo.cc.utexas.edu:utexas*class.*:mail rmgroup:fletcher@cs.utexas.edu:utexas.*:doit rmgroup:news@geraldo.cc.utexas.edu:utexas.*:doit ## UTWENTE (*LOCAL* -- University of Twente, Netherlands) # Contact: newsmaster@utwente.nl # For local use only, contact the above address for information. newgroup:*:utwente.*:mail rmgroup:*:utwente.*:doit ## UVA (*LOCAL* -- University of Virginia, USA) # Contact: usenet@virginia.edu # For local use only, contact the above address for information. newgroup:*:uva.*:mail rmgroup:*:uva.*:doit ## UW (University of Waterloo, Canada) # Admin group: uw.newsgroups # Syncable server: news.uwaterloo.ca # *PGP* See comment at top of file. newgroup:*:uw.*:drop rmgroup:*:uw.*:drop checkgroups:newsgroups@news.uwaterloo.ca:uw.*:verify-uw.newsgroups newgroup:newsgroups@news.uwaterloo.ca:uw.*:verify-uw.newsgroups rmgroup:newsgroups@news.uwaterloo.ca:uw.*:verify-uw.newsgroups ## UWARWICK (*LOCAL* -- University of Warwick, UK) # Contact: Jon Harley # For local use only, contact the above address for information. newgroup:*:uwarwick.*:mail rmgroup:*:uwarwick.*:doit ## UWO (University of Western Ontario, London, Canada) # URL: http://www.uwo.ca/its/news/groups.uwo.html checkgroups:reggers@julian.uwo.ca:uwo.*:doit newgroup:reggers@julian.uwo.ca:uwo.*:doit rmgroup:reggers@julian.uwo.ca:uwo.*:doit ## VAN (Vancouver, British Columbia, Canada) checkgroups:bc_van_usenet@fastmail.ca:van.*:doit newgroup:bc_van_usenet@fastmail.ca:van.*:doit rmgroup:bc_van_usenet@fastmail.ca:van.*:doit ## VEGAS (Las Vegas, Nevada, USA) checkgroups:cshapiro@netcom.com:vegas.*:doit checkgroups:doctor@netcom.com:vegas.*:doit newgroup:cshapiro@netcom.com:vegas.*:doit newgroup:doctor@netcom.com:vegas.*:doit rmgroup:cshapiro@netcom.com:vegas.*:doit rmgroup:doctor@netcom.com:vegas.*:doit ## VGC (Japan groups?) checkgroups:news@isl.melco.co.jp:vgc.*:doit newgroup:news@isl.melco.co.jp:vgc.*:doit rmgroup:news@isl.melco.co.jp:vgc.*:doit ## VMSNET (VMS Operating System) checkgroups:cts@dragon.com:vmsnet.*:doit newgroup:cts@dragon.com:vmsnet.*:doit rmgroup:cts@dragon.com:vmsnet.*:doit ## WA (Western Australia) # Contact: ausadmin@aus.news-admin.org # URL: http://wa.news-admin.org/ # Key URL: http://aus.news-admin.org/ausadmin.asc # *PGP* See comment at top of file. newgroup:*:wa.*:drop rmgroup:*:wa.*:drop checkgroups:ausadmin@aus.news-admin.org:wa.*:verify-ausadmin@aus.news-admin.org newgroup:ausadmin@aus.news-admin.org:wa.*:verify-ausadmin@aus.news-admin.org rmgroup:ausadmin@aus.news-admin.org:wa.*:verify-ausadmin@aus.news-admin.org ## WADAI (Japanese ?) checkgroups:kohe-t@*wakayama-u.ac.jp:wadai.*:doit newgroup:kohe-t@*wakayama-u.ac.jp:wadai.*:doit rmgroup:kohe-t@*wakayama-u.ac.jp:wadai.*:doit ## WALES (Wales) # Contact: committee@wales-usenet.org # URL: http://www.wales-usenet.org/ # Admin group: wales.usenet.config # Key URL: http://www.wales-usenet.org/english/newsadmin.txt # Key fingerprint: 2D 9E DE DF 12 DA 34 5C 49 E1 EE 28 E3 AB 0D AD # *PGP* See comment at top of file. newgroup:*:wales.*:drop rmgroup:*:wales.*:drop checkgroups:control@wales-usenet.org:wales.*:verify-wales-usenet newgroup:control@wales-usenet.org:wales.*:verify-wales-usenet rmgroup:control@wales-usenet.org:wales.*:verify-wales-usenet ## WASH (Washington State, USA) checkgroups:graham@ee.washington.edu:wash.*:doit newgroup:graham@ee.washington.edu:wash.*:doit rmgroup:graham@ee.washington.edu:wash.*:doit ## WEST-VIRGINIA (West Virginia, USA) checkgroups:bryan27@hgo.net:west-virginia.*:doit newgroup:mark@bluefield.net:west-virginia.*:doit newgroup:bryan27@hgo.net:west-virginia.*:doit rmgroup:mark@bluefield.net:west-virginia.*:doit rmgroup:bryan27@hgo.net:west-virginia.*:doit ## WORLDONLINE (*LOCAL* -- ?) # Contact: newsmaster@worldonline.nl # For local use only, contact the above address for information. newgroup:*:worldonline.*:mail rmgroup:*:worldonline.*:doit ## WPG (Winnipeg, Manitoba, Canada) # # This hierarchy is still in use, but it has no active maintainer. # Control messages for this hierarchy should not be honored without # confirming that the sender is the new hierarchy maintainer. ## WPI (*LOCAL* -- Worcester Polytechnic Institute, Worcester, MA) # For local use only. newgroup:aej@*.wpi.edu:wpi.*:mail rmgroup:aej@*.wpi.edu:wpi.*:doit ## WU (Washington University at St. Louis, MO) checkgroups:*@*.wustl.edu:wu.*:doit newgroup:*@*.wustl.edu:wu.*:doit rmgroup:*@*.wustl.edu:wu.*:doit ## X-PRIVAT (Italian) # Contact: dmitry@x-privat.org # URL: http://www.x-privat.org/ # Admin group: x-privat.info # Key URL: http://www.x-privat.org/dmitry.asc # Key fingerprint: 9B 0A 7E 68 27 80 C7 96 47 6B 03 90 51 05 68 43 # *PGP* See comment at top of file. newgroup:*:x-privat.*:drop rmgroup:*:x-privat.*:drop checkgroups:dmitry@x-privat.org:x-privat.*:verify-dmitry@x-privat.org newgroup:dmitry@x-privat.org:x-privat.*:verify-dmitry@x-privat.org rmgroup:dmitry@x-privat.org:x-privat.*:verify-dmitry@x-privat.org ## XS4ALL (XS4ALL, Netherlands) # Contact: XS4ALL Newsmaster checkgroups:news@xs4all.nl:xs4all.*:doit newgroup:news@xs4all.nl:xs4all.*:doit rmgroup:news@xs4all.nl:xs4all.*:doit ## YORK (*LOCAL* -- York University, Toronto, ON) # Contact: Peter Marques # For local use only, contact the above address for information. newgroup:*:york.*:mail rmgroup:*:york.*:doit ## Z-NETZ (German non-Internet based network) # Contact: teko@dinoex.sub.org # Admin group: z-netz.koordination.user+sysops # Key URL: ftp://ftp.dinoex.de/pub/keys/z-netz.koordination.user+sysops.asc # *PGP* See comment at top of file. newgroup:*:z-netz.*:drop rmgroup:*:z-netz.*:drop checkgroups:teko@dinoex.sub.org:z-netz.*:verify-z-netz.koordination.user+sysops newgroup:teko@dinoex.sub.org:z-netz.*:verify-z-netz.koordination.user+sysops rmgroup:teko@dinoex.sub.org:z-netz.*:verify-z-netz.koordination.user+sysops ## ZA (South Africa) checkgroups:ccfj@hippo.ru.ac.za:za.*:doit checkgroups:root@duvi.eskom.co.za:za.*:doit newgroup:ccfj@hippo.ru.ac.za:za.*:doit newgroup:root@duvi.eskom.co.za:za.*:doit rmgroup:ccfj@hippo.ru.ac.za:za.*:doit rmgroup:root@duvi.eskom.co.za:za.*:doit ## ZER (*DEFUNCT* -- Germany) # This hierarchy is defunct. Please remove it. newgroup:*:zer.*:mail rmgroup:*:zer.*:doit ## ------------------------------------------------------------------------- ## CONTROL.CTL ADDITIONS ## ------------------------------------------------------------------------- # Incoming encodings in newgroup and checkgroups control articles. # These lines are additions to the official control.ctl file. # Default (for any description). /encoding/:*:*:cp1252 /encoding/:*:cn.*:gb18030 /encoding/:*:han.*:gb18030 /encoding/:*:fido7.*:koi8-r /encoding/:*:medlux.*:koi8-r /encoding/:*:relcom.*:koi8-r /encoding/:*:ukr.*:koi8-u /encoding/:*:fr.*:iso-8859-15 /encoding/:*:nctu.*:big5 /encoding/:*:ncu.*:big5 /encoding/:*:tw.*:big5 /encoding/:*:scout.forum.chinese:big5 /encoding/:*:scout.forum.korean:big5 /encoding/:*:fido.*:utf-8 inn-2.6.4/samples/filter_innd.pl0000644000175200017520000001477514002373703016234 0ustar iuliusiulius# # $Id: filter_innd.pl 9205 2011-06-13 15:08:31Z iulius $ # # Sample Perl filtering file for the innd hooks. # # This file gets loaded at innd process startup, and everytime a # "ctlinnd reload filter.perl 'reason'" or a # "ctlinnd reload all 'reason'" is done. # # Before this file is loaded, the perl routine `filter_before_reload' is # called, and after it's finished loading, the perl routine # `filter_after_reload' is called. See startup_innd.pl for more details. # # When filtering is disabled, the filter_end() Perl routine is called, # if defined, prior to the deactivation of the filter. # # The following routines can be defined here for use by innd: # # sub filter_art { ... } # # This routine is called before every article is accepted for # posting. Is is called with no arguments, but has access to # all the non-empty standard headers of the article via the # global associative array `%hdr.' If it returns the empty # string ("") then the article is accepted. If it returns any # non-null string value, then the article is rejected and the # returned string value is logged as the reason why (make sure # that such a message is properly encoded in UTF-8 so as to comply # with the NNTP protocol). # # The standard headers are: # # Approved, Control, Date, Distribution, Expires, # From, Lines, Message-ID, Newsgroups, Path, # Reply-To, Sender, Subject, Supersedes, Bytes, # Also-Control, References # # sub filter_mode { ... } # # This routine is called every time `go', `pause', or # `throttle' is called. It is called with no arguments and # returns no value. The global associative array `%mode' has # three keyed values stored in it: # # 'Mode' The current mode # ("running", "paused", "throttled") # 'NewMode" The new mode # 'reason' The reason given. # # For example: %mode = ('Mode', 'running', # 'NewMode', 'throttled', # 'reason', 'doing nightly backups') # # If filter_art is not defined when this file is done loading, then # filtering is disabled. If any syntax error occurs when loading the file, # then filtering is disabled. # # sub filter_messageid { ... } # # This routine is called when each article (in streaming # mode only) is checked to see if INN wants to accept the # article. If it returns the empty string, the article # is accepted. If it returns a non-empty value, the # article is refused (make sure that such a message is # properly encoded in UTF-8 so as to comply with the # NNTP protocol). It is called with one argument, # the message-id to check. # # Called on each article innd receives from a peer. Return "" to accept, # and any other non-null string to reject. If rejecting the string returned # will be part of the logged reason. # sub filter_art { my $rval = "" ; # Assume we'll accept. Cannot be `0' ### Remove two leading '##' from the following section (and then ### "ctlinnd reload filter.perl 'reason'" and the filter will reject articles that ### have "make money" in the subject, or are posted to more than 10 ### newsgroups. ## my ($maxgroups) = 10 ; ## ### Normally this output would be lost, but if you run innd with '-d -f' you ### can see what's going on. ### ### foreach $key (sort keys %hdr) { ### print "Header:\t$key Value:\t $hdr{$key}\n" ; ### } ## ## if ($hdr{"Subject"} =~ /\$*make.*money.*\$*/i ) { ## $rval = "no money requests here" ## } elsif ( ( @_ = split(",",$hdr{'Newsgroups'}) ) > $maxgroups ) { ## $rval = "too many groups" ; ### Kill article with "Re: " but no References: ## } elsif ($hdr{'Subject'} =~ /^Re: /o and $hdr{'References'} eq "") { ## $rval = "Followup without References:"; ### Kill article with invalid From: ## } elsif ($hdr{'From'} =~ /^\w*$/o or ## $hdr{'From'} !~ /^(.+?)\@([-\w\d]+\.)*([-\w\d]+)\.([-\w\d]{2,})$/o) { ## $rval = "From: is invalid, must be user\@[host.]domain.tld"; ## } ### ### print "Accepting\n" if ! $rval ; $rval ; } sub filter_mode { if ($mode{'NewMode'} eq "throttled" || $mode{'NewMode'} eq "paused") { # print "Closing spam database\n" ; # won't kill server. # &close_spam_database ; } else { # print "Opening spam database\n" ; # won't kill server # &open_spam_database ; } } sub filter_messageid { my ($messageid) = @_; $rval = ''; # $rval = 'No' if ($messageid =~ /a\.spam\.domain>?/i); $rval; } sub filter_end { # Do whatever you want to clean up things when Perl filtering is disabled. } ########################################################################### ## ## Another sample. More elaborate, but cleaner... from Christophe ## Wolfhugel . ## #### Regular expressions we reject. #### Format : Header => regexp => reason ##%reject = ( ## 'Subject' => { ## 'make.*money.*fast' => 'MMF rejected', ## 'cash.*cash.*cash' => 'Cash rejected' ## }, ##); ## ##sub filter_art { ## my($rval) = ''; ## my(@ng, $i, $j, $k, $l); ## ## if ($hdr{'From'} !~ /\@/o) { ## $rval = 'Invalid From'; ## } else { ## while (($i, $j) = each %reject) { ## while (($k, $l) = each %{$j}) { ## if ($hdr{$i} =~ /$k/i) { ## $rval = $l; ## goto the_end; ## } ## } ## } ## } ## @ng = split(/,/, $hdr{'Newsgroups'}); ## if ($#ng > 10) { ## $rval = 'ECP rejected'; ## } ##the_end: ## undef %hdr; ## return $rval ##} ## ##sub filter_mode { ##} ## ###%hdr = ( ### 'Subject' => 'Make money fast', ### 'From' => 'bozo@gov.org' ###); ###&filter_art; ########################################################################### ## ## From Chrisophe Wolfhugel again (wolf@pasteur.fr). This is not ## standalone code. ## ##Just for the fun, I've added following code to filter_innd.pl : ## ## ## Keep track of the From and subject. ## $i = "$hdr{'From'} $hdr{'Subject'}"; ## push(@history, $i); ## $history{$i}++; ## ## ## Reject the EMP. ## if ($history{$i} > 10) { ## $rval = "EMP rejected (appeared $history{$i} times): $i"; ## } ## ## ## Remove too old things. ## while ($#history > 1000) { ## delete($history{shift(@history)}); ## } ## ##It is pretty successfull in detecting and refusing excessive multi-posting. ##Same sender, same subject, appearing more than 10 times without the last ##1000 articles gets junked. ## ##Already catched a few hundreds : ## ##Nov 20 08:27:23.175 - vishnu.jussieu.fr <3292ac9a.4064710@nntp.cts.com> 437 EMP rejected (btr@trenet.com Be a Beta Tester!) ## ##That was just for the pleasure. It is still sucking a non significant CPU ##time on my slow Alpha. inn-2.6.4/samples/innreport.css0000644000175200017520000000336514002373703016125 0ustar iuliusiulius/* ** $Id: innreport.css 10385 2020-06-13 15:21:43Z iulius $ ** ** innreport.css -- for parameter html_css_url in innreport.conf ** ** Style created by Alexander Bartolich, 2008. ** ** In case you modify this file, please keep old definitions for backward ** compatibility with previously generated reports. */ div.ir-pageTitle { border-bottom:4px double black; border-top:4px double black; margin-bottom:2ex; margin-top:2ex; text-align:center; } div.ir-feedTotals { margin-bottom:1ex; margin-left:auto; margin-right:auto; text-align:center; } table.ir-archives, table.ir-report { border-collapse:collapse; margin-left:auto; margin-right:auto; margin-top:1ex; margin-bottom:1ex; } table.ir-archives td, table.ir-archives th, table.ir-report td, table.ir-report th { border:1px solid black; empty-cells:show; padding:0.3ex 0.3em 0.3ex 0.3em; } table.ir-archives th, table.ir-report th { font-weight:bold; background-color:#D3D3D3; } table.ir-archives th, table.ir-report th, tr.ir-totalRow td, tr.ir-headerRow th { border-bottom:2px solid black; border-top:2px solid black; } div.ir-pageFooter { border-top:4px double black; padding-top:1ex; margin-top:1ex; vertical-align:top; } div.ir-pageFooter img { border:0; float:left; margin-right:1em; } div.ir-versionNotice { font-size:small; } div.ir-section { border-top:1px solid black; } p.ir-sectionTitle { font-weight:bold; } div.ir-logFileLines { font-family:monospace; } div.ir-reportGraph { margin-left:auto; margin-right:auto; margin-top:1ex; margin-bottom:1ex; text-align:center; } td.ir-totalColumn { text-align:left; font-weight:bold; } tr.ir-oddRow td, td.ir-primaryKey { background-color:#F8E0E0; } inn-2.6.4/samples/nnrpd_auth.pl.in0000644000175200017520000000540414002373703016473 0ustar iuliusiulius#! /usr/bin/perl -w # fixscript will replace this line with code to load INN::Config ## ## Sample code for the nnrpd Perl authentication hooks. ## ## This file is loaded when a perl_auth: parameter is reached in ## readers.conf. If it defines a sub named authenticate, that ## function will be called during processing of a perl_auth: ## parameter. Attributes about the connection are passed to the ## program in the %attributes global variable. It should return an ## array with two elements: ## ## 1) NNTP response code. Should be one of the codes from %authcodes ## below to not risk violating the protocol. ## 2) An error string to be passed to the client (make sure that ## such a message is properly encoded in UTF-8 so as to comply with the ## NNTP protocol). ## Both elements are required. If there is a problem, nnrpd will die ## and syslog the exact error. ## The code below uses a user database based on CDB_File. It is ## provided here as an example of an authentication script. ## This file cannot be run as a standalone script, although it would be ## worthwhile to add some code so that it could so that one could test the ## results of various authentication and connection queries from the ## command line. The #! line at the top is just so that fixscript will ## work. use strict; use vars qw(%attributes %authcodes %users); # These codes are a widely implemented de facto standard. %authcodes = ('allowed' => 281, 'denied' => 481, 'error' => 403); # This sub should perform any initialization work that the # authentication stuff needs. sub auth_init { require CDB_File; tie (%users, 'CDB_File', $INN::Config::pathdb . '/users.cdb') or warn "Could not open $INN::Config::pathdb/users.cdb for users: $!\n"; } # This function is called for authentication requests. For details on # all the information passed to it, see ~news/doc/hook-perl. sub authenticate { return &checkuser(); } # This function assumes that there's a database tied as %users that # contains, keyed by users, a tab-separated list of the password (in # crypt format), whether they can post, a wildmat matching what # newsgroups they have access to, and the number of bytes per second # they're allowed to use. This section of the code only accesses the # username and password fields. See the file nnrpd_access.pl for # access rights based on the other fields. sub checkuser { my $user = $attributes{'username'}; my $pass = $attributes{'password'}; return ($authcodes{denied}, "No username given.") unless defined $users{$user}; my ($password, $post, $speed, $subscription) = split(/\t/, $users{$user}); return ($authcodes{denied}, "Incorrect password.") if (crypt($pass, $password) ne $password); return ($authcodes{allowed}, ""); } inn-2.6.4/samples/actsync.cfg0000644000175200017520000000060714002373703015514 0ustar iuliusiulius## $Id: actsync.cfg 10283 2018-05-14 12:43:05Z iulius $ ## ## Sample actsync configuration file. ## ## It permits synchronizing, comparing, or merging active files. ## It is useful for keeping the list of carried newsgroups ## up to date. ## See the actsync man page for more information. host=ftp.isc.org ftppath=/pub/usenet/CONFIG/active.gz flags=-v 0 -p 80 ignore_file=actsync.ign inn-2.6.4/samples/passwd.nntp0000644000175200017520000000156714002373703015577 0ustar iuliusiulius## $Id: passwd.nntp 10283 2018-05-14 12:43:05Z iulius $ ## ## Sample passwd.nntp configuration file. ## ## It permits authenticating on remote NNTP servers. ## ## Format: ## ::[: