diff --git a/AUTHORS b/AUTHORS index 4d198be..93c18a1 100644 --- a/AUTHORS +++ b/AUTHORS @@ -9,6 +9,8 @@ Other Authors 2001-2004 Herbert Straub See ChangeLog file for details. +2008 Christof Meerwald + IPv6 support, removed libsocket++ dependency Author of Program Parts diff --git a/NEWS b/NEWS index 3692175..e50ac41 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,13 @@ +Release 1.3.ipv6: +Christof Meerwald + +New functions: +* IPv6 support + +* new ConnectTimeout, ConnectBackoff and LimitGroupSize options + +* client support for SSL connections + Release 1.2: Herbert Straub - 2004-09-28 New functions: diff --git a/NServer-0.9.1/ActiveDB.cc b/NServer-0.9.1/ActiveDB.cc index 5fbfbca..26dd68d 100644 --- a/NServer-0.9.1/ActiveDB.cc +++ b/NServer-0.9.1/ActiveDB.cc @@ -7,3 +7,11 @@ ActiveDB::ActiveDB() ActiveDB::~ActiveDB() { } + +/* + * Local Variables: + * mode: c++ + * tab-width: 4 + * c-basic-offset: 4 + * End: + */ diff --git a/NServer-0.9.1/ActiveDB.h b/NServer-0.9.1/ActiveDB.h index 78795fc..c8141d5 100644 --- a/NServer-0.9.1/ActiveDB.h +++ b/NServer-0.9.1/ActiveDB.h @@ -12,9 +12,10 @@ #include "VirtualIterator.h" class ActiveDB { - protected: + protected: ActiveDB(); - public: + + public: virtual ~ ActiveDB(); // Used for set enum { @@ -57,3 +58,11 @@ class ActiveDB { }; #endif + +/* + * Local Variables: + * mode: c++ + * tab-width: 4 + * c-basic-offset: 4 + * End: + */ diff --git a/NServer-0.9.1/ArtSpooler.cc b/NServer-0.9.1/ArtSpooler.cc index e3bc426..f26589f 100644 --- a/NServer-0.9.1/ArtSpooler.cc +++ b/NServer-0.9.1/ArtSpooler.cc @@ -176,3 +176,11 @@ string ArtSpooler::extractID(Article & a) ID.replace(ID.length() - 1, 1, ""); return ID; } + +/* + * Local Variables: + * mode: c++ + * tab-width: 4 + * c-basic-offset: 4 + * End: + */ diff --git a/NServer-0.9.1/ArtSpooler.h b/NServer-0.9.1/ArtSpooler.h index 56759a6..ca5a4d5 100644 --- a/NServer-0.9.1/ArtSpooler.h +++ b/NServer-0.9.1/ArtSpooler.h @@ -37,7 +37,7 @@ * \li .resourceSpooler.lock (LockFile). */ class ArtSpooler { - public: + public: /** * If the spool directory doesn't exists, the contstructor creates * it. It uses ObjLock to manage the access to the Spool. @@ -45,7 +45,7 @@ class ArtSpooler { * \throw Error * \todo Das ist ein Testpunkt */ - ArtSpooler(const string & spoolDir); + ArtSpooler(const std::string & spoolDir); ~ArtSpooler(); @@ -81,26 +81,34 @@ class ArtSpooler { * Create a unique ID * \return The ID String */ - string createID(void); + std::string createID(void); /** * Extract ID from article message id * \return The ID String */ - string extractID(Article & a); + std::string extractID(Article & a); /** * store Article in path * return 0 success, 1 duplicated */ - int storeArticle(const string & path, Article & a); + int storeArticle(const std::string & path, Article & a); - private: - string spoolDir; - string artSpool; - string badArticles; + private: + std::string spoolDir; + std::string artSpool; + std::string badArticles; ObjLock *pLock; }; #endif + +/* + * Local Variables: + * mode: c++ + * tab-width: 4 + * c-basic-offset: 4 + * End: + */ diff --git a/NServer-0.9.1/Article.cc b/NServer-0.9.1/Article.cc index ab0dd46..122197c 100644 --- a/NServer-0.9.1/Article.cc +++ b/NServer-0.9.1/Article.cc @@ -26,22 +26,18 @@ using namespace std; InvalidArticleError::InvalidArticleError(const char *txt, const char *file, - const char *function, int line):NSError(txt, - file, - function, - line) + const char *function, int line) + : NSError(txt, file, function, line) { } InvalidArticleError::InvalidArticleError(const string & txt, const char *file, - const char *function, int line):NSError(txt, - file, - function, - line) + const char *function, int line) + : NSError(txt, file, function, line) { } -void InvalidArticleError::print(void) +void InvalidArticleError::print(void) const { slog << "Exception!\n" << " Type: InvalidArticle\n" @@ -53,13 +49,8 @@ Article::Article() } Article::Article(Article * a) - //: _nbr(a->getnbr()), _text(a->GetText()), _ctext(_text.c_str()) -{ - _nbr = a->getnbr(); - _text = a->GetText(); - _ctext = _text.c_str(); - -} + : _nbr(a->getnbr()), _text(a->GetText()), _ctext(_text.c_str()) +{ } Article::Article(int artnbr) { @@ -67,7 +58,6 @@ Article::Article(int artnbr) } Article::Article(int artnbr, const char *text, int textlen) - //: setnbr(artnbr), _text.assign(text, textlen), _ctext = _text.c_str() { setnbr(artnbr); _text.assign(text, textlen); @@ -373,3 +363,11 @@ ostream & operator <<(ostream & os, Article & art) os << art._text; return os; } + +/* + * Local Variables: + * mode: c++ + * tab-width: 4 + * c-basic-offset: 4 + * End: + */ diff --git a/NServer-0.9.1/Article.h b/NServer-0.9.1/Article.h index 2a44613..afeb913 100644 --- a/NServer-0.9.1/Article.h +++ b/NServer-0.9.1/Article.h @@ -16,14 +16,14 @@ * Syntactic error in Article dectected */ class InvalidArticleError:public NSError { - public: + public: InvalidArticleError(const char *txt, const char *file, - const char *function, int line); + const char *function, int line); InvalidArticleError(const std::string & txt, const char *file, - const char *function, int line); + const char *function, int line); - virtual void print(void); + virtual void print(void) const; }; /** @@ -34,7 +34,7 @@ class InvalidArticleError:public NSError { * \bug Method documentation is missing. */ class Article { - private: + private: /** * Return the position of a given field in the article's header. @@ -43,12 +43,12 @@ class Article { */ const char *find_field(const char *ifld) const; - protected: + protected: int _nbr; std::string _text; const char *_ctext; - public: + public: enum { Head = 0x1, Body = 0x2 @@ -96,3 +96,11 @@ class Article { }; #endif + +/* + * Local Variables: + * mode: c++ + * tab-width: 4 + * c-basic-offset: 4 + * End: + */ diff --git a/NServer-0.9.1/CNewsgroup.cc b/NServer-0.9.1/CNewsgroup.cc index bec6506..7711389 100644 --- a/NServer-0.9.1/CNewsgroup.cc +++ b/NServer-0.9.1/CNewsgroup.cc @@ -23,7 +23,7 @@ void CNewsgroup::listgroup(char *lstgrp, unsigned int f, unsigned int l) } void CNewsgroup::sUpdateGroupInfo(unsigned int *infofp, - unsigned int *infolp) + unsigned int *infolp) { GroupInfo *info; unsigned int f, l, infof, infol; @@ -79,40 +79,54 @@ void CNewsgroup::sUpdateOverview(void) try { listgroup(lstgrp, infof, infol); - f = infof; - while (f <= infol) { - if ((NVArray::shas_element(f) && lstgrp[f - infof]) - || (!NVArray::shas_element(f) - && !lstgrp[f - infof])) { - f++; - continue; - } - if (lstgrp[f - infof]) { - // We do not have this article - l = f; - for (i = l + 1; i < l + 8 && i <= infol; - i++) { - if (!NVArray::shas_element(i) - && lstgrp[i - infof]) - l = i; + if (_RServer->getnntpflags() & MPListEntry::F_LISTGROUP) { + f = infof; + while (f <= infol) { + if ((NVArray::shas_element(f) && lstgrp[f - infof]) + || (!NVArray::shas_element(f) + && !lstgrp[f - infof])) { + f++; + continue; } - _RServer->overviewdb(this, f, l); - f = i; - } else { - i = f - infof; - // We do have this article, but it has been deleted - if (*(mem_p + arrtab[i] + sizeof(long)) == - bigarticle) { - // Remove article from disk - sprintf(fn, "%s/.art%ud", - _SpoolDirectory, i); - unlink(fn); + if (lstgrp[f - infof]) { + // We do not have this article + l = f; + for (i = l + 1; i < l + 8 && i <= infol; + i++) { + if (!NVArray::shas_element(i) + && lstgrp[i - infof]) + l = i; + } + _RServer->overviewdb(this, f, l); + f = i; + } else { + i = f - infof; + // We do have this article, but it has been deleted + if (*(mem_p + arrtab[i] + sizeof(long)) == + bigarticle) { + // Remove article from disk + sprintf(fn, "%s/.art%ud", + _SpoolDirectory, i); + unlink(fn); + } + nvfree(arrtab[i]); + arrtab[i] = 0; + f++; } - nvfree(arrtab[i]); - arrtab[i] = 0; - f++; } + } else { + f = infol; + while ((f >= infof) && !NVArray::shas_element(f)) { + f--; + } + + /* do we have at least one new article? */ + if (f < infol) + { + _RServer->overviewdb(this, f + 1, infol); + } } + time(&now); setmtime(now); } catch(Error & e) { @@ -248,3 +262,11 @@ void CNewsgroup::prefetchGroup(int lockgrp) free(lstgrp); NVArray::lock(NVcontainer::UnLock); } + +/* + * Local Variables: + * mode: c++ + * tab-width: 4 + * c-basic-offset: 4 + * End: + */ diff --git a/NServer-0.9.1/CNewsgroup.h b/NServer-0.9.1/CNewsgroup.h index 7ced37f..5317336 100644 --- a/NServer-0.9.1/CNewsgroup.h +++ b/NServer-0.9.1/CNewsgroup.h @@ -11,7 +11,7 @@ * \bug method documentation are mising. */ class CNewsgroup:public NVNewsgroup { - protected: + protected: nvtime_t _TTLGroup; RServer *_RServer; @@ -28,10 +28,11 @@ class CNewsgroup:public NVNewsgroup { NVArray::lock(NVcontainer::ExclLock); sUpdateOverview(); NVArray::lock(NVcontainer::UnLock); - } void listgroup(char *lstgrp, unsigned int f, unsigned int l); + } + void listgroup(char *lstgrp, unsigned int f, unsigned int l); virtual Article *retrievearticle(unsigned int nbr); - public: + public: CNewsgroup(RServer * nsrvr, OverviewFmt * fmt, const char *spooldir, const char *name):NVNewsgroup(fmt, spooldir, @@ -95,3 +96,11 @@ class CNewsgroup:public NVNewsgroup { }; #endif + +/* + * Local Variables: + * mode: c++ + * tab-width: 4 + * c-basic-offset: 4 + * End: + */ diff --git a/NServer-0.9.1/GroupInfo.cc b/NServer-0.9.1/GroupInfo.cc index 99d0585..09c5692 100644 --- a/NServer-0.9.1/GroupInfo.cc +++ b/NServer-0.9.1/GroupInfo.cc @@ -1 +1,9 @@ #include "GroupInfo.h" + +/* + * Local Variables: + * mode: c++ + * tab-width: 4 + * c-basic-offset: 4 + * End: + */ diff --git a/NServer-0.9.1/GroupInfo.h b/NServer-0.9.1/GroupInfo.h index 1116029..2d6f26a 100644 --- a/NServer-0.9.1/GroupInfo.h +++ b/NServer-0.9.1/GroupInfo.h @@ -19,10 +19,11 @@ class GroupInfo { char _flag; char _name[512]; - public: - GroupInfo() { + public: + GroupInfo() { init(); - } GroupInfo(const char *gd) { + } + GroupInfo(const char *gd) { _name[sizeof(_name) - 1] = '\0'; set(gd); } @@ -114,20 +115,28 @@ class GroupInfo { nvtime_t ctime() const { return _ctime; - } nvtime_t mtime() const { + } + nvtime_t mtime() const { return _mtime; - } const char *name() const { + } + const char *name() const { return _name; - } unsigned int first() const { + } + unsigned int first() const { return _fst; - } unsigned int last() const { + } + unsigned int last() const { return _lst; - } unsigned int n() const { + } + unsigned int n() const { return _n; - } char flags() const { + } + char flags() const { return _flag; - } friend std::ostream & operator <<(std::ostream & os, - const GroupInfo & gd) { + } + + friend std::ostream & operator <<(std::ostream & os, + const GroupInfo & gd) { os << gd._name << ' ' << gd._lst << ' ' << gd. _fst << ' ' << gd._flag; return os; @@ -135,3 +144,11 @@ class GroupInfo { }; #endif + +/* + * Local Variables: + * mode: c++ + * tab-width: 4 + * c-basic-offset: 4 + * End: + */ diff --git a/NServer-0.9.1/Lexer.cc b/NServer-0.9.1/Lexer.cc index 5b1e4d9..cac8aac 100644 --- a/NServer-0.9.1/Lexer.cc +++ b/NServer-0.9.1/Lexer.cc @@ -1 +1,9 @@ #include "Lexer.h" + +/* + * Local Variables: + * mode: c++ + * tab-width: 4 + * c-basic-offset: 4 + * End: + */ diff --git a/NServer-0.9.1/Lexer.h b/NServer-0.9.1/Lexer.h index 24a108a..86adabb 100644 --- a/NServer-0.9.1/Lexer.h +++ b/NServer-0.9.1/Lexer.h @@ -17,22 +17,23 @@ */ class Lexer { friend class SyntaxError; - private: + private: const char *_fn; - std::ifstream _is; + std::ifstream _is; - string _tok; + std::string _tok; - string _buf; + std::string _buf; int _line; const char *_cbuf; const char *_cbufp; - public: - Lexer(const char *fn = NULL) { + public: + Lexer(const char *fn = NULL) { _fn = NULL; if (fn) open(fn); - } void close() { + } + void close() { if (!_fn) return; _fn = NULL; @@ -53,11 +54,11 @@ class Lexer { return _is.eof(); } - string curToken() { + std::string curToken() { return _tok; } - string getToken() { + std::string getToken() { const char *q; while (!(*_cbufp)) { if (!_is.good()) @@ -86,12 +87,12 @@ class Lexer { return _tok; } - void putbackToken(string token) { + void putbackToken(std::string token) { _buf.replace(0, _cbufp - _cbuf, token + ' '); _cbufp = _cbuf = _buf.c_str(); } - int isFlag(const string & token, const char *strg, int *flag) { + int isFlag(const std::string & token, const char *strg, int *flag) { const char *ctok = token.c_str(); if (strcmp(ctok, strg) == 0) { *flag = 1; @@ -113,19 +114,22 @@ class Lexer { * \bug Documentation is missing. */ class SyntaxError:public Error { - public: + public: SyntaxError(const Lexer & lex, const char *txt, const char *file, - const char *function, int line) - :Error(txt, file, function, line) { + const char *function, int line) + : Error(txt, file, function, line) + { char buf[256]; - sprintf(buf, ":%d: ", lex._line); - - _errtext = lex._fn; - _errtext += buf; - _errtext += txt; - VERB(slog.p(Logger::Error); - SyntaxError::print()); - } virtual void print() { + sprintf(buf, ":%d: ", lex._line); + + _errtext = lex._fn; + _errtext += buf; + _errtext += txt; + VERB(slog.p(Logger::Error); + SyntaxError::print()); + } + + virtual void print() const { slog << "Exception!\n" << " Type: Syntax\n" << " Desc: " << _errtext << "\n"; @@ -133,3 +137,11 @@ class SyntaxError:public Error { }; #endif + +/* + * Local Variables: + * mode: c++ + * tab-width: 4 + * c-basic-offset: 4 + * End: + */ diff --git a/NServer-0.9.1/MPList.cc b/NServer-0.9.1/MPList.cc index 1d189fd..95a227f 100644 --- a/NServer-0.9.1/MPList.cc +++ b/NServer-0.9.1/MPList.cc @@ -1,10 +1,11 @@ #include "util.h" #include "MPList.h" -//#include -//#include +#include -using namespace std; +#include +#include +#include MPListEntry *MPList::postserver(const char *group) { @@ -13,7 +14,7 @@ MPListEntry *MPList::postserver(const char *group) int bm = -1, bmlen = 0, clen; for (i = 0; i < entries.size(); i++) { - clen = matchgroup(entries[i].postTo, group); + clen = matchgroup(entries[i].postTo.c_str(), group); if (clen > bmlen) { bm = i; bmlen = clen; @@ -31,7 +32,7 @@ MPListEntry *MPList::server(const char *group) int bm = -1, bmlen = 0, clen; for (i = 0; i < entries.size(); i++) { - clen = matchgroup(entries[i].read, group); + clen = matchgroup(entries[i].read.c_str(), group); if (clen > bmlen) { bm = i; bmlen = clen; @@ -42,30 +43,27 @@ MPListEntry *MPList::server(const char *group) return NULL; } -void MPListEntry::printParameters (ostream *pOut) +void MPListEntry::printParameters (std::ostream *pOut) { if (hostname[0] != '\0') { *pOut << "\tServer " << hostname << " " << servicename - << " {" << endl; + << " {" << std::endl; } else { - *pOut << "\tNoServer " << " {" << endl; + *pOut << "\tNoServer " << " {" << std::endl; } if (user[0] != '\0') { - *pOut << "\t\tUser " << user << endl; + *pOut << "\t\tUser " << user << std::endl; } if (passwd[0] != '\0') { - *pOut << "\t\tPassword " << passwd << endl; + *pOut << "\t\tPassword " << passwd << std::endl; } if (read[0] != '\0') { - *pOut << "\t\tRead "<< read << endl; + *pOut << "\t\tRead "<< read << std::endl; } if (postTo[0] != '\0') { - *pOut << "\t\tPostTo " << postTo << endl; + *pOut << "\t\tPostTo " << postTo << std::endl; } - if (bindFrom[0] != '\0') { - *pOut << "\t\tBindFrom " << bindFrom << endl; - } - *pOut << "\t\tGroupTimeout " << groupTimeout << endl; + *pOut << "\t\tGroupTimeout " << groupTimeout << std::endl; *pOut << "\t\tOptions"; if (flags & F_SETPOSTFLAG) { *pOut << " setpostflag"; @@ -79,7 +77,7 @@ void MPListEntry::printParameters (ostream *pOut) if (flags & F_SEMIOFFLINE) { *pOut << " semioffline"; } - *pOut << endl; + *pOut << std::endl; if (~nntpflags) { *pOut << "\t\tCommands"; if ((~nntpflags) & F_LIST_ACTIVE_WILDMAT) { @@ -103,15 +101,18 @@ void MPListEntry::printParameters (ostream *pOut) if ((~nntpflags) & F_POST) { *pOut << " not-post"; } - *pOut << endl; + *pOut << std::endl; } - *pOut << "\t\tRetries " << retries << endl; - *pOut << "\t}" << endl; + *pOut << "\t\tLimitGroupSize " << limitgroupsize << std::endl; + *pOut << "\t\tRetries " << retries << std::endl; + *pOut << "\t\tConnectBackoff " << connectBackoff << std::endl; + *pOut << "\t\tConnectTimeout " << connectTimeout << std::endl; + *pOut << "\t}" << std::endl; } void MPList::read(Lexer & lex) { - string tok, host, port; + std::string tok, host, port; tok = lex.getToken(); if (tok != "{") @@ -136,13 +137,13 @@ void MPList::read(Lexer & lex) void MPList::readServer(Lexer & lex, const char *host, const char *port) { - string tok, a1, a2, a3; + std::string tok, a1, a2, a3; int havePostTo = 0; MPListEntry cur; if (host) { - strcpy(cur.hostname, host); - strcpy(cur.servicename, port); + cur.hostname = host; + cur.servicename = port; } tok = lex.getToken(); @@ -152,44 +153,52 @@ void MPList::readServer(Lexer & lex, const char *host, const char *port) tok = lex.getToken(); if (tok == "Read") { a1 = lex.getToken(); - if (a1.length() >= sizeof(cur.read)) - throw SyntaxError(lex, - "group description too long", - ERROR_LOCATION); - strcpy(cur.read, a1.c_str()); + cur.read = a1; if (!havePostTo) { - if (a1.length() >= sizeof(cur.postTo)) - throw SyntaxError(lex, - "group description too long", - ERROR_LOCATION); - strcpy(cur.postTo, a1.c_str()); + cur.postTo = a1; } } else if (tok == "BindFrom") { a1 = lex.getToken(); - if (a1.length() >= sizeof(cur.bindFrom)) + struct addrinfo hints; + memset(&hints, 0, sizeof(hints)); + hints.ai_flags = AI_ADDRCONFIG | AI_PASSIVE | AI_NUMERICHOST; + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_TCP; + + struct addrinfo *res; + if (getaddrinfo(a1.c_str(), NULL, &hints, &res)) { throw SyntaxError(lex, - "BindFrom field is too long", + "unable to resolve BindFrom", ERROR_LOCATION); - strcpy(cur.bindFrom, a1.c_str()); + } + + memcpy(&cur.bindFrom, res->ai_addr, res->ai_addrlen); + freeaddrinfo(res); } else if (tok == "PostTo") { a1 = lex.getToken(); - if (a1.length() >= sizeof(cur.postTo)) - throw SyntaxError(lex, - "group description too long", - ERROR_LOCATION); - strcpy(cur.postTo, a1.c_str()); + cur.postTo = a1; } else if (tok == "GroupTimeout") { a1 = lex.getToken(); cur.groupTimeout = atoi(a1.c_str()); + } else if (tok == "LimitGroupSize") { + a1 = lex.getToken(); + cur.limitgroupsize = atoi(a1.c_str()); } else if (tok == "Retries") { a1 = lex.getToken(); cur.retries = atoi(a1.c_str()); + } else if (tok == "ConnectBackoff") { + a1 = lex.getToken(); + cur.connectBackoff = atoi(a1.c_str()); + } else if (tok == "ConnectTimeout") { + a1 = lex.getToken(); + cur.connectTimeout = atoi(a1.c_str()); } else if (tok == "User") { a1 = lex.getToken(); - strncpy(cur.user, a1.c_str(), 64); + cur.user = a1; } else if (tok == "Password") { a1 = lex.getToken(); - strncpy(cur.passwd, a1.c_str(), 64); + cur.passwd = a1; } else if (tok == "Options") { int flag; for (;;) { @@ -227,6 +236,15 @@ void MPList::readServer(Lexer & lex, const char *host, const char *port) } else if (a1 == "semioffline") { cur.flags |= MPListEntry::F_SEMIOFFLINE; + } else if(a1=="dontgenmsgid") { + cur.flags |= + MPListEntry::F_DONTGENMSGID; + } else if(a1=="ssl") { + cur.flags |= + MPListEntry::F_SSL; + } else if(a1=="starttls") { + cur.flags |= + MPListEntry::F_STARTTLS; } else { break; } @@ -273,11 +291,11 @@ void MPList::readServer(Lexer & lex, const char *host, const char *port) entries.push_back(cur); } -void MPList::printParameters (ostream *pOut) +void MPList::printParameters (std::ostream *pOut) { - vector::iterator begin, end; + std::vector::iterator begin, end; - *pOut << "NewsServerList {" << endl; + *pOut << "NewsServerList {" << std::endl; for (begin=entries.begin(), end=entries.end(); @@ -285,5 +303,13 @@ void MPList::printParameters (ostream *pOut) begin->printParameters (pOut); } - *pOut << "}" << endl; + *pOut << "}" << std::endl; } + +/* + * Local Variables: + * mode: c++ + * tab-width: 4 + * c-basic-offset: 4 + * End: + */ diff --git a/NServer-0.9.1/MPList.h b/NServer-0.9.1/MPList.h index befb0c7..1ea11db 100644 --- a/NServer-0.9.1/MPList.h +++ b/NServer-0.9.1/MPList.h @@ -4,9 +4,11 @@ #include #include #include +#include +#include #include -#include +#include #include #include "Debug.h" @@ -15,12 +17,15 @@ #include "Lexer.h" struct MPListEntry { - public: + public: enum { F_SETPOSTFLAG = 0x01, F_CACHED = 0x02, F_OFFLINE = 0x04, - F_SEMIOFFLINE = 0x08 + F_SEMIOFFLINE = 0x08, + F_DONTGENMSGID = 0x10, + F_SSL = 0x20, + F_STARTTLS = 0x40 }; // nntp commands supported by the server enum { @@ -33,21 +38,26 @@ struct MPListEntry { F_POST = 0x40 }; - char hostname[MAXHOSTNAMELEN]; - char servicename[256]; - char user[64]; - char passwd[64]; + std::string hostname; + std::string servicename; + std::string user; + std::string passwd; OverviewFmt overview; - char read[2048]; // Groups read from that server - char postTo[2048]; // Postings handled by this server - char bindFrom[2048]; // From which interface - time_t groupTimeout; + std::string read; // Groups read from that server + std::string postTo; // Postings handled by this server + struct sockaddr_storage bindFrom; // From which interface + unsigned int groupTimeout; unsigned int flags; // configuration flags unsigned int nntpflags; // supported NNTP-Commands - int retries; + unsigned int limitgroupsize; // limit the size of a group + unsigned int retries; + unsigned int connectBackoff; + unsigned int connectTimeout; + + mutable time_t connectFailed; MPListEntry(); void init(void); @@ -61,16 +71,16 @@ struct MPListEntry { * \bug Documentation is missing. */ class MPList { - public: + public: std::vector < MPListEntry > entries; - private: + private: - public: + public: MPList() {}; // void addserver(const char *ns,const char *p,const char *g) {// if(e_used==e_alloc) myrealloc(e_used+1);// entries[e_used].init(ns,p);// if(g) {// strcpy(entries[e_used].read,g);// strcpy(entries[e_used].postTo,g);// }// e_used++;// } - const char *makeFilter(unsigned int servernbr, - const char *listarg) const; + std::string makeFilter(unsigned int servernbr, + const char *listarg) const; MPListEntry *server(const char *group); MPListEntry *postserver(const char *group); void init(void); @@ -88,76 +98,82 @@ inline MPListEntry::MPListEntry () { inline void MPListEntry::init(void) { - hostname[0] = servicename[0] = '\0'; - user[0] = passwd[0] = '\0'; - - read[0] = postTo[0] = bindFrom[0] = '\0'; + bindFrom.ss_family = AF_UNSPEC; groupTimeout = 600; // 10m + limitgroupsize = 0; retries = 3; + connectBackoff = 0; + connectTimeout = 0; + connectFailed = 0; + flags = F_SETPOSTFLAG | F_CACHED; nntpflags = 0xffffffff; } -inline const char *MPList::makeFilter(unsigned int servernbr, const char *listarg) const +inline std::string MPList::makeFilter(unsigned int servernbr, const char *listarg) const { - static string filter; - char c; - unsigned int i; + std::string filter; if (strcmp(listarg, "*") == 0) { - const char *p, *q; filter = entries[servernbr].read; - for (i = 0; i < entries.size(); i++) { + for (unsigned int i = 0; i < entries.size(); i++) { if (i != servernbr) { - p = entries[i].read; + std::string::const_iterator p = entries[i].read.begin(); + const std::string::const_iterator end = entries[i].read.end(); + std::string::const_iterator q; for (;;) { q = p; - while ((c = *p) != ',' && c) - p++; + char c; + while (p != end && (c = *p) != ',') + ++p; filter += ",!"; - filter.append(q, p - q); - if (!c) + filter.append(q, p); + if (p == end) break; - p++; + ++p; } } } } else { - const char *listp, *p = NULL, *q = NULL; + unsigned int i; filter = "*"; if (servernbr == 0) i = 1; else i = 0; - listp = listarg; - c = '\0'; + const char *listp = listarg; + char c = '\0'; + std::string::const_iterator p, q; + std::string::const_iterator end; while (i < entries.size()) { if (!c) { - q = p = entries[i].read; + q = p = entries[i].read.begin(); + end = entries[i].read.end(); } - while ((c = *listp) && c == *p) { + while ((c = *listp) && p != end && c == *p) { listp++; - p++; + ++p; } if (*listp == '*') { // p is matched by listarg - ASSERT(if (*p == '*') { + ASSERT(if (p != end && *p == '*') { slog. p(Logger:: Error) << "Same newsgroup expression configured for two different servers!\n";} ); filter += ",!"; - while ((c = *p) != ',' && c) - p++; - filter.append(q, p - q); + while (p != end && (c = *p) != ',') + ++p; + filter.append(q, p); } else { // p is not matched by listarg - while ((c = *p) != ',' && c) - p++; + while (p != end && (c = *p) != ',') + ++p; } - if (!c) { + if (p == end) { + c = '\0'; i++; if (servernbr == i) i++; @@ -167,7 +183,7 @@ inline const char *MPList::makeFilter(unsigned int servernbr, const char *listar } } - return filter.c_str(); + return filter; } inline void MPList::init(void) @@ -176,3 +192,11 @@ inline void MPList::init(void) } #endif + +/* + * Local Variables: + * mode: c++ + * tab-width: 4 + * c-basic-offset: 4 + * End: + */ diff --git a/NServer-0.9.1/Makefile.am b/NServer-0.9.1/Makefile.am index 7eeced5..fe69e16 100644 --- a/NServer-0.9.1/Makefile.am +++ b/NServer-0.9.1/Makefile.am @@ -39,8 +39,8 @@ libnserver_a_SOURCES = ActiveDB.cc\ RNewsgroup.cc\ RNewsgroup.h\ VirtualIterator.h\ - sstream.cc\ - sstream.h\ + sockstream.cc\ + sockstream.h\ util.cc\ util.h\ readline.cc\ diff --git a/NServer-0.9.1/NSError.h b/NServer-0.9.1/NSError.h index e7c7bbe..bc9920f 100644 --- a/NServer-0.9.1/NSError.h +++ b/NServer-0.9.1/NSError.h @@ -27,20 +27,23 @@ * \bug Documentation is missing. */ class NSError:public Error { - public: + public: NSError(const char *txt = "unknown"):Error(txt) { - } NSError(const char *txt, const char *file, const char *function, - int line):Error(txt, file, function, line) { } - NSError(const string & txt):Error(txt) { + NSError(const char *txt, const char *file, const char *function, + int line) + : Error(txt, file, function, line) { } - NSError(const string & txt, const char *file, const char *function, - int line):Error(txt, file, function, line) { + NSError(const std::string & txt):Error(txt) { + } + NSError(const std::string & txt, const char *file, const char *function, + int line) + : Error(txt, file, function, line) { } virtual ~ NSError() { } - virtual void print() { + virtual void print() const { slog << "Exception! " << " Type: NServer" << " File: " << _file @@ -56,23 +59,25 @@ class NSError:public Error { * \bug Documentation is missing. */ class NoSuchFieldError:public NSError { - public: - NoSuchFieldError(const char *txt):NSError(txt) { - } NoSuchFieldError(const char *txt, const char *file, - const char *function, int line):NSError(txt, - file, - function, - line) { - } - NoSuchFieldError(const string & txt):NSError(txt) { - } - NoSuchFieldError(const string & txt, const char *file, - const char *function, int line):NSError(txt, file, - function, - line) { - } + public: + NoSuchFieldError(const char *txt):NSError(txt) + { } + + NoSuchFieldError(const char *txt, const char *file, + const char *function, int line) + : NSError(txt, file, function, line) + { } - virtual void print() { + NoSuchFieldError(const std::string & txt) + : NSError(txt) + { } + + NoSuchFieldError(const std::string & txt, const char *file, + const char *function, int line) + : NSError(txt, file, function, line) + { } + + virtual void print() const { slog << "Exception!" << " Type: NotFound" << " File: " << _file @@ -88,24 +93,26 @@ class NoSuchFieldError:public NSError { * \bug Documentation is missing. */ class NoNewsServerError:public NSError { - public: - NoNewsServerError(const char *txt = "unknown"):NSError(txt) { - } NoNewsServerError(const char *txt, const char *file, - const char *function, int line):NSError(txt, - file, - function, - line) { - } - NoNewsServerError(const string & txt):NSError(txt) { - } - NoNewsServerError(const string & txt, const char *file, - const char *function, int line):NSError(txt, - file, - function, - line) { - } + public: + NoNewsServerError(const char *txt = "unknown") + : NSError(txt) + { } - virtual void print() { + NoNewsServerError(const char *txt, const char *file, + const char *function, int line) + : NSError(txt, file, function, line) + { } + + NoNewsServerError(const std::string & txt) + : NSError(txt) + { } + + NoNewsServerError(const std::string & txt, const char *file, + const char *function, int line) + : NSError(txt, file, function, line) + { } + + virtual void print() const { slog << "Exception!" << " Type: NoNewsServer" << " File: " << _file @@ -121,23 +128,24 @@ class NoNewsServerError:public NSError { * \bug Documentation is missing. */ class NoSuchGroupError:public NSError { - public: - NoSuchGroupError(const char *txt = "unknown"):NSError(txt) { - } NoSuchGroupError(const char *txt, const char *file, - const char *function, int line):NSError(txt, - file, - function, - line) { - } - NoSuchGroupError(const string & txt):NSError(txt) { - } - NoSuchGroupError(const string & txt, const char *file, - const char *function, int line):NSError(txt, file, - function, - line) { - } + public: + NoSuchGroupError(const char *txt = "unknown") + : NSError(txt) { } + + NoSuchGroupError(const char *txt, const char *file, + const char *function, int line) + : NSError(txt, file, function, line) + { } + + NoSuchGroupError(const std::string & txt) + : NSError(txt) + { } + NoSuchGroupError(const std::string & txt, const char *file, + const char *function, int line) + : NSError(txt, file, function, line) + { } - virtual void print() { + virtual void print() const { slog << "Exception!" << " Type: NoSuchGroup" << " File: " << _file @@ -153,24 +161,27 @@ class NoSuchGroupError:public NSError { * \bug Documentation is missing. */ class DuplicateArticleError:public NSError { - public: - DuplicateArticleError(const char *txt = "unknown"):NSError(txt) { - } DuplicateArticleError(const char *txt, const char *file, - const char *function, - int line):NSError(txt, file, function, - line) { - } - DuplicateArticleError(const string & txt):NSError(txt) { - } - DuplicateArticleError(const string & txt, const char *file, - const char *function, int line):NSError(txt, - file, - function, - line) - { - } + public: + DuplicateArticleError(const char *txt = "unknown") + : NSError(txt) + { } + + DuplicateArticleError(const char *txt, const char *file, + const char *function, + int line) + : NSError(txt, file, function, line) + { } + + DuplicateArticleError(const std::string & txt) + : NSError(txt) + { } - virtual void print() { + DuplicateArticleError(const std::string & txt, const char *file, + const char *function, int line) + : NSError(txt, file, function, line) + { } + + virtual void print() const { slog << "Exception!" << " Type: DuplicateArticle" << " File: " << _file @@ -186,25 +197,27 @@ class DuplicateArticleError:public NSError { * \bug Documentation is missing. */ class NoSuchArticleError:public NSError { - public: - NoSuchArticleError(const char *txt = "unknown"):NSError(txt) { - } NoSuchArticleError(const char *txt, const char *file, - const char *function, int line):NSError(txt, - file, - function, - line) - { - } - NoSuchArticleError(const string & txt):NSError(txt) { - } - NoSuchArticleError(const string & txt, const char *file, + public: + NoSuchArticleError(const char *txt = "unknown") + : NSError(txt) + { } + + NoSuchArticleError(const char *txt, const char *file, + const char *function, int line) + : NSError(txt, file, function, line) + { } + + NoSuchArticleError(const std::string & txt) + : NSError(txt) + { } + NoSuchArticleError(const std::string & txt, const char *file, const char *function, int line):NSError(txt, file, function, line) { } - virtual void print() { + virtual void print() const { slog << "Exception!" << " Type: NoSuchArticle" << " File: " << _file @@ -220,25 +233,26 @@ class NoSuchArticleError:public NSError { * \bug Documentation is missing. */ class PostingFailedError:public NSError { - public: - PostingFailedError(const char *txt = "unknown"):NSError(txt) { - } PostingFailedError(const char *txt, const char *file, - const char *function, int line):NSError(txt, - file, - function, - line) - { - } - PostingFailedError(const string & txt):NSError(txt) { - } - PostingFailedError(const string & txt, const char *file, - const char *function, int line):NSError(txt, - file, - function, - line) { - } + public: + PostingFailedError(const char *txt = "unknown") + : NSError(txt) + { } + + PostingFailedError(const char *txt, const char *file, + const char *function, int line) + : NSError(txt, file, function, line) + { } + + PostingFailedError(const std::string & txt) + : NSError(txt) + { } - virtual void print() { + PostingFailedError(const std::string & txt, const char *file, + const char *function, int line) + : NSError(txt, file, function, line) + { } + + virtual void print() const { slog << "Exception!" << " Type: PostingFailedError" << " File: " << _file @@ -248,23 +262,25 @@ class PostingFailedError:public NSError { }; class NotAllowedError:public NSError { - public: + public: NotAllowedError(const char *txt = "unknown"):NSError(txt) { - } NotAllowedError(const char *txt, const char *file, - const char *function, int line):NSError(txt, - file, - function, - line) { - } - NotAllowedError(const string & txt):NSError(txt) { - } - NotAllowedError(const string & txt, const char *file, - const char *function, int line):NSError(txt, file, - function, - line) { } - virtual void print() { + NotAllowedError(const char *txt, const char *file, + const char *function, int line) + : NSError(txt, file, function, line) + { } + + NotAllowedError(const std::string & txt) + : NSError(txt) + { } + + NotAllowedError(const std::string & txt, const char *file, + const char *function, int line) + : NSError(txt, file, function, line) + { } + + virtual void print() const { slog << "Exception!" << " Type: NoSuchArticle" << " File: " << _file @@ -280,22 +296,25 @@ class NotAllowedError:public NSError { * \bug Documentation is missing. */ class UsageError:public NSError { - public: - UsageError(const char *txt = "unknown"):NSError(txt) { - } UsageError(const char *txt, const char *file, - const char *function, int line):NSError(txt, file, - function, - line) { - } - UsageError(const string & txt):NSError(txt) { - } - UsageError(const string & txt, const char *file, - const char *function, int line):NSError(txt, file, - function, - line) { - } + public: + UsageError(const char *txt = "unknown"):NSError(txt) + { } + + UsageError(const char *txt, const char *file, + const char *function, int line) + : NSError(txt, file, function, line) + { } + + UsageError(const std::string & txt) + : NSError(txt) + { } - virtual void print() { + UsageError(const std::string & txt, const char *file, + const char *function, int line) + : NSError(txt, file, function, line) + { } + + virtual void print() const { slog << "Exception!" << " Type: Usage" << " File: " << _file @@ -312,32 +331,39 @@ typedef UsageError UsageErr; * \bug Documentation is missing. */ class ResponseError:public NSError { - public: - string _command; - string _expected; - string _got; - - ResponseError() { - } ResponseError(const char *command, const char *exp, - const char *got) - :_command(command), _expected(exp), _got(got) { + public: + std::string _command; + std::string _expected; + std::string _got; + + ResponseError() + { } + + ResponseError(const char *command, const char *exp, + const char *got) + : _command(command), _expected(exp), _got(got) + { slog.p(Logger::Error); ResponseError::print(); } + ResponseError(const char *command, const char *exp, - const string & got) - :_command(command), _expected(exp), _got(got) { + const std::string & got) + : _command(command), _expected(exp), _got(got) + { slog.p(Logger::Error); ResponseError::print(); } - ResponseError(const string & command, const string & exp, - const string & got) - :_command(command), _expected(exp), _got(got) { + + ResponseError(const std::string & command, const std::string & exp, + const std::string & got) + : _command(command), _expected(exp), _got(got) + { slog.p(Logger::Error); ResponseError::print(); } - virtual void print() { + virtual void print() const { slog << "Exception!" << " Type: Response" << " File: " << _file @@ -350,3 +376,11 @@ class ResponseError:public NSError { typedef ResponseError ResponseErr; #endif + +/* + * Local Variables: + * mode: c++ + * tab-width: 4 + * c-basic-offset: 4 + * End: + */ diff --git a/NServer-0.9.1/NServer.cc b/NServer-0.9.1/NServer.cc index 1436857..1ffeaee 100644 --- a/NServer-0.9.1/NServer.cc +++ b/NServer-0.9.1/NServer.cc @@ -226,8 +226,9 @@ void RServer::init(MPList * serverlist) sleep(1); \ continue; \ } \ - sprintf(buf,"Connection to %s:%s failed", \ - _CurrentServer->hostname,_CurrentServer->servicename); \ + snprintf(buf, sizeof(buf), "Connection to %s:%s failed",\ + _CurrentServer->hostname.c_str(),\ + _CurrentServer->servicename.c_str()); \ throw SystemError(buf,errno, ERROR_LOCATION); \ } void RServer::connect() @@ -236,47 +237,41 @@ void RServer::connect() if (is_connected()) return; + const time_t now = time(NULL); + if (now < + _CurrentServer->connectFailed + _CurrentServer->connectBackoff) { + throw SystemError("RServer::connect: no connection to news server"); + } + string grt, resp; char buf[1024]; - int i = _CurrentServer->retries; - _pServerStream = new sstream; + unsigned int i = _CurrentServer->retries; + _pServerStream = new sockstream(_CurrentServer->flags & MPListEntry::F_SSL); for (;;) { - // Open connection - if (strcmp(_CurrentServer->bindFrom, "") == 0) { - slog. - p(Logger:: - Debug) << "RServer::connect: Connecting to " - << _CurrentServer-> - hostname << - " from DEFAULT interface to servicename " << - _CurrentServer->servicename << "\n"; - _pServerStream->connectTo(_CurrentServer->hostname, - _CurrentServer-> - servicename); - } else { - slog. - p(Logger:: - Debug) << "RServer::connect: Connecting to " - << _CurrentServer-> - hostname << " from interface " << - _CurrentServer-> - bindFrom << " to servicename " << - _CurrentServer->servicename << "\n"; - _pServerStream->connectTo(_CurrentServer->hostname, - _CurrentServer-> - servicename, - _CurrentServer-> - bindFrom); - } + slog.p(Logger::Debug) << "RServer::connect: Connecting to " << + _CurrentServer->hostname << " to servicename " << + _CurrentServer->servicename << "\n"; + + const struct sockaddr *bindFrom = + (_CurrentServer->bindFrom.ss_family == AF_UNSPEC) ? + NULL : (const struct sockaddr *) &_CurrentServer->bindFrom; + + _pServerStream->connect(_CurrentServer->hostname.c_str(), + _CurrentServer->servicename.c_str(), + bindFrom, + sizeof(_CurrentServer->bindFrom), + _CurrentServer->connectTimeout); if (!_pServerStream->good()) { delete _pServerStream; _pServerStream = NULL; + _CurrentServer->connectFailed = time(NULL); throw SystemError ("RServer::connect: cannot connect to news server", errno, ERROR_LOCATION); } + _pServerStream->setnodelay(); _pServerStream->unsetf(ios::skipws); //FIXME! repl nlreadline by nntpreadline that transparently @@ -296,26 +291,10 @@ void RServer::connect() string c("_connect_"), e("20[01]"); delete _pServerStream; _pServerStream = NULL; + _CurrentServer->connectFailed = time(NULL); throw ResponseError(c, e, grt); } - if (_CurrentServer->user[0]) { - sprintf(buf, "authinfo user %s\r\n", - _CurrentServer->user); - resp = issue(buf, NULL); - if (resp[0] == '3') { - sprintf(buf, "authinfo pass %s\r\n", - _CurrentServer->passwd); - resp = issue(buf, NULL); - } - if (resp[0] != '2') { - string c("_authenticate_"), e("[23].."); - delete _pServerStream; - _pServerStream = NULL; - throw ResponseError(c, e, resp); - } - } - if (_CurrentServer->nntpflags & MPListEntry::F_MODE_READER) { // mode reader resp = issue("mode reader\r\n", NULL); @@ -336,6 +315,43 @@ void RServer::connect() _CurrentServer->nntpflags &= ~MPListEntry::F_POST; } +#if defined(HAVE_GNUTLS) + if (_CurrentServer->flags & MPListEntry::F_STARTTLS) { + // starttls + resp = issue("starttls\r\n", NULL); + RSERVER_CONNECT_CHECK_CONNECTION + ("Cannot read data from %s:%s"); + if (resp[0] != '3' || resp[1] != '8' || resp[2] != '2') { + slog.p(Logger::Warning) << "starttls failed, ignored\n"; + _CurrentServer->flags &= ~MPListEntry::F_STARTTLS; + } else { + if (sockstream *sslStream = _pServerStream->starttls()) + { + delete _pServerStream; + _pServerStream = sslStream; + } + } + } +#endif + + if (_CurrentServer->user[0]) { + snprintf(buf, sizeof(buf), "authinfo user %s\r\n", + _CurrentServer->user.c_str()); + resp = issue(buf, NULL); + if (resp[0] == '3') { + snprintf(buf, sizeof(buf), "authinfo pass %s\r\n", + _CurrentServer->passwd.c_str()); + resp = issue(buf, NULL); + } + if (resp[0] != '2') { + string c("_authenticate_"), e("[23].."); + delete _pServerStream; + _pServerStream = NULL; + _CurrentServer->connectFailed = time(NULL); + throw ResponseError(c, e, resp); + } + } + if (_CurrentServer-> nntpflags & MPListEntry::F_LIST_OVERVIEW_FMT) { resp = issue("list overview.fmt\r\n", "215"); @@ -364,6 +380,7 @@ void RServer::connect() if (_CurrentGroup.name()[0] != '\0') { selectgroup(_CurrentGroup.name(), 1); } + _CurrentServer->connectFailed = 0; return; } } @@ -512,7 +529,7 @@ void RServer::selectgroup(const char *name, int force) } setserver(mpe); - sprintf(buf, "group %s\r\n", name); + snprintf(buf, sizeof(buf), "group %s\r\n", name); resp = issue(buf, NULL); p = resp.c_str(); @@ -551,6 +568,14 @@ void RServer::selectgroup(const char *name, int force) _ActiveDB->get(name, &_CurrentGroup); // If the above call fails, _ActiveDB will be updated with a // probably inconsistent posting flag ('y') + + if (mpe->limitgroupsize) { + if (lst - fst + 1 > mpe->limitgroupsize) { + fst = lst - mpe->limitgroupsize + 1; + nbr = mpe->limitgroupsize; + } + } + _CurrentGroup.set(name, fst, lst, nbr); _ActiveDB->set(_CurrentGroup); } @@ -577,7 +602,6 @@ ActiveDB *RServer::active() VERB(slog.p(Logger::Debug) << "RServer::active()\n"); unsigned int i, flags; char cgroup[MAXGROUPNAMELEN + 1], *cgp, buf[1024]; - const char *sp; char c; ASSERT(if (!_ServerList) { @@ -610,26 +634,29 @@ ActiveDB *RServer::active() nntpflags & MPListEntry:: F_LIST_ACTIVE_WILDMAT) { try { - sp = _CurrentServer->read; + std::string::const_iterator sp = + _CurrentServer->read.begin(); + const std::string::const_iterator end = + _CurrentServer->read.end(); do { // Extract a newsgroup-expression cgp = cgroup; - while ((c = *sp++) != ',' - && c) + while (sp != end && + (c = *sp++) != ',') *cgp++ = c; *cgp = '\0'; - sprintf(buf, - "list active %s\r\n", - cgroup); + snprintf(buf, sizeof(buf), + "list active %s\r\n", + cgroup); issue(buf, "215"); // read active database and filter unwanted groups _ActiveDB-> read(*_pServerStream, _ServerList-> makeFilter(i, - cgroup), + cgroup).c_str(), flags); - } while (c); + } while (sp != end); } catch(ResponseError & re) { slog.p(Logger::Notice) @@ -651,7 +678,7 @@ ActiveDB *RServer::active() issue("list active\r\n", "215"); _ActiveDB->read(*_pServerStream, _ServerList->makeFilter(i, - "*"), + "*").c_str(), flags); } } @@ -726,24 +753,31 @@ void RServer::listgroup(const char *gname, char *lstgrp, string resp, line; selectgroup(gname); - resp = issue("listgroup\r\n", NULL); - p = resp.c_str(); - if (!NNTP_ISCODE(p, "211")) { - string c("listgroup\r\n"), e("211"); - throw ResponseError(c, e, resp); - } + if (_CurrentServer->nntpflags & MPListEntry::F_LISTGROUP) { + resp = issue("listgroup\r\n", NULL); + p = resp.c_str(); + if (!NNTP_ISCODE(p, "211")) { + _CurrentServer->nntpflags &= ~MPListEntry::F_LISTGROUP; + string c("listgroup\r\n"), e("211"); + throw ResponseError(c, e, resp); + } - for (;;) { - nlreadline(*_pServerStream, line); - if (line == ".\r\n") - break; - if (!_pServerStream->good()) - throw - SystemError("error while reading from server", - errno, ERROR_LOCATION); - i = atoi(line.data()); - if (f <= i && i <= l) + for (;;) { + nlreadline(*_pServerStream, line); + if (line == ".\r\n") + break; + if (!_pServerStream->good()) + throw + SystemError("error while reading from server", + errno, ERROR_LOCATION); + i = atoi(line.data()); + if (f <= i && i <= l) + lstgrp[i - f] = 1; + } + } else { + for (i = f; i <= l; i++) { lstgrp[i - f] = 1; + } } } @@ -779,7 +813,7 @@ void RServer::overviewdb(Newsgroup * ng, unsigned int fst, ERROR_LOCATION); } - sprintf(buf, fmt, fst, lst); + snprintf(buf, sizeof(buf), fmt, fst, lst); resp = issue(buf, NULL); p = resp.c_str(); if (NNTP_ISCODE(p, "224")) { @@ -815,7 +849,7 @@ void RServer::article(const char *gname, unsigned int nbr, Article * art) selectgroup(gname); - sprintf(buf, "article %u\r\n", nbr); + snprintf(buf, sizeof(buf), "article %u\r\n", nbr); resp = issue(buf, NULL); p = resp.c_str(); if (strncmp(p, "220", 3) != 0) { @@ -838,7 +872,7 @@ void RServer::article(const char *id, Article * art) const char *p; string resp; - sprintf(buf, "article %s\r\n", id); + snprintf(buf, sizeof(buf), "article %s\r\n", id); if (_CurrentServer) { resp = issue(buf, NULL); p = resp.c_str(); @@ -853,7 +887,7 @@ void RServer::article(const char *id, Article * art) if (strncmp(p, "430", 3) != 0) { slog.p(Logger::Notice) << - "illegal response code to > request\n" + "illegal response code to
> request\n" << p; } } @@ -877,7 +911,7 @@ void RServer::article(const char *id, Article * art) if (strncmp(p, "430", 3) != 0) { slog.p(Logger::Notice) << - "illegal response code to > request\n" + "illegal response code to
> request\n" << p; } } @@ -903,17 +937,27 @@ void RServer::post(MPListEntry * srvr, Article * article) try { resp = article->getfield("message-id:"); - sprintf(buf, "stat %s\r\n", resp.c_str()); + snprintf(buf, sizeof(buf), "stat %s\r\n", resp.c_str()); resp = issue(buf, NULL); p = resp.c_str(); - if (strncmp(p, "223", 3) == 0) + if (strncmp(p, "223", 3) == 0) { throw DuplicateArticleError("Response 223", ERROR_LOCATION); - else - if (strncmp(p, "430", 3) != 0) { - string c(buf), e("223|430"); - throw ResponseError(c, e, resp); - } + } else if (strncmp(p, "430", 3) != 0) { + if (strncmp(p, "423", 3) == 0) { + // some broken newsservers (like + // groups.gandi.net) appear to return + // 423 instead of 430 - log it and + // carry on + slog.p(Logger::Notice) + << + "illegal response code to > request\n" + << p; + } else { + string c(buf), e("223|430"); + throw ResponseError(c, e, resp); + } + } } catch(NoSuchFieldError e) { VERB(slog. @@ -1001,38 +1045,16 @@ int RServer::post(Article * article) MPListEntry **mpe; MPListEntry *c; int sc = 0, i; + bool needmsgid = false; //FIXME! We should use the path field here, or introduce a //FIXME! new field that shows the cache-posting-chain if (nntp_posting_host[0]) { - sprintf(buf, "X-NNTP-Posting-Host: %s\r\n", - nntp_posting_host); + snprintf(buf, sizeof(buf), "X-NNTP-Posting-Host: %s\r\n", + nntp_posting_host); article->setfield("X-NNTP-Posting-Host:", buf); } - if (!article->has_field("message-id:")) { - struct timeval tv; - int j; - char mid[768]; - char *p; - p = mid; - gettimeofday(&tv, NULL); - TOBASE36(i, tv.tv_sec, p); - *p++ = '$'; - - j = getpid(); - TOBASE36(i, j, p); - *p++ = '$'; - - TOBASE36(i, pc, p); - *p++ = '@'; - strcpy(p, nntp_hostname); - pc++; - - sprintf(msgid, "Message-ID: \r\n", mid); - article->setfield("Message-ID:", msgid); - } - if ((mpe = (MPListEntry **) malloc(_ServerList->entries.size() * sizeof(MPListEntry *))) == NULL) { @@ -1055,6 +1077,7 @@ int RServer::post(Article * article) while (i < sc && c != mpe[i]) i++; if (i == sc) { + needmsgid |= !(c->flags & MPListEntry::F_DONTGENMSGID); mpe[sc] = c; sc++; } @@ -1069,12 +1092,39 @@ int RServer::post(Article * article) if (!sc) { slog.p(Logger::Info) << "no news server configured for " - << msgid << "\n"; + << newsgroups << "\n"; free(mpe); throw InvalidArticleError("no valid newsgroup", ERROR_LOCATION); } + // we need a msg-id if posting to more than one server to avoid + // duplicates + needmsgid |= (sc > 1); + if (needmsgid && !article->has_field("message-id:")) { + struct timeval tv; + int j; + char mid[768]; + char *p; + p = mid; + gettimeofday(&tv, NULL); + TOBASE36(i, tv.tv_sec, p); + *p++ = '$'; + + j = getpid(); + TOBASE36(i, j, p); + *p++ = '$'; + + TOBASE36(i, pc, p); + *p++ = '@'; + strcpy(p, nntp_hostname); + pc++; + + snprintf(msgid, sizeof(msgid), + "Message-ID: \r\n", mid); + article->setfield("Message-ID:", msgid); + } + int posts = 0, spool = 0, err = 0; i = 0; // Error classification: @@ -1158,7 +1208,7 @@ CServer::CServer(const char *spooldir, MPList * serverlist) _OverviewFormat = new OverviewFmt; } if (!_ActiveDB) { - sprintf(buf, "%s/.active", spooldir); + snprintf(buf, sizeof(buf), "%s/.active", spooldir); _ActiveDB = _NVActiveDB = new NVActiveDB(buf); } @@ -1197,6 +1247,60 @@ CServer::~CServer() } } +void CServer::filter_xref(Article *art, MPListEntry *server, const char *gname) +{ + static const char delim[] = " \t\r\n"; + + bool xref_changed = false; + std::string xref = art->getfield("xref:", 1); + + std::string::size_type beg_header = + xref.find_first_not_of(delim, 5); + std::string::size_type end_entry = + xref.find_first_of(delim, beg_header); + while (end_entry != std::string::npos) { + const std::string::size_type end_old = end_entry; + const std::string::size_type beg_entry = + xref.find_first_not_of(delim, end_old); + + if (beg_entry != std::string::npos) { + const std::string::size_type colon = + xref.find_first_of(": \t\r\n", beg_entry); + if ((colon != std::string::npos) && + (xref[colon] == ':')) { + end_entry = xref.find_first_of(delim, colon); + const std::string group = + xref.substr(beg_entry, + colon - beg_entry); + + // check that the group is configured + // for the specified server + if ((gname == NULL) || (group != gname)) { + if (_ServerList->server(group.c_str()) != server) { + // we have to remove + // this Xref entry + xref_changed = true; + + if (end_entry != std::string::npos) { + xref.erase(end_old, end_entry - end_old); + end_entry = end_old; + } else { + xref.erase(end_old); + } + } + } + } else { + end_entry = std::string::npos; + } + } + } + + if (xref_changed) { + xref.append("\r\n"); + art->setfield("Xref:", xref.c_str()); + } +} + ActiveDB *CServer::active() { // The validity of the active database has to be tested twice, @@ -1339,7 +1443,7 @@ int CServer::post(Article * article) gettimeofday(&tv, NULL); - sprintf(fn, "%s/.headerlog", _SpoolDirectory); + ssprintf(fn, sizeof(fn), "%s/.headerlog", _SpoolDirectory); fs.open(fn, ios::app); fs << getpid() << " " << tv.tv_sec << endl; article->write(fs, Article::Head); @@ -1478,6 +1582,7 @@ void CServer::article(const char *gname, unsigned int nbr, Article * art) ERROR_LOCATION); RServer::article(gname, nbr, art); + filter_xref(art, mpe, gname); } void CServer::article(const char *id, Article * art) @@ -1487,7 +1592,10 @@ void CServer::article(const char *id, Article * art) const char *p; string resp; - sprintf(buf, "article %s\r\n", id); + const char * const gname = + (_CurrentGroup.name()[0] != '\0') ? _CurrentGroup.name() : NULL; + + snprintf(buf, sizeof(buf), "article %s\r\n", id); if (_CurrentServer && !(_CurrentServer->flags & MPListEntry::F_OFFLINE)) { resp = issue(buf, NULL); @@ -1495,6 +1603,7 @@ void CServer::article(const char *id, Article * art) if (strncmp(p, "220", 3) == 0) { art->read(*_pServerStream); art->setnbr(-1); + filter_xref(art, gname ? _CurrentServer : NULL, gname); return; } // 412 cannot happen since we specified the article id @@ -1503,7 +1612,7 @@ void CServer::article(const char *id, Article * art) if (strncmp(p, "430", 3) != 0) { slog.p(Logger::Notice) << - "illegal response code to > request\n" + "illegal response code to
> request\n" << p; } } @@ -1522,14 +1631,23 @@ void CServer::article(const char *id, Article * art) if (strncmp(p, "220", 3) == 0) { art->read(*_pServerStream); art->setnbr(-1); + filter_xref(art, NULL); return; } if (strncmp(p, "430", 3) != 0) { slog.p(Logger::Notice) << - "illegal response code to > request\n" + "illegal response code to
> request\n" << p; } } throw NoSuchArticleError(resp, ERROR_LOCATION); } + +/* + * Local Variables: + * mode: c++ + * tab-width: 4 + * c-basic-offset: 4 + * End: + */ diff --git a/NServer-0.9.1/NServer.h b/NServer-0.9.1/NServer.h index b24f607..8ff4a0f 100644 --- a/NServer-0.9.1/NServer.h +++ b/NServer-0.9.1/NServer.h @@ -39,7 +39,7 @@ class CServer; #include "config.h" #include "Debug.h" -#include "sstream.h" +#include "sockstream.h" #include "util.h" #include "OverviewFmt.h" @@ -72,28 +72,23 @@ extern char nntp_posting_host[MAXHOSTNAMELEN]; * \li err-err_dup-err_perm-err_failed => Internal errors */ class PostResult { - public: + public: MPListEntry ** server; int *error; int nservers; - PostResult(int sz):server(NULL), errors(NULL), nserver(0) { - if ((server = - (MPListEntry **) malloc(sz * - sizeof(MPListEntry *))) == - NULL) { - throw - SystemError - ("cannot allocate buffer for post servers", - errno, ERROR_LOCATION); + PostResult(int sz):server(NULL), errors(NULL), nserver(0) { + if ((server = (MPListEntry **) malloc(sz * sizeof(MPListEntry *))) == + NULL) + { + throw SystemError("cannot allocate buffer for post servers", + errno, ERROR_LOCATION); } if ((error = (int *) malloc(sz * sizeof(int))) == NULL) { free(server); server = NULL; - throw - SystemError - ("cannot allocate buffer for result list", - errno, ERROR_LOCATION); + throw SystemError("cannot allocate buffer for result list", + errno, ERROR_LOCATION); } } @@ -113,21 +108,23 @@ class PostResult { * \author Thomas Gschwind */ class NServer { - protected: + protected: OverviewFmt * _OverviewFormat; ActiveDB *_ActiveDB; - NServer(); + NServer(); /** * Free allocated data. Virtual because it is possible, that * a news server instance is destructed via the abstract * parent class. */ - virtual ~ NServer(); - public: - virtual OverviewFmt * overviewfmt() { + virtual ~ NServer(); + + public: + virtual OverviewFmt * overviewfmt() { return _OverviewFormat; - } virtual ActiveDB *active() = 0; + } + virtual ActiveDB *active() = 0; virtual GroupInfo *groupinfo(const char *name) = 0; virtual Newsgroup *getgroup(const char *name) = 0; @@ -143,15 +140,18 @@ class NServer { * \brief Provides an interface to access news locally */ class LServer:virtual public NServer { - protected: + protected: char _SpoolDirectory[MAXPATHLEN]; ArtSpooler *pSpool; - LServer():NServer(), pSpool(0) { + LServer() + : NServer(), pSpool(0) + { _SpoolDirectory[0] = '\0'; - } void init(const char *spooldir); + } + void init(const char *spooldir); - public: + public: //! Construct an LServer class //! \param spooldir Name of spool-directory @@ -203,7 +203,7 @@ class LServer:virtual public NServer { * \brief Provides an interface to access news on a remote site */ class RServer:virtual public NServer { - private: + private: /** * \note @@ -233,18 +233,19 @@ class RServer:virtual public NServer { */ void post(MPListEntry * srvr, Article * article); - protected: - MPList * _ServerList; + protected: + MPList * _ServerList; MPListEntry *_CurrentServer; GroupInfo _CurrentGroup; - sstream *_pServerStream; + sockstream *_pServerStream; - RServer():NServer() { + RServer():NServer() { _ServerList = NULL; _CurrentServer = NULL; _pServerStream = NULL; - } void init(MPList * serverlist); + } + void init(MPList * serverlist); /** * Connect to the news server. Stores whether posting is allowed @@ -310,7 +311,7 @@ class RServer:virtual public NServer { */ void selectgroup(const char *name, int force = 0); - public: + public: /** * Initialize the new RServer class. Sets up the server list and @@ -412,7 +413,7 @@ class RServer:virtual public NServer { * code. */ virtual void listgroup(const char *gname, char *lstgrp, - unsigned int f, unsigned int l); + unsigned int f, unsigned int l); /** * Return the overviewdatabase of the newsgroup >ng<. This function @@ -431,7 +432,7 @@ class RServer:virtual public NServer { * \throw NSError If news server does not implement over and xover. */ virtual void overviewdb(Newsgroup * ng, unsigned int fst, - unsigned int lst); + unsigned int lst); /** * Return a given article of a given newsgroup @@ -456,7 +457,7 @@ class RServer:virtual public NServer { * \todo Synchronize Description and Code (Parameters). */ virtual void article(const char *gname, unsigned int nb, - Article * artr); + Article * artr); /** * Return a given article of a given newsgroup @@ -478,6 +479,14 @@ class RServer:virtual public NServer { * \todo Synchronize Description and Code (Parameters). */ virtual void article(const char *id, Article * art); + + inline unsigned int getserverflags() { + return _CurrentServer->flags; + } + + inline unsigned int getnntpflags() { + return _CurrentServer->nntpflags; + } }; /** @@ -489,28 +498,43 @@ class RServer:virtual public NServer { * spool directory. * \author Thomas Gschwind */ -class CServer:virtual public LServer, public RServer { - protected: +class CServer + : virtual public LServer, public RServer +{ + protected: NVActiveDB * _NVActiveDB; nvtime_t _TTLActive; nvtime_t _TTLDesc; - int active_valid() { + + int active_valid() + { unsigned long tm; _NVActiveDB->getmtime(&tm); return (tm + _TTLActive) > nvtime(NULL); - } int desc_valid() { + } + + int desc_valid() + { return 1; } + int group_valid(); + /** + * Filter the XRef header to only contain entries for groups + * matching the specified server. + */ + void filter_xref(Article *art, MPListEntry *server, + const char *gname = NULL); + // This variable indicates, whether a newsgroup has been // already selected on the remote news server // int _RSGroup; // Select group on remote server, if not already selected // int RSGroup(const char *name); - public: + public: //! \param spooldir Name of spool-directory. //! \param serverlist List of news servers and their newsgroups. @@ -626,7 +650,7 @@ class CServer:virtual public LServer, public RServer { * \todo Synchronize Description and Code (Parameters). */ virtual void listgroup(const char *gname, char *lstgrp, - unsigned int f, unsigned int l); + unsigned int f, unsigned int l); /** * Return the overviewdatabase of the newsgroup >ng<. This function @@ -642,7 +666,7 @@ class CServer:virtual public LServer, public RServer { * \todo Synchronize Description and Code (throw). */ virtual void overviewdb(Newsgroup * ng, unsigned int fst, - unsigned int lst); + unsigned int lst); /** * Return a given article of a given newsgroup. @@ -660,7 +684,7 @@ class CServer:virtual public LServer, public RServer { * \todo Synchronize Description and Code (return). */ virtual void article(const char *gname, unsigned int nbr, - Article * art); + Article * art); /** * Return the article for a given article id. @@ -689,3 +713,11 @@ inline void CServer::invalidateActiveDB (void) _NVActiveDB->setmtime (0,1); // force flag 1 !! } #endif + +/* + * Local Variables: + * mode: c++ + * tab-width: 4 + * c-basic-offset: 4 + * End: + */ diff --git a/NServer-0.9.1/NVActiveDB.cc b/NServer-0.9.1/NVActiveDB.cc index 97611ec..3f8ebd5 100644 --- a/NServer-0.9.1/NVActiveDB.cc +++ b/NServer-0.9.1/NVActiveDB.cc @@ -225,3 +225,11 @@ void NVActiveDB::write(ostream & os, } } /* for */ } + +/* + * Local Variables: + * mode: c++ + * tab-width: 4 + * c-basic-offset: 4 + * End: + */ diff --git a/NServer-0.9.1/NVActiveDB.h b/NServer-0.9.1/NVActiveDB.h index 3f02e4f..8559822 100644 --- a/NServer-0.9.1/NVActiveDB.h +++ b/NServer-0.9.1/NVActiveDB.h @@ -39,7 +39,7 @@ class NVActiveDB_Iter; * \bug Documentation is missing. */ class NVActiveDB:public ActiveDB, protected NVHash { - protected: + protected: friend class NVActiveDB_Iter; unsigned long hash(const char *strg); @@ -54,10 +54,13 @@ class NVActiveDB:public ActiveDB, protected NVHash { */ void sset(GroupInfo & gi, int flags = 0); - public: - NVActiveDB():NVHash() { - } NVActiveDB(char *dbname):NVHash(dbname, NVActiveDB_HASHSIZE) { - } + public: + NVActiveDB():NVHash() + { } + + NVActiveDB(char *dbname) + : NVHash(dbname, NVActiveDB_HASHSIZE) + { } int lock(int command, int block = Block) { return NVHash::lock(command, block); @@ -132,7 +135,7 @@ class NVActiveDB:public ActiveDB, protected NVHash { Iter < GroupInfo > end(); friend std::ostream & operator<<(std::ostream & os, - NVActiveDB & adb) { + NVActiveDB & adb) { adb.write(os); return os; } @@ -141,14 +144,14 @@ class NVActiveDB:public ActiveDB, protected NVHash { /****************************************************************/ class NVActiveDB_Iter:public _Iter < GroupInfo > { - private: + private: friend class NVActiveDB; NVActiveDB *active_database; unsigned long hash_val; - NVActiveDB::Record * pos; - NVActiveDB::Record * tail; + NVActiveDB::Record * pos; + NVActiveDB::Record * tail; GroupInfo newsgroup; @@ -176,7 +179,7 @@ class NVActiveDB_Iter:public _Iter < GroupInfo > { _skip_nulls(); } - public: + public: _Iter < GroupInfo > *clone() { return new NVActiveDB_Iter(*this); } @@ -230,3 +233,11 @@ inline Iter < GroupInfo > NVActiveDB::end() } #endif + +/* + * Local Variables: + * mode: c++ + * tab-width: 4 + * c-basic-offset: 4 + * End: + */ diff --git a/NServer-0.9.1/NVNewsgroup.cc b/NServer-0.9.1/NVNewsgroup.cc index bbb5c93..099481d 100644 --- a/NServer-0.9.1/NVNewsgroup.cc +++ b/NServer-0.9.1/NVNewsgroup.cc @@ -506,3 +506,11 @@ void NVNewsgroup::printlistgroup(ostream & os) } lock(NVcontainer::UnLock); } + +/* + * Local Variables: + * mode: c++ + * tab-width: 4 + * c-basic-offset: 4 + * End: + */ diff --git a/NServer-0.9.1/NVNewsgroup.h b/NServer-0.9.1/NVNewsgroup.h index 355419e..8281a85 100644 --- a/NServer-0.9.1/NVNewsgroup.h +++ b/NServer-0.9.1/NVNewsgroup.h @@ -29,7 +29,7 @@ * \bug Documentation is missing. */ class NVNewsgroup:public Newsgroup, protected NVArray { - protected: + protected: void sprintover(std::ostream & os, unsigned int nbr); enum { @@ -40,17 +40,19 @@ class NVNewsgroup:public Newsgroup, protected NVArray { }; char _SpoolDirectory[MAXPATHLEN]; - public: - NVNewsgroup(OverviewFmt * fmt, const char *spooldir, - const char *name) - :Newsgroup(fmt, name), NVArray() { + public: + NVNewsgroup(OverviewFmt * fmt, const char *spooldir, + const char *name) + : Newsgroup(fmt, name), NVArray() + { char fn[MAXPATHLEN]; - sprintf(_SpoolDirectory, "%s/%s", spooldir, - group2dir(name)); - mkpdir(_SpoolDirectory, 0755); - sprintf(fn, "%s/.db", _SpoolDirectory); - NVArray::open(fn); + sprintf(_SpoolDirectory, "%s/%s", spooldir, + group2dir(name)); + mkpdir(_SpoolDirectory, 0755); + sprintf(fn, "%s/.db", _SpoolDirectory); + NVArray::open(fn); } + #ifdef ENABLE_ASSERTIONS virtual void testdb(void); #endif @@ -81,7 +83,7 @@ class NVNewsgroup:public Newsgroup, protected NVArray { } virtual const char *getover(unsigned int nbr); - virtual void setover(const string & over); + virtual void setover(const std::string & over); virtual void printover(std::ostream & os, unsigned int nbr) { NVArray::lock(NVcontainer::ShrdLock); sprintover(os, nbr); @@ -103,3 +105,11 @@ class NVNewsgroup:public Newsgroup, protected NVArray { */ #endif + +/* + * Local Variables: + * mode: c++ + * tab-width: 4 + * c-basic-offset: 4 + * End: + */ diff --git a/NServer-0.9.1/Newsgroup.cc b/NServer-0.9.1/Newsgroup.cc index 580aaa0..5e86277 100644 --- a/NServer-0.9.1/Newsgroup.cc +++ b/NServer-0.9.1/Newsgroup.cc @@ -3,3 +3,11 @@ Newsgroup::~Newsgroup() { } + +/* + * Local Variables: + * mode: c++ + * tab-width: 4 + * c-basic-offset: 4 + * End: + */ diff --git a/NServer-0.9.1/Newsgroup.h b/NServer-0.9.1/Newsgroup.h index a1ef1d0..10f59bb 100644 --- a/NServer-0.9.1/Newsgroup.h +++ b/NServer-0.9.1/Newsgroup.h @@ -28,21 +28,22 @@ #define MAXNEWSGROUPNAMELEN MAXGROUPNAMELEN class Newsgroup { - protected: + protected: char _NewsgroupName[MAXGROUPNAMELEN + 1]; OverviewFmt *_OverviewFormat; virtual Article *retrievearticle(unsigned int nbr) { return NULL; - } public: - Newsgroup(OverviewFmt * fmt, const char *name) { + } + + public: + Newsgroup(OverviewFmt * fmt, const char *name) + { _OverviewFormat = fmt; _NewsgroupName[MAXGROUPNAMELEN] = '\0'; strncpy(_NewsgroupName, name, MAXGROUPNAMELEN); ASSERT(if (strlen(name) > MAXGROUPNAMELEN) { - slog. - p(Logger:: - Error) << - "Name of newsgroup too long - truncated\n";} + slog.p(Logger::Error) << + "Name of newsgroup too long - truncated\n";} ); } virtual ~ Newsgroup(); @@ -76,7 +77,7 @@ class Newsgroup { virtual void prefetchOverview(void) = 0; virtual const char *getover(unsigned int nbr) = 0; - virtual void setover(const string & over) = 0; + virtual void setover(const std::string & over) = 0; virtual void printover(std::ostream & os, unsigned int nbr) { const char *o = getover(nbr); if (o) @@ -98,23 +99,27 @@ class Newsgroup { } } virtual void printheaderdb(std::ostream & os, - const char *header, - unsigned int f = 0, unsigned int l = - UINT_MAX) = 0; + const char *header, + unsigned int f = 0, unsigned int l = + UINT_MAX) = 0; virtual void printlistgroup(std::ostream & os) = 0; }; #ifdef _INCLUDE_NewsgroupIter_ class NewsgroupIter { - protected: + protected: Newsgroup * _ng; unsigned int i; int lck; - public: - NewsgroupIter() { - } NewsgroupIter(Newsgroup * ng) { + + public: + NewsgroupIter() + { } + + NewsgroupIter(Newsgroup * ng) { _ng = ng; } + void attach(Newsgroup * ng) { _ng = ng; } @@ -137,3 +142,11 @@ class NewsgroupIter { }; #endif #endif + +/* + * Local Variables: + * mode: c++ + * tab-width: 4 + * c-basic-offset: 4 + * End: + */ diff --git a/NServer-0.9.1/NewsgroupFilter.cc b/NServer-0.9.1/NewsgroupFilter.cc index 052476c..3bc9684 100644 --- a/NServer-0.9.1/NewsgroupFilter.cc +++ b/NServer-0.9.1/NewsgroupFilter.cc @@ -1 +1,9 @@ #include "NewsgroupFilter.h" + +/* + * Local Variables: + * mode: c++ + * tab-width: 4 + * c-basic-offset: 4 + * End: + */ diff --git a/NServer-0.9.1/NewsgroupFilter.h b/NServer-0.9.1/NewsgroupFilter.h index 1f90807..16e63c9 100644 --- a/NServer-0.9.1/NewsgroupFilter.h +++ b/NServer-0.9.1/NewsgroupFilter.h @@ -17,23 +17,28 @@ * \bug Documentation is missing. */ class NewsgroupFilter { - private: - string rulelist; + private: + std::string rulelist; const char *c_rulelist; - string Wildmat; + std::string Wildmat; int WildmatSearch; class RuleIterator { const char *rulelist, *rulelistp; char rule[1 + MAXNEWSGROUPNAMELEN]; // '!'+MAXNEWSGROUPNAMELEN - public: + public: enum { iter_begin, iter_end }; - RuleIterator():rulelist(NULL), rulelistp(NULL) { + RuleIterator() + : rulelist(NULL), rulelistp(NULL) + { rule[0] = '\0'; - } RuleIterator(const char *rulelist, int pos) - :rulelist(rulelist) { + } + + RuleIterator(const char *rulelist, int pos) + : rulelist(rulelist) + { if (pos == iter_begin) { char *rulep = rule; char c; @@ -91,7 +96,7 @@ class NewsgroupFilter { * \param rulelist The list of rules. * \param rule Rule to be added. */ - void add_rule_to_rulelist(string & rulelist, const char *rule) { + void add_rule_to_rulelist(std::string & rulelist, const char *rule) { const char *p = rulelist.c_str(), *q; do { @@ -111,12 +116,20 @@ class NewsgroupFilter { rulelist += ','; } - RuleIterator begin() const { + RuleIterator begin() const + { return RuleIterator(c_rulelist, RuleIterator::iter_begin); - } RuleIterator end() const { + } + + RuleIterator end() const + { return RuleIterator(c_rulelist, RuleIterator::iter_end); - } public: - NewsgroupFilter():WildmatSearch(0) { + } + + public: + NewsgroupFilter() + : WildmatSearch(0) + { c_rulelist = rulelist.c_str(); } @@ -126,7 +139,8 @@ class NewsgroupFilter { * \param filter The initial filter */ NewsgroupFilter(const NewsgroupFilter & filter) - : rulelist(filter.rulelist), WildmatSearch(0) { + : rulelist(filter.rulelist), WildmatSearch(0) + { this->c_rulelist = this->rulelist.c_str(); } @@ -138,7 +152,8 @@ class NewsgroupFilter { * rule and may end with the '*' wildcard. */ NewsgroupFilter(const char *rulelist) - :rulelist(rulelist), WildmatSearch(0) { + : rulelist(rulelist), WildmatSearch(0) + { this->c_rulelist = this->rulelist.c_str(); } @@ -158,7 +173,7 @@ class NewsgroupFilter { return *this; } - NewsgroupFilter & operator=(const string & rulelist) { + NewsgroupFilter & operator=(const std::string & rulelist) { this->rulelist = rulelist; this->c_rulelist = this->rulelist.c_str(); return *this; @@ -185,7 +200,7 @@ class NewsgroupFilter { * \author Herbert Straub * \return rulelist */ - const string& getRulelist (void) { + const std::string& getRulelist (void) { return rulelist; } @@ -268,7 +283,7 @@ class NewsgroupFilter { * \param filter2 The other filter. */ NewsgroupFilter & operator|=(const NewsgroupFilter & filter2) { - string new_rulelist; + std::string new_rulelist; RuleIterator begin, end; const char *grp; @@ -317,7 +332,7 @@ class NewsgroupFilter { * \param filter2 The other filter. */ NewsgroupFilter & operator&=(const NewsgroupFilter & filter2) { - string new_rulelist; + std::string new_rulelist; RuleIterator begin, end; const char *grp; @@ -365,3 +380,11 @@ class NewsgroupFilter { }; #endif + +/* + * Local Variables: + * mode: c++ + * tab-width: 4 + * c-basic-offset: 4 + * End: + */ diff --git a/NServer-0.9.1/ObjLock.cc b/NServer-0.9.1/ObjLock.cc index b12d7ad..6f7e22b 100644 --- a/NServer-0.9.1/ObjLock.cc +++ b/NServer-0.9.1/ObjLock.cc @@ -25,7 +25,7 @@ #include "Error.h" #include "ObjLock.h" -ObjLock::ObjLock(const string & name) +ObjLock::ObjLock(const std::string & name) { this->name = name; @@ -125,3 +125,11 @@ void ObjLock::unlock(void) ERROR_LOCATION)); #endif } + +/* + * Local Variables: + * mode: c++ + * tab-width: 4 + * c-basic-offset: 4 + * End: + */ diff --git a/NServer-0.9.1/ObjLock.h b/NServer-0.9.1/ObjLock.h index 4508525..d3c9f47 100644 --- a/NServer-0.9.1/ObjLock.h +++ b/NServer-0.9.1/ObjLock.h @@ -30,11 +30,11 @@ * lock in blocked or non-blocked operation. */ class ObjLock { - public: + public: //! Constructor //! \param name of Resource //! \throw SystemError Error creating Lock File - ObjLock(const string & name); + ObjLock(const std::string & name); //! Destructor ~ObjLock(); @@ -63,8 +63,8 @@ class ObjLock { //! \throw SystemError Error in flock or fcntl void unlock(void); - private: - string name; + private: + std::string name; int fd; #ifndef USE_FLOCK struct flock l; @@ -73,3 +73,11 @@ class ObjLock { }; #endif + +/* + * Local Variables: + * mode: c++ + * tab-width: 4 + * c-basic-offset: 4 + * End: + */ diff --git a/NServer-0.9.1/OverviewFmt.cc b/NServer-0.9.1/OverviewFmt.cc index dabfc37..6fcb658 100644 --- a/NServer-0.9.1/OverviewFmt.cc +++ b/NServer-0.9.1/OverviewFmt.cc @@ -46,3 +46,11 @@ void OverviewFmt::readxoin(istream & is) } } } + +/* + * Local Variables: + * mode: c++ + * tab-width: 4 + * c-basic-offset: 4 + * End: + */ diff --git a/NServer-0.9.1/OverviewFmt.h b/NServer-0.9.1/OverviewFmt.h index b4ef7ac..2ffd5f5 100644 --- a/NServer-0.9.1/OverviewFmt.h +++ b/NServer-0.9.1/OverviewFmt.h @@ -34,7 +34,7 @@ * \author Thomas Gschwind */ class OverviewFmt { - private: + private: struct overdesc { char name[256]; // Name of field includeing : int len; // strlen(name) @@ -57,9 +57,10 @@ class OverviewFmt { transtab _trans[128]; int _osz; - public: + public: int dotrans; - OverviewFmt() { + + OverviewFmt() { const char *tmp[] = CONF_OverviewFmt, *q; char *p; for (_osz = 0; tmp[_osz]; _osz++) { @@ -81,8 +82,8 @@ class OverviewFmt { * \li 0 => strip fieldname * \li 1 => add fieldname */ - string getfield(const char *over, const char *fld, int full = -1) { - string field; + std::string getfield(const char *over, const char *fld, int full = -1) { + std::string field; int i; for (i = 0; i < _osz; i++) { @@ -133,7 +134,7 @@ class OverviewFmt { * \param recin The overview record that has to be converted. * \param recout The converted overview record. */ - void convert(const string & recin, string & recout) const { + void convert(const std::string & recin, std::string & recout) const { int tabs[256]; int i, j, k, rinsz; if (!dotrans) { @@ -206,9 +207,9 @@ class OverviewFmt { } } - void convert(const Article & article, string & recout) const { + void convert(const Article & article, std::string & recout) const { char buf[256]; - string fld; + std::string fld; int i; sprintf(buf, "%d", article.getnbr()); @@ -249,3 +250,11 @@ class OverviewFmt { }; #endif + +/* + * Local Variables: + * mode: c++ + * tab-width: 4 + * c-basic-offset: 4 + * End: + */ diff --git a/NServer-0.9.1/RNewsgroup.cc b/NServer-0.9.1/RNewsgroup.cc index 80bb5d5..0478e81 100644 --- a/NServer-0.9.1/RNewsgroup.cc +++ b/NServer-0.9.1/RNewsgroup.cc @@ -22,7 +22,7 @@ void RNewsgroup::setsize(unsigned int f, unsigned int l) } } -void RNewsgroup::printarticle(ostream & os, unsigned int nbr) +void RNewsgroup::printarticle(std::ostream & os, unsigned int nbr) { try { Article article; @@ -31,3 +31,11 @@ void RNewsgroup::printarticle(ostream & os, unsigned int nbr) } catch(...) { } } + +/* + * Local Variables: + * mode: c++ + * tab-width: 4 + * c-basic-offset: 4 + * End: + */ diff --git a/NServer-0.9.1/RNewsgroup.h b/NServer-0.9.1/RNewsgroup.h index 0177f88..9688d74 100644 --- a/NServer-0.9.1/RNewsgroup.h +++ b/NServer-0.9.1/RNewsgroup.h @@ -30,21 +30,24 @@ * \bug Documentation is missing. */ class RNewsgroup:public Newsgroup { - typedef std::map < unsigned int, string >::iterator iterator; + typedef std::map < unsigned int, std::string >::iterator iterator; - std::map < unsigned int, string > _OverviewDB; + std::map < unsigned int, std::string > _OverviewDB; unsigned int _first, _last; // News stuff RServer *_RemoteServer; - public: - RNewsgroup():Newsgroup(NULL, NULL) { - } RNewsgroup(RServer * srvr, OverviewFmt * fmt, const char *name) - :Newsgroup(fmt, name), _first(1), _last(0), _RemoteServer(srvr) { - } - ~RNewsgroup() { - } + public: + RNewsgroup():Newsgroup(NULL, NULL) + { } + + RNewsgroup(RServer * srvr, OverviewFmt * fmt, const char *name) + : Newsgroup(fmt, name), _first(1), _last(0), _RemoteServer(srvr) + { } + + ~RNewsgroup() + { } virtual void getsize(unsigned int *f, unsigned int *l) { *f = _first; @@ -94,7 +97,7 @@ class RNewsgroup:public Newsgroup { return NULL; } - virtual void setover(const string & over) { + virtual void setover(const std::string & over) { unsigned int i = atoi(over.c_str()); if (_first <= i && i <= _last) { @@ -105,7 +108,7 @@ class RNewsgroup:public Newsgroup { virtual void readoverdb(std::istream & is) { VERB(slog. p(Logger::Debug) << "RNewsgroup::readoverdb(&is)\n"); - string line1, line2; + std::string line1, line2; for (;;) { nlreadline(is, line1, 0); @@ -121,13 +124,13 @@ class RNewsgroup:public Newsgroup { } } - virtual void printheaderdb(ostream & os, + virtual void printheaderdb(std::ostream & os, const char *header, unsigned int f = 0, unsigned int l = UINT_MAX) { char xheader[512], *p; const char *q; - string fld; + std::string fld; p = xheader; q = header; @@ -157,7 +160,7 @@ class RNewsgroup:public Newsgroup { } } - virtual void printlistgroup(ostream & os) { + virtual void printlistgroup(std::ostream & os) { iterator begin = _OverviewDB.begin(), end = _OverviewDB.end(); @@ -168,3 +171,11 @@ class RNewsgroup:public Newsgroup { } }; #endif + +/* + * Local Variables: + * mode: c++ + * tab-width: 4 + * c-basic-offset: 4 + * End: + */ diff --git a/NServer-0.9.1/VirtualIterator.h b/NServer-0.9.1/VirtualIterator.h index ba64d6b..4ec6ad1 100644 --- a/NServer-0.9.1/VirtualIterator.h +++ b/NServer-0.9.1/VirtualIterator.h @@ -7,10 +7,10 @@ * \bug Documentation is missing. */ template < class T > class _Iter { - protected: + protected: int _type; - public: + public: virtual ~ _Iter() { }; virtual _Iter *clone() = 0; @@ -25,7 +25,7 @@ template < class T > class _Iter { * \bug Documentation is missing. */ template < class T > class Iter { - private: + private: _Iter < T > *iter; Iter():iter(NULL) { @@ -75,3 +75,11 @@ template < class T > class Iter { }; #endif + +/* + * Local Variables: + * mode: c++ + * tab-width: 4 + * c-basic-offset: 4 + * End: + */ diff --git a/NServer-0.9.1/readline.cc b/NServer-0.9.1/readline.cc index dd646af..924f001 100644 --- a/NServer-0.9.1/readline.cc +++ b/NServer-0.9.1/readline.cc @@ -1,3 +1,4 @@ +#include #include #include #include @@ -18,7 +19,7 @@ int nlreadline(istream & is, // Input-Stream } catch(...) { // FIXME: should be improved or removed (Debugging) slog.p(Logger::Error) << "nlreadline: Error in getline\n"; - exit(1); + std::exit(1); } pos = len = strg.length(); while (pos) { @@ -60,3 +61,11 @@ int readtext(istream & is, // Input-Stream return lines; } + +/* + * Local Variables: + * mode: c++ + * tab-width: 4 + * c-basic-offset: 4 + * End: + */ diff --git a/NServer-0.9.1/readline.h b/NServer-0.9.1/readline.h index dc82392..0ab3330 100644 --- a/NServer-0.9.1/readline.h +++ b/NServer-0.9.1/readline.h @@ -23,3 +23,11 @@ int readtext(std::istream & is, std::string & strg, int keepnl = 1, ); #endif + +/* + * Local Variables: + * mode: c++ + * tab-width: 4 + * c-basic-offset: 4 + * End: + */ diff --git a/NServer-0.9.1/sockstream.cc b/NServer-0.9.1/sockstream.cc new file mode 100644 index 0000000..0710e08 --- /dev/null +++ b/NServer-0.9.1/sockstream.cc @@ -0,0 +1,447 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "config.h" +#include "Debug.h" +#include "sockstream.h" + + +namespace { +#if defined(HAVE_GNUTLS) +struct Gnutls_Initer +{ + Gnutls_Initer() + { + gnutls_global_init(); + } + + ~Gnutls_Initer() + { + gnutls_global_deinit(); + } +} gnutls_initer; +#endif +} + + +sig_atomic_t *sockstream::sockstreambuf::_alarm_indicator = NULL; + + +void sockstream::sockstreambuf::connect(const char *name, const char *service, + const struct sockaddr *from, + socklen_t fromlen, + unsigned int timeout) +{ + disconnect(); + + struct addrinfo hints; + + memset(&hints, 0, sizeof(hints)); + hints.ai_flags = AI_ADDRCONFIG | ((service[0] == '#') ? AI_NUMERICSERV : 0); + hints.ai_family = (from != NULL) ? from->sa_family : AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_TCP; + + struct addrinfo *res; + if (getaddrinfo(name, (service[0] == '#') ? service + 1 : service, + &hints, &res)) + { + slog.p(Logger::Error) << "Can't resolve " << name << ' ' << service + << "\n"; + return; + } + + struct addrinfo *addr = res; + while ((_fd < 0) && (addr != NULL)) + { + _fd = ::socket(addr->ai_addr->sa_family, SOCK_STREAM, IPPROTO_TCP); + if (_fd >= 0) + { + if (from != NULL) + { + if (::bind(_fd, from, fromlen) < 0) + { + slog.p(Logger::Error) << "Unable to bind to outgoing address" + << "\n"; + + while (::close(_fd) && (errno == EINTR)) + { } + _fd = -1; + freeaddrinfo(res); + + return; + } + } + + if (timeout && _alarm_indicator) + { + *_alarm_indicator = 0; + alarm(timeout); + } + + int rc_connect; + while (((rc_connect = ::connect(_fd, addr->ai_addr, + addr->ai_addrlen)) < 0) && + (errno == EINTR) && + (!timeout || !_alarm_indicator || !*_alarm_indicator)) + { } + + if (timeout && _alarm_indicator) + { + alarm(0); + } + + if (rc_connect) + { + if (timeout && _alarm_indicator && *_alarm_indicator) + { + *_alarm_indicator = 0; + slog.p(Logger::Notice) << "Connection attempt to " << name + << " timed out\n"; + } + else + { + slog.p(Logger::Notice) << "Connection attempt to " << name + << " failed: " << strerror(errno) << "\n"; + } + + while (::close(_fd) && (errno == EINTR)) + { } + _fd = -1; + } + } + + addr = addr->ai_next; + } + + if (_fd < 0) + { + slog.p(Logger::Warning) << "Unable to connect to " << name << ' ' + << service << "\n"; + } + + freeaddrinfo(res); +} + +void sockstream::sockstreambuf::attach(int fd) +{ + disconnect(); + _fd = fd; +} + +void sockstream::sockstreambuf::disconnect() +{ + if (connected()) + { + sync(); + setg(_gbuf, _gbuf + sizeof(_gbuf), _gbuf + sizeof(_gbuf)); + setp(_pbuf, _pbuf + sizeof(_gbuf)); + + while (::close(_fd) && (errno == EINTR)) + { } + + _fd = -1; + } +} + +void sockstream::sockstreambuf::setkeepalive(bool fl) +{ + const int value = fl; + + if (setsockopt(_fd, SOL_SOCKET, SO_KEEPALIVE, &value, sizeof(value)) < 0) + { + slog.p(Logger::Error) << "setsockopt failed: " + << strerror(errno) << "\n"; + } +} + +void sockstream::sockstreambuf::setnodelay(bool fl) +{ + const int value = fl; + if (setsockopt(_fd, IPPROTO_TCP, TCP_NODELAY, &value, sizeof(value)) < 0) + { + slog.p(Logger::Error) << "setsockopt failed: " + << strerror(errno) << "\n"; + } +} + + +int sockstream::sockstreambuf::overflow(int c) +{ + if (_fd < 0) + { + return traits_type::eof(); + } + + if (c == traits_type::eof()) + { + return sync() ? traits_type::eof() : 0; + } + + if (pptr() == epptr()) + { + if (sync()) + { + return traits_type::eof(); + } + } + + *pptr() = char(c); + pbump(1); + + return c; +} + +int sockstream::sockstreambuf::sync() +{ + size_t off = 0; + + while ((pbase() + off) != pptr()) + { + int rc_send; + do + { + rc_send = ::send(_fd, pbase() + off, pptr() - pbase() - off, 0); + } while ((rc_send < 0) && (errno == EINTR) && + (!_alarm_indicator || !*_alarm_indicator)); + + if (rc_send < 0) + { + return -1; + } + + off += rc_send; + } + + setp(_pbuf, _pbuf + sizeof(_pbuf)); + + return 0; +} + +int sockstream::sockstreambuf::underflow() +{ + if (gptr() < egptr()) + { + return *gptr(); + } + + int rc_recv; + do + { + rc_recv = ::recv(_fd, _gbuf, sizeof(_gbuf), 0); + } while ((rc_recv < 0) && (errno == EINTR) && + (!_alarm_indicator || !*_alarm_indicator)); + + if (rc_recv > 0) + { + setg(_gbuf, _gbuf, _gbuf + rc_recv); + return (unsigned char) *gptr(); + } + else + { + return traits_type::eof(); + } +} + + +#if defined(HAVE_GNUTLS) +sockstream::sslstreambuf::sslstreambuf(sockstreambuf &buf) + : _buf(buf), _connected(false) +{ + setg(_buf._gbuf, _buf._gbuf + sizeof(_buf._gbuf), + _buf._gbuf + sizeof(_buf._gbuf)); + setp(_buf._pbuf, _buf._pbuf + sizeof(_buf._pbuf)); + + gnutls_init(&_session, GNUTLS_CLIENT); + + if (gnutls_anon_allocate_client_credentials(&_anon_cred) < 0) + { + gnutls_deinit(_session); + } + + if (gnutls_certificate_allocate_credentials(&_cert_cred) < 0) + { + gnutls_anon_free_client_credentials(_anon_cred); + gnutls_deinit(_session); + } + + // set up SSL/TLS parameters + static const int cipher_priority[] = { + GNUTLS_CIPHER_AES_128_CBC, + GNUTLS_CIPHER_AES_256_CBC, + GNUTLS_CIPHER_ARCFOUR_128, + GNUTLS_CIPHER_3DES_CBC, + 0 + }; + gnutls_cipher_set_priority(_session, cipher_priority); + + static const int compression_priority[] = { + GNUTLS_COMP_ZLIB, + GNUTLS_COMP_NULL, + 0 + }; + gnutls_compression_set_priority(_session, compression_priority); + + static const int kx_priority[] = { + GNUTLS_KX_RSA, GNUTLS_KX_DHE_DSS, + GNUTLS_KX_DHE_RSA, GNUTLS_KX_SRP, + GNUTLS_KX_ANON_DH, GNUTLS_KX_RSA_EXPORT, + 0 + }; + gnutls_kx_set_priority(_session, kx_priority); + + static const int protocol_priority[] = { + GNUTLS_TLS1, GNUTLS_SSL3, 0 + }; + gnutls_protocol_set_priority(_session, protocol_priority); + + + static const int mac_priority[] = { + GNUTLS_MAC_MD5, GNUTLS_MAC_SHA, 0 + }; + gnutls_mac_set_priority(_session, mac_priority); + + static const int cert_type_priority[] = { + GNUTLS_CRT_X509, + GNUTLS_CRT_OPENPGP, 0 + }; + gnutls_certificate_type_set_priority(_session, cert_type_priority); + + gnutls_credentials_set(_session, GNUTLS_CRD_ANON, _anon_cred); + gnutls_credentials_set(_session, GNUTLS_CRD_CERTIFICATE, _cert_cred); +} + +sockstream::sslstreambuf::~sslstreambuf() +{ + disconnect(); + + gnutls_deinit(_session); + + gnutls_anon_free_client_credentials(_anon_cred); + gnutls_certificate_free_credentials(_cert_cred); +} + + +void sockstream::sslstreambuf::connect() +{ + gnutls_transport_set_ptr(_session, + reinterpret_cast(_buf.fd())); + + int rc_connect = GNUTLS_E_AGAIN; + while (rc_connect == GNUTLS_E_AGAIN) + { + rc_connect = gnutls_handshake(_session); + } + + _connected = !rc_connect; +} + +void sockstream::sslstreambuf::disconnect() +{ + int rc_shutdown = GNUTLS_E_AGAIN; + while (rc_shutdown == GNUTLS_E_AGAIN) + { + rc_shutdown = gnutls_bye(_session, GNUTLS_SHUT_RDWR); + } +} + + +int sockstream::sslstreambuf::overflow(int c) +{ + if (!_connected || !_buf.connected()) + { + return traits_type::eof(); + } + + if (c == traits_type::eof()) + { + return sync() ? traits_type::eof() : 0; + } + + if (pptr() == epptr()) + { + if (sync()) + { + return traits_type::eof(); + } + } + + *pptr() = char(c); + pbump(1); + + return c; +} + +int sockstream::sslstreambuf::sync() +{ + size_t off = 0; + + while ((pbase() + off) != pptr()) + { + const int rc_write = + gnutls_write(_session, pbase() + off, pptr() - pbase() - off); + if (rc_write < 0) + { + return -1; + } + + off += rc_write; + } + + setp(_buf._pbuf, _buf._pbuf + sizeof(_buf._pbuf)); + + return 0; +} + +int sockstream::sslstreambuf::underflow() +{ + if (gptr() < egptr()) + { + return *gptr(); + } + + const int rc_read = gnutls_read(_session, _buf._gbuf, sizeof(_buf._gbuf)); + if (rc_read > 0) + { + setg(_buf._gbuf, _buf._gbuf, _buf._gbuf + rc_read); + return (unsigned char) *gptr(); + } + else + { + return traits_type::eof(); + } +} + +sockstream *sockstream::starttls() +{ + if (!_ssl && _buf.connected()) + { + sockstream * const ssl_stream = new sockstream(true); + ssl_stream->attach(_buf.fd()); + _buf.dispose(); + ssl_stream->_ssl->connect(); + return ssl_stream; + } + else + { + return NULL; + } +} +#endif + +/* + * Local Variables: + * mode: c++ + * tab-width: 8 + * c-basic-offset: 2 + * End: + */ diff --git a/NServer-0.9.1/sockstream.h b/NServer-0.9.1/sockstream.h new file mode 100644 index 0000000..7b93905 --- /dev/null +++ b/NServer-0.9.1/sockstream.h @@ -0,0 +1,209 @@ +#ifndef __sstream_h__ +#define __sstream_h__ + +#include +#include + +#if defined(HAVE_GNUTLS) +#include +#endif + +#include + + +class sockstream + : public std::iostream +{ + class sockstreambuf; + + class sslstreambuf + : public std::streambuf + { +#if defined(HAVE_GNUTLS) + sockstreambuf &_buf; + bool _connected; + + gnutls_session _session; + gnutls_anon_client_credentials _anon_cred; + gnutls_certificate_credentials _cert_cred; + + public: + explicit sslstreambuf(sockstreambuf &buf); + + ~sslstreambuf(); + + virtual int overflow(int c = traits_type::eof()); + virtual int sync(); + + virtual int underflow(); + + inline bool connected() const + { return _connected; } + + void connect(); + void disconnect(); +#else + public: + inline bool connected() const + { return false; } + + inline void connect() + { } + inline void disconnect() + { } +#endif + }; + + sslstreambuf *_ssl; + + class sockstreambuf + : public std::streambuf + { + friend class sslstreambuf; + + static sig_atomic_t *_alarm_indicator; + + int _fd; + char _gbuf[4096]; + char _pbuf[4096]; + + public: + static inline void alarm_indicator(sig_atomic_t &var) + { + _alarm_indicator = &var; + } + + inline sockstreambuf() + : _fd(-1) + { + setg(_gbuf, _gbuf + sizeof(_gbuf), _gbuf + sizeof(_gbuf)); + setp(_pbuf, _pbuf + sizeof(_pbuf)); + } + + inline ~sockstreambuf() + { disconnect(); } + + inline bool connected() const + { return _fd >= 0; } + + inline int fd() const + { return _fd; } + + void connect(const char *name, const char *service, + const struct sockaddr *from, socklen_t fromlen, + unsigned int timeout = 0); + + void attach(int fd); + + void disconnect(); + void dispose() + { + sync(); + _fd = -1; + } + + void setkeepalive(bool fl = true); + void setnodelay(bool fl = true); + + virtual int overflow(int c = traits_type::eof()); + virtual int sync(); + + virtual int underflow(); + } _buf; + + public: + static inline void alarm_indicator(sig_atomic_t &var) + { + sockstreambuf::alarm_indicator(var); + } + + inline explicit sockstream(const bool ssl = false) +#if defined(HAVE_GNUTLS) + : std::iostream(ssl ? + static_cast(new sslstreambuf(_buf)) : + static_cast(&_buf)), + _ssl(ssl ? static_cast(rdbuf()) : NULL) +#else + : std::iostream(static_cast(&_buf)), + _ssl(NULL) +#endif + { + setstate(std::ios::badbit); + } + + inline sockstream(const char *name, const char *service, + const struct sockaddr *from = NULL, socklen_t fromlen = 0) + : std::iostream(&_buf), _ssl(NULL) + { + _buf.connect(name, service, from, fromlen); + } + + inline ~sockstream() + { + if (_ssl) + { + delete _ssl; + } + } + + inline bool connected() const + { + return _ssl ? _ssl->connected() : _buf.connected(); + } + + inline void connect(const char *name, const char *service, + const struct sockaddr *from = NULL, + socklen_t fromlen = 0, unsigned int timeout = 0) + { + _buf.connect(name, service, from, fromlen, timeout); + if (_ssl && _buf.connected()) _ssl->connect(); + clear((_ssl ? _ssl->connected() : _buf.connected()) ? + std::ios::goodbit : std::ios::badbit); + } + + inline void connect(const char *name, const char *service, + unsigned int timeout = 0) + { + _buf.connect(name, service, NULL, 0, timeout); + if (_ssl && _buf.connected()) _ssl->connect(); + clear((_ssl ? _ssl->connected() : _buf.connected()) ? + std::ios::goodbit : std::ios::badbit); + } + + inline void attach(int fd) + { + _buf.attach(fd); + clear(); + } + + inline void disconnect() + { + if (_ssl) + { + _ssl->disconnect(); + } + + _buf.disconnect(); + clear(std::ios::badbit); + } + + inline void setkeepalive(bool fl = true) + { _buf.setkeepalive(fl); } + + inline void setnodelay(bool fl = true) + { _buf.setnodelay(fl); } + +#if defined(HAVE_GNUTLS) + sockstream *starttls(); +#endif +}; + +#endif + +/* + * Local Variables: + * mode: c++ + * tab-width: 8 + * c-basic-offset: 2 + * End: + */ diff --git a/NServer-0.9.1/sstream.cc b/NServer-0.9.1/sstream.cc deleted file mode 100644 index 7137e4e..0000000 --- a/NServer-0.9.1/sstream.cc +++ /dev/null @@ -1,118 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "config.h" -#include "Debug.h" -#include "sstream.h" - -using namespace std; - -void sstream::connectTo(char *name, char *service) -{ - connectTo(name, service, ""); -} - -void sstream::connectTo(char *name, char *service, char *from) -{ - char buf[1024]; - - if (is_connected()) - disconnect(); - strcpy(_name, name); - strcpy(_service, service); - - try { - if ((strcmp(from, "") != 0)) { - VERB(slog. - p(Logger:: - Debug) << - "sstream::connectTo using interface " << from - << "\n"); - sockinetaddr bindAddr(from); - (*((iosockinet *) this))->bind(bindAddr); - } - } - catch(sockerr e) { - sprintf(buf, "can't bind to %s\n", from); - slog. - p(Logger:: - Error) << "sstream::connectTo: can't bind to " << - from << " sockerr code: " << e.serrno() - << " sockerr operation: " << e.operation() - << " sockerrtext: " << e.errstr() << "\n"; - setstate(ios::badbit); - return; - } - - try { - VERB(slog. - p(Logger:: - Debug) << "sstream::connectTo connecting to " << - name << " service " << service << "\n"); - sockinetaddr serverAddr(name, service); - (*this)->connect(serverAddr); - } - catch(sockerr e) { - sprintf(buf, "cannot connect to %s (%s)\n", name, service); - slog. - p(Logger:: - Error) << "sstream::connectTo can't connect to " << - name << " " << service << " sockerr code: " << e. - serrno() << " sockerr operation: " << e.operation() - << " sockerrtext: " << e.errstr() << "\n"; - setstate(ios::badbit); - return; - } - - try { - (*this)->recvtimeout(-1); - //(*this)->sendtimeout (-1); - (*this)->keepalive(1); - } - catch(sockerr e) { - slog. - p(Logger:: - Error) << - "sstream::connectTo: setting keepalive error " << - " sockerr code: " << e. - serrno() << " sockerr operation: " << e.operation() - << " sockerrtext: " << e.errstr() << "\n"; - // FIXME: is this a fatal error? - } - - connected = 1; - clear(); -} - -void sstream::disconnect() -{ - sockbuf *pS; - - VERB(slog.p(Logger::Debug) << "sstream::disconnect()\n"); - try { - pS = rdbuf(); - pS->shutdown(sockbuf::shut_readwrite); - } catch (sockerr e) { - VERB(slog.p(Logger::Debug) << "sstream::disconnect() sockerror" - << e.serrno() << " sockerr operation: " - << e.operation() << " sockerrtext: " << e.errstr() - << "\n"); - } - _name[0] = '\0'; - _service[0] = '\0'; - connected = 0; - setstate(ios::badbit); -} - -int sstream::is_connected() -{ - return connected; -} diff --git a/NServer-0.9.1/sstream.h b/NServer-0.9.1/sstream.h deleted file mode 100644 index a231b44..0000000 --- a/NServer-0.9.1/sstream.h +++ /dev/null @@ -1,61 +0,0 @@ -#ifndef __sstream_h__ -#define __sstream_h__ - -/* - * Copyright (C) 2002 Herbert Straub - * Change the original hierachy [(C) Thomas Gschwind] - * from fstream -> sstream to iosockinet -> sstream - * This is for g++ >= 3.0 necessary. - */ - - -#include - -/** - * \class sstream - * \author Herbert Straub - * \date 2002 - * Change the original hierachy [(C) Thomas Gschwind] - * from fstream -> sstream to iosockinet -> sstream - * This is for g++ >= 3.0 necessary. - * - * \bug Documentation is missing. - */ -class sstream:public iosockinet { - char _name[256]; - char _service[256]; - int connected; - public: - sstream():iosockinet(sockbuf::sock_stream) { - _name[0] = '\0'; - _service[0] = '\0'; - connected = 0; - setstate(std::ios::badbit); - rdbuf()->setname ("upstream server socket"); - } sstream(char *name, - char *service):iosockinet(sockbuf::sock_stream) { - rdbuf()->setname ("upstream server socket"); - connectTo(name, service); - } - sstream(char *name, char *service, - char *from):iosockinet(sockbuf::sock_stream) { - rdbuf()->setname ("upstream server socket"); - connectTo(name, service, from); - } - ~sstream() { - disconnect(); - } - - const char *hostname() { - return _name; - } - const char *servicename() { - return _service; - } - int is_connected(); - void connectTo(char *name, char *service); - void connectTo(char *name, char *service, char *from); - void disconnect(); -}; - -#endif diff --git a/NServer-0.9.1/util.cc b/NServer-0.9.1/util.cc index 6550c91..13a875f 100644 --- a/NServer-0.9.1/util.cc +++ b/NServer-0.9.1/util.cc @@ -134,3 +134,11 @@ const char *getfqdn(void) return primary_hostname; } + +/* + * Local Variables: + * mode: c++ + * tab-width: 4 + * c-basic-offset: 4 + * End: + */ diff --git a/NServer-0.9.1/util.h b/NServer-0.9.1/util.h index 209e251..a70ac31 100644 --- a/NServer-0.9.1/util.h +++ b/NServer-0.9.1/util.h @@ -25,7 +25,6 @@ extern const char *group2dir(const char *name); * will be returned. */ extern int matchgroup(const char *pattern, const char *group); -extern int matchaddress(const char *pattern, const char *address); /** * \author Thomas Gschwind @@ -41,3 +40,11 @@ extern int matchaddress(const char *pattern, const char *address); extern const char *getfqdn(void); #endif + +/* + * Local Variables: + * mode: c++ + * tab-width: 4 + * c-basic-offset: 4 + * End: + */ diff --git a/NServer-0.9.1/wildmat.h b/NServer-0.9.1/wildmat.h index 7a14548..843dfe6 100644 --- a/NServer-0.9.1/wildmat.h +++ b/NServer-0.9.1/wildmat.h @@ -37,3 +37,11 @@ int wildmat(const char *pText, const char *p); #endif #endif + +/* + * Local Variables: + * mode: c++ + * tab-width: 4 + * c-basic-offset: 4 + * End: + */ diff --git a/NVClasses-0.9.1/Debug.h b/NVClasses-0.9.1/Debug.h index 2bf420c..0ace058 100644 --- a/NVClasses-0.9.1/Debug.h +++ b/NVClasses-0.9.1/Debug.h @@ -36,37 +36,28 @@ extern Logger slog; #endif #define NC_CATCH_ALL(text) \ -catch(sockerr e) \ -{ \ - slog.p(Logger::Error) << text << " caught " \ - << "sockbuf " << e.operation() \ - << e.serrno() \ - << " " << e.errstr() << "\n"; \ - throw; \ -} \ - \ -catch(UsageError e) \ +catch(const UsageError &e) \ { \ slog.p(Logger::Error) << text << " caught " << "UsageError "; \ e.print(); \ throw; \ } \ \ -catch(NotAllowedError e) \ +catch(const NotAllowedError &e) \ { \ slog.p(Logger::Error) << text << " caught " << "NotAllowdError "; \ e.print(); \ throw; \ } \ \ -catch(NoSuchArticleError e) \ +catch(const NoSuchArticleError &e) \ { \ slog.p(Logger::Error) << text << " caught " << "NoSuchArticleError "; \ e.print(); \ throw; \ } \ \ -catch(DuplicateArticleError e) \ +catch(const DuplicateArticleError &e) \ { \ slog.p(Logger::Error) << text << " caught " \ << "DuplicateArticleError "; \ @@ -74,56 +65,56 @@ catch(DuplicateArticleError e) \ throw; \ } \ \ -catch(NoSuchGroupError e) \ +catch(const NoSuchGroupError &e) \ { \ slog.p(Logger::Error) << text << " caught " << "NoSuchGroupError "; \ e.print(); \ throw; \ } \ \ -catch(NoNewsServerError e) \ +catch(const NoNewsServerError &e) \ { \ slog.p(Logger::Error) << text << " caught " << "NoNewsServerError "; \ e.print(); \ throw; \ } \ \ -catch(NoSuchFieldError e) \ +catch(const NoSuchFieldError &e) \ { \ slog.p(Logger::Error) << text << " caught " << "NoSuchFieldError "; \ e.print(); \ throw; \ } \ \ -catch(NSError e) \ +catch(const NSError &e) \ { \ slog.p(Logger::Error) << text << " caught " << "NSError "; \ e.print(); \ throw; \ } \ \ -catch(AssertionError e) \ +catch(const AssertionError &e) \ { \ slog.p(Logger::Error) << text << " caught " << "AssertionError "; \ e.print(); \ throw; \ } \ \ -catch(IOError e) \ +catch(const IOError &e) \ { \ slog.p(Logger::Error) << text << " caught " << "IOError "; \ e.print(); \ throw; \ } \ \ -catch(SystemError e) \ +catch(const SystemError &e) \ { \ slog.p(Logger::Error) << text << " caught " << "SystemError "; \ e.print(); \ throw; \ } \ \ -catch(Error e) \ +catch(const Error &e) \ { \ slog.p(Logger::Error) << text << " caught " << "Error "; \ e.print(); \ @@ -137,3 +128,11 @@ catch(...) \ } #endif + +/* + * Local Variables: + * mode: c++ + * tab-width: 4 + * c-basic-offset: 4 + * End: + */ diff --git a/NVClasses-0.9.1/Error.h b/NVClasses-0.9.1/Error.h index c0facca..b6de7c3 100644 --- a/NVClasses-0.9.1/Error.h +++ b/NVClasses-0.9.1/Error.h @@ -32,9 +32,9 @@ extern Logger slog; */ class Error { public: - string _errtext; - string _file; - string _function; + std::string _errtext; + std::string _file; + std::string _function; int _line; Error(const char *txt = "unknown"):_errtext(txt) { VERB(slog.p(Logger::Debug); @@ -45,11 +45,11 @@ class Error { VERB(slog.p(Logger::Debug); print()); } - Error(const string & txt):_errtext(txt) { + Error(const std::string & txt):_errtext(txt) { VERB(slog.p(Logger::Debug); print()); } - Error(const string & txt, const char *file, const char *function, + Error(const std::string & txt, const char *file, const char *function, int line) :_errtext(txt), _file(file), _function(function), _line(line) { VERB(slog.p(Logger::Debug); @@ -58,7 +58,7 @@ class Error { virtual ~ Error() { } - virtual void print() { + virtual void print() const { slog << "Exception!" << " File: " << _file << " Function: " << _function @@ -77,19 +77,19 @@ class SystemError:public Error { int _errno; SystemError(const char *txt = "unknown", int errnbr = -1) :Error(txt), _errno(errnbr) { - } SystemError(const string & txt, int errnbr = -1) + } SystemError(const std::string & txt, int errnbr = -1) :Error(txt), _errno(errnbr) { } SystemError(const char *txt, int errnbr, const char *file, const char *function, int line) :Error(txt, file, function, line), _errno(errnbr) { } - SystemError(const string & txt, int errnbr, const char *file, + SystemError(const std::string & txt, int errnbr, const char *file, const char *function, int line) :Error(txt, file, function, line), _errno(errnbr) { } - virtual void print() { + virtual void print() const { slog << "Exception!" << " Type: System" << " File: " << _file @@ -117,16 +117,16 @@ class IOError:public SystemError { function, line) { } - IOError(const string & txt, int errnbr = + IOError(const std::string & txt, int errnbr = -1):SystemError(txt, errnbr) { } - IOError(const string & txt, int errnbr, const char *file, + IOError(const std::string & txt, int errnbr, const char *file, const char *function, int line):SystemError(txt, errnbr, file, function, line) { } - virtual void print() { + virtual void print() const { slog << "Exception!" << " Type: IO" << " File: " << _file @@ -152,15 +152,15 @@ class AssertionError:public Error { function, line) { } - AssertionError(const string & txt):Error(txt) { + AssertionError(const std::string & txt):Error(txt) { } - AssertionError(const string & txt, const char *file, + AssertionError(const std::string & txt, const char *file, const char *function, int line):Error(txt, file, function, line) { } - virtual void print() { + virtual void print() const { slog << "Exception!" << " Type: Assertion" << " File: " << _file @@ -170,3 +170,11 @@ class AssertionError:public Error { }; #endif + +/* + * Local Variables: + * mode: c++ + * tab-width: 4 + * c-basic-offset: 4 + * End: + */ diff --git a/NVClasses-0.9.1/Logger.cc b/NVClasses-0.9.1/Logger.cc index d702790..f62ca16 100644 --- a/NVClasses-0.9.1/Logger.cc +++ b/NVClasses-0.9.1/Logger.cc @@ -92,6 +92,7 @@ void Logger::open(char *ident, int option, int facility) Logger::~Logger() { close(); + free(buf); } void Logger::close() @@ -116,6 +117,7 @@ Logger::Logger(char *fn, int option) Logger::~Logger() { close(); + free(buf); } void Logger::open(char *fn) @@ -177,3 +179,11 @@ Logger & operator<<(Logger & l, int i) sprintf(s, "%d", i); return l.write(s); } + +/* + * Local Variables: + * mode: c++ + * tab-width: 4 + * c-basic-offset: 4 + * End: + */ diff --git a/NVClasses-0.9.1/Logger.h b/NVClasses-0.9.1/Logger.h index 8d4009e..f31b8fa 100644 --- a/NVClasses-0.9.1/Logger.h +++ b/NVClasses-0.9.1/Logger.h @@ -15,8 +15,6 @@ #include #endif -using std::string; - /** * \class Logger * \author Thomas Gschwind @@ -105,10 +103,18 @@ class Logger { } friend Logger & operator<<(Logger & l, const char *s); - friend Logger & operator<<(Logger & l, const string & s); + friend Logger & operator<<(Logger & l, const std::string & s); friend Logger & operator<<(Logger & l, char ch); friend Logger & operator<<(Logger & l, unsigned int i); friend Logger & operator<<(Logger & l, int i); }; #endif + +/* + * Local Variables: + * mode: c++ + * tab-width: 4 + * c-basic-offset: 4 + * End: + */ diff --git a/NVClasses-0.9.1/NVArray.cc b/NVClasses-0.9.1/NVArray.cc index eac847c..906c22e 100644 --- a/NVClasses-0.9.1/NVArray.cc +++ b/NVClasses-0.9.1/NVArray.cc @@ -112,12 +112,14 @@ void NVArray::sprint(ostream & os) } NVArray::NVArray(const char *dbname, int flags) -:NVcontainer() + : NVcontainer() { open(dbname, flags); } -ASSERT(nvoff_t NVArray::nvalloc(size_t rsz) { +ASSERT( + nvoff_t NVArray::nvalloc(size_t rsz) + { nvoff_t r = NVcontainer::nvalloc(rsz); if (!arrtab) return r; if ((const char *) (arrtab + (arrlst - arrfst)) <= @@ -136,13 +138,14 @@ ASSERT(nvoff_t NVArray::nvalloc(size_t rsz) { int psz = *(unsigned long *) (mem_p + (p - sizeof(unsigned long))); if (mem_p + (p + psz) <= (const char *) arrtab) { NVcontainer::nvfree(p); return;} - kill(getpid(), SIGABRT);} - + kill(getpid(), SIGABRT); + } ) -void NVArray::open(const char *dbname, int flags) { +void NVArray::open(const char *dbname, int flags) +{ NVcontainer::open(dbname, flags); - } +} void NVArray::ssetsize(unsigned long fst, unsigned long lst) { @@ -274,3 +277,11 @@ void NVArray::print(ostream & os) sprint(os); lock(UnLock); } + +/* + * Local Variables: + * mode: c++ + * tab-width: 4 + * c-basic-offset: 4 + * End: + */ diff --git a/NVClasses-0.9.1/NVArray.h b/NVClasses-0.9.1/NVArray.h index 0dd1c9b..04078cf 100644 --- a/NVClasses-0.9.1/NVArray.h +++ b/NVClasses-0.9.1/NVArray.h @@ -5,8 +5,6 @@ #include"NVcontainer.h" -using std::ostream; - /* NVContainer Class Library */ class NVArray; class NVArrayIter; @@ -17,7 +15,7 @@ class NVArrayIter; * \bug Documentation is missing. */ class NVArray:public NVcontainer { - protected: + protected: void make_current(void); nvoff_t *arrtab; unsigned long arrfst, arrlst; @@ -28,9 +26,9 @@ class NVArray:public NVcontainer { int sis_empty(void); int shas_element(unsigned long i); void sget(unsigned long i, char **data, size_t * szdata); - void sprint(ostream & os); + void sprint(std::ostream & os); - public: + public: enum { force = 0x1 }; @@ -79,7 +77,7 @@ class NVArray:public NVcontainer { int is_empty(void); int has_element(unsigned long i); void get(unsigned long i, const char **data, size_t * szdata); - void print(ostream & os); + void print(std::ostream & os); }; #ifdef NVArrayIter @@ -88,7 +86,7 @@ class NVArrayIter { NVHash::Record * pos; NVHash::Record * curtail; unsigned long curhashval; - public: + public: NVHashIter() { ht = NULL; pos = NULL; @@ -162,3 +160,11 @@ class NVArrayIter { #endif #endif + +/* + * Local Variables: + * mode: c++ + * tab-width: 4 + * c-basic-offset: 4 + * End: + */ diff --git a/NVClasses-0.9.1/NVHash.cc b/NVClasses-0.9.1/NVHash.cc index 99c9e49..826e3be 100644 --- a/NVClasses-0.9.1/NVHash.cc +++ b/NVClasses-0.9.1/NVHash.cc @@ -54,7 +54,7 @@ void NVHash::sprint(ostream & os) } NVHash::NVHash(const char *dbname, unsigned long hashsz, int flags) -:NVlist() + : NVlist() { open(dbname, hashsz, flags); } @@ -115,3 +115,11 @@ void NVHash::print(ostream & os) sprint(os); lock(UnLock); } + +/* + * Local Variables: + * mode: c++ + * tab-width: 4 + * c-basic-offset: 4 + * End: + */ diff --git a/NVClasses-0.9.1/NVHash.h b/NVClasses-0.9.1/NVHash.h index 5045ee5..673eaf5 100644 --- a/NVClasses-0.9.1/NVHash.h +++ b/NVClasses-0.9.1/NVHash.h @@ -15,7 +15,7 @@ class NVHashIter; class NVHash:public NVlist { friend class NVHashIter; - protected: + protected: void make_current(void); nvoff_t *hashtab; unsigned long hashsz; @@ -25,10 +25,11 @@ class NVHash:public NVlist { void sadd(unsigned long h, const char *data, size_t szdata); void sprint(std::ostream & os); - public: - NVHash():NVlist() { - } NVHash(const char *dbname, unsigned long hashsz = 97, int flags = - 0); + public: + NVHash():NVlist() + { } + + NVHash(const char *dbname, unsigned long hashsz = 97, int flags = 0); /** * Open an NVHash object. @@ -36,14 +37,14 @@ class NVHash:public NVlist { * \param hashsz Size of the hash-table, if a new one is created. * \param flags Ignored at the moment. */ - void open(const char *dbname, unsigned long hashsz = - 97, int flags = 0); + void open(const char *dbname, unsigned long hashsz = 97, int flags = 0); /** * Returns the size of the has-table. * \return size of the hash table */ - unsigned long gethashsz(void) { + unsigned long gethashsz(void) + { // No lock and make_current invocation necessary, since // the hash-size must not change return hashsz; @@ -63,14 +64,16 @@ class NVHash:public NVlist { */ class NVHashIter { NVHash *ht; - NVHash::Record * pos; - NVHash::Record * curtail; + NVHash::Record * pos; + NVHash::Record * curtail; unsigned long curhashval; - public: - NVHashIter() { + + public: + NVHashIter() { ht = NULL; pos = NULL; - } NVHashIter(NVHash & nvl) { + } + NVHashIter(NVHash & nvl) { ht = &nvl; ht->lock(NVHash::ShrdLock); pos = NULL; @@ -139,3 +142,11 @@ class NVHashIter { }; #endif + +/* + * Local Variables: + * mode: c++ + * tab-width: 4 + * c-basic-offset: 4 + * End: + */ diff --git a/NVClasses-0.9.1/NVList.cc b/NVClasses-0.9.1/NVList.cc index 58b0a01..5cb52e2 100644 --- a/NVClasses-0.9.1/NVList.cc +++ b/NVClasses-0.9.1/NVList.cc @@ -53,3 +53,11 @@ void NVList::print(ostream & os) sprint(getdatap(), os); lock(UnLock); } + +/* + * Local Variables: + * mode: c++ + * tab-width: 4 + * c-basic-offset: 4 + * End: + */ diff --git a/NVClasses-0.9.1/NVList.h b/NVClasses-0.9.1/NVList.h index a2aaae1..c637c26 100644 --- a/NVClasses-0.9.1/NVList.h +++ b/NVClasses-0.9.1/NVList.h @@ -88,3 +88,11 @@ class NVListIter { }; #endif + +/* + * Local Variables: + * mode: c++ + * tab-width: 4 + * c-basic-offset: 4 + * End: + */ diff --git a/NVClasses-0.9.1/NVcontainer.cc b/NVClasses-0.9.1/NVcontainer.cc index 6d4732c..f317941 100644 --- a/NVClasses-0.9.1/NVcontainer.cc +++ b/NVClasses-0.9.1/NVcontainer.cc @@ -751,3 +751,11 @@ void NVcontainer::getmtime(nvtime_t * tm) (*tm) = mem_hdr->mtime; lock(UnLock); } + +/* + * Local Variables: + * mode: c++ + * tab-width: 4 + * c-basic-offset: 4 + * End: + */ diff --git a/NVClasses-0.9.1/NVcontainer.h b/NVClasses-0.9.1/NVcontainer.h index b3a8246..9c54dad 100644 --- a/NVClasses-0.9.1/NVcontainer.h +++ b/NVClasses-0.9.1/NVcontainer.h @@ -63,7 +63,7 @@ class NVcontainer { return r ? (char *) r - mem_p : 0; } - protected: + protected: NVcontainer(void); NVcontainer(const char *dbname, int flags = 0); virtual ~ NVcontainer(void); @@ -94,7 +94,7 @@ class NVcontainer { nvoff_t nvalloc(size_t rsz); void nvfree(nvoff_t f); - public: + public: enum { UnLock = F_UNLCK, ShrdLock = F_RDLCK, @@ -137,3 +137,11 @@ class NVcontainterIter { */ #endif + +/* + * Local Variables: + * mode: c++ + * tab-width: 4 + * c-basic-offset: 4 + * End: + */ diff --git a/NVClasses-0.9.1/NVlist.cc b/NVClasses-0.9.1/NVlist.cc index 3144ccc..79fe9e1 100644 --- a/NVClasses-0.9.1/NVlist.cc +++ b/NVClasses-0.9.1/NVlist.cc @@ -75,3 +75,11 @@ void NVlist::sprint(nvoff_t proot, ostream & os) r = NULL; } } + +/* + * Local Variables: + * mode: c++ + * tab-width: 4 + * c-basic-offset: 4 + * End: + */ diff --git a/NVClasses-0.9.1/NVlist.h b/NVClasses-0.9.1/NVlist.h index 5ebf069..380dc46 100644 --- a/NVClasses-0.9.1/NVlist.h +++ b/NVClasses-0.9.1/NVlist.h @@ -12,18 +12,22 @@ * \bug Documentation is missing. */ class NVlist:public NVcontainer { - protected: - NVlist(void):NVcontainer() { - } NVlist(const char *dbname, int flags = - 0):NVcontainer(dbname, flags) { - } + protected: + NVlist(void):NVcontainer() + { } + + NVlist(const char *dbname, int flags = 0) + : NVcontainer(dbname, flags) + { } + struct Record { unsigned long next; /* 64 */ unsigned long szdata; /* 64 */ // Data follows here char *datap() { return ((char *) this) + sizeof(Record); - }}; + } + }; Record *o2r(nvoff_t o) { return (Record *) (o ? mem_p + o : NULL); @@ -43,3 +47,11 @@ class NVlist:public NVcontainer { }; #endif + +/* + * Local Variables: + * mode: c++ + * tab-width: 4 + * c-basic-offset: 4 + * End: + */ diff --git a/README b/README index 0c6c833..a63118f 100644 --- a/README +++ b/README @@ -1,6 +1,7 @@ # NewsCache --- The free cache server for USENET News. # Copyright (C) 1996-1998 Thomas Gschwind # Copyright (C) 2001,2002 Herbert Straub +# Copyright (C) 2008 Christof Meerwald # # 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 @@ -46,10 +47,6 @@ Installation See INSTALL for details. -The Library Socket++ 1.2 is required by NewsCache. You can install Socket++ -as shared or static library. Please see: -http://www.linuxhacker.at/socketxx - After successful installation, you have to create your configuration file ${prefix}/etc/newscache.conf. A sample configuration file is copied to ${prefix}/etc/newscache.conf-dist. @@ -112,4 +109,4 @@ internet connectivity. Latest Release The latest release is always available from -http://www.linuxhacker.at/NewsCache +http://members.aon.at/hstraub/linux/newscache/ diff --git a/acconfig.h b/acconfig.h deleted file mode 100644 index dd39b47..0000000 --- a/acconfig.h +++ /dev/null @@ -1,59 +0,0 @@ -/* acconfig.h - This file is in the public domain. - - Descriptive text for the C preprocessor macros that - the distributed Autoconf macros can define. - No software package will use all of them; autoheader copies the ones - your configure.in uses into your configuration header file templates. - - The entries are in sort -df order: alphabetical, case insensitive, - ignoring punctuation (such as underscores). Although this order - can split up related entries, it makes it easier to check whether - a given entry is in the file. - - Leave the following blank line there!! Autoheader needs it. */ - - -/* These get defined to the options given to configure */ -#undef HAVE_LIBWRAP -#undef HAVE_SSTREAM -#undef MD5_CRYPT -#undef MD5_AUTO -#undef SHADOW_PASSWORD -#undef PAM_AUTH -#undef PAM_DEFAULT_SERVICENAME -#undef WITH_UNIQUE_PACKAGE_NAME -#undef WITH_LIBGPP -#undef WITH_SYSLOG -#undef WITH_EXCEPTIONS -#undef SYSCONFDIR -#ifdef WITH_EXCEPTIONS -#define EXCEPTION(x) throw x -#else -#define EXCEPTION(x) -#endif -#undef ENABLE_HEADERLOG -#undef ENABLE_DEBUG -#undef ENABLE_ASSERTIONS -#undef PLAIN_TEXT_PASSWORDS - -/* Which type does the third argument of accept have */ -#undef SOCKLEN_TYPE - -/* These get defined to the package/version numbers in configure.in */ -#undef PACKAGE -#undef VERSION - -/* Other obsolete configuration parameters */ -#undef CONF_ServerRoot -#undef CONF_UIDROOT - -/* Package names for NewsCacheClean and updatenews */ -#undef PACKAGE_NEWSCACHECLEAN -#undef PACKAGE_UPDATENEWS - - -/* Leave that blank line there!! Autoheader needs it. - If you're adding to this file, keep in mind: - The entries are in sort -df order: alphabetical, case insensitive, - ignoring punctuation (such as underscores). */ diff --git a/autogen b/autogen index 61bf763..5df4434 100755 --- a/autogen +++ b/autogen @@ -8,14 +8,8 @@ if [ -f Makefile ]; then make clean fi -echo "aclocal..." -aclocal -echo "autoheader..." -autoheader -echo "automake..." -automake --add-missing -echo "autoconf..." -autoconf +echo "autoreconf..." +autoreconf -i echo "Next run ./configure" echo "Next run make" diff --git a/configure.in b/configure.in index 18b2068..af1c20a 100644 --- a/configure.in +++ b/configure.in @@ -5,13 +5,10 @@ dnl Specify a header configuration file AM_CONFIG_HEADER(config.h) dnl Initialize automake stuff -AM_INIT_AUTOMAKE(NewsCache, 1.2rc6) +AM_INIT_AUTOMAKE(NewsCache, 1.3.ipv6) AC_DEFUN([AC_PROG_CXX_EXCEPTIONS],[]) -dnl Compiler flags -CXXFLAGS="-Wall ${CXXFLAGS}" - dnl **************************************************************** dnl Configuration options. dnl **************************************************************** @@ -19,17 +16,17 @@ dnl **************************************************************** dnl md5 AC_ARG_WITH(md5, [ --with-md5 enable md5 hashes for authinfo [default=yes]], if eval "test x$with_md5 = xyes"; then - AC_DEFINE(MD5_CRYPT) + AC_DEFINE(MD5_CRYPT, [1], [enable md5 hashes for authinfo]) fi, -AC_DEFINE(MD5_CRYPT) +AC_DEFINE(MD5_CRYPT, [1], [enable md5 hashes for authinfo]) ) dnl md5auto AC_ARG_WITH(md5_auto, [ --with-md5auto enable autodetection of md5 hashes [default=yes]], if eval "test x$with_md5auto = xyes"; then - AC_DEFINE(MD5_AUTO) + AC_DEFINE(MD5_AUTO, [1], [enable autodetection of md5 hashes]) fi, -AC_DEFINE(MD5_AUTO) +AC_DEFINE(MD5_AUTO, [1], [enable autodetection of md5 hashes]) ) dnl shadow @@ -43,64 +40,72 @@ with_shadow=auto dnl pam AC_ARG_WITH(pam, [ --with-pam support for PAM [default=no]], [case $withval in - yes) AC_DEFINE(PAM_AUTH) - AC_DEFINE(PAM_DEFAULT_SERVICENAME,"newscache") + yes) AC_DEFINE(PAM_AUTH, [1], [support for PAM]) + AC_DEFINE(PAM_DEFAULT_SERVICENAME, "newscache", [PAM default service name]) ;; - no) AC_DEFINE(PAM_DEFAULT_SERVICENAME,"newscache") + no) AC_DEFINE(PAM_DEFAULT_SERVICENAME, "newscache", [PAM default service name]) ;; - *) AC_DEFINE(PAM_AUTH) - AC_DEFINE_UNQUOTED(PAM_DEFAULT_SERVICENAME,"${withval}") + *) AC_DEFINE(PAM_AUTH, [1], [support for PAM]) + AC_DEFINE_UNQUOTED(PAM_DEFAULT_SERVICENAME, "${withval}", [PAM default service name]) ;; esac ] -,[AC_DEFINE(PAM_DEFAULT_SERVICENAME,"newscache")]) +,[AC_DEFINE(PAM_DEFAULT_SERVICENAME, "newscache", [PAM default service name])]) dnl syslog AC_ARG_WITH(syslog, [ --with-syslog use syslogd for logging [default=auto]], if eval "test x$with_syslog = xyes"; then - AC_DEFINE(WITH_SYSLOG) + AC_DEFINE(WITH_SYSLOG, [1], [use syslogd for logging]) fi, with_syslog=auto ) AC_ARG_ENABLE(headerlog, [ --enable-headerlog enable logging of postings' headers [default=no]], if eval "test x$enable_headerlog = xyes"; then - AC_DEFINE(ENABLE_HEADERLOG) + AC_DEFINE(ENABLE_HEADERLOG, [1], [enable logging of postings]) fi, ) AC_ARG_ENABLE(debug, [ --enable-debug turn on verbosity [default=no]], if eval "test x$enable_debug = xyes"; then - AC_DEFINE(ENABLE_DEBUG) + AC_DEFINE(ENABLE_DEBUG, [1], [turn on verbosity]) CXXFLAGS="-g -O0 $CXXFLAGS" fi, ) AC_ARG_ENABLE(plainpass, [ --enable-plainpass use plain text passwords check[default=no]], if eval "test x$enable_plainpass = xyes"; then - AC_DEFINE(PLAIN_TEXT_PASSWORDS) + AC_DEFINE(PLAIN_TEXT_PASSWORDS, [1], [use plain text passwords check]) fi, ) dnl Enable assertions AC_ARG_ENABLE(assertions, [ --enable-assertions turn on assertions [default=yes]], if eval "test x$enable_assertions = xyes"; then - AC_DEFINE(ENABLE_ASSERTIONS) + AC_DEFINE(ENABLE_ASSERTIONS, [1], [turn on assertions]) fi, -AC_DEFINE(ENABLE_ASSERTIONS) +AC_DEFINE(ENABLE_ASSERTIONS, [1], [turn on assertions]) ) -AC_ARG_WITH(uniquename, [ --with-uniquename with unique package name [default=no]], +AC_ARG_WITH(uniquename, [ --with-uniquename with unique package name [default=no]], if eval " test x$with_uniquenames = xno"; then - AC_DEFINE(WITH_UNIQUE_PACKAGE_NAME) + AC_DEFINE(WITH_UNIQUE_PACKAGE_NAME, [1], [with unique package name]) fi, ) -AC_DEFINE(PACKAGE_NEWSCACHECLEAN,"NewsCacheClean") -AC_DEFINE(PACKAGE_UPDATENEWS,"updatenews") +AC_ARG_WITH(gnutls, [ --with-gnutls build with GnuTLS support [default=yes]]) -dnl Set SYSCONFDIR in config.h. -AC_DEFINE_UNQUOTED(SYSCONFDIR,"${sysconfdir}") +AC_DEFINE(PACKAGE_NEWSCACHECLEAN, ["NewsCacheClean"], [newscacheclean package]) +AC_DEFINE(PACKAGE_UPDATENEWS, ["updatenews"], [updatenews package]) + +dnl Set CONFDIR in config.h. +if test x"$sysconfdir" = x"\${prefix}/etc"; then + # sysconfdir is set to its default value... fine + sysconfdir=`eval echo "$sysconfdir"` +fi +CONFDIR=$sysconfdir + +AC_DEFINE_UNQUOTED(SYSCONFDIR, ["$CONFDIR"], [sysconfdir]) dnl **************************************************************** dnl Checks for programs. @@ -171,8 +176,6 @@ dnl **************************************************************** AC_HEADER_STDC AC_HEADER_SYS_WAIT AC_CHECK_HEADERS(fcntl.h limits.h shadow.h sys/file.h syslog.h unistd.h tcpd.h sstream getopt.h) -AC_CHECK_HEADER(socket++/sockinet.h,, - AC_MSG_ERROR(Headers for library libsocket++ not found)) if eval "test x${with_pam+set} = xset"; then AC_CHECK_HEADERS(security/pam_appl.h) if test $ac_cv_header_security_pam_appl_h = no; then @@ -214,7 +217,7 @@ AC_TRY_LINK([#include extern "C" int hosts_ctl(char *daemon, char *client_name, char *client_addr, char *client_user); int allow_severity; int deny_severity;], [hosts_ctl(0,0,0,0);], AC_MSG_RESULT([yes]) -AC_DEFINE(HAVE_LIBWRAP) +AC_DEFINE(HAVE_LIBWRAP, [1], [have libwrap]) ac_cv_lib_wrap_hosts_ctl=yes, LIBS="$ac_save_LIBS" AC_MSG_RESULT([no]) @@ -242,31 +245,13 @@ ac_cv_accept_arg3_int=yes, AC_MSG_RESULT([size_t*]) ac_cv_accept_arg3_int=no) if eval "test x$ac_cv_accept_arg3_int = xyes"; then - AC_DEFINE(SOCKLEN_TYPE,unsigned int) -fi - -dnl libsocket++ -OLDLIBS=$LIBS -libsocket_found=no -AC_MSG_CHECKING("libsocket++") -LIBS="-lsocket++ $LIBS" -AC_TRY_LINK([#include ], [iosockinet sio; sio.rdbuf()->setname("Test");], - libsocket_found=yes ,) -if eval "test x$libsocket_found = xyes"; then - AC_MSG_RESULT(yes) -else - AC_MSG_RESULT(no) - LIBS=$OLDLIBS -fi - -if eval "test x$libsocket_found = xno"; then - AC_MSG_ERROR(No libsocket++ Library found!) + AC_DEFINE(SOCKLEN_TYPE, [unsigned int], [socklen type]) fi dnl CONF_UIDROOT dnl The userid of your superuser (usually root). dnl Usually, this is 0. -AC_DEFINE(CONF_UIDROOT,0) +AC_DEFINE(CONF_UIDROOT, 0, [The userid of your superuser (usually root)]) dnl **************************************************************** dnl Checks for required functions/headers. @@ -292,11 +277,23 @@ if eval "test x$with_shadow = xyes"; then exit 1 fi elif eval "test x$with_shadow = xyes -a x$ac_cv_header_shadow_h = xyes"; then - AC_DEFINE(SHADOW_PASSWORD) + AC_DEFINE(SHADOW_PASSWORD, [1], [shadow passwords]) with_shadow=yes fi +dnl **** Check for libgnutls **** +if test "x$with_gnutls" != "xno" +then + AC_CHECK_LIB(gnutls, gnutls_global_init, [ + AC_CHECK_HEADERS(gnutls/gnutls.h, [ + AC_DEFINE(HAVE_GNUTLS,, Build with GNUTLS support) + LIBS="$LIBS -lgnutls -lgcrypt" + have_gnutls=yes + ]) + ],, -lgcrypt) +fi + dnl **************************************************************** dnl Generate output files dnl **************************************************************** diff --git a/debian/README.Debian b/debian/README.Debian new file mode 100644 index 0000000..1351b92 --- /dev/null +++ b/debian/README.Debian @@ -0,0 +1,19 @@ +newscache for Debian +-------------------- + +This is not a official package from Debian. Please don't file bugs to the +Debian Bug Database! Send bug report direct to the Newscache Mailinglist +newscache@linuxhacker.org or direct to me using one of the following e-mail +addresses: herbert@linuxhacker.at or h.straub@aon.at or herbert@hstraub.at. + +The Debian Package is also available on http://apt-get.linuxhacker.at/ Package +Archive. If you want to use this Package Archiv on you server, then you have to +add the following lines to your /etc/apt/sources.list file: + +deb http://apt-get.linuxhacker.at/debian/ stable newscache +deb-src http://apt-get.linuxhacker.at/debian/ stable newscache + +deb http://apt-get.linuxhacker.at/debian/ stable libsocket++ +deb-src http://apt-get.linuxhacker.at/debian/ stable libsocket++ + + -- Herbert Straub , Mon, 5 Jul 2004 10:43:02 +0200 diff --git a/debian/changelog b/debian/changelog new file mode 100644 index 0000000..8e82ade --- /dev/null +++ b/debian/changelog @@ -0,0 +1,217 @@ +newscache (1.3.ipv6-1~cmeerw.11) unstable; urgency=low + + * autoconf/build updates + + -- Christof Meerwald Mon, 25 Apr 2011 10:23:51 +0100 + +newscache (1.3.ipv6-1~cmeerw.10) unstable; urgency=low + + * Fixed crash when a client tries to post as the first thing after + connecting + * Fixed default sysconfdir setting in config.h + + -- Christof Meerwald Fri, 15 Apr 2011 22:56:27 +0100 + +newscache (1.3.ipv6-0cmeerw.9) unstable; urgency=low + + * Added (client side) STARTTLS support + * Added (server side) CAPABILITIES support + + -- Christof Meerwald Sun, 26 Dec 2010 15:58:20 +0000 + +newscache (1.3.ipv6-0cmeerw.8) unstable; urgency=low + + * Updated documentation + * Fixed source code formatting + * Fixed two minor memory leaks + + -- Christof Meerwald Sat, 23 May 2009 15:40:02 +0100 + +newscache (1.3.ipv6-0cmeerw.7) unstable; urgency=low + + * Added GnuTLS support + + -- Christof Meerwald Fri, 15 May 2009 22:41:59 +0100 + +newscache (1.3.ipv6-0cmeerw.6) unstable; urgency=low + + * Implemented filtering of Xref headers + + -- Christof Meerwald Sun, 08 Feb 2009 13:25:43 +0000 + +newscache (1.3.ipv6-0cmeerw.5) unstable; urgency=low + + * Fix 64-bit issue when trying to post + + -- Christof Meerwald Sun, 21 Dec 2008 21:56:24 +0000 + +newscache (1.3.ipv6-0cmeerw.4) unstable; urgency=low + + * Updated Build-depends + + -- Christof Meerwald Wed, 17 Dec 2008 11:27:12 +0000 + +newscache (1.3.ipv6-0cmeerw.3) unstable; urgency=low + + * Fixed crash in MPList::makeFilter + + -- Christof Meerwald Wed, 17 Dec 2008 11:18:27 +0000 + +newscache (1.3.ipv6-0cmeerw.2) unstable; urgency=low + + * Be more liberal and accept 423 response to stat command + + -- Christof Meerwald Sat, 02 Aug 2008 23:21:16 +0100 + +newscache (1.3.ipv6-0cmeerw) unstable; urgency=low + + * IPv6 support + * new ConnectTimeout, ConnectBackoff and LimitGroupSize options + + -- Christof Meerwald Sat, 14 Jun 2008 21:33:39 +0100 + +newscache (1.2rc6-1cmeerw.2) unstable; urgency=low + + * Issue "mode reader" command before authentication + + -- Christof Meerwald Mon, 21 May 2007 20:02:53 +0100 + +newscache (1.2rc6-1cmeerw) unstable; urgency=low + + * Applied my own patches. + + -- Christof Meerwald Sun, 20 Feb 2005 17:45:27 +0100 + +newscache (1.2rc6-1) unstable; urgency=low + + * New upstream release + + * debian/control: adding build-depends: libpam0g-dev + + -- Herbert Straub Sun, 26 Sep 2004 22:36:54 +0200 + +newscache (1.2rc5-1) unstable; urgency=low + + * New upstream release + + * debian/dirs: adding var/log/news and var/spool/newscache + + * debian/init.d: lowercase for pidfilename and checking newscache.conf file, + restart is now $0 stop and $0 start; sleep 2 seconds; implementing reload + + * debian/newscache.cron.daily: removing updatenews + + * debian/postinst: removing obsolete links in/from doc dir. Setting + permissions on SpoolDirectory. Removing "Press return". + + * debian/postrm: don't remove /var/log/news directory, start-stop-daemon + with --oknodo + + * debian/rules: configure --with-pam, moving /etc/newscache.auth-dist and + /etc/newscache.conf-dist to ../examples/ + + -- Herbert Straub Mon, 7 Jul 2004 14:17:25 +0200 + +newscache (1.1.2-1) unstable; urgency=low + + * New upstream version + + -- Herbert Straub Mon, 28 Jun 2004 00:00:00 +0200 + +newscache (1.1.12-1) unstable; urgency=low + + * New upstream version + + * Bugfix: this version including the Tilman Linneweh patch-configure.in + + * Bugfix: this version including the Tilman Linneweh patch-Article.cc + + -- Herbert Straub Thu, 10 Apr 2003 15:53:41 +0200 + +newscache (1.1.8-1) unstable; urgency=low + + * New upstream version. + + * /usr/sbin/hoststat conflicts with sendmail, therefore /usr/sbin/hoststats + + -- Herbert Straub Wed, 18 Dec 2002 21:25:16 +0100 + +newscache (0.99.22-1) unstable; urgency=low + + * New upstream version. + + * /usr/sbin/hoststat conflicts with sendmail, therefor /usr/sbin/hoststats + + -- Herbert Straub Sat, 09 Nov 2002 12:44:41 +0100 + +newscache (0.99.19-0cmeerw) unstable; urgency=low + + * New upstream version. + + -- Christof Meerwald Sat, 16 Mar 2002 01:45:00 +0100 + +newscache (0.99.17-0cmeerw) unstable; urgency=low + + * New upstream version. + + -- Christof Meerwald Sat, 16 Mar 2002 00:15:00 +0100 + +newscache (0.99.9-2) frozen unstable; urgency=low + + * Recompiled against libstdc++2.9 + + -- Michael Alan Dorman Mon, 19 Oct 1998 09:09:09 -0400 + +newscache (0.99.9-1) unstable; urgency=low + + * New upstream version. + + -- Michael Alan Dorman Thu, 25 Jun 1998 09:09:09 -0400 + +newscache (0.99.7-1) unstable; urgency=low + + * New upstream version. + + -- Michael Alan Dorman Thu, 1 Jun 1998 09:09:09 -0400 + +newscache (0.99.6-1) unstable; urgency=low + + * New upstream version. + + -- Michael Alan Dorman Thu, 30 Apr 1998 09:09:09 -0400 + +newscache (0.99.4-1) unstable; urgency=low + + * New upstream version. + + -- Michael Alan Dorman Wed, 22 Apr 1998 09:09:09 -0400 + +newscache (0.99.3-1) unstable; urgency=low + + * New upstream version. + * Move /etc/newscache.conf-dist into examples + * Add /etc/init.d/newscache + * Add postinst, prerm, postrm + + -- Michael Alan Dorman Mon, 20 Apr 1998 09:09:09 -0400 + +newscache (0.99.2-1) unstable; urgency=low + + * New upstream version. + * Fix NVClasses/Error.h to not use errno as an internal variable name. + + -- Michael Alan Dorman Tue, 13 Apr 1998 09:09:09 -0400 + +newscache (0.99.1-1) unstable; urgency=low + + * New upstream version + + -- Michael Alan Dorman Tue, 3 Apr 1998 09:09:09 -0400 + +newscache (0.9.16-1) unstable; urgency=low + + * Initial Debianization. + + -- Michael Alan Dorman Tue, 3 Mar 1998 09:09:09 -0400 + + diff --git a/debian/control b/debian/control new file mode 100644 index 0000000..1b15f11 --- /dev/null +++ b/debian/control @@ -0,0 +1,18 @@ +Source: newscache +Section: unknown +Priority: optional +Maintainer: Herbert Straub +Build-Depends: debhelper (>= 4.0.0), libgnutls-dev, libpam0g-dev, texinfo +Standards-Version: 3.6.0 + +Package: newscache +Architecture: any +Depends: ${shlibs:Depends}, ${misc:Depends} +Description: NewsCache is a free cache server for USENET News. + NewsCache is a free cache server for USENET News. NewsCache acts to news + reading clients like a news server, except that it stores only those articles + that have been requested by at least one client. NewsCache targets problems + of the current News System like network bandwidth consump- tion or the IO + load caused by news clients. NewsCache acts to the upstream news server like + a news reader programm. It supports the following modes: cached, not-cached, + offline. diff --git a/debian/copyright b/debian/copyright new file mode 100644 index 0000000..1f7bb98 --- /dev/null +++ b/debian/copyright @@ -0,0 +1,14 @@ +This package was debianized by Herbert Straub on +Thu, 10 Apr 2003 15:53:41 +0200. + +It was downloaded from http://members.aon.at/hstraub/linux/newscache/ + +Upstream Author(s): + + 1996-2000 Thomas Gschwind + 2001-2003 Herbert Straub + +Copyright: + +This package is licensed under the GNU GENERAL PUBLIC LICENSE. A copy of the +GPL is provided on Debian systems in the /usr/share/common-licenses directory. diff --git a/debian/dirs b/debian/dirs new file mode 100644 index 0000000..5d2a87d --- /dev/null +++ b/debian/dirs @@ -0,0 +1,3 @@ +usr/sbin +var/log/news +var/cache/newscache diff --git a/debian/docs b/debian/docs new file mode 100644 index 0000000..5502ed8 --- /dev/null +++ b/debian/docs @@ -0,0 +1,3 @@ +NEWS +README +TODO diff --git a/debian/info b/debian/info new file mode 100644 index 0000000..c8cbec7 --- /dev/null +++ b/debian/info @@ -0,0 +1 @@ +doc/NewsCache.info diff --git a/debian/init.d b/debian/init.d new file mode 100644 index 0000000..005c990 --- /dev/null +++ b/debian/init.d @@ -0,0 +1,64 @@ +#! /bin/sh +### BEGIN INIT INFO +# Provides: newscache +# Required-Start: $remote_fs $syslog $named +# Required-Stop: $remote_fs $syslog +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Description: NNTP caching daemon +### END INIT INFO + +PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin +DAEMON=/usr/sbin/newscache +NAME=newscache +DESC=newscache + +test -x $DAEMON || exit 0 +test -f /etc/newscache.conf || exit 0 + +# Include newscache defaults if available +if [ -f /etc/default/newscache ] ; then + . /etc/default/newscache +fi + +set -e + +case "$1" in + start) + echo -n "Starting $DESC: " + start-stop-daemon --start --quiet --pidfile /var/run/$NAME.pid \ + --exec $DAEMON -- $DAEMON_OPTS + echo "$NAME." + ;; + stop) + echo -n "Stopping $DESC: " + start-stop-daemon --stop --oknodo --quiet --pidfile /var/run/$NAME.pid \ + --exec $DAEMON + echo "$NAME." + ;; + reload) + echo "Reloading $DESC configuration files." + start-stop-daemon --stop --signal 1 --quiet --pidfile \ + /var/run/$NAME.pid --exec $DAEMON + ;; + restart|force-reload) + # + # If the "reload" option is implemented, move the "force-reload" + # option to the "reload" entry above. If not, "force-reload" is + # just the same as "restart". + # + echo -n "Restarting $DESC: " + $0 stop + sleep 2 + $0 start + echo "$NAME." + ;; + *) + N=/etc/init.d/$NAME + # echo "Usage: $N {start|stop|restart|reload|force-reload}" >&2 + echo "Usage: $N {start|stop|restart|force-reload}" >&2 + exit 1 + ;; +esac + +exit 0 diff --git a/debian/newscache.cron.daily b/debian/newscache.cron.daily new file mode 100644 index 0000000..70ae570 --- /dev/null +++ b/debian/newscache.cron.daily @@ -0,0 +1,6 @@ +#!/bin/sh -e + +# If it's configured +if [ -f /etc/newscache.conf ]; then + /usr/sbin/newscacheclean > /dev/null +fi diff --git a/debian/postinst b/debian/postinst new file mode 100644 index 0000000..ef98ffd --- /dev/null +++ b/debian/postinst @@ -0,0 +1,21 @@ +#!/bin/sh -e + +# Install the links into /etc/init.d +update-rc.d newscache defaults >/dev/null + +# Setting the permissions on SpoolDirectory +chown news:news /var/cache/newscache +chmod 0770 /var/cache/newscache + +# If there's not already a configuration file +if [ ! -f /etc/newscache.conf ]; then + echo " " + echo "There is currently no autoconfiguration for newscache." + echo " " + echo "Please examine /usr/share/doc/newscache/examples/newscache.conf" + echo "and read the manpage for newscache.conf(5)." + echo " " +else + /etc/init.d/newscache start +fi + diff --git a/debian/postrm b/debian/postrm new file mode 100644 index 0000000..5d9ab0a --- /dev/null +++ b/debian/postrm @@ -0,0 +1,22 @@ +#!/bin/sh -e + +# If we're purging the package +if [ "$1" = "purge" ]; then + + # Remove the links + update-rc.d newscache remove >/dev/null + + # Remove the configuration file + if [ -f /etc/newscache.conf ]; then + rm -f /etc/newscache.conf + fi + + # Remove the spool directory + if [ -d /var/cache/newscache ]; then + rm -rf /var/cache/newscache + fi + + # Remove the log directory + # Not done here, because the log directory + # is configured by the sysklogd package +fi diff --git a/debian/rules b/debian/rules new file mode 100755 index 0000000..756d73e --- /dev/null +++ b/debian/rules @@ -0,0 +1,120 @@ +#!/usr/bin/make -f +# -*- makefile -*- +# Author: Herbert Straub +# derived from: +# Sample debian/rules that uses debhelper. +# GNU copyright 1997 to 1999 by Joey Hess. + +# Uncomment this to turn on verbose mode. +#export DH_VERBOSE=1 +DH_COMPAT=2 + +CFLAGS = -Wall -g + +ifneq (,$(findstring noopt,$(DEB_BUILD_OPTIONS))) + CFLAGS += -O0 +else + CFLAGS += -O2 +endif +ifeq (,$(findstring nostrip,$(DEB_BUILD_OPTIONS))) + INSTALL_PROGRAM += -s +endif + +configure: configure-stamp +configure-stamp: + dh_testdir + + chmod a+rx configure depcomp install-sh missing + ./configure --prefix=/usr --infodir=/usr/share/info \ + --mandir=/user/share/man --sysconfdir=/etc --with-pam \ + --with-gnutls + + touch configure-stamp + + +build: build-stamp + +build-stamp: configure-stamp + dh_testdir + + $(MAKE) + + touch build-stamp + +clean: + dh_testdir + dh_testroot + rm -f build-stamp configure-stamp + + # Add here commands to clean up after the build process. + #-$(MAKE) clean + if [ -e Makefile ]; then \ + $(MAKE) clean; \ + fi + + rm -fR autom4te.cache + rm -f config.guess config.log config.status config.sub \ + etc/NewsCache.init etc/newscache.init stamp-h1 + + find . -name "Makefile" -print0 | \ + xargs -0 --no-run-if-empty rm -f + find . -name ".deps" -print0 | \ + xargs -0 --no-run-if-empty rm -rf + + dh_clean + +install: build + dh_testdir + dh_testroot + dh_clean -k + dh_installdirs + + # Add here commands to install the package into debian/newscache. + $(MAKE) prefix="$(CURDIR)/debian/tmp/usr" \ + infodir="$(CURDIR)/debian/tmp/usr/share/info" \ + mandir="$(CURDIR)/debian/tmp/usr/share/man" \ + sysconfdir="$(CURDIR)/debian/tmp/etc" \ + install + + # Now correcting Names + mv "etc/NewsCache.init" "etc/newscache.init" + +# Build architecture-independent files here. +binary-indep: build install +# We have nothing to do by default. + +# Build architecture-dependent files here. +binary-arch: build install + dh_testdir + dh_testroot + dh_installchangelogs ChangeLog + dh_installdocs + dh_installexamples "$(CURDIR)/etc/newscache.conf-dist" \ + "$(CURDIR)/etc/newscache.auth-dist" \ + "$(CURDIR)/etc/newscache.init" +# dh_install +# dh_installmenu +# dh_installdebconf +# dh_installlogrotate +# dh_installemacsen +# dh_installpam +# dh_installmime + dh_installinit + dh_installcron + dh_installinfo + dh_installman + dh_link + dh_strip + dh_compress + dh_fixperms +# dh_perl +# dh_python +# dh_makeshlibs + dh_installdeb + dh_shlibdeps + dh_gencontrol + dh_md5sums + dh_builddeb + +binary: binary-indep binary-arch +.PHONY: build clean binary-indep binary-arch binary install configure diff --git a/doc/NewsCache.info b/doc/NewsCache.info deleted file mode 100644 index afd6337..0000000 --- a/doc/NewsCache.info +++ /dev/null @@ -1,822 +0,0 @@ -This is Info file NewsCache.info, produced by Makeinfo version 1.68 -from the input file NewsCache.texinfo. - - This is the NewsCache Reference Manual. - - Copyright (C) 1998 Thomas Gschwind - - This edition is for NewsCache version 0.2. - - Permission is granted to make and distribute verbatim copies of this -manual provided the copyright notice and this permission notice are -preserved on all copies. - - Permission is granted to copy and distribute modified versions of -this manual under the conditions for verbatim copying, provided that the -entire resulting derived work is distributed under the terms of a -permission notice identical to this one. - - Permission is granted to copy and distribute translations of this -manual into another language, under the above conditions for modified -versions, except that this permission notice may be stated in a -translation approved by the Free Software Foundation. - - -File: NewsCache.info, Node: Top, Next: Introduction, Prev: (dir), Up: (dir) - -NewsCache Reference Manual -************************** - - NewsCache is a free cache server for USENET News. This manual -explains the configuration options and describes, how to configure -NewsCache to work in different environments. This manual applies to -NewsCache version 0.2. - -* Menu: - -* Introduction:: Introduction -* Compatibility:: Compatible news readers and servers -* General Options:: General configuration options -* ServerList Option:: How to configure the list of news servers -* Access Control:: Allow/Deby hosts from connecting to NewsCache -* Statistics:: Gathering statistics from the log files -* Bugs and Misfeatures:: Bugs and Misfeatures -* FAQ:: Frequently Asked Questions -* Inside NewsCache:: The source code of NewsCache -* Concept Index:: Concept index - - -File: NewsCache.info, Node: Introduction, Next: Compatibility, Prev: Top, Up: Top - -Introduction -************ - - NewsCache is a free cache server for USENET News. NewsCache acts to -news reading clients like a news server, except that it stores only -those articles that have been requested by at least one client. -NewsCache targets problems of the current News System like network -bandwidth consumption or the IO load caused by news clients. - - NewsCache can be used in combination with a news server. In this -setup news reading clients are connected to NewsCache instead of to the -news server. In a small test at our university, we got a hit rate of -over 30%, although the interests of the people accessing NewsCache was -relatively wide spread. This figure can be mapped onto a reduction of -the load at the news server. - - NewsCache can also replace leaf node news servers, if not all of the -articles are permanently accessed by news clients. NewsCache only stores -those newsgroups and articles being accessed frequently, while still -providing a virtual full feed. This reduces the network bandwidth -between the former news server and the news feed and also hardware -requirements (both in terms of disk space and CPU performance). Less -CPU performance is sufficient because no local article numbering has to -be performed and a smaller database has to be searched. - - NewsCache can also be used for the provision of local newsgroups -without setting up and maintaining a news server with a full feed. -Instead you set up a news server holding only your local newsgorups and -let NewsCache multiplex between those news servers. - - In the rest of this document, we will explain, how NewsCache can be -configured for different operation environments. - - -File: NewsCache.info, Node: Compatibility, Next: General Options, Prev: Introduction, Up: Top - -Compatibility -************* - - NewsCache has been tested in combination with several news readers -and servers. - -News Readers -============ - - The following news readers have been reported to work in combination -with NewsCache: gnus, knews, MS Internet Mail and News, MS Outlook -Express, netscape, pine, slrn, tin, xrn. - - MS Internet Explorer für Windows 3.1, Version 3.01.2723 should work -starting from NewsCache Version 0.99.12. However, this version of -Internet Explorer retrieves articles by their article id and this -version of NewsCache does not cache articles retrieved by their article -identifier. - -Article Reinstatement Bug -------------------------- - - Some news readers mark deleted articles as read. However, if the -article is reinstated on the news server, the article is still marked -as read and the user will never see this article as unread. According -to RFC977, (Network News Transfer Protocol) (http://info.internet.isi.edu/in-notes/rfc/files/rfc977.txt) it is allowed that deleted articles -are reinstated. This is also documented in the new NNTP-draft which -should be published as RFC within the next months. - - This bug can only occur if NewsCache cannot connect to its news -server. The following gives a scenario when this can happen, which is -mainly the case in offline mode. - - 1. A client requests the active database from NewsCache. (The active - database is a list of all the available newsgroups and their low - and high watermarks.) - - 2. The client selects a newsgroup and requests its overview database. - - 3. However, the link between NewsCache and its news server is down - and thus NewsCache cannot provide the overview records for all the - articles. - - 4. The client assumes that all the articles without overview record - have been deleted and marks those as read. - -News Servers -============ - - All news servers that provide an overview database should work in -combination with NewsCache. Tested news servers are: INN, Microsoft's -News server, AMU News under VMS. In fact NewsCache should work with -every News Server that supports the `list', `group', `listgroup', -`[x]over', `article' commands. - - -File: NewsCache.info, Node: General Options, Next: ServerList Option, Prev: Compatibility, Up: Top - -General Configuration Options -***************************** - - No matter which configuration you use, I recommend to set up a -separate user for NewsCache, although I took care of security issues, -when writing NewsCache. *A service that needs not to run as priviledged -user, should not run as priviledged user.* - - First of all, you should specify, which configuration version, you -are using. The current version is version 5. Thus, you should include -the following line at the beginning of your `newscache.conf'-file: - - ConfigVersion 5 - - NewsCache can be started either as `standalone' server or from -`inetd'. Using a standalone server has the advantage that the -configuration file will be read only at the first startup. However, you -will have one more process running all of the time (although sleeping). -Starting NewsCache in standalone mode allows you specify some additional -configuration options. Usually, you start a service (NewsCache in this -case) as standalone server, if it is accessed frequently or, if you need -one of the additional configuration options. - - If you are running NewsCache as standalone server, you should also -specify the port where NewsCache should listen for NNTP connections and -a pid file where NewsCache stores its pid. The port name may be one of -the well known ports (usually listed in `/etc/services') or a port -number prepended by the `#'-sign. - - ServerType standalone - CachePort nntp - PidFile /var/run/NewsCache.pid - - If NewsCache is started as standalone server, the maximum number of -connections can be specified using the `MaxConnections' command. -Whenever a new client connects when this limit is reached, it will -receive a `400 too many users' response and the connection will be -closed afterwards. - - MaxConnections 16 - - If you start NewsCache as standalone server with a port below 1024, -you have to start NewsCache as root. However, NewsCache will switch the -user and groupname as soon as it has bound to the socket. The Username -and Groupname options specify the user and group to switch to. If -NewsCache is started by inetd, you should set the username in -inetd.conf and repeat it in `newscache.conf' as shown above. - - Username news - Groupname news - - If NewsCache cannot determine your hostname, you must specify your -hostname using the `Hostname' directive. - Hostname my.host.name - - You also should set the email-address of the person responsible for -this installation of NewsCache. This address will be displayed in the -help message displayed by NNTP's `HELP' command. - - Admin you@your.provider - - Timeouts for the retrieval of the active database and the description -(*In version 0.99.13, the retrieval of the newsgroup descriptions is -not implemented*) of the newsgroups are set with the `Timeouts' command -(The values are given in seconds). The values indicate the time, when -NewsCache reloads the active database or the description of the -newsgroups. While the active database changes rather frequently, the -description for newsgroups changes seldomly. I recommend to use a value -around 5 minutes for the active database and a value around 1 day for -the newsgroup descriptions. - - With `ClientTimeout' you can specify an inactivity timer. If the -client does not send any commands for this time, the connection is -closed by the server. A useful value is around 15 minutes. Values below -3 minutes should not be used because that would violate the current NNTP -draft specification. - - Timeouts 300 86400 - ClientTimeout 900 - - The directory for the spool area of NewsCache is set using the -`SpoolDirectory' command. The size in KiloBytes of the spool area can -be set with with the `SpoolSize' directive. Usually, the spool area -should be big enough to store the most frequently used newsgroups. -NewsCache itself does not perform article replacement. This is done by -the the `NewsCacheClean' program which should be run every few hours by -crond. `NewsCacheClean' removes newsgroups until the used diskspace is -below `SpoolSize'. - - *Before starting NewsCache, check that this directory exists and -that NewsCache has read and write permissions. Additionally, this -directory must be on a local partition! NewsCache uses file locking and -does not make use of lockd. Mounting this directory via NFS would -decrease performance, so it does not make sense anyway.* - - SpoolDirectory /lhome/newscache/NSpool - SpoolSize 100000 - - NewsCache supports two different log-facilities. a) it can log -messages using syslogd (the default) and b) it can use its own log -files. This has to be configured, when building NewsCache. If you -prefer log files, use the `--without-syslog' when configuring -NewsCache. For detailed build instructions see the INSTALL and README -files. - - If you are using log files you have to set the log directory using -the `LogDirectory' command. If you are using syslogd, this statement -has no effect. *Before starting NewsCache, check that this directory -exists and that NewsCache has read and write permissions.* - - LogDirectory /lhome/newscache/log - - NewsCache supports several log styles. A host accessing NewsCache -can be logged with its IP-address (`ip-address'), its (`hostname'), or -both. NewsCache uses the same log format as INN and some additional log -entries. If you want to log only INN style log messages, add the -`strict-inn' option. This will be only useful if you use some statistic -tools for INN that get confused with those extra messages. *In version -0.99.13 `strict-inn' is only supported on the LOG_NOTICE level.* - - LogStyle ip-address strict-inn - - Whenever a News Server closes the connection, NewsCache retries to -connect to the News Server and to issue the command again. After a -certain number of retries, NewsCache gives up. - - Retries 3 - - The file that lists all those newsgroups that have to be prefetched -is set by the `PrefetchFile'-directive. - - PrefetchFile /lhome/newscache/etc/prefetch - - -File: NewsCache.info, Node: ServerList Option, Next: Access Control, Prev: General Options, Up: Top - -ServerList Configuration -************************ - - The list of News Servers to be used is specified using the -`NewsServerList' command. The command's syntax is as follows: - - NewsServerList := "NewsServerList" "{" serverlist "}" - serverlist := | "Server" hostname port "{" optionlist "}" serverlist - optionlist := | option optionlist - option := "Read" grouplist | "PostTo" grouplist | - "User" string | "Password" string - "GroupTimeout" number | "Options" flags - - In the following example, all articles are cached, read from and -posted to the news server `news.tuwien.ac.at'. When a client accesses a -newsgroup older than 180 seconds, NewsCache checks whether new articles -arrived on its upstream news server. - - NewsServerList { - Server news.tuwien.ac.at nntp { - Read * - PostTo * - GroupTimeout 180 - Options cached - } - } - - The arguments given to the `Server'-directive are the name of your -news server followed by its port, followed by the per-server -configuration options. The per-server configuration options are: - -`Read' - indicates which newsgroups should be read from the news server. Its - argument is a comma separated list of newsgroup names. Each - newsgroup name may have the `*' at its end indicating any sequence - of characters. - -`PostTo' - indicates which articles should be posted to the news server. Its - argument has the same syntax as the argument of the `Read'-option. - All articles posted to one or more of these newsgroups will be - sent to that news server. - -`GroupTimeout' - after that amount of seconds the newsgroup's active database is - requested anew. - -`User' - If authentication is required by the upstream news server, use this - option to specify the username that should be used. - -`Password' - If authentication is required by the upstream news server, use this - option to specify the password for the above mentioned username. - -`Options' - gives one or more of the following options: `not-offline'--contact - the upstream news server whenever necessary; `offline'--never - contact the upstream news server; `semioffline'--contact the - upstream news server whenever necessary, except for retrieving the - list of newsgroups; `not-setpostflag', `setpostflag'; - `not-cached', `cached'. - -`Commands' - This option indicates which commands are (or are not) supported by - the upstream news server. Some versions of the netscape collabra - server do not support the `OVER' command correctly. If you are - connecting to such a news server, you might want to specify - `not-over' here. - - The configuration of the news server(s) depends on your application -domain. The following sections present and discuss different -NewsCache-configurations. - -Reducing the Load of a News Server -================================== - - If you just want to reduce the load caused by news reading clients, -you set up NewsCache with your news server as its feed and let all the -clients read news from NewsCache. The server configuration can be as -simple as in the following example because you have only one news server -where newsgroups are read from and all the articles are posted to. - - NewsServerList { - Server news.tuwien.ac.at nntp { - Read * - PostTo * - GroupTimeout 180 - Options cached - } - } - -Local Newsgroups -================ - - NewsCache can be configured to provide transparent access to local -newsgroups. For this configuration you have to setup a small news server -holding all your local newsgroups and let NewsCache multiplex betwenn -these two news servers. - - Assume that our primary news server is `news.tuwien.ac.at' as in the -example above and that the news server holding our local newsgroups is -located at `news.infosys.tuwien.ac.at'. In this case our server -configuration looks as follows: - - NewsServerList { - Server news.tuwien.ac.at nntp { - Read * - PostTo * - GroupTimeout 180 - Options cached - } - Server news.infosys.tuwien.ac.at #120 { - Read at.tuwien.infosys.* - PostTo at.tuwien.infosys.* - GroupTimeout 120 - Options not-cached - } - } - - The newsgroups starting with at.tuwien.infosys.* are retrieved from -our local news server and the others from `news.tuwien.ac.at'. With the -statements above all the newsgroups from our primary news server -beginning with `at.tuwien.infosys.' are eliminated. Even those that do -not appear on our local news servers. This behavior is intended -because newsgroups are added and deleted rather frequently and otherwise -it would be difficult to say which newsgroup comes from which news -server. - - The matching of newsgroup-names is based on the longest match. For -instance if the newsgroup configuration of our primary news server is -`*,at.tuwien.infosys.tuwien.general' than -`at.tuwien.infosys.tuwien.general' would be retrieved from our primary -news server. - - The `not-cached' option indicates that articles requested from our -local news server must now be cached. Caching these articles is -pointless because our local news server is not that much loaded and has -a good connection to our local news server. In fact they are located on -the same machine. - - *Whether the cached/not-cached flag is supported depends on your -installation. If you configured NewsCache at compile time with the -`--enable-notcached' flag this flag is supported, otherwise not. This -is disabled by default due to problems of gcc-2.7.2. If you are using -egcs or gcc-2.8.1, you can turn on this flag safely.* - -Replacing a Leaf Node News Server -================================= - - NewsCache can also be used to replace leaf node news servers. The -advantages are clear: The cache server retrieves articles on demand -only. Thus fewer disk space and CPU performance is sufficient because -the news database is smaller. - - Below, you can find a sample configuration file: - - NewsServerList { - Server news.tuwien.ac.at nntp { - Read * - PostTo * - GroupTimeout 120 - Options cached - } - Server starnews.stardivision.de nntp { - Read stardivision.* - PostTo stardivision.* - GroupTimeout 180 - Options cached,semioffline - } - NoServer { - Read alt.binaries.*,another.hierarchy.* - PostTo alt.binaries.* - } - } - - In this example, we read all groups except `stardivison.*', -`alt.binaries.*', and `another.hierarchy.*' from `news.tuwien.ac.at'. -All postings, except for `stardivision.*' and `alt.binaries.*' are -posted to `news.tuwien.ac.at'. All articles being retrieved from any -news server are cached. - - All of these configurations are already explained in the previous -section except for `semioffline'. This option indicates that the active -database should not be retrieved from this news server. In that case it -has to be retrieved seperately using `updatenews'. - - Explain this option in more detail. Why it is useful (servers with -slow link)... - -Offline Mode -============ - - In the case, you cannot (or do not want to) have a permanent -connection to your news server, you must operate NewsCache in offline -mode. This is usually the case if you have some sort of dial-up -networking. Two types of offline operation modes are possible: - - 1. You tell NewsCache that it must never try to contact its news - server. - - 2. NewsCache may contact the news server, but fails because no - network is available. - - If you use some sort of dial on demand solution like diald, you have -to use the first solution. Otherwise, it depends on your preferences. -The second solution has the advantage that users can access all -newsgroups, when the connection to your provider is active. However, the -disadvantage is additional overhead because NewsCache will try to -connect to the news server, whenever a newsgroup times out. - - Assume, that we chose the first approach because we have diald -installed. Here is a sample news server configuration for this case. -Since we are reading news from different news servers, we want -NewsCache to do the multiplexing for us. - - NewsServerList { - Server news.tuwien.ac.at nntp { - Read * - PostTo * - GroupTimeout 180 - Options offline - } - Server news.wu-wien.ac.at nntp { - Read at.wu-wien.* - PostTo .none. - GroupTimeout 300 - Options offline not-setpostflag - } - } - - The first Server definition indicates your primary news server. The -news server at Technische Universität Wien. The GroupTimeout directive -is ignored in offline and semioffline mode. - - The secondary news server is `news.wu-wien.ac.at'. However, from our -provider (TU Wien), we are not allowed to post on this news server. So -posting is switched off by specifying `.none.' for the `PostTo' -newsgroup pattern. Postings to those newsgroups will also be handled by -news.tuwien.ac.at because some of the at.wu-wien groups are also -available from news.tuwien.ac.at. This is the reason, why we set the -`not-setpostflag'. Otherwise the posting flag of all the at.wu-wien -groups would be set to `n' (=forbidden) since we do not have permission -to submit postings to that server. - - Since the configuration options prohibit NewsCache to retrieve News -from `news.tuwien.ac.at' or `news.wu-wien.ac.at', we have to fetch the -newsgroups we are interested to read manually. This is done with the -`updatenews' program which retrieves all newsgroups listed in your -`prefetch'-file. - -Different Configuration for Newsgroups on same News Server -========================================================== - - It is possible to have different configurations for different -newsgroups on the same news server. The trick is to list one server -several times--each time with a different set of newsgroups. - - The example below shows a configuration, where the local newsgroups -are updated every 60 seconds and all the other groups every 15 minutes. -The reason to do is obvious. Over 90% of postings to the at.* groups are -posted to news.tuwien.ac.at. While most of the postings to the other -groups are not posted directly to news.tuwien.ac.at. Since our news -server does not permanently check for new articles on its news feed, it -makes no sense to request those articles every minute. - - NewsServerList { - Server news.tuwien.ac.at nntp { - Read * - PostTo * - GroupTimeout 900 - Options offline - } - Server news.tuwien.ac.at nntp { - Read at.tuwien.* - PostTo .none. - GroupTimeout 60 - Options semioffline - } - } - - In the current implementation, the configuration as shown above has a -slight disadvantage, if the group descriptions are not disjunct. The -active database will be requested twice from news.tuwien.ac.at. In our -case for all newsgroups, with all the at.tuwien.* groups eliminated and -once for all the at.tuwien.* groups. If the news server does not support -the `list active [wildmat]' command, the *whole* active database will -be requested twice. While this does not matter for a news server with -a good connection to the cache, you will think twice reconsider your -choice if the connection is not that good. - - Whether `list active [wildmat]' is supported by your news server can -be found out by connecting with telnet to the news server on port NNTP. -As soon as the news server welcomes you, you type `list active -comp.*'. If the server replies with `215 ...' and a list of -newsgroups, it is supported, otherwise your server does not support it. - - $ telnet news.tuwien.ac.at nntp - 200 news.tuwien.ac.at InterNetNews... - list active comp.* - 215 Newsgroups in form "group high low flags". - comp.ai 0000045852 0000045542 y - comp.ai.alife 0000010191 0000010141 y - ... - . - - -File: NewsCache.info, Node: Access Control, Next: Statistics, Prev: ServerList Option, Up: Top - -Access Control -************** - - Access Control is implemented using libwrap (the same mechanism as -used by `tcpd'). However, NewsCache has to be compiled with libwrap -(This is done automatically, if it is found on your system). libwrap -allows to sepcify hosts that are allowed or denied from accessing -NewsCache in `/etc/hosts.allow' or `/etc/hosts.deny'. The service name -is `NewsCache'. - - If users from `news.tuwien.ac.at' and the domain `bad.guy.com' -should be blocked from accessing NewsCache, the `hosts.deny' should -include the following line. - - NewsCache: news.tuwien.ac.at, .bad.guy.com - - For detailed information, please consult the `libwrap', -`hosts.allow', `hosts.deny' manual pages. - - -File: NewsCache.info, Node: Statistics, Next: Bugs and Misfeatures, Prev: Access Control, Up: Top - -Statistics -********** - - The NewsCache distribution includes several programs for analyzing -log files. - - There are two commands: accesslog, cachestat - - Tool for hit and miss statistics, should accept inet and file format -(conversion script). - - Top newsgroups (#art, bytes) - - Top hosts (#connect, bytes) - - -File: NewsCache.info, Node: Bugs and Misfeatures, Next: FAQ, Prev: Statistics, Up: Top - -Bugs and Misfeatures -******************** - - The description of newsgroups is currently not cached properly. The -file containing the descriptions (`.newsgroups' in NewsCache's spool -directory) has to be created manually. The file's format is `newsgroup -description'. - - comp.os.linux.alpha Linux on Digital Alpha machines. - comp.os.linux.m68k Linux operating system on 680x0 Amiga, Atari, VME. - comp.os.linux.networking Networking and communications under Linux. - comp.os.linux.setup Linux installation and system administration. - comp.os.linux.x Linux X Window System servers, clients, libs and fonts. - - The file containing the descriptions can be obtained from your News -Server. Initiate a `telnet' session on port `nntp' and issue the `list -newsgroups' command. - - $ telnet news.tuwien.ac.at nntp - 200 news.tuwien.ac.at InterNetNews... - list newsgroups - 215 Newsgroups in form "group high low flags". - comp.os.linux.alpha Linux on Digital Alpha machines. - comp.os.linux.m68k Linux operating system on 680x0 Amiga, Atari, VME. - ... - . - - -File: NewsCache.info, Node: FAQ, Next: Inside NewsCache, Prev: Bugs and Misfeatures, Up: Top - -Frequently Asked Questions -************************** - -Where can I get NewsCache? - You can can get NewsCache from its - homepage (http://www.infosys.tuwien.ac.at/NewsCache/). - -What is the latest version of NewsCache? - As of this writing the latest version is 0.99.13. The latest - version of NewsCache can always be found at its - homepage (http://www.infosys.tuwien.ac.at/NewsCache/). - -How does this compare to NNTPCACHE? - NNTPCACHE is a cache server similar to NewsCache. Features of - NewsCache are offline news reading and a cleanly designed class - hierarchy, which is easily extendible. It provides classes for - accessing news from a news server and base classes for - implementing a news server tailored to user needs. - -How can I contribute to the development of NewsCache? - Volunteers are always welcome! Simply send an email to - tom@infosys.tuwien.ac.at. I am sure that we will find something - interesting for you. - -Does it have any concept of expiry of articles? - At the moment, NewsCache expires articles on a per newsgroup basis. - This degrades the hit rate of NewsCache only slightly as long as - the most frequently read newsgroups fit into the spool area. With - the current implementation, expiry on a per article basis would be - too inefficient, since this requires an index of all the articles. - An index with all the articles and thus article replacement on a - per article basis should be finished around January. - -Which newsgroups are returned by the list commands? - The list command will return those newsgroups from the news - server(s) that match the newsgroup descriptions of the Server - directives. - -Why does the list command return more than the configured newsgroups? - Whenever you change the set of newsgroups to be retrieved from the - news server(s), you should remove the active database. Simply type - rm /path/to/news/spool/.active. This is not done automatically. - -I do not get any logging messages? - NewsCache uses either syslog or log files (depending on the - compile time configuration). For syslog, you should include a line - similar to: news.info /var/log/news/newslog For a detailed - explanation, see man syslog.conf. - -When I start my news reader it takes several seconds before I can - read news. Many news readers request the active database or a - list of new newsgrousp when starting up. The latter is implemented - by the former in NewsCache which may take more time. If your news - reader issues only a request for new newsgroups it will take - substantially longer when you use NewsCache. In this situation set - the timeout for the active database to once a week or even higher. - If the news reader does not request the active database, it uses - another mean for requesting the number of articles in each group - (E.g., netscape issues the group command for each newsgroup). - - -File: NewsCache.info, Node: Inside NewsCache, Next: Concept Index, Prev: FAQ, Up: Top - -Inside NewsCache -**************** - - The source code of NewsCache is structured as follows: - -`src/Config*' - reads and stores the general configuration options. - -`NServer/MPList*' - responsible for storing per server configuration options. - -`NServer/*' - handles all the news databases and the communication with News - Servers. - -`NServer/NServer*' - the logic to retrieve information from different servers (LServer - for retrieving information from the local database; RServer for - retrieving articles from a remote News Server; CServer an RServer - with caching functionality) - -`NVClasses/*' - the basic database routines. - -`src/NewsCache.cc' - responsible for interacting with news readers. - - This will help you to look around. If you have questions, send email. - - -File: NewsCache.info, Node: Concept Index, Prev: Inside NewsCache, Up: Top - -Concept Index -************* - -* Menu: - -* access control: Access Control. -* accesslog: Statistics. -* Admin: General Options. -* authentication: ServerList Option. -* cachestat: Statistics. -* ClientTimeout: General Options. -* compatible news readers: Compatibility. -* compatible news servers: Compatibility. -* ConfigVersion: General Options. -* FAQ: FAQ. -* Groupname: General Options. -* GroupTimeout: ServerList Option. -* Hostname: General Options. -* Implementation: Inside NewsCache. -* Introduction: Introduction. -* list newsgroups: Bugs and Misfeatures. -* load reduction: ServerList Option. -* local newsgroups: ServerList Option. -* LogDirectory: General Options. -* logging <1>: Statistics. -* logging: General Options. -* LogStyle: General Options. -* MaxConnections: General Options. -* multiplexing: ServerList Option. -* NewsCacheClean: General Options. -* newsgroup descriptions: Bugs and Misfeatures. -* NewsServerList: ServerList Option. -* offline operation: ServerList Option. -* Options: ServerList Option. -* Password: ServerList Option. -* PidFile: General Options. -* PostTo: ServerList Option. -* PrefetchFile: General Options. -* Read: ServerList Option. -* replace leaf node news server: ServerList Option. -* Retries: General Options. -* Server: ServerList Option. -* ServerType: General Options. -* slow server: ServerList Option. -* SpoolDirectory: General Options. -* SpoolSize: General Options. -* statistics: Statistics. -* Timeouts: General Options. -* updatenews: ServerList Option. -* User: ServerList Option. -* Username: General Options. - - - -Tag Table: -Node: Top939 -Node: Introduction1929 -Node: Compatibility3686 -Node: General Options5941 -Node: ServerList Option12020 -Node: Access Control24092 -Node: Statistics24900 -Node: Bugs and Misfeatures25318 -Node: FAQ26509 -Node: Inside NewsCache29572 -Node: Concept Index30467 - -End Tag Table diff --git a/doc/NewsCache.texinfo b/doc/NewsCache.texinfo index e194943..505c26f 100644 --- a/doc/NewsCache.texinfo +++ b/doc/NewsCache.texinfo @@ -393,8 +393,10 @@ NewsServerList := "NewsServerList" "@{" serverlist "@}" serverlist := | "Server" hostname port "@{" optionlist "@}" serverlist optionlist := | option optionlist option := "Read" grouplist | "PostTo" grouplist | - "User" string | "Password" string - "GroupTimeout" number | "Options" flags + "User" string | "Password" string | + "GroupTimeout" number | "LimitGroupSize" number | + "ConnectTimeout" number | "ConnectBackoff" number | + "Options" flags @end example In the following example, all articles are cached, read from and posted @@ -445,14 +447,26 @@ option to specify the username that should be used. @cindex authentication If authentication is required by the upstream news server, use this option to specify the password for the above mentioned username. +@item ConnectTimeout +@cdindex ConnectTimeout +Limit the timeout for connections to upstream servers. +@item ConnectBackoff +@cdindex ConnectBackoff +Wait the specfied amount of seconds before trying to reconnect to an +upstream server again after a refused connection attempt. +@item LimitGroupSize +@cdindex LimitGroupSize +Limits the maximum size of a group. @item Options @cdindex Options gives one or more of the following options: @code{not-offline}---contact the upstream news server whenever necessary; @code{offline}---never contact the upstream news server; @code{semioffline}---contact the upstream news server whenever necessary, except for retrieving the list -of newsgroups; @code{not-setpostflag}, @code{setpostflag}; -@code{not-cached}, @code{cached}. +of newsgroups; @code{ssl}---use (plain) SSL encrypted connection; +@code{starttls}---use STARTTLS encrypted connection; +@code{not-setpostflag}, @code{setpostflag}; @code{not-cached}, +@code{cached}, @code{dontgenmsgid}. @item Commands This option indicates which commands are (or are not) supported by the upstream news server. Some versions of the netscape collabra server do diff --git a/etc/newscache.conf-dist b/etc/newscache.conf-dist index da17779..12b99de 100644 --- a/etc/newscache.conf-dist +++ b/etc/newscache.conf-dist @@ -191,11 +191,22 @@ AccessList { # BindFrom: # Interface for outgoing connections (for multihomed hosts) # (Code by Vladislav Bogdanov, slava@nsys.by) +# LimitGroupSize: +# Limit the group size to the specified number of messages - this is +# useful if your upstream server has very long group retention (or +# never expires at all) +# ConnectBackoff: +# Don't try to reconnect for specified amount of seconds after failed +# connection attempt +# ConnectTimeout: +# Timeout connects after specified amount of seconds # Options: # (not-)offline, semioffline ... retrieve nothing/everything/articles # (not-)setpostflag ... set postflag to n in the active database, if # posting to the news server is not allowed # (not-)cached ... not yet implemented +# (not-)ssl ... use (plain) SSL encrypted connection +# (not-)starttls ... use STARTTLS encrypted connection # Commands: # All commands are switched on by default and NewsCache tries itself # to find out which of the commands are supported. In some situations diff --git a/install-sh b/install-sh deleted file mode 100755 index e843669..0000000 --- a/install-sh +++ /dev/null @@ -1,250 +0,0 @@ -#!/bin/sh -# -# install - install a program, script, or datafile -# This comes from X11R5 (mit/util/scripts/install.sh). -# -# Copyright 1991 by the Massachusetts Institute of Technology -# -# Permission to use, copy, modify, distribute, and sell this software and its -# documentation for any purpose 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 M.I.T. not be used in advertising or -# publicity pertaining to distribution of the software without specific, -# written prior permission. M.I.T. makes no representations about the -# suitability of this software for any purpose. It is provided "as is" -# without express or implied warranty. -# -# Calling this script install-sh is preferred over install.sh, to prevent -# `make' implicit rules from creating a file called install from it -# when there is no Makefile. -# -# This script is compatible with the BSD install script, but was written -# from scratch. It can only install one file at a time, a restriction -# shared with many OS's install programs. - - -# set DOITPROG to echo to test this script - -# Don't use :- since 4.3BSD and earlier shells don't like it. -doit="${DOITPROG-}" - - -# put in absolute paths if you don't have them in your path; or use env. vars. - -mvprog="${MVPROG-mv}" -cpprog="${CPPROG-cp}" -chmodprog="${CHMODPROG-chmod}" -chownprog="${CHOWNPROG-chown}" -chgrpprog="${CHGRPPROG-chgrp}" -stripprog="${STRIPPROG-strip}" -rmprog="${RMPROG-rm}" -mkdirprog="${MKDIRPROG-mkdir}" - -transformbasename="" -transform_arg="" -instcmd="$mvprog" -chmodcmd="$chmodprog 0755" -chowncmd="" -chgrpcmd="" -stripcmd="" -rmcmd="$rmprog -f" -mvcmd="$mvprog" -src="" -dst="" -dir_arg="" - -while [ x"$1" != x ]; do - case $1 in - -c) instcmd="$cpprog" - shift - continue;; - - -d) dir_arg=true - shift - continue;; - - -m) chmodcmd="$chmodprog $2" - shift - shift - continue;; - - -o) chowncmd="$chownprog $2" - shift - shift - continue;; - - -g) chgrpcmd="$chgrpprog $2" - shift - shift - continue;; - - -s) stripcmd="$stripprog" - shift - continue;; - - -t=*) transformarg=`echo $1 | sed 's/-t=//'` - shift - continue;; - - -b=*) transformbasename=`echo $1 | sed 's/-b=//'` - shift - continue;; - - *) if [ x"$src" = x ] - then - src=$1 - else - # this colon is to work around a 386BSD /bin/sh bug - : - dst=$1 - fi - shift - continue;; - esac -done - -if [ x"$src" = x ] -then - echo "install: no input file specified" - exit 1 -else - true -fi - -if [ x"$dir_arg" != x ]; then - dst=$src - src="" - - if [ -d $dst ]; then - instcmd=: - else - instcmd=mkdir - fi -else - -# Waiting for this to be detected by the "$instcmd $src $dsttmp" command -# might cause directories to be created, which would be especially bad -# if $src (and thus $dsttmp) contains '*'. - - if [ -f $src -o -d $src ] - then - true - else - echo "install: $src does not exist" - exit 1 - fi - - if [ x"$dst" = x ] - then - echo "install: no destination specified" - exit 1 - else - true - fi - -# If destination is a directory, append the input filename; if your system -# does not like double slashes in filenames, you may need to add some logic - - if [ -d $dst ] - then - dst="$dst"/`basename $src` - else - true - fi -fi - -## this sed command emulates the dirname command -dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` - -# Make sure that the destination directory exists. -# this part is taken from Noah Friedman's mkinstalldirs script - -# Skip lots of stat calls in the usual case. -if [ ! -d "$dstdir" ]; then -defaultIFS=' -' -IFS="${IFS-${defaultIFS}}" - -oIFS="${IFS}" -# Some sh's can't handle IFS=/ for some reason. -IFS='%' -set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'` -IFS="${oIFS}" - -pathcomp='' - -while [ $# -ne 0 ] ; do - pathcomp="${pathcomp}${1}" - shift - - if [ ! -d "${pathcomp}" ] ; - then - $mkdirprog "${pathcomp}" - else - true - fi - - pathcomp="${pathcomp}/" -done -fi - -if [ x"$dir_arg" != x ] -then - $doit $instcmd $dst && - - if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi && - if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi && - if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi && - if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi -else - -# If we're going to rename the final executable, determine the name now. - - if [ x"$transformarg" = x ] - then - dstfile=`basename $dst` - else - dstfile=`basename $dst $transformbasename | - sed $transformarg`$transformbasename - fi - -# don't allow the sed command to completely eliminate the filename - - if [ x"$dstfile" = x ] - then - dstfile=`basename $dst` - else - true - fi - -# Make a temp file name in the proper directory. - - dsttmp=$dstdir/#inst.$$# - -# Move or copy the file name to the temp name - - $doit $instcmd $src $dsttmp && - - trap "rm -f ${dsttmp}" 0 && - -# and set any options; do chmod last to preserve setuid bits - -# If any of these fail, we abort the whole thing. If we want to -# ignore errors from any of these, just make sure not to ignore -# errors from the above "$doit $instcmd $src $dsttmp" command. - - if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi && - if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi && - if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi && - if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi && - -# Now rename the file to the real destination. - - $doit $rmcmd -f $dstdir/$dstfile && - $doit $mvcmd $dsttmp $dstdir/$dstfile - -fi && - - -exit 0 diff --git a/md5lib/md5.cc b/md5lib/md5.cc index 4f70253..405d6bb 100644 --- a/md5lib/md5.cc +++ b/md5lib/md5.cc @@ -254,3 +254,11 @@ void MD5Transform(uint32 buf[4], uint32 const in[16]) #endif #endif /* MD5_CRYPT */ + +/* + * Local Variables: + * mode: c++ + * tab-width: 4 + * c-basic-offset: 4 + * End: + */ diff --git a/md5lib/md5.h b/md5lib/md5.h index f0eb22c..2e0db04 100644 --- a/md5lib/md5.h +++ b/md5lib/md5.h @@ -28,3 +28,11 @@ extern "C" { } #endif #endif /* !MD5_H */ + +/* + * Local Variables: + * mode: c++ + * tab-width: 4 + * c-basic-offset: 4 + * End: + */ diff --git a/md5lib/md5crypt.cc b/md5lib/md5crypt.cc index d1fa6a4..780004d 100644 --- a/md5lib/md5crypt.cc +++ b/md5lib/md5crypt.cc @@ -87,3 +87,11 @@ char *md5crypt(const char *password) return (strdup(base64digest)); } + +/* + * Local Variables: + * mode: c++ + * tab-width: 4 + * c-basic-offset: 4 + * End: + */ diff --git a/md5lib/md5crypt.h b/md5lib/md5crypt.h index ad7e768..5729f90 100644 --- a/md5lib/md5crypt.h +++ b/md5lib/md5crypt.h @@ -14,3 +14,11 @@ extern "C" { } #endif #endif /*MD5_CRYPT_H */ + +/* + * Local Variables: + * mode: c++ + * tab-width: 4 + * c-basic-offset: 4 + * End: + */ diff --git a/missing b/missing deleted file mode 100755 index a6abd06..0000000 --- a/missing +++ /dev/null @@ -1,134 +0,0 @@ -#! /bin/sh -# Common stub for a few missing GNU programs while installing. -# Copyright (C) 1996, 1997 Free Software Foundation, Inc. -# Franc,ois Pinard , 1996. - -# 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, 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., 59 Temple Place - Suite 330, Boston, MA -# 02111-1307, USA. - -if test $# -eq 0; then - echo 1>&2 "Try \`$0 --help' for more information" - exit 1 -fi - -case "$1" in - - -h|--h|--he|--hel|--help) - echo "\ -$0 [OPTION]... PROGRAM [ARGUMENT]... - -Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an -error status if there is no known handling for PROGRAM. - -Options: - -h, --help display this help and exit - -v, --version output version information and exit - -Supported PROGRAM values: - aclocal touch file \`aclocal.m4' - autoconf touch file \`configure' - autoheader touch file \`config.h.in' - automake touch all \`Makefile.in' files - bison touch file \`y.tab.c' - makeinfo touch the output file - yacc touch file \`y.tab.c'" - ;; - - -v|--v|--ve|--ver|--vers|--versi|--versio|--version) - echo "missing - GNU libit 0.0" - ;; - - -*) - echo 1>&2 "$0: Unknown \`$1' option" - echo 1>&2 "Try \`$0 --help' for more information" - exit 1 - ;; - - aclocal) - echo 1>&2 "\ -WARNING: \`$1' is missing on your system. You should only need it if - you modified \`acinclude.m4' or \`configure.in'. You might want - to install the \`Automake' and \`Perl' packages. Grab them from - any GNU archive site." - touch aclocal.m4 - ;; - - autoconf) - echo 1>&2 "\ -WARNING: \`$1' is missing on your system. You should only need it if - you modified \`configure.in'. You might want to install the - \`Autoconf' and \`GNU m4' packages. Grab them from any GNU - archive site." - touch configure - ;; - - autoheader) - echo 1>&2 "\ -WARNING: \`$1' is missing on your system. You should only need it if - you modified \`acconfig.h' or \`configure.in'. You might want - to install the \`Autoconf' and \`GNU m4' packages. Grab them - from any GNU archive site." - touch config.h.in - ;; - - automake) - echo 1>&2 "\ -WARNING: \`$1' is missing on your system. You should only need it if - you modified \`Makefile.am', \`acinclude.m4' or \`configure.in'. - You might want to install the \`Automake' and \`Perl' packages. - Grab them from any GNU archive site." - find . -type f -name Makefile.am -print \ - | sed 's/^\(.*\).am$/touch \1.in/' \ - | sh - ;; - - bison|yacc) - echo 1>&2 "\ -WARNING: \`$1' is missing on your system. You should only need it if - you modified a \`.y' file. You may need the \`Bison' package - in order for those modifications to take effect. You can get - \`Bison' from any GNU archive site." - touch y.tab.c - ;; - - makeinfo) - echo 1>&2 "\ -WARNING: \`$1' is missing on your system. You should only need it if - you modified a \`.texi' or \`.texinfo' file, or any other file - indirectly affecting the aspect of the manual. The spurious - call might also be the consequence of using a buggy \`make' (AIX, - DU, IRIX). You might want to install the \`Texinfo' package or - the \`GNU make' package. Grab either from any GNU archive site." - file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'` - if test -z "$file"; then - file=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'` - file=`sed -n '/^@setfilename/ { s/.* \([^ ]*\) *$/\1/; p; q; }' $file` - fi - touch $file - ;; - - *) - echo 1>&2 "\ -WARNING: \`$1' is needed, and you do not seem to have it handy on your - system. You might have modified some files without having the - proper tools for further handling them. Check the \`README' file, - it often tells you about the needed prerequirements for installing - this package. You may also peek at any GNU archive site, in case - some other package would contain this missing \`$1' program." - exit 1 - ;; -esac - -exit 0 diff --git a/mkinstalldirs b/mkinstalldirs deleted file mode 100755 index 4eec994..0000000 --- a/mkinstalldirs +++ /dev/null @@ -1,40 +0,0 @@ -#! /bin/sh -# mkinstalldirs --- make directory hierarchy -# Author: Noah Friedman -# Created: 1993-05-16 -# Public domain - -# $Id: mkinstalldirs,v 1.1.1.2 2002/02/05 10:07:56 stb Exp $ - -errstatus=0 - -for file -do - set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'` - shift - - pathcomp= - for d - do - pathcomp="$pathcomp$d" - case "$pathcomp" in - -* ) pathcomp=./$pathcomp ;; - esac - - if test ! -d "$pathcomp"; then - echo "mkdir $pathcomp" 1>&2 - - mkdir "$pathcomp" || lasterr=$? - - if test ! -d "$pathcomp"; then - errstatus=$lasterr - fi - fi - - pathcomp="$pathcomp/" - done -done - -exit $errstatus - -# mkinstalldirs ends here diff --git a/src/AccessList.cc b/src/AccessList.cc index 5ef67b5..d53a678 100644 --- a/src/AccessList.cc +++ b/src/AccessList.cc @@ -6,12 +6,16 @@ #include #endif +#include +#include +#include + #include using namespace std; -ostream & operator<<(ostream & os, const AccessEntry & ae) +std::ostream & operator<<(std::ostream & os, const AccessEntry & ae) { #ifdef HAVE_SSTREAM stringstream sb; @@ -28,7 +32,7 @@ ostream & operator<<(ostream & os, const AccessEntry & ae) os << " postto=" << ae.postTo << endl; ae.authentication.printParameters (&sb); os << " PAMServicename " << ae.PAMServicename << endl; - string t = sb.str(); + std::string t = sb.str(); // replace \t\tAuthentication with "" t.replace(0, 17, ""); os << " authentication=" << t << endl; @@ -45,64 +49,98 @@ ostream & operator<<(ostream & os, const AccessEntry & ae) #define NOT_INADDR(s) (s[strspn(s,"01234567890./")] != 0) -int in_domain(const char *name, const char *domain) +bool in_domain(const std::string &name, const std::string &domain) { - int name_len = strlen(name); - int domain_len = strlen(domain); - - if (domain[domain_len - 1] == '.') { /* prefix */ - return STRN_EQ(name, domain, domain_len); - } else if (domain[0] == '.') { /* suffix */ - int n = name_len - domain_len; - return n > 0 && STR_EQ(name + n, domain); + const size_t name_len = name.length(); + const size_t domain_len = domain.length(); + + if (domain[0] == '.') { /* suffix */ + if (name_len > domain_len) { + const size_t n = name_len - domain_len; + return STR_EQ(name.c_str() + n, domain.c_str()); + } } else { /* exact match */ - return STR_EQ(name, domain); + return STR_EQ(name.c_str(), domain.c_str()); } + + return false; } -int matchaddress(const char *pattern, - const char *name, const struct in_addr &host_addr) +bool matchaddress(const struct sockaddr *pattern_addr, + socklen_t pattern_addrlen, unsigned short prefixlen, + const struct sockaddr *host_addr, socklen_t host_addrlen) { - const char *p = pattern; + const uint8_t *pattern_bytes = NULL; + const uint8_t *host_bytes = NULL; + size_t addrlen = 0; + + if ((pattern_addr->sa_family == AF_INET) && + (host_addr->sa_family == AF_INET)) { + addrlen = 4; + pattern_bytes = (uint8_t *) &((const struct sockaddr_in *) pattern_addr)->sin_addr.s_addr; + host_bytes = (uint8_t *) &((const struct sockaddr_in *) host_addr)->sin_addr.s_addr; + } - while (*p && *p != '/') - ++p; + if ((pattern_addr->sa_family == AF_INET6) && + (host_addr->sa_family == AF_INET6)) { + addrlen = 16; + pattern_bytes = ((const struct sockaddr_in6 *) pattern_addr)->sin6_addr.s6_addr; + host_bytes = ((const struct sockaddr_in6 *) host_addr)->sin6_addr.s6_addr; + } - if (*p) { - string net(pattern, p - pattern); - string mask(p + 1); + if ((pattern_addr->sa_family == AF_INET) && + (host_addr->sa_family == AF_INET6) && + (IN6_IS_ADDR_V4MAPPED(&((const struct sockaddr_in6 *) host_addr)->sin6_addr))) { + addrlen = 4; + pattern_bytes = (uint8_t *) &((const struct sockaddr_in *) pattern_addr)->sin_addr.s_addr; + host_bytes = &((const struct sockaddr_in6 *) host_addr)->sin6_addr.s6_addr[12]; + } - struct in_addr net_addr, mask_addr; - if (!inet_aton(net.c_str(), &net_addr)) - return 0; - if (!inet_aton(mask.c_str(), &mask_addr)) - return 0; + if ((pattern_bytes != NULL) && (host_bytes != NULL)) { + for (unsigned int i = 0; i < addrlen; i++) { + if (prefixlen >= (8*i + 8)) { + if ((*pattern_bytes ^ *host_bytes) != 0) { + return false; + } + } else { + return (*pattern_bytes ^ *host_bytes) < (1 << (8 - (prefixlen % 8))); + } - return (host_addr.s_addr & mask_addr.s_addr) == - net_addr.s_addr; - } else { /* anything else */ - return NOT_INADDR(name) && in_domain(name, pattern); + pattern_bytes++; + host_bytes++; + } } + + return false; } -AccessEntry *AccessList::client(const char *name, struct in_addr addr) +AccessEntry *AccessList::client(const char *name, const struct sockaddr *addr, + socklen_t addrlen) { - std::vector < AccessEntry >::iterator begin = vector.begin(), end = - vector.end(); - - while (begin != end) { - if (matchaddress(begin->hostname, name, addr) || - begin->hostname[0] == '\0') { - return &(*begin); + std::vector < AccessEntry >::iterator iter = vector.begin(); + const std::vector < AccessEntry >::iterator &end = vector.end(); + + while (iter != end) { + if (iter->addr.ss_family == AF_UNSPEC) { + if (iter->hostname.empty() || + in_domain(name, iter->hostname)) { + return &(*iter); + } + } else { + if (matchaddress((const struct sockaddr *) &iter->addr, + sizeof(iter->addr), + iter->prefixlen, addr, addrlen)) { + return &(*iter); + } } - ++begin; + ++iter; } return NULL; } void AccessList::read(Lexer & lex) { - string tok, host, port; + std::string tok, host, port; int default_found = 0; tok = lex.getToken(); if (tok != "{") @@ -135,7 +173,7 @@ void AccessList::read(Lexer & lex) if (!(filter_set&0x02)) cur.read=a1; \ if (!(filter_set&0x04)) cur.postTo=a1; -void AccessEntry::printParameters (ostream *pOut) +void AccessEntry::printParameters (std::ostream *pOut) { if (hostname[0] != '\0') { *pOut << "\tClient " << hostname << " {" << endl; @@ -159,17 +197,17 @@ void AccessEntry::printParameters (ostream *pOut) *pOut << "\t}" << endl; } -void AccessEntry::modifyAccessFlags (const string &flags) +void AccessEntry::modifyAccessFlags (const std::string &flags) { - string t; - string::size_type i=0, j; + std::string t; + std::string::size_type i=0, j; if (flags.length() == 0) { return; } do { - if ((j=flags.find (",", i)) == string::npos) { + if ((j=flags.find (",", i)) == std::string::npos) { j=flags.length(); } t = flags.substr (i, j-i); @@ -196,10 +234,68 @@ void AccessEntry::modifyAccessFlags (const string &flags) void AccessList::readClient(Lexer & lex, const char *address) { - string tok, a1, a2, a3; + std::string tok, a1, a2, a3; int filter_set = 0; AccessEntry cur; - strcpy(cur.hostname, address); + + int family = AF_UNSPEC; + const char *slash = strchr(address, '/'); + if (slash != NULL) { + if (strspn(slash + 1, "0123456789") == strlen(slash + 1)) { + cur.prefixlen = atoi(slash + 1); + } else { + unsigned char mask[4]; + if (inet_pton(AF_INET, slash + 1, &mask) != 1) { + throw SyntaxError(lex, "unable to parse IPv4 netmask", ERROR_LOCATION); + } + + unsigned char b = 0; + for (unsigned int i = 0; i < sizeof(mask); i++) { + if (mask[i] != 0xff) { + b = mask[i]; + break; + } + cur.prefixlen += 8; + } + + if ((b & 0xf0) == 0xf0) { + cur.prefixlen += 4; + b &= 0x0f; + } else { + b >>= 4; + } + + if ((b & 0x0c) == 0x0c) { + cur.prefixlen += 2; + b &= 0x03; + } else { + b >>= 2; + } + + if (b & 0x02) { + cur.prefixlen++; + } + } + + cur.hostname.assign(address, slash); + } else { + cur.hostname = address; + } + + struct addrinfo hints; + memset(&hints, 0, sizeof(hints)); + hints.ai_flags = AI_ADDRCONFIG | AI_NUMERICHOST; + hints.ai_family = family; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_TCP; + + struct addrinfo *res; + if (!getaddrinfo(cur.hostname.c_str(), NULL, &hints, &res)) { + memcpy(&cur.addr, res->ai_addr, res->ai_addrlen); + + cur.hostname.erase(); + freeaddrinfo(res); + } tok = lex.getToken(); if (tok != "{") @@ -241,7 +337,7 @@ void AccessList::readClient(Lexer & lex, const char *address) filter_set |= 0x04; ACCESSLIST_SET_FILTERS; } else if (tok == "Authentication") { - string t = lex.getToken(); + std::string t = lex.getToken(); cur.authentication.set (t); } else if (tok == "PAMServicename") { cur.PAMServicename = lex.getToken(); @@ -271,9 +367,9 @@ void AccessList::printParameters (std::ostream *pOut) *pOut << "}" << endl; } -void Authentication::set (const string &AuthString) +void Authentication::set (const std::string &AuthString) { - string::size_type beg=0, end=0; + std::string::size_type beg=0, end=0; fields.clear(); @@ -282,24 +378,24 @@ void Authentication::set (const string &AuthString) } do { - if ((end=AuthString.find(":",beg)) == string::npos) { + if ((end=AuthString.find(":",beg)) == std::string::npos) { end=AuthString.length(); } if (end>beg) { fields.push_back (AuthString.substr(beg, end-beg)); } else { - fields.push_back (string("")); + fields.push_back (std::string("")); } beg=++end; } while (end::iterator sp, se; - vector::iterator dp, de; + vector::iterator sp, se; + vector::iterator dp, de; sp = source.fields.begin(); se = source.fields.end(); @@ -336,7 +432,7 @@ void Authentication::modify (unsigned int start, Authentication &source) sp++; } else if (sp == se) { if (i>=start) - fields.push_back (string("")); + fields.push_back (std::string("")); dp++; } else { if (i>=start) @@ -346,7 +442,7 @@ void Authentication::modify (unsigned int start, Authentication &source) } } -int Authentication::typeEqual (const string &v) +int Authentication::typeEqual (const std::string &v) { const char *s = fields[0].c_str(); const char *p = v.c_str(); @@ -364,3 +460,11 @@ int Authentication::typeEqual (const string &v) return -1; } + +/* + * Local Variables: + * mode: c++ + * tab-width: 4 + * c-basic-offset: 4 + * End: + */ diff --git a/src/AccessList.h b/src/AccessList.h index 5888fdb..5897b7c 100644 --- a/src/AccessList.h +++ b/src/AccessList.h @@ -99,7 +99,7 @@ class Authentication { private: std::vector fields; - string defAuth; + std::string defAuth; }; /** @@ -109,8 +109,10 @@ class Authentication { * \bug Documentation is missing. */ class AccessEntry { - public: - char hostname[MAXHOSTNAMELEN]; + public: + std::string hostname; + struct sockaddr_storage addr; + unsigned short prefixlen; enum { af_read = 0x1, @@ -125,12 +127,15 @@ class AccessEntry { NewsgroupFilter read; //! groups that clients may read NewsgroupFilter postTo; //! groups that clients may post to Authentication authentication; - string PAMServicename; //! PAM Service name for this Client + std::string PAMServicename; //! PAM Service name for this Client - AccessEntry() { + AccessEntry() { init(); - } void init() { - hostname[0] = '\0'; + } + + void init() { + addr.ss_family = AF_UNSPEC; + prefixlen = 0; access_flags = 0x0; PAMServicename = PAM_DEFAULT_SERVICENAME; } @@ -140,7 +145,7 @@ class AccessEntry { } void modifyAccessFlags (const std::string &flags); friend std::ostream & operator<<(std::ostream & os, - const AccessEntry & ae); + const AccessEntry & ae); /* * print the actual setting to std:ostream @@ -165,12 +170,16 @@ class AccessEntry { * \bug Documentation is missing. */ class AccessList { - private: + private: std::vector < AccessEntry > vector; - public: + public: AccessList() { - } AccessEntry *client(const char *name, struct in_addr addr); + } + + AccessEntry *client(const char *name, const struct sockaddr *addr, + socklen_t addrlen); + void init() { vector.clear(); } @@ -232,3 +241,11 @@ inline void Authentication::appendField (const char *v) fields.push_back (v); } #endif + +/* + * Local Variables: + * mode: c++ + * tab-width: 4 + * c-basic-offset: 4 + * End: + */ diff --git a/src/Config.cc b/src/Config.cc index 5fd568f..f720391 100644 --- a/src/Config.cc +++ b/src/Config.cc @@ -82,9 +82,10 @@ MPListEntry *Config::server(const char *group) return srvrs.server(group); } -AccessEntry *Config::client(const char *name, struct in_addr addr) +AccessEntry *Config::client(const char *name, const struct sockaddr *addr, + socklen_t addrlen) { - return clnts.client(name, addr); + return clnts.client(name, addr, addrlen); } void Config::read(const char *fn) @@ -228,3 +229,11 @@ void Config::printParameters (ostream *pOut) clnts.printParameters (pOut); srvrs.printParameters (pOut); } + +/* + * Local Variables: + * mode: c++ + * tab-width: 4 + * c-basic-offset: 4 + * End: + */ diff --git a/src/Config.h b/src/Config.h index 7269508..dcd322f 100644 --- a/src/Config.h +++ b/src/Config.h @@ -20,7 +20,7 @@ * \bug Documentation is missing. */ class Config { - public: + public: char Username[256]; char Groupname[256]; char Admin[512]; @@ -63,8 +63,17 @@ class Config { void init(void); void read(const char *fn); MPListEntry *server(const char *group); - AccessEntry *client(const char *name, struct in_addr addr); + AccessEntry *client(const char *name, const struct sockaddr *addr, + socklen_t addrlen); void printParameters(std::ostream * pOut); }; #endif + +/* + * Local Variables: + * mode: c++ + * tab-width: 4 + * c-basic-offset: 4 + * End: + */ diff --git a/src/NewsCache.cc b/src/NewsCache.cc index f8886a7..c42bdc2 100644 --- a/src/NewsCache.cc +++ b/src/NewsCache.cc @@ -31,7 +31,9 @@ #include #include #include +#ifdef HAVE_GETOPT_H #include +#endif #include #include #include @@ -47,9 +49,8 @@ #include #include #include -#include -char *ConfigurationOptions[] = { +const char * const ConfigurationOptions[] = { #ifdef MD5_CRYPT "--with-md5", #endif @@ -83,8 +84,6 @@ char *ConfigurationOptions[] = { NULL }; -using namespace std; - #ifdef HAVE_LIBWRAP #include extern "C" int hosts_ctl(char *daemon, char *client_name, @@ -111,6 +110,7 @@ extern "C" int hosts_ctl(char *daemon, char *client_name, #include #include #include +#include #include "NServer.h" #include "Newsgroup.h" @@ -119,9 +119,21 @@ extern "C" int hosts_ctl(char *daemon, char *client_name, #include "setugid.h" #include "Config.h" #include "Logger.h" - -using namespace std; - +#include "sockstream.h" + +using std::cin; +using std::cout; +using std::cerr; +using std::endl; +using std::for_each; +using std::ifstream; +using std::ios; +using std::istream; +using std::ofstream; +using std::ostream; +using std::map; +using std::string; +using std::vector; /* CONF_MultiClient * Allow several simultaneous clients in standalone mode. @@ -138,7 +150,7 @@ using namespace std; #define SOCKLEN_TYPE size_t #endif -int clientTimeoutReached=0; +sig_atomic_t alarmed=0; Logger slog; const char *cmnd; class ClientData; @@ -159,6 +171,7 @@ int ns_quit(ClientData * clt, int argc, char *argv[]); int ns_xmotd(ClientData * clt, int argc, char *argv[]); int ns_xover(ClientData * clt, int argc, char *argv[]); int ns_xdebug(ClientData * clt, int argc, char *argv[]); +int ns_capabilities(ClientData * clt, int argc, char *argv[]); typedef struct nnrp_command_t { const char *name; @@ -209,6 +222,8 @@ static nnrp_command_t all_nnrp_commands[] = { , {"xover", "[range]", ns_xover} , + {"capabilities", "", ns_capabilities} + , {NULL, NULL, NULL} }; @@ -297,8 +312,9 @@ static NNRPCommandMap nnrp_commands; char config_file[MAXPATHLEN]; Config Cfg; +bool reReadConfig; -int Xsignal; +sig_atomic_t Xsignal; int nntp_connections; enum { @@ -315,10 +331,11 @@ enum { * \bug Documentation is missing. */ class ClientData { - public: - struct sockaddr_in sock; + public: + struct sockaddr_storage sock; SOCKLEN_TYPE socklen; char client_name[MAXHOSTNAMELEN]; + char client_addr[INET6_ADDRSTRLEN]; string client_logname; istream *ci; ostream *co; @@ -347,15 +364,17 @@ class ClientData { NNRPCommandMap client_command_map; - ClientData() - :client_logname(""), - grp(NULL), nbr(-1), - access_entry(NULL), auth_state(AUTH_OK), auth_failures(0), - auth_max_failures(3), auth_failure_sleep_time(15), - stat_groups(0), stat_artingrp(0), stat_articles(0) { + ClientData() + : client_logname(""), + grp(NULL), nbr(-1), + access_entry(NULL), auth_state(AUTH_OK), auth_failures(0), + auth_max_failures(3), auth_failure_sleep_time(15), + stat_groups(0), stat_artingrp(0), stat_articles(0) + { auth_user[0] = auth_pass[0] = '\0'; groupname[0] = '\0'; -}}; + } +}; #ifdef PAM_AUTH /* pam_conv_func by Tuomo Pyhala */ @@ -752,76 +771,6 @@ int check_authentication(ClientData * clt) return -1; } -// fills sin_addr.s and sin_port in addr -// return -1 if an error occurred -int fillHostStruct(struct sockaddr_in *addr, char *pHost) -{ - char fname[] = "getHost"; - char *p; - struct servent *cport; - struct hostent *host; - int portFlg = 0; - - addr->sin_family = AF_INET; - - if ((p = strchr(pHost, ':')) != NULL) { - portFlg = 1; - *p = '\0'; - } - - if (strcmp(pHost, "DEFAULT") == 0) { - addr->sin_addr.s_addr = INADDR_ANY; - } else if ((addr->sin_addr.s_addr = inet_addr(pHost)) == - INADDR_NONE) { - if ((host = - gethostbyname(pHost)) == NULL | host->h_addrtype != - AF_INET) { - if (portFlg) - *p = ':'; - slog. - p(Logger:: - Error) << fname << ": gethostbyname (" << - pHost << ") error: " << strerror(errno) << - "\n"; - return -1; - } else { - if (host->h_addr_list[0]) { - memcpy(&addr->sin_addr.s_addr, - host->h_addr_list[0], - host->h_length); - } else { - if (portFlg) - *p = ':'; - slog. - p(Logger:: - Error) << fname << - ":host->h_addr_list[0] of " << pHost << - "not valid\n"; - return -1; - } - } - } - if (portFlg) - *p = ':'; - - if (portFlg && isdigit(*(p + 1))) { - addr->sin_port = htons(atoi(p + 1)); - } else - if ((cport = - getservbyname((portFlg) ? (p + 1) : ("nntp"), - "tcp")) == NULL) { - - slog.p(Logger::Error) << fname << ": getservbyname (" - << ((portFlg) ? ((const char *) (p + 1)) - : ((const char *) "nntp")) << "/tcp error \n"; - return -1; - } else { - addr->sin_port = cport->s_port; - } - - return 1; -} - GroupInfo *selectgroup(ClientData * clt, const char *group) { @@ -832,7 +781,7 @@ GroupInfo *selectgroup(ClientData * clt, const char *group) try { gi = clt->srvr->groupinfo(group); - } catch(NSError & nse) { + } catch(const NSError & nse) { return NULL; } catch(...) { @@ -975,11 +924,11 @@ int ns_article(ClientData * clt, int argc, char *argv[]) clt->grp = clt->srvr->getgroup(clt->groupname); } - catch(NoSuchGroupError & nsge) { + catch(const NoSuchGroupError & nsge) { (*clt->co) << "411 no such newsgroup\r\n"; return -1; } - catch(Error & e) { + catch(const Error & e) { (*clt->co) << "412 operation failed\r\n"; return -1; } @@ -1016,16 +965,16 @@ int ns_article(ClientData * clt, int argc, char *argv[]) clt->srvr->article(argv[1], &a); nsh_particle(clt, argv[0], 0, &a); } - catch(NoSuchArticleError nsae) { + catch(const NoSuchArticleError &nsae) { (*clt->co) << "430 no such article id found\r\n"; return -1; } - catch(ResponseError e) { + catch(const ResponseError &e) { // error (*clt->co) << e._got << "\r\n"; return -1; } - catch(Error e) { + catch(const Error &e) { // error (*clt->co) << "520 ???\r\n"; slog. @@ -1080,11 +1029,11 @@ int ns_stat(ClientData * clt, int argc, char *argv[]) clt->grp = clt->srvr->getgroup(clt->groupname); } - catch(NoSuchGroupError & nsge) { + catch(const NoSuchGroupError & nsge) { (*clt->co) << "411 no such newsgroup\r\n"; return -1; } - catch(Error & e) { + catch(const Error & e) { (*clt->co) << "412 operation failed\r\n"; return -1; } @@ -1115,16 +1064,16 @@ int ns_stat(ClientData * clt, int argc, char *argv[]) clt->srvr->article(argv[1], &a); //nsh_particle(clt, argv[0], 0, &a); } - catch(NoSuchArticleError nsae) { + catch(const NoSuchArticleError &nsae) { (*clt->co) << "430 no such article id found\r\n"; return -1; } - catch(ResponseError e) { + catch(const ResponseError &e) { // error (*clt->co) << e._got << "\r\n"; return -1; } - catch(Error e) { + catch(const Error &e) { // error (*clt->co) << "520 ???\r\n"; slog. @@ -1255,11 +1204,11 @@ int ns_lastnext(ClientData * clt, int argc, char *argv[]) if (!clt->grp) clt->grp = clt->srvr->getgroup(clt->groupname); } - catch(NoSuchGroupError & nsge) { + catch(const NoSuchGroupError & nsge) { (*clt->co) << "411 no such news group\r\n"; return -1; } - catch(Error & e) { + catch(const Error & e) { (*clt->co) << "412 operation failed\r\n"; return -1; } @@ -1396,7 +1345,7 @@ int ns_list(ClientData * clt, int argc, char *argv[]) print_list_active > (*clt->co, filter)); } - catch(SystemError & se) { + catch(const SystemError & se) { return -2; } (*clt->co) << ".\r\n"; @@ -1417,7 +1366,7 @@ int ns_list(ClientData * clt, int argc, char *argv[]) print_list_active_times > (*clt->co, filter)); } - catch(SystemError & se) { + catch(const SystemError & se) { return -2; } (*clt->co) << ".\r\n"; @@ -1492,11 +1441,11 @@ int ns_listgroup(ClientData * clt, int argc, char *argv[]) if (!clt->grp) clt->grp = clt->srvr->getgroup(clt->groupname); } - catch(NoSuchGroupError & nsge) { + catch(const NoSuchGroupError & nsge) { (*clt->co) << "411 no such news group\r\n"; return -1; } - catch(Error & e) { + catch(const Error & e) { (*clt->co) << "412 operation failed\r\n"; e.print(); return -1; @@ -1624,7 +1573,7 @@ int ns_newgroups(ClientData * clt, int argc, char *argv[]) try { active = clt->srvr->active(); } - catch(Error & e) { + catch(const Error & e) { (*clt->co) << "410 operation failed\r\n"; return -1; } @@ -1639,7 +1588,7 @@ int ns_newgroups(ClientData * clt, int argc, char *argv[]) clt->access_entry-> list, lt)); } - catch(SystemError & se) { + catch(const SystemError & se) { return -2; } (*clt->co) << ".\r\n"; @@ -1666,7 +1615,7 @@ int ns_post(ClientData * clt, int argc, char *argv[]) // check whether client is authorized to post this article. string newsgroups = art.getfield("newsgroups:"); - unsigned int i1 = 0, i2 = newsgroups.find(","); + string::size_type i1 = 0, i2 = newsgroups.find(","); for (;;) { string group = newsgroups.substr(i1, i2); if (clt->access_entry->postTo. @@ -1681,11 +1630,11 @@ int ns_post(ClientData * clt, int argc, char *argv[]) i2 = newsgroups.find(",", i1); } } - catch(InvalidArticleError & iae) { + catch(const InvalidArticleError & iae) { (*clt->co) << "441 invalid article\r\n"; return -1; } - catch(NoSuchFieldError & nsfe) { + catch(const NoSuchFieldError & nsfe) { (*clt->co) << "441 invalid article\r\n"; return -1; } @@ -1696,15 +1645,15 @@ int ns_post(ClientData * clt, int argc, char *argv[]) (*clt->co) << "240 Article posted\r\n"; return 0; } - catch(InvalidArticleError & iae) { + catch(const InvalidArticleError & iae) { (*clt->co) << "441 invalid article\r\n"; return -1; } - catch(NotAllowedError & nae) { + catch(const NotAllowedError & nae) { (*clt->co) << "440 posting not allowed\r\n"; return -1; } - catch(Error & e) { + catch(const Error & e) { (*clt->co) << "449 operation failed\r\n"; return -1; } @@ -1768,11 +1717,11 @@ int ns_xover(ClientData * clt, int argc, char *argv[]) if (!clt->grp) clt->grp = clt->srvr->getgroup(clt->groupname); } - catch(NoSuchGroupError & nsge) { + catch(const NoSuchGroupError & nsge) { (*clt->co) << "411 no such news group\r\n"; return -1; } - catch(Error & e) { + catch(const Error & e) { e.print(); (*clt->co) << "412 operation failed\r\n"; return -1; @@ -1830,6 +1779,25 @@ int ns_xdebug(ClientData * clt, int argc, char *argv[]) return -1; } +/** + * \author Christof Meerwald + * Capabilities, see RFC 3977. + */ +int ns_capabilities(ClientData * clt, int argc, char *argv[]) +{ + (*clt->co) << "101 Capability list:\r\n"; + (*clt->co) << "VERSION 2\r\n"; + (*clt->co) << "IMPLEMENTATION NewsCache\r\n"; + if (clt->access_entry->authentication.getType() != "none") { + (*clt->co) << "AUTHINFO USER\r\n"; + } + (*clt->co) << "READER\r\n"; + (*clt->co) << "POST\r\n"; + (*clt->co) << "LIST ACTIVE ACTIVE.TIMES NEWSGROUPS OVERVIEW.FMT\r\n"; + (*clt->co) << ".\r\n"; + return 0; +} + #ifdef HAVE_LIBWRAP #ifndef WITH_SYSLOG @@ -1868,7 +1836,6 @@ void set_client_command_table (ClientData &clt) */ void nnrpd(int fd) { - struct hostent *he; ClientData clt; char req[1024], oreq[1024], *rp; char *argv[256]; @@ -1877,8 +1844,7 @@ void nnrpd(int fd) map < string, nnrp_command_t * >::iterator cmdp, end = nnrp_commands.end(); int errc = 0; - sockbuf *psock_buff = NULL; - iosockstream *psock_stream = NULL; + sockstream sock_stream; int nice; /* set nice value for master server */ @@ -1901,15 +1867,13 @@ void nnrpd(int fd) #endif if (fd >= 0) { - // FIXME: check NULL Pointer and throw exception - psock_buff = new sockbuf(fd); - psock_buff->setname ("nntp client socket"); - psock_stream = new iosockstream(psock_buff); - psock_buff->recvtimeout(-1); - psock_buff->sendtimeout(-1); - psock_stream->unsetf(ios::skipws); - clt.co = psock_stream; - clt.ci = psock_stream; + sock_stream.attach(fd); + + sock_stream.setkeepalive(); + sock_stream.setnodelay(); + + clt.co = &sock_stream; + clt.ci = &sock_stream; // get network address and name of client clt.socklen = sizeof(clt.sock); @@ -1923,21 +1887,60 @@ void nnrpd(int fd) // get the name of the client and store it in clt.client_name. // if the client does not have a name, use the ip-address instead // store it in nntp_posting_host as used by libnserver - he = gethostbyaddr((const char *) - &(clt.sock.sin_addr), - sizeof(clt.sock.sin_addr), - AF_INET); - if (he) { - strncpy(clt.client_name, he->h_name, - sizeof(clt.client_name)); - clt.client_name[sizeof(clt.client_name) - - 1] = '\0'; - } else { - strncpy(clt.client_name, - inet_ntoa(clt.sock.sin_addr), - sizeof(clt.client_name)); - clt.client_name[sizeof(clt.client_name) - - 1] = '\0'; + clt.client_name[0] = '\0'; + getnameinfo((const struct sockaddr *) &clt.sock, + clt.socklen, + clt.client_name, sizeof(clt.client_name), + NULL, 0, 0); + + struct addrinfo hints; + memset(&hints, 0, sizeof(hints)); + hints.ai_flags = + (clt.sock.ss_family == AF_INET6) ? AI_V4MAPPED : 0; + hints.ai_family = clt.sock.ss_family; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_TCP; + + struct addrinfo *res = NULL; + getaddrinfo(clt.client_name, NULL, &hints, &res); + + // have to verify the address we got from getnameinfo + bool found_addr = false; + struct addrinfo *addr = res; + while (addr != NULL) { + if (addr->ai_addr->sa_family == clt.sock.ss_family) { + if (addr->ai_addr->sa_family == AF_INET) { + if (((const struct sockaddr_in *) addr->ai_addr)->sin_addr.s_addr == + ((const struct sockaddr_in *) &clt.sock)->sin_addr.s_addr) { + found_addr = true; + break; + } + } else if (addr->ai_addr->sa_family == AF_INET6) { + if (!memcmp(((const struct sockaddr_in6 *) addr->ai_addr)->sin6_addr.s6_addr, + ((const struct sockaddr_in6 *) &clt.sock)->sin6_addr.s6_addr, + 16)) { + found_addr = true; + break; + } + } + } + + addr = addr->ai_next; + } + freeaddrinfo(res); + + if (!found_addr) { + clt.client_name[0] = '\0'; + } + + clt.client_addr[0] = '\0'; + getnameinfo((const struct sockaddr *) &clt.sock, + clt.socklen, + clt.client_addr, sizeof(clt.client_addr), + NULL, 0, NI_NUMERICHOST); + + if (clt.client_name[0] == '\0') { + strcpy(clt.client_name, clt.client_addr); } strcpy(nntp_posting_host, clt.client_name); @@ -1952,8 +1955,7 @@ void nnrpd(int fd) clt.client_logname += " ["; else clt.client_logname += '['; - clt.client_logname += - inet_ntoa(clt.sock.sin_addr); + clt.client_logname += clt.client_addr; clt.client_logname += ']'; } // check whether the client is allowed access according to @@ -1961,8 +1963,7 @@ void nnrpd(int fd) #ifdef HAVE_LIBWRAP // Check the hosts_access configuration; emulate INN error message if (!hosts_ctl(PACKAGE, - clt.client_name, - inet_ntoa(clt.sock.sin_addr), + clt.client_name, clt.client_addr, STRING_UNKNOWN)) { slog.p(Logger::Notice) << clt. client_logname << " denied - hosts.allow\n"; @@ -1998,7 +1999,8 @@ void nnrpd(int fd) // check whether the client is allowed access according to // our own access configuration clt.access_entry = - Cfg.clnts.client(clt.client_name, clt.sock.sin_addr); + Cfg.client(clt.client_name, + (struct sockaddr *) &clt.sock, clt.socklen); if (!clt.access_entry || !clt.access_entry->access_flags) { // nnrpd_deny: slog.p(Logger::Notice) << clt. @@ -2043,7 +2045,7 @@ void nnrpd(int fd) clt.srvr = new CServer(Cfg.SpoolDirectory, &(Cfg.srvrs)); clt.srvr->setttl(Cfg.ttl_list, Cfg.ttl_desc); } - catch(SystemError & se) { + catch(const SystemError & se) { slog. p(Logger:: Alert) << "CServer failed, check permissions\n"; @@ -2059,15 +2061,17 @@ void nnrpd(int fd) do { flush(*clt.co); + alarmed = 0; alarm (Cfg.ClientTimeout); clt.ci->getline(req, sizeof(req), '\n'); alarm (0); - if (clientTimeoutReached) { + if (alarmed) { + alarmed = 0; (*clt.co) << "400 " PACKAGE " " VERSION ", service timed out!\r\n"; slog.p(Logger::Notice) << clt.client_logname << " ClientTimeout reached\n"; goto client_exit; } - if (Xsignal >= 0) { + if (Xsignal != -1) { (*clt.co) << "400 " PACKAGE " " VERSION ", service discontinued\r\n"; slog.p(Logger::Notice) << clt.client_logname << " discontinued due to Signal\n"; goto client_exit; @@ -2171,23 +2175,12 @@ void nnrpd(int fd) void nntpd() { - int sock; - struct sockaddr_in nproxy; - struct servent *cport; - - struct sockaddr_in clt_sa; - SOCKLEN_TYPE clt_salen; - - int clt_fd; - int clt_pid = 0; - int nice; - slog.p(Logger::Notice) << "NewsCache Server Start\n"; /* set nice value for master server */ #ifdef HAVE_SETPRIORITY errno = 0; - nice = Cfg.NiceServer; + int nice = Cfg.NiceServer; nice += getpriority(PRIO_PROCESS, 0); if (nice == -1 && errno != 0) { slog. @@ -2206,9 +2199,79 @@ void nntpd() /* nobody is connecting to NewsCache currently */ nntp_connections = 0; - { /* create socket and set some socket options */ - int one = 1; - if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { + /* create socket and set some socket options */ + string hostname; + const char *nodename = NULL; + const char *servname = NULL; + struct addrinfo hints; + + memset(&hints, 0, sizeof(hints)); + hints.ai_flags = AI_ADDRCONFIG | AI_PASSIVE | AI_NUMERICHOST; + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_TCP; + + /* fill the sockaddr with the port we should listen too */ + if (Cfg.CachePort[0] != '\0') { + // old variant + if (Cfg.CachePort[0] != '#') { + servname = Cfg.CachePort + 1; + hints.ai_flags |= AI_NUMERICSERV; + } else { + servname = Cfg.CachePort; + } + } else { + if (Cfg.ListenTo[0] == '[') { + const char *end = strrchr(Cfg.ListenTo, ']'); + if ((end == NULL) || + ((end[1] != '\0') && (end[1] != ':'))) { + slog. + p(Logger:: + Error) << cmnd << + ": Invalid parameter ListenTo: " << + Cfg.ListenTo << "\n"; + exit(1); + } + + hostname.assign(const_cast(Cfg.ListenTo + 1), end); + nodename = hostname.c_str(); + + if (end[1] == ':') { + servname = end + 2; + } else { + servname = "nntp"; + } + } else { + const char *colon = strrchr(Cfg.ListenTo, ':'); + if (colon != NULL) { + hostname.assign(const_cast(Cfg.ListenTo), colon); + servname = colon + 1; + } else { + hostname.assign(Cfg.ListenTo); + servname = "nntp"; + } + + if (hostname != "DEFAULT") { + nodename = hostname.c_str(); + } + } + } + + struct addrinfo *res; + if (getaddrinfo(nodename, servname, &hints, &res)) { + slog. + p(Logger:: + Error) << cmnd << + ": Can't resolve parameter ListenTo: " << Cfg. + ListenTo << "\n"; + exit(1); + } + + int sock = -1; + struct addrinfo *addr = res; + while ((sock < 0) && (addr != NULL)) { + if ((sock = socket(addr->ai_addr->sa_family, + SOCK_STREAM, 0)) < 0) { slog. p(Logger:: Error) << "socket failed: " << @@ -2216,6 +2279,7 @@ void nntpd() exit(1); } + int one = 1; if (setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (char *) &one, sizeof(int)) < 0) { slog. @@ -2232,43 +2296,17 @@ void nntpd() strerror(errno) << "\n"; } - /* fill the sockaddr with the port we should listen too */ - if (Cfg.CachePort[0] != '\0') { - // old variant - const char *cp = Cfg.CachePort; - nproxy.sin_family = AF_INET; - nproxy.sin_addr.s_addr = INADDR_ANY; - if (cp[0] != '#') { - if ((cport = - getservbyname(cp, "tcp")) == NULL) { - slog. - p(Logger:: - Error) << cmnd << - ": Can't resolve service " << - cp << "/tcp\n"; - exit(1); - } - nproxy.sin_port = cport->s_port; - } else { - nproxy.sin_port = htons(atoi(cp + 1)); - } - } else if (fillHostStruct(&nproxy, Cfg.ListenTo) == -1) { + if (bind(sock, addr->ai_addr, addr->ai_addrlen) < 0) { slog. - p(Logger:: - Error) << cmnd << - ": Can't resolve parameter ListenTo: " << Cfg. - ListenTo << "\n"; + p(Logger:: + Error) << "can't bind socket: " << strerror(errno) << + "\n"; exit(1); } - } /* end create socket and set some socket options */ - if (bind(sock, (struct sockaddr *) &nproxy, sizeof(nproxy)) < 0) { - slog. - p(Logger:: - Error) << "can't bind socket: " << strerror(errno) << - "\n"; - exit(1); - } + addr = addr->ai_next; + } /* end create socket and set some socket options */ + freeaddrinfo(res); { /* store pid in Cfg.PidFile */ ofstream pid(Cfg.PidFile); @@ -2282,14 +2320,20 @@ void nntpd() setugid(Cfg.Username, Cfg.Groupname); listen(sock, 4); for (;;) { + int clt_fd; + int clt_pid = 0; + /* Accept connection */ - clt_salen = sizeof(clt_sa); do { + if (reReadConfig) { + Cfg.init(); + Cfg.read(config_file); + reReadConfig = false; + } + errno = 0; - clt_fd = - accept(sock, (struct sockaddr *) &clt_sa, - &clt_salen); - if (Xsignal >= 0) { + clt_fd = accept(sock, NULL, NULL); + if (Xsignal != -1) { close(sock); exit(0); } @@ -2316,69 +2360,55 @@ void nntpd() // success if (clt_pid == 0) { // child - int one = 1; close(sock); - if (setsockopt - (clt_fd, SOL_SOCKET, SO_KEEPALIVE, - (char *) &one, sizeof(int)) < 0) { - slog. - p(Logger:: - Error) << - "client setsockopt failed: " << - strerror(errno) << "\n"; - } + try { nnrpd(clt_fd); - } catch (sockerr e) { - slog.p(Logger::Error) << "nnrpd caught " - << "sockbuf " << e.operation () - << e.serrno () - << " " << e.errstr () << "\n"; - } catch (UsageError e) { + } catch (const UsageError &e) { slog.p(Logger::Error) << "nnrpd caught " << "UsageError "; e.print(); - } catch (NotAllowedError e) { + } catch (const NotAllowedError &e) { slog.p(Logger::Error) << "nnrpd caught " << "NotAllowdError "; e.print(); - } catch (NoSuchArticleError e) { + } catch (const NoSuchArticleError &e) { slog.p(Logger::Error) << "nnrpd caught " << "NoSuchArticleError "; e.print(); - } catch (DuplicateArticleError e) { + } catch (const DuplicateArticleError &e) { slog.p(Logger::Error) << "nnrpd caught " << "DuplicateArticleError "; e.print(); - } catch (NoSuchGroupError e) { + } catch (const NoSuchGroupError &e) { slog.p(Logger::Error) << "nnrpd caught " << "NoSuchGroupError "; e.print(); - } catch (NoNewsServerError e) { + } catch (const NoNewsServerError &e) { slog.p(Logger::Error) << "nnrpd caught " << "NoNewsServerError "; e.print(); - } catch (NoSuchFieldError e) { + } catch (const NoSuchFieldError &e) { slog.p(Logger::Error) << "nnrpd caught " << "NoSuchFieldError "; e.print(); - } catch (NSError e) { + } catch (const NSError &e) { slog.p(Logger::Error) << "nnrpd caught " << "NSError "; e.print(); - } catch (AssertionError e) { + } catch (const AssertionError &e) { slog.p(Logger::Error) << "nnrpd caught " << "AssertionError "; e.print(); - } catch (IOError e) { + } catch (const IOError &e) { slog.p(Logger::Error) << "nnrpd caught " << "IOError "; e.print(); - } catch (SystemError e) { + } catch (const SystemError &e) { slog.p(Logger::Error) << "nnrpd caught " << "SystemError "; e.print(); - } catch (Error e) { + } catch (const Error &e) { slog.p(Logger::Error) << "nnrpd caught " << "Error "; e.print(); @@ -2390,7 +2420,9 @@ void nntpd() exit(0); } //Parent - close(clt_fd); + + while ((close(clt_fd) < 0) && (errno == EINTR)) { + } nntp_connections++; } #else @@ -2407,7 +2439,7 @@ void sigchld(int num) int pid; int st; - slog.p(Logger::Debug) << "receiving signal SIGCHLD: " << num << "\n"; + //slog.p(Logger::Debug) << "receiving signal SIGCHLD: " << num << "\n"; /* Reinstall the signal handler */ #ifdef HAVE_SIGACTION struct sigaction action; @@ -2443,8 +2475,7 @@ void sigchld(int num) void catchsigalarm(int num) { - slog.p(Logger::Debug) << "receiving signal SIGALRM: " << num << "\n"; - clientTimeoutReached=1; + alarmed=1; #ifdef HAVE_SIGACTION /* Reinstall the signal handler */ struct sigaction action; @@ -2459,9 +2490,7 @@ void catchsigalarm(int num) void catchsighup(int num) { - slog.p(Logger::Debug) << "receiving signal SIGHUP: " << num << "\n"; - Cfg.init(); - Cfg.read(config_file); + reReadConfig=true; #ifdef HAVE_SIGACTION /* Reinstall the signal handler */ struct sigaction action; @@ -2476,7 +2505,6 @@ void catchsighup(int num) void catchsignal(int num) { - slog.p(Logger::Debug) << "receiving signal: " << num << "\n"; Xsignal = num; #ifdef HAVE_SIGACTION /* Reinstall the signal handler */ @@ -2529,6 +2557,7 @@ int main(int argc, char **argv) cmnd = argv[0]; while (1) { +#ifdef HAVE_GETOPT_H int option_index = 0; static struct option long_options[] = { {"version", 0, 0, 'v'}, @@ -2544,6 +2573,9 @@ int main(int argc, char **argv) c = getopt_long (argc, argv, "vfhc:idpo", long_options, &option_index); +#else + c = getopt (argc, argv, "vfhc:idpo"); +#endif if (c == -1) break; @@ -2597,11 +2629,11 @@ int main(int argc, char **argv) Cfg.read(config_file); strcpy(nntp_hostname, Cfg.Hostname); } - catch(IOError & io) { + catch(const IOError & io) { cerr << "unexpected EOF in " << config_file << "\n"; exit(2); } - catch(SyntaxError & se) { + catch(const SyntaxError & se) { cerr << se._errtext << "\n"; exit(2); } @@ -2628,7 +2660,9 @@ int main(int argc, char **argv) #endif // signal handling + sockstream::alarm_indicator(alarmed); Xsignal = -1; + reReadConfig = false; #ifdef HAVE_SIGACTION struct sigaction action; @@ -2707,3 +2741,11 @@ int main(int argc, char **argv) return 0; } + +/* + * Local Variables: + * mode: c++ + * tab-width: 4 + * c-basic-offset: 4 + * End: + */ diff --git a/src/NewsCacheClean.cc b/src/NewsCacheClean.cc index 0e4db5a..ae55779 100644 --- a/src/NewsCacheClean.cc +++ b/src/NewsCacheClean.cc @@ -31,7 +31,9 @@ #include "config.h" #include +#ifdef HAVE_GETOPT_H #include +#endif #include #include #include @@ -70,13 +72,15 @@ const char *cmnd; Config Cfg; class Entry { -public: + public: Entry (const char *path, time_t time, long blocks) - : Path(path), atime(time), blocks(blocks) {}; + : Path(path), atime(time), blocks(blocks) + { } - void print (ostream &out) { + void print (ostream &out) + { out << Path << " " << atime << " " << blocks << " " << endl; - }; + } string Path; time_t atime; @@ -274,7 +278,7 @@ void clean(const char *cpath) } else { ng = NULL; } - } catch (NoSuchGroupError e) { + } catch (const NoSuchGroupError &e) { ng = NULL; } // FIXME: what we are doing with bad database files? @@ -284,6 +288,7 @@ void clean(const char *cpath) lastnr = ng->lastnbr (); delete ng; } + delete fmt; string art; int nr; while ((f = readdir(d)) != NULL) { @@ -360,6 +365,7 @@ int main(int argc, char **argv) cmnd = argv[0]; while (1) { +#ifdef HAVE_GETOPT_H int option_index = 0; static struct option long_options[] = { {"version", 0, 0, 'v'}, @@ -373,6 +379,9 @@ int main(int argc, char **argv) c = getopt_long (argc, argv, "vhc:stp", long_options, &option_index); +#else + c = getopt (argc, argv, "vhc:stp"); +#endif if (c == -1) break; @@ -421,11 +430,11 @@ int main(int argc, char **argv) Cfg.read(conffile); // strcpy(nntp_hostname,Cfg.Hostname); } - catch(IOError & io) { + catch(const IOError & io) { cerr << "unexpected EOF in " << conffile << "\n"; exit(2); } - catch(SyntaxError & se) { + catch(const SyntaxError & se) { cerr << se._errtext << "\n"; exit(2); } @@ -488,3 +497,11 @@ int main(int argc, char **argv) << (unsigned int) (_blocks / 2) << "K\n"; return 0; } + +/* + * Local Variables: + * mode: c++ + * tab-width: 4 + * c-basic-offset: 4 + * End: + */ diff --git a/src/cConfig.cc b/src/cConfig.cc index 04accd4..46c6d68 100644 --- a/src/cConfig.cc +++ b/src/cConfig.cc @@ -16,3 +16,11 @@ int main(int argc, char *argv[]) cout << "cConfig: newscache.conf-dist ok\n"; exit(0); } + +/* + * Local Variables: + * mode: c++ + * tab-width: 4 + * c-basic-offset: 4 + * End: + */ diff --git a/src/crypt.cc b/src/crypt.cc index 9205c5e..1629fe0 100644 --- a/src/crypt.cc +++ b/src/crypt.cc @@ -40,3 +40,11 @@ int main(int argc, char *argv[]) cout << "crypt: " << crypt(argv[1], salt) << endl; } + +/* + * Local Variables: + * mode: c++ + * tab-width: 4 + * c-basic-offset: 4 + * End: + */ diff --git a/src/setugid.cc b/src/setugid.cc index 76a3ea1..0fac090 100644 --- a/src/setugid.cc +++ b/src/setugid.cc @@ -44,3 +44,11 @@ void setugid(const char *uname, const char *gname) } } } + +/* + * Local Variables: + * mode: c++ + * tab-width: 4 + * c-basic-offset: 4 + * End: + */ diff --git a/src/setugid.h b/src/setugid.h index 46abd6f..5f40973 100644 --- a/src/setugid.h +++ b/src/setugid.h @@ -4,3 +4,11 @@ extern void setugid(const char *uname, const char *gname); #endif + +/* + * Local Variables: + * mode: c++ + * tab-width: 4 + * c-basic-offset: 4 + * End: + */ diff --git a/src/updatenews.cc b/src/updatenews.cc index 4e95a6f..1af0dc0 100644 --- a/src/updatenews.cc +++ b/src/updatenews.cc @@ -15,10 +15,14 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include "config.h" + #include #include #include +#ifdef HAVE_GETOPT_H #include +#endif #include #include #include @@ -30,7 +34,6 @@ #include #include -#include "config.h" #include "Debug.h" #include "Config.h" #include "NServer.h" @@ -66,7 +69,6 @@ int Xsignal; void catchsignal(int num) { Xsignal = num; - slog.p(Logger::Warning) << "received signal " << num << "\n"; #ifdef HAVE_SIGACTION /* Reinstall the signal handler */ struct sigaction action; @@ -234,6 +236,7 @@ int main(int argc, char **argv) cmnd = argv[0]; while (1) { +#ifdef HAVE_GETOPT_H int option_index = 0; static struct option long_options[] = { {"version", 0, 0, 'v'}, @@ -249,7 +252,9 @@ int main(int argc, char **argv) c = getopt_long (argc, argv, "vhc:agolw:", long_options, &option_index); - +#else + c = getopt (argc, argv, "vhc:agolw:"); +#endif if (c == -1) break; @@ -366,3 +371,11 @@ int main(int argc, char **argv) update(); return 0; } + +/* + * Local Variables: + * mode: c++ + * tab-width: 4 + * c-basic-offset: 4 + * End: + */ diff --git a/test/tartspool.cc b/test/tartspool.cc index bee8c59..037c76e 100644 --- a/test/tartspool.cc +++ b/test/tartspool.cc @@ -62,3 +62,11 @@ int main(int argc, char **argv) return (1); } } + +/* + * Local Variables: + * mode: c++ + * tab-width: 4 + * c-basic-offset: 4 + * End: + */ diff --git a/test/tlock.cc b/test/tlock.cc index cf00f98..409875f 100644 --- a/test/tlock.cc +++ b/test/tlock.cc @@ -17,6 +17,7 @@ #include #include +#include #include #include "Logger.h" @@ -67,3 +68,11 @@ int main(int argc, char **argv) } } + +/* + * Local Variables: + * mode: c++ + * tab-width: 4 + * c-basic-offset: 4 + * End: + */