From b7a32e2d73e3ab1add8208d3e157f7269a31ef4d Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Sat, 15 May 2010 17:17:27 +0100 Subject: [PATCH] REORG Delete everything that's not innduct or build system or changed for innduct --- CONTRIBUTORS | 261 -- ChangeLog | 238 -- HACKING | 708 ---- INSTALL | 1527 -------- LICENSE | 87 - MANIFEST | 745 ---- NEWS | 860 ---- README | 288 -- TODO | 847 ---- authprogs/Makefile | 115 - authprogs/auth_krb5.c | 217 - authprogs/auth_smb.c | 66 - authprogs/ckpasswd.c | 411 -- authprogs/domain.c | 49 - authprogs/ident.c | 179 - authprogs/libauth.c | 216 - authprogs/libauth.h | 39 - authprogs/radius.c | 564 --- authprogs/smbval/Makefile | 51 - authprogs/smbval/byteorder.h | 70 - authprogs/smbval/rfcnb-common.h | 36 - authprogs/smbval/rfcnb-error.h | 48 - authprogs/smbval/rfcnb-io.c | 310 -- authprogs/smbval/rfcnb-io.h | 28 - authprogs/smbval/rfcnb-priv.h | 115 - authprogs/smbval/rfcnb-util.c | 331 -- authprogs/smbval/rfcnb-util.h | 42 - authprogs/smbval/rfcnb.h | 48 - authprogs/smbval/session.c | 304 -- authprogs/smbval/smbdes.c | 337 -- authprogs/smbval/smbencrypt.c | 60 - authprogs/smbval/smblib-common.h | 69 - authprogs/smbval/smblib-priv.h | 249 -- authprogs/smbval/smblib-util.c | 332 -- authprogs/smbval/smblib.c | 379 -- authprogs/smbval/smblib.h | 50 - authprogs/smbval/valid.c | 48 - authprogs/smbval/valid.h | 12 - backends/actmerge.in | 216 - backends/actsync.c | 2766 ------------- backends/actsyncd.in | 256 -- backends/archive.c | 653 ---- backends/batcher.c | 428 -- backends/buffchan.c | 483 --- backends/crosspost.c | 338 -- backends/cvtbatch.c | 128 - backends/filechan.c | 132 - backends/inndf.c | 335 -- backends/innxbatch.c | 550 --- backends/innxmit.c | 1457 ------- backends/map.c | 99 - backends/map.h | 7 - backends/mod-active.in | 115 - backends/news2mail.in | 153 - backends/ninpaths.c | 519 --- backends/nntpget.c | 469 --- backends/nntpsend.in | 472 --- backends/overchan.c | 142 - backends/send-ihave.in | 95 - backends/send-nntp.in | 88 - backends/send-uucp.in | 382 -- backends/sendinpaths.in | 44 - backends/sendxbatches.in | 39 - backends/shlock.c | 204 - backends/shrinkfile.c | 390 -- contrib/Makefile | 56 - contrib/README | 150 - contrib/archivegz.in | 334 -- contrib/auth_pass.README | 75 - contrib/auth_pass.c | 163 - contrib/backlogstat.in | 118 - contrib/backupfeed.in | 249 -- contrib/cleannewsgroups.in | 45 - contrib/count_overview.pl | 27 - contrib/delayer.in | 71 - contrib/expirectl.c | 306 -- contrib/findreadgroups.in | 38 - contrib/fixhist | 89 - contrib/innconfcheck | 125 - contrib/makeexpctl.in | 76 - contrib/makestorconf.in | 56 - contrib/mkbuf | 29 - contrib/mlockfile.c | 182 - contrib/newsresp.c | 297 -- contrib/pullart.c | 297 -- contrib/reset-cnfs.c | 56 - contrib/respool.c | 95 - contrib/sample.init.script | 18 - contrib/showtoken.in | 95 - contrib/stathist.in | 79 - contrib/thdexpire.in | 647 --- contrib/tunefeed.in | 474 --- control/Makefile | 51 - control/controlbatch.in | 90 - control/controlchan.in | 467 --- control/docheckgroups.in | 149 - control/gpgverify.in | 237 -- control/modules/checkgroups.pl | 89 - control/modules/ihave.pl | 58 - control/modules/newgroup.pl | 214 - control/modules/rmgroup.pl | 92 - control/modules/sendme.pl | 55 - control/modules/sendsys.pl | 64 - control/modules/senduuname.pl | 61 - control/modules/version.pl | 61 - control/perl-nocem.in | 631 --- control/pgpverify.in | 876 ----- control/signcontrol.in | 600 --- debian/changelog | 339 -- debian/changelog.old | 688 ---- debian/compat | 1 - debian/inn2-dev.files | 5 - debian/inn2-dev.links | 4 - debian/inn2-inews.files | 13 - debian/inn2-inews.links | 2 - debian/inn2.README.Debian | 102 - debian/inn2.cron.d | 37 - debian/inn2.docs | 10 - debian/inn2.examples | 2 - debian/inn2.init | 63 - debian/inn2.links | 6 - debian/inn2.logcheck.ignore.server | 57 - debian/inn2.logcheck.violations.ignore | 10 - debian/inn2.postinst | 181 - debian/inn2.postrm | 14 - debian/inn2.preinst | 28 - debian/inn2.prerm | 25 - debian/patches/debian-paths | 10 - debian/patches/fix_ad_flag | 15 - debian/patches/fix_body_regexps | 82 - debian/patches/no-makedbz-on-install | 11 - debian/patches/nocem-gpg-import | 28 - debian/patches/series | 20 - debian/patches/typo_inn_conf_man | 11 - debian/patches/u_innreport_misc | 136 - debian/patches/u_right_length | 15 - debian/patches/u_status_init_ip | 26 - debian/patches/u_tls_duplicate_reply | 15 - debian/patches/u_xhdr_permissions | 49 - debian/patches/u_xover_duplicate_reply | 30 - debian/rules | 198 - debian/watch | 3 - doc/GPL | 347 -- doc/IPv6-info | 47 - doc/checklist | 210 - doc/compliance-nntp | 320 -- doc/config-design | 121 - doc/config-semantics | 79 - doc/config-syntax | 242 -- doc/external-auth | 111 - doc/history | 258 -- doc/hook-perl | 597 --- doc/hook-python | 614 --- doc/hook-tcl | 99 - doc/man/Makefile | 66 - doc/man/active.5 | 221 -- doc/man/active.times.5 | 163 - doc/man/actsync.8 | 1123 ------ doc/man/actsyncd.8 | 9 - doc/man/archive.8 | 151 - doc/man/auth_krb5.8 | 209 - doc/man/auth_smb.8 | 182 - doc/man/batcher.8 | 196 - doc/man/buffchan.8 | 197 - doc/man/buffindexed.conf.5 | 120 - doc/man/ckpasswd.8 | 311 -- doc/man/clientlib.3 | 105 - doc/man/cnfsheadconf.8 | 46 - doc/man/cnfsstat.8 | 100 - doc/man/control.ctl.5 | 316 -- doc/man/controlchan.8 | 80 - doc/man/convdate.1 | 236 -- doc/man/ctlinnd.8 | 661 ---- doc/man/cvtbatch.8 | 53 - doc/man/cycbuff.conf.5 | 320 -- doc/man/dbz.3 | 303 -- doc/man/distrib.pats.5 | 174 - doc/man/domain.8 | 187 - doc/man/expire.8 | 251 -- doc/man/expire.ctl.5 | 319 -- doc/man/expireover.8 | 267 -- doc/man/expirerm.8 | 30 - doc/man/fastrm.1 | 308 -- doc/man/filechan.8 | 149 - doc/man/getlist.1 | 99 - doc/man/grephistory.1 | 200 - doc/man/history.5 | 91 - doc/man/ident.8 | 192 - doc/man/incoming.conf.5 | 190 - doc/man/inews.1 | 256 -- doc/man/inn.conf.5 | 1220 ------ doc/man/inncheck.8 | 172 - doc/man/innconfval.1 | 198 - doc/man/innd.8 | 600 --- doc/man/inndcomm.3 | 142 - doc/man/inndf.8 | 244 -- doc/man/inndstart.8 | 394 -- doc/man/innfeed.1 | 511 --- doc/man/innfeed.conf.5 | 732 ---- doc/man/innmail.1 | 187 - doc/man/innreport.8 | 40 - doc/man/innstat.8 | 23 - doc/man/innupgrade.8 | 204 - doc/man/innwatch.8 | 59 - doc/man/innwatch.ctl.5 | 226 -- doc/man/innxbatch.8 | 126 - doc/man/innxmit.8 | 191 - doc/man/libauth.3 | 207 - doc/man/libinn.3 | 533 --- doc/man/libinnhist.3 | 421 -- doc/man/libstorage.3 | 405 -- doc/man/list.3 | 211 - doc/man/mailpost.8 | 258 -- doc/man/makeactive.8 | 9 - doc/man/makedbz.8 | 78 - doc/man/makehistory.8 | 308 -- doc/man/mod-active.8 | 84 - doc/man/moderators.5 | 86 - doc/man/motd.news.5 | 154 - doc/man/news.daily.8 | 227 -- doc/man/news2mail.8 | 73 - doc/man/newsfeeds.5 | 911 ----- doc/man/newslog.5 | 227 -- doc/man/ninpaths.8 | 235 -- doc/man/nnrpd.8 | 382 -- doc/man/nnrpd.track.5 | 55 - doc/man/nntpget.1 | 90 - doc/man/nntpsend.8 | 247 -- doc/man/nntpsend.ctl.5 | 46 - doc/man/ovdb.5 | 412 -- doc/man/ovdb_init.8 | 234 -- doc/man/ovdb_monitor.8 | 155 - doc/man/ovdb_server.8 | 154 - doc/man/ovdb_stat.8 | 205 - doc/man/overchan.8 | 60 - doc/man/overview.fmt.5 | 58 - doc/man/parsedate.3 | 138 - doc/man/passwd.nntp.5 | 181 - doc/man/perl-nocem.8 | 255 -- doc/man/pgpverify.1 | 293 -- doc/man/prunehistory.8 | 67 - doc/man/pullnews.1 | 373 -- doc/man/putman.sh | 51 - doc/man/qio.3 | 242 -- doc/man/radius.8 | 196 - doc/man/radius.conf.5 | 226 -- doc/man/rc.news.8 | 216 - doc/man/readers.conf.5 | 932 ----- doc/man/rnews.1 | 144 - doc/man/sasl.conf.5 | 196 - doc/man/scanlogs.8 | 41 - doc/man/send-nntp.8 | 84 - doc/man/send-uucp.8 | 235 -- doc/man/sendinpaths.8 | 163 - doc/man/shlock.1 | 82 - doc/man/shrinkfile.1 | 101 - doc/man/simpleftp.1 | 172 - doc/man/sm.1 | 211 - doc/man/startinnfeed.1 | 25 - doc/man/storage.conf.5 | 282 -- doc/man/subscriptions.5 | 176 - doc/man/tally.control.8 | 29 - doc/man/tdx-util.8 | 304 -- doc/man/tst.3 | 204 - doc/man/uwildmat.3 | 290 -- doc/man/writelog.8 | 38 - doc/pod/Makefile | 104 - doc/pod/active.pod | 91 - doc/pod/active.times.pod | 35 - doc/pod/auth_krb5.pod | 87 - doc/pod/auth_smb.pod | 55 - doc/pod/checklist.pod | 271 -- doc/pod/ckpasswd.pod | 187 - doc/pod/control.ctl.pod | 198 - doc/pod/convdate.pod | 106 - doc/pod/cycbuff.conf.pod | 201 - doc/pod/distrib.pats.pod | 46 - doc/pod/domain.pod | 60 - doc/pod/expire.ctl.pod | 172 - doc/pod/expireover.pod | 155 - doc/pod/external-auth.pod | 112 - doc/pod/fastrm.pod | 190 - doc/pod/grephistory.pod | 85 - doc/pod/hacking.pod | 746 ---- doc/pod/hook-perl.pod | 614 --- doc/pod/hook-python.pod | 657 ---- doc/pod/ident.pod | 70 - doc/pod/inews.pod | 142 - doc/pod/inn.conf.pod | 1273 ------ doc/pod/innconfval.pod | 83 - doc/pod/innd.pod | 513 --- doc/pod/inndf.pod | 120 - doc/pod/inndstart.pod | 317 -- doc/pod/innmail.pod | 68 - doc/pod/innupgrade.pod | 85 - doc/pod/install.pod | 1560 -------- doc/pod/libauth.pod | 73 - doc/pod/libinnhist.pod | 300 -- doc/pod/list.pod | 83 - doc/pod/mailpost.pod | 152 - doc/pod/makehistory.pod | 196 - doc/pod/motd.news.pod | 26 - doc/pod/news.pod | 1200 ------ doc/pod/newsfeeds.pod | 805 ---- doc/pod/ninpaths.pod | 124 - doc/pod/nnrpd.pod | 294 -- doc/pod/ovdb.pod | 323 -- doc/pod/ovdb_init.pod | 142 - doc/pod/ovdb_monitor.pod | 30 - doc/pod/ovdb_server.pod | 29 - doc/pod/ovdb_stat.pod | 97 - doc/pod/passwd.nntp.pod | 51 - doc/pod/pullnews.pod | 284 -- doc/pod/qio.pod | 111 - doc/pod/radius.conf.pod | 109 - doc/pod/radius.pod | 77 - doc/pod/rc.news.pod | 104 - doc/pod/readers.conf.pod | 829 ---- doc/pod/readme.pod | 305 -- doc/pod/sasl.conf.pod | 78 - doc/pod/sendinpaths.pod | 43 - doc/pod/simpleftp.pod | 46 - doc/pod/sm.pod | 95 - doc/pod/subscriptions.pod | 49 - doc/pod/tdx-util.pod | 184 - doc/pod/tst.pod | 76 - doc/pod/uwildmat.pod | 180 - doc/sample-control | 26 - expire/Makefile | 131 - expire/convdate.c | 167 - expire/expire.c | 727 ---- expire/expireover.c | 244 -- expire/expirerm.in | 30 - expire/fastrm.c | 728 ---- expire/grephistory.c | 180 - expire/makedbz.c | 318 -- expire/makehistory.c | 944 ----- expire/prunehistory.c | 125 - extra/active | 8 - extra/buildinnkeyring | 36 - extra/bunbatch | 2 - extra/dh_cloneconf | 15 - extra/ginpaths2 | 6 - extra/newsgroups | 8 - extra/sasl.conf | 4 - extra/send-uucp.cf | 26 - frontends/Makefile | 185 - frontends/cnfsheadconf.in | 342 -- frontends/cnfsstat.in | 552 --- frontends/ctlinnd.c | 342 -- frontends/decode.c | 161 - frontends/encode.c | 116 - frontends/feedone.c | 192 - frontends/getlist.c | 194 - frontends/inews.c | 1092 ------ frontends/innconfval.c | 102 - frontends/mailpost.in | 565 --- frontends/ovdb_init.c | 481 --- frontends/ovdb_monitor.c | 331 -- frontends/ovdb_server.c | 744 ---- frontends/ovdb_stat.c | 1031 ----- frontends/pullnews.in | 822 ---- frontends/rnews.c | 972 ----- frontends/scanspool.in | 460 --- frontends/sm.c | 189 - frontends/sys2nf.c | 343 -- history/Make.methods | 5 - history/Makefile | 108 - history/buildconfig.in | 197 - history/his.c | 473 --- history/hisinterface.h | 47 - history/hisv6/hismethod.config | 3 - history/hisv6/hisv6-private.h | 81 - history/hisv6/hisv6.c | 1426 ------- history/hisv6/hisv6.h | 45 - include/Makefile | 53 - include/acconfig.h | 262 -- include/clibrary.h | 186 - include/conffile.h | 35 - include/dbz.h | 76 - include/inn/buffer.h | 48 - include/inn/confparse.h | 78 - include/inn/defines.h | 66 - include/inn/hashtab.h | 60 - include/inn/history.h | 110 - include/inn/innconf.h | 211 - include/inn/list.h | 51 - include/inn/md5.h | 79 - include/inn/messages.h | 99 - include/inn/mmap.h | 33 - include/inn/qio.h | 49 - include/inn/sequence.h | 21 - include/inn/timer.h | 38 - include/inn/tst.h | 88 - include/inn/vector.h | 87 - include/inn/wire.h | 46 - include/inndcomm.h | 92 - include/innperl.h | 27 - include/libinn.h | 214 - include/nntp.h | 175 - include/ov.h | 80 - include/paths.h.in | 113 - include/portable/mmap.h | 66 - include/portable/setproctitle.h | 25 - include/portable/socket.h | 84 - include/portable/time.h | 25 - include/portable/wait.h | 41 - include/ppport.h | 196 - innd/Makefile | 245 -- innd/art.c | 2545 ------------ innd/cc.c | 2107 ---------- innd/chan.c | 1235 ------ innd/icd.c | 510 --- innd/innd.c | 735 ---- innd/innd.h | 858 ---- innd/inndstart.c | 416 -- innd/keywords.c | 271 -- innd/lc.c | 119 - innd/nc.c | 1462 ------- innd/newsfeeds.c | 957 ----- innd/ng.c | 425 -- innd/perl.c | 497 --- innd/proc.c | 181 - innd/python.c | 732 ---- innd/rc.c | 2017 ---------- innd/site.c | 1246 ------ innd/status.c | 364 -- innd/tcl.c | 196 - innd/util.c | 382 -- innd/wip.c | 187 - innfeed/Makefile | 176 - innfeed/README | 412 -- innfeed/article.c | 1061 ----- innfeed/article.h | 80 - innfeed/buffer.c | 550 --- innfeed/buffer.h | 119 - innfeed/config_l.c | 1861 --------- innfeed/configfile.h | 106 - innfeed/configfile.l | 252 -- innfeed/configfile.y | 1103 ------ innfeed/connection.c | 4904 ----------------------- innfeed/connection.h | 116 - innfeed/endpoint.c | 1803 --------- innfeed/endpoint.h | 184 - innfeed/host.c | 4046 ------------------- innfeed/host.h | 207 - innfeed/imap_connection.c | 4681 ---------------------- innfeed/innfeed-convcfg.in | 187 - innfeed/innfeed.h | 203 - innfeed/innlistener.c | 784 ---- innfeed/innlistener.h | 71 - innfeed/main.c | 967 ----- innfeed/misc.c | 782 ---- innfeed/misc.h | 139 - innfeed/procbatch.in | 146 - innfeed/startinnfeed.c | 130 - innfeed/tape.c | 1294 ------ innfeed/tape.h | 68 - innfeed/testListener.pl | 160 - lib/Makefile | 298 -- lib/buffer.c | 99 - lib/cleanfrom.c | 83 - lib/clientactive.c | 144 - lib/clientlib.c | 157 - lib/concat.c | 79 - lib/conffile.c | 170 - lib/confparse.c | 1301 ------ lib/daemonize.c | 64 - lib/date.c | 637 --- lib/dbz.c | 1785 --------- lib/defdist.c | 191 - lib/fdflags.c | 103 - lib/fdlimit.c | 136 - lib/fseeko.c | 56 - lib/ftello.c | 38 - lib/genid.c | 39 - lib/getfqdn.c | 87 - lib/getmodaddr.c | 177 - lib/getpagesize.c | 24 - lib/gettime.c | 80 - lib/hash.c | 163 - lib/hashtab.c | 457 --- lib/hstrerror.c | 44 - lib/inet_aton.c | 130 - lib/inet_ntoa.c | 37 - lib/innconf.c | 785 ---- lib/inndcomm.c | 469 --- lib/list.c | 125 - lib/localopen.c | 89 - lib/lockfile.c | 45 - lib/makedir.c | 55 - lib/md5.c | 513 --- lib/memcmp.c | 42 - lib/messages.c | 390 -- lib/mkstemp.c | 79 - lib/mmap.c | 36 - lib/parsedate.y | 861 ---- lib/perl.c | 357 -- lib/pread.c | 48 - lib/pwrite.c | 48 - lib/qio.c | 192 - lib/radix32.c | 64 - lib/readin.c | 84 - lib/reservedfd.c | 91 - lib/resource.c | 52 - lib/sendarticle.c | 39 - lib/sendpass.c | 108 - lib/sequence.c | 37 - lib/setenv.c | 52 - lib/seteuid.c | 34 - lib/setproctitle.c | 106 - lib/snprintf.c | 871 ----- lib/sockaddr.c | 47 - lib/strcasecmp.c | 103 - lib/strerror.c | 57 - lib/strlcat.c | 40 - lib/strlcpy.c | 38 - lib/strspn.c | 59 - lib/strtok.c | 87 - lib/timer.c | 375 -- lib/tst.c | 408 -- lib/uwildmat.c | 401 -- lib/vector.c | 409 -- lib/version.c | 13 - lib/wire.c | 174 - lib/xfopena.c | 22 - lib/xmalloc.c | 139 - lib/xsignal.c | 75 - lib/xwrite.c | 177 - nnrpd/Makefile | 194 - nnrpd/article.c | 1107 ------ nnrpd/cache.c | 123 - nnrpd/cache.h | 14 - nnrpd/commands.c | 639 --- nnrpd/group.c | 262 -- nnrpd/line.c | 248 -- nnrpd/list.c | 284 -- nnrpd/misc.c | 552 --- nnrpd/newnews.c | 301 -- nnrpd/nnrpd.c | 1362 ------- nnrpd/nnrpd.h | 287 -- nnrpd/perl.c | 412 -- nnrpd/perm.c | 2362 ----------- nnrpd/post.c | 1281 ------ nnrpd/post.h | 52 - nnrpd/python.c | 777 ---- nnrpd/sasl_config.c | 142 - nnrpd/sasl_config.h | 25 - nnrpd/tls.c | 713 ---- nnrpd/tls.h | 52 - nnrpd/track.c | 67 - samples/INN.py | 39 - samples/Makefile | 44 - samples/active.minimal | 6 - samples/actsync.cfg | 6 - samples/actsync.ign | 30 - samples/buffindexed.conf | 11 - samples/control.ctl | 2535 ------------ samples/cycbuff.conf | 26 - samples/distrib.pats | 13 - samples/expire.ctl | 32 - samples/filter.tcl | 19 - samples/filter_innd.pl | 212 - samples/filter_innd.py | 274 -- samples/filter_nnrpd.pl | 74 - samples/incoming.conf | 142 - samples/inn.conf.in | 185 - samples/innfeed.conf | 135 - samples/innreport.conf.in | 2473 ------------ samples/innwatch.ctl | 40 - samples/moderators | 33 - samples/motd.news | 3 - samples/news2mail.cf | 20 - samples/newsfeeds.in | 129 - samples/newsgroups.minimal | 6 - samples/nnrpd.py | 18 - samples/nnrpd.track | 14 - samples/nnrpd_access.pl.in | 121 - samples/nnrpd_access.py | 92 - samples/nnrpd_access_wrapper.pl.in | 48 - samples/nnrpd_access_wrapper.py | 64 - samples/nnrpd_auth.pl.in | 68 - samples/nnrpd_auth.py | 106 - samples/nnrpd_auth_wrapper.pl.in | 49 - samples/nnrpd_auth_wrapper.py | 62 - samples/nnrpd_dynamic.py | 99 - samples/nnrpd_dynamic_wrapper.py | 57 - samples/nntpsend.ctl | 15 - samples/ovdb.conf | 104 - samples/overview.fmt | 16 - samples/passwd.nntp | 14 - samples/radius.conf | 63 - samples/readers.conf | 136 - samples/sasl.conf.in | 3 - samples/startup.tcl | 15 - samples/startup_innd.pl | 46 - samples/storage.conf | 45 - samples/subscriptions | 6 - scripts/Makefile | 79 - scripts/inncheck.in | 937 ----- scripts/innmail.in | 78 - scripts/innreport.in | 2598 ------------ scripts/innreport_inn.pm | 2227 ----------- scripts/innshellvars.in | 114 - scripts/innshellvars.pl.in | 116 - scripts/innshellvars.tcl.in | 105 - scripts/innstat.in | 79 - scripts/innupgrade.in | 152 - scripts/innwatch.in | 334 -- scripts/news.daily.in | 537 --- scripts/rc.news.in | 186 - scripts/scanlogs.in | 331 -- scripts/simpleftp.in | 90 - scripts/tally.control.in | 59 - scripts/writelog.in | 56 - site/Makefile | 268 -- site/getsafe.sh | 46 - storage/Make.methods | 31 - storage/Makefile | 225 -- storage/buffindexed/buffindexed.c | 2275 ----------- storage/buffindexed/buffindexed.h | 26 - storage/buffindexed/ovmethod.config | 3 - storage/buffindexed/ovmethod.mk | 8 - storage/buildconfig.in | 258 -- storage/cnfs/cnfs-private.h | 111 - storage/cnfs/cnfs.c | 1771 --------- storage/cnfs/cnfs.h | 20 - storage/cnfs/method.config | 3 - storage/expire.c | 906 ----- storage/interface.c | 962 ----- storage/interface.h | 58 - storage/ov.c | 372 -- storage/ovdb/ovdb-private.h | 233 -- storage/ovdb/ovdb.c | 3004 -------------- storage/ovdb/ovdb.h | 26 - storage/ovdb/ovmethod.config | 3 - storage/overdata.c | 416 -- storage/ovinterface.h | 56 - storage/timecaf/README.CAF | 125 - storage/timecaf/caf.c | 1823 --------- storage/timecaf/caf.h | 153 - storage/timecaf/method.config | 3 - storage/timecaf/timecaf.c | 853 ---- storage/timecaf/timecaf.h | 25 - storage/timehash/method.config | 3 - storage/timehash/timehash.c | 530 --- storage/timehash/timehash.h | 23 - storage/tradindexed/ovmethod.config | 5 - storage/tradindexed/ovmethod.mk | 6 - storage/tradindexed/tdx-cache.c | 214 - storage/tradindexed/tdx-data.c | 1090 ------ storage/tradindexed/tdx-group.c | 1424 ------- storage/tradindexed/tdx-private.h | 176 - storage/tradindexed/tdx-structure.h | 128 - storage/tradindexed/tdx-util.c | 469 --- storage/tradindexed/tradindexed.c | 408 -- storage/tradindexed/tradindexed.h | 40 - storage/tradspool/README.tradspool | 43 - storage/tradspool/method.config | 3 - storage/tradspool/tradspool.c | 1313 ------- storage/tradspool/tradspool.h | 23 - storage/trash/method.config | 3 - storage/trash/trash.c | 94 - storage/trash/trash.h | 23 - support/config.guess | 1526 -------- support/config.sub | 1669 -------- support/fixscript.in | 77 - support/indent | 29 - support/install-sh | 276 -- support/ltmain.sh | 4995 ------------------------ support/makedepend | 36 - support/mkchangelog | 23 - support/mkmanifest | 74 - support/mksnapshot | 50 - support/mksystem | 47 - support/mkversion | 39 - tests/Makefile | 179 - tests/TESTS | 32 - tests/authprogs/ckpasswd.t | 80 - tests/authprogs/domain.t | 70 - tests/authprogs/passwd | 10 - tests/lib/articles/no-body | 5 - tests/lib/articles/strange | Bin 477 -> 0 bytes tests/lib/articles/truncated | 5 - tests/lib/buffer-t.c | 69 - tests/lib/concat-t.c | 31 - tests/lib/config/errors | 52 - tests/lib/config/line-endings | 10 - tests/lib/config/no-newline | 2 - tests/lib/config/null | Bin 84 -> 0 bytes tests/lib/config/simple | 2 - tests/lib/config/valid | 29 - tests/lib/config/warn-bool | 13 - tests/lib/config/warn-int | 13 - tests/lib/config/warnings | 18 - tests/lib/confparse-t.c | 399 -- tests/lib/date-t.c | 178 - tests/lib/fakewrite.c | 101 - tests/lib/hash-t.c | 47 - tests/lib/hashtab-t.c | 191 - tests/lib/hstrerror-t.c | 32 - tests/lib/inet_aton-t.c | 95 - tests/lib/inet_ntoa-t.c | 33 - tests/lib/innconf-t.c | 64 - tests/lib/list-t.c | 67 - tests/lib/md5-t.c | 141 - tests/lib/memcmp-t.c | 34 - tests/lib/messages-t.c | 265 -- tests/lib/mkstemp-t.c | 65 - tests/lib/pread-t.c | 57 - tests/lib/pwrite-t.c | 51 - tests/lib/qio-t.c | 155 - tests/lib/setenv-t.c | 59 - tests/lib/setenv.t | 17 - tests/lib/snprintf-t.c | 165 - tests/lib/strerror-t.c | 29 - tests/lib/strlcat-t.c | 54 - tests/lib/strlcpy-t.c | 49 - tests/lib/tst-t.c | 132 - tests/lib/uwildmat-t.c | 240 -- tests/lib/vector-t.c | 189 - tests/lib/wire-t.c | 123 - tests/lib/xmalloc.c | 215 - tests/lib/xmalloc.t | 97 - tests/lib/xwrite-t.c | 126 - tests/libtest.c | 114 - tests/libtest.h | 29 - tests/overview/data/basic | 99 - tests/overview/data/bogus | 9 - tests/overview/data/high-numbered | 2 - tests/overview/data/reversed | 99 - tests/overview/munge-data | 43 - tests/overview/tradindexed-t.c | 507 --- tests/runtests.c | 690 ---- tests/util/convdate.t | 54 - 735 files changed, 214273 deletions(-) delete mode 100644 CONTRIBUTORS delete mode 100644 ChangeLog delete mode 100644 HACKING delete mode 100644 INSTALL delete mode 100644 LICENSE delete mode 100644 MANIFEST delete mode 100644 NEWS delete mode 100644 README delete mode 100644 TODO delete mode 100644 authprogs/Makefile delete mode 100644 authprogs/auth_krb5.c delete mode 100644 authprogs/auth_smb.c delete mode 100644 authprogs/ckpasswd.c delete mode 100644 authprogs/domain.c delete mode 100644 authprogs/ident.c delete mode 100644 authprogs/libauth.c delete mode 100644 authprogs/libauth.h delete mode 100644 authprogs/radius.c delete mode 100644 authprogs/smbval/Makefile delete mode 100644 authprogs/smbval/byteorder.h delete mode 100644 authprogs/smbval/rfcnb-common.h delete mode 100644 authprogs/smbval/rfcnb-error.h delete mode 100644 authprogs/smbval/rfcnb-io.c delete mode 100644 authprogs/smbval/rfcnb-io.h delete mode 100644 authprogs/smbval/rfcnb-priv.h delete mode 100644 authprogs/smbval/rfcnb-util.c delete mode 100644 authprogs/smbval/rfcnb-util.h delete mode 100644 authprogs/smbval/rfcnb.h delete mode 100644 authprogs/smbval/session.c delete mode 100644 authprogs/smbval/smbdes.c delete mode 100644 authprogs/smbval/smbencrypt.c delete mode 100644 authprogs/smbval/smblib-common.h delete mode 100644 authprogs/smbval/smblib-priv.h delete mode 100644 authprogs/smbval/smblib-util.c delete mode 100644 authprogs/smbval/smblib.c delete mode 100644 authprogs/smbval/smblib.h delete mode 100644 authprogs/smbval/valid.c delete mode 100644 authprogs/smbval/valid.h delete mode 100644 backends/actmerge.in delete mode 100644 backends/actsync.c delete mode 100644 backends/actsyncd.in delete mode 100644 backends/archive.c delete mode 100644 backends/batcher.c delete mode 100644 backends/buffchan.c delete mode 100644 backends/crosspost.c delete mode 100644 backends/cvtbatch.c delete mode 100644 backends/filechan.c delete mode 100644 backends/inndf.c delete mode 100644 backends/innxbatch.c delete mode 100644 backends/innxmit.c delete mode 100644 backends/map.c delete mode 100644 backends/map.h delete mode 100644 backends/mod-active.in delete mode 100644 backends/news2mail.in delete mode 100644 backends/ninpaths.c delete mode 100644 backends/nntpget.c delete mode 100644 backends/nntpsend.in delete mode 100644 backends/overchan.c delete mode 100644 backends/send-ihave.in delete mode 100644 backends/send-nntp.in delete mode 100644 backends/send-uucp.in delete mode 100644 backends/sendinpaths.in delete mode 100644 backends/sendxbatches.in delete mode 100644 backends/shlock.c delete mode 100644 backends/shrinkfile.c delete mode 100644 contrib/Makefile delete mode 100644 contrib/README delete mode 100644 contrib/archivegz.in delete mode 100644 contrib/auth_pass.README delete mode 100644 contrib/auth_pass.c delete mode 100644 contrib/backlogstat.in delete mode 100644 contrib/backupfeed.in delete mode 100644 contrib/cleannewsgroups.in delete mode 100755 contrib/count_overview.pl delete mode 100644 contrib/delayer.in delete mode 100644 contrib/expirectl.c delete mode 100644 contrib/findreadgroups.in delete mode 100755 contrib/fixhist delete mode 100755 contrib/innconfcheck delete mode 100644 contrib/makeexpctl.in delete mode 100644 contrib/makestorconf.in delete mode 100755 contrib/mkbuf delete mode 100644 contrib/mlockfile.c delete mode 100644 contrib/newsresp.c delete mode 100644 contrib/pullart.c delete mode 100644 contrib/reset-cnfs.c delete mode 100644 contrib/respool.c delete mode 100644 contrib/sample.init.script delete mode 100644 contrib/showtoken.in delete mode 100644 contrib/stathist.in delete mode 100644 contrib/thdexpire.in delete mode 100644 contrib/tunefeed.in delete mode 100644 control/Makefile delete mode 100644 control/controlbatch.in delete mode 100644 control/controlchan.in delete mode 100644 control/docheckgroups.in delete mode 100644 control/gpgverify.in delete mode 100644 control/modules/checkgroups.pl delete mode 100644 control/modules/ihave.pl delete mode 100644 control/modules/newgroup.pl delete mode 100644 control/modules/rmgroup.pl delete mode 100644 control/modules/sendme.pl delete mode 100644 control/modules/sendsys.pl delete mode 100644 control/modules/senduuname.pl delete mode 100644 control/modules/version.pl delete mode 100644 control/perl-nocem.in delete mode 100644 control/pgpverify.in delete mode 100644 control/signcontrol.in delete mode 100644 debian/changelog delete mode 100644 debian/changelog.old delete mode 100644 debian/compat delete mode 100644 debian/inn2-dev.files delete mode 100644 debian/inn2-dev.links delete mode 100644 debian/inn2-inews.files delete mode 100644 debian/inn2-inews.links delete mode 100644 debian/inn2.README.Debian delete mode 100644 debian/inn2.cron.d delete mode 100644 debian/inn2.docs delete mode 100644 debian/inn2.examples delete mode 100644 debian/inn2.init delete mode 100644 debian/inn2.links delete mode 100644 debian/inn2.logcheck.ignore.server delete mode 100644 debian/inn2.logcheck.violations.ignore delete mode 100644 debian/inn2.postinst delete mode 100644 debian/inn2.postrm delete mode 100644 debian/inn2.preinst delete mode 100644 debian/inn2.prerm delete mode 100644 debian/patches/debian-paths delete mode 100644 debian/patches/fix_ad_flag delete mode 100644 debian/patches/fix_body_regexps delete mode 100644 debian/patches/no-makedbz-on-install delete mode 100644 debian/patches/nocem-gpg-import delete mode 100644 debian/patches/series delete mode 100644 debian/patches/typo_inn_conf_man delete mode 100644 debian/patches/u_innreport_misc delete mode 100644 debian/patches/u_right_length delete mode 100644 debian/patches/u_status_init_ip delete mode 100644 debian/patches/u_tls_duplicate_reply delete mode 100644 debian/patches/u_xhdr_permissions delete mode 100644 debian/patches/u_xover_duplicate_reply delete mode 100755 debian/rules delete mode 100644 debian/watch delete mode 100644 doc/GPL delete mode 100644 doc/IPv6-info delete mode 100644 doc/checklist delete mode 100644 doc/compliance-nntp delete mode 100644 doc/config-design delete mode 100644 doc/config-semantics delete mode 100644 doc/config-syntax delete mode 100644 doc/external-auth delete mode 100644 doc/history delete mode 100644 doc/hook-perl delete mode 100644 doc/hook-python delete mode 100644 doc/hook-tcl delete mode 100644 doc/man/Makefile delete mode 100644 doc/man/active.5 delete mode 100644 doc/man/active.times.5 delete mode 100644 doc/man/actsync.8 delete mode 100644 doc/man/actsyncd.8 delete mode 100644 doc/man/archive.8 delete mode 100644 doc/man/auth_krb5.8 delete mode 100644 doc/man/auth_smb.8 delete mode 100644 doc/man/batcher.8 delete mode 100644 doc/man/buffchan.8 delete mode 100644 doc/man/buffindexed.conf.5 delete mode 100644 doc/man/ckpasswd.8 delete mode 100644 doc/man/clientlib.3 delete mode 100644 doc/man/cnfsheadconf.8 delete mode 100644 doc/man/cnfsstat.8 delete mode 100644 doc/man/control.ctl.5 delete mode 100644 doc/man/controlchan.8 delete mode 100644 doc/man/convdate.1 delete mode 100644 doc/man/ctlinnd.8 delete mode 100644 doc/man/cvtbatch.8 delete mode 100644 doc/man/cycbuff.conf.5 delete mode 100644 doc/man/dbz.3 delete mode 100644 doc/man/distrib.pats.5 delete mode 100644 doc/man/domain.8 delete mode 100644 doc/man/expire.8 delete mode 100644 doc/man/expire.ctl.5 delete mode 100644 doc/man/expireover.8 delete mode 100644 doc/man/expirerm.8 delete mode 100644 doc/man/fastrm.1 delete mode 100644 doc/man/filechan.8 delete mode 100644 doc/man/getlist.1 delete mode 100644 doc/man/grephistory.1 delete mode 100644 doc/man/history.5 delete mode 100644 doc/man/ident.8 delete mode 100644 doc/man/incoming.conf.5 delete mode 100644 doc/man/inews.1 delete mode 100644 doc/man/inn.conf.5 delete mode 100644 doc/man/inncheck.8 delete mode 100644 doc/man/innconfval.1 delete mode 100644 doc/man/innd.8 delete mode 100644 doc/man/inndcomm.3 delete mode 100644 doc/man/inndf.8 delete mode 100644 doc/man/inndstart.8 delete mode 100644 doc/man/innfeed.1 delete mode 100644 doc/man/innfeed.conf.5 delete mode 100644 doc/man/innmail.1 delete mode 100644 doc/man/innreport.8 delete mode 100644 doc/man/innstat.8 delete mode 100644 doc/man/innupgrade.8 delete mode 100644 doc/man/innwatch.8 delete mode 100644 doc/man/innwatch.ctl.5 delete mode 100644 doc/man/innxbatch.8 delete mode 100644 doc/man/innxmit.8 delete mode 100644 doc/man/libauth.3 delete mode 100644 doc/man/libinn.3 delete mode 100644 doc/man/libinnhist.3 delete mode 100644 doc/man/libstorage.3 delete mode 100644 doc/man/list.3 delete mode 100644 doc/man/mailpost.8 delete mode 100644 doc/man/makeactive.8 delete mode 100644 doc/man/makedbz.8 delete mode 100644 doc/man/makehistory.8 delete mode 100644 doc/man/mod-active.8 delete mode 100644 doc/man/moderators.5 delete mode 100644 doc/man/motd.news.5 delete mode 100644 doc/man/news.daily.8 delete mode 100644 doc/man/news2mail.8 delete mode 100644 doc/man/newsfeeds.5 delete mode 100644 doc/man/newslog.5 delete mode 100644 doc/man/ninpaths.8 delete mode 100644 doc/man/nnrpd.8 delete mode 100644 doc/man/nnrpd.track.5 delete mode 100644 doc/man/nntpget.1 delete mode 100644 doc/man/nntpsend.8 delete mode 100644 doc/man/nntpsend.ctl.5 delete mode 100644 doc/man/ovdb.5 delete mode 100644 doc/man/ovdb_init.8 delete mode 100644 doc/man/ovdb_monitor.8 delete mode 100644 doc/man/ovdb_server.8 delete mode 100644 doc/man/ovdb_stat.8 delete mode 100644 doc/man/overchan.8 delete mode 100644 doc/man/overview.fmt.5 delete mode 100644 doc/man/parsedate.3 delete mode 100644 doc/man/passwd.nntp.5 delete mode 100644 doc/man/perl-nocem.8 delete mode 100644 doc/man/pgpverify.1 delete mode 100644 doc/man/prunehistory.8 delete mode 100644 doc/man/pullnews.1 delete mode 100644 doc/man/putman.sh delete mode 100644 doc/man/qio.3 delete mode 100644 doc/man/radius.8 delete mode 100644 doc/man/radius.conf.5 delete mode 100644 doc/man/rc.news.8 delete mode 100644 doc/man/readers.conf.5 delete mode 100644 doc/man/rnews.1 delete mode 100644 doc/man/sasl.conf.5 delete mode 100644 doc/man/scanlogs.8 delete mode 100644 doc/man/send-nntp.8 delete mode 100644 doc/man/send-uucp.8 delete mode 100644 doc/man/sendinpaths.8 delete mode 100644 doc/man/shlock.1 delete mode 100644 doc/man/shrinkfile.1 delete mode 100644 doc/man/simpleftp.1 delete mode 100644 doc/man/sm.1 delete mode 100644 doc/man/startinnfeed.1 delete mode 100644 doc/man/storage.conf.5 delete mode 100644 doc/man/subscriptions.5 delete mode 100644 doc/man/tally.control.8 delete mode 100644 doc/man/tdx-util.8 delete mode 100644 doc/man/tst.3 delete mode 100644 doc/man/uwildmat.3 delete mode 100644 doc/man/writelog.8 delete mode 100644 doc/pod/Makefile delete mode 100644 doc/pod/active.pod delete mode 100644 doc/pod/active.times.pod delete mode 100644 doc/pod/auth_krb5.pod delete mode 100644 doc/pod/auth_smb.pod delete mode 100644 doc/pod/checklist.pod delete mode 100644 doc/pod/ckpasswd.pod delete mode 100644 doc/pod/control.ctl.pod delete mode 100644 doc/pod/convdate.pod delete mode 100644 doc/pod/cycbuff.conf.pod delete mode 100644 doc/pod/distrib.pats.pod delete mode 100644 doc/pod/domain.pod delete mode 100644 doc/pod/expire.ctl.pod delete mode 100644 doc/pod/expireover.pod delete mode 100644 doc/pod/external-auth.pod delete mode 100644 doc/pod/fastrm.pod delete mode 100644 doc/pod/grephistory.pod delete mode 100644 doc/pod/hacking.pod delete mode 100644 doc/pod/hook-perl.pod delete mode 100644 doc/pod/hook-python.pod delete mode 100644 doc/pod/ident.pod delete mode 100644 doc/pod/inews.pod delete mode 100644 doc/pod/inn.conf.pod delete mode 100644 doc/pod/innconfval.pod delete mode 100644 doc/pod/innd.pod delete mode 100644 doc/pod/inndf.pod delete mode 100644 doc/pod/inndstart.pod delete mode 100644 doc/pod/innmail.pod delete mode 100644 doc/pod/innupgrade.pod delete mode 100644 doc/pod/install.pod delete mode 100644 doc/pod/libauth.pod delete mode 100644 doc/pod/libinnhist.pod delete mode 100644 doc/pod/list.pod delete mode 100644 doc/pod/mailpost.pod delete mode 100644 doc/pod/makehistory.pod delete mode 100644 doc/pod/motd.news.pod delete mode 100644 doc/pod/news.pod delete mode 100644 doc/pod/newsfeeds.pod delete mode 100644 doc/pod/ninpaths.pod delete mode 100644 doc/pod/nnrpd.pod delete mode 100644 doc/pod/ovdb.pod delete mode 100644 doc/pod/ovdb_init.pod delete mode 100644 doc/pod/ovdb_monitor.pod delete mode 100644 doc/pod/ovdb_server.pod delete mode 100644 doc/pod/ovdb_stat.pod delete mode 100644 doc/pod/passwd.nntp.pod delete mode 100644 doc/pod/pullnews.pod delete mode 100644 doc/pod/qio.pod delete mode 100644 doc/pod/radius.conf.pod delete mode 100644 doc/pod/radius.pod delete mode 100644 doc/pod/rc.news.pod delete mode 100644 doc/pod/readers.conf.pod delete mode 100644 doc/pod/readme.pod delete mode 100644 doc/pod/sasl.conf.pod delete mode 100644 doc/pod/sendinpaths.pod delete mode 100644 doc/pod/simpleftp.pod delete mode 100644 doc/pod/sm.pod delete mode 100644 doc/pod/subscriptions.pod delete mode 100644 doc/pod/tdx-util.pod delete mode 100644 doc/pod/tst.pod delete mode 100644 doc/pod/uwildmat.pod delete mode 100644 doc/sample-control delete mode 100644 expire/Makefile delete mode 100644 expire/convdate.c delete mode 100644 expire/expire.c delete mode 100644 expire/expireover.c delete mode 100644 expire/expirerm.in delete mode 100644 expire/fastrm.c delete mode 100644 expire/grephistory.c delete mode 100644 expire/makedbz.c delete mode 100644 expire/makehistory.c delete mode 100644 expire/prunehistory.c delete mode 100644 extra/active delete mode 100644 extra/buildinnkeyring delete mode 100644 extra/bunbatch delete mode 100644 extra/dh_cloneconf delete mode 100644 extra/ginpaths2 delete mode 100644 extra/newsgroups delete mode 100644 extra/sasl.conf delete mode 100644 extra/send-uucp.cf delete mode 100644 frontends/Makefile delete mode 100644 frontends/cnfsheadconf.in delete mode 100644 frontends/cnfsstat.in delete mode 100644 frontends/ctlinnd.c delete mode 100644 frontends/decode.c delete mode 100644 frontends/encode.c delete mode 100644 frontends/feedone.c delete mode 100644 frontends/getlist.c delete mode 100644 frontends/inews.c delete mode 100644 frontends/innconfval.c delete mode 100644 frontends/mailpost.in delete mode 100644 frontends/ovdb_init.c delete mode 100644 frontends/ovdb_monitor.c delete mode 100644 frontends/ovdb_server.c delete mode 100644 frontends/ovdb_stat.c delete mode 100644 frontends/pullnews.in delete mode 100644 frontends/rnews.c delete mode 100644 frontends/scanspool.in delete mode 100644 frontends/sm.c delete mode 100644 frontends/sys2nf.c delete mode 100644 history/Make.methods delete mode 100644 history/Makefile delete mode 100644 history/buildconfig.in delete mode 100644 history/his.c delete mode 100644 history/hisinterface.h delete mode 100644 history/hisv6/hismethod.config delete mode 100644 history/hisv6/hisv6-private.h delete mode 100644 history/hisv6/hisv6.c delete mode 100644 history/hisv6/hisv6.h delete mode 100644 include/Makefile delete mode 100644 include/acconfig.h delete mode 100644 include/clibrary.h delete mode 100644 include/conffile.h delete mode 100644 include/dbz.h delete mode 100644 include/inn/buffer.h delete mode 100644 include/inn/confparse.h delete mode 100644 include/inn/defines.h delete mode 100644 include/inn/hashtab.h delete mode 100644 include/inn/history.h delete mode 100644 include/inn/innconf.h delete mode 100644 include/inn/list.h delete mode 100644 include/inn/md5.h delete mode 100644 include/inn/messages.h delete mode 100644 include/inn/mmap.h delete mode 100644 include/inn/qio.h delete mode 100644 include/inn/sequence.h delete mode 100644 include/inn/timer.h delete mode 100644 include/inn/tst.h delete mode 100644 include/inn/vector.h delete mode 100644 include/inn/wire.h delete mode 100644 include/inndcomm.h delete mode 100644 include/innperl.h delete mode 100644 include/libinn.h delete mode 100644 include/nntp.h delete mode 100644 include/ov.h delete mode 100644 include/paths.h.in delete mode 100644 include/portable/mmap.h delete mode 100644 include/portable/setproctitle.h delete mode 100644 include/portable/socket.h delete mode 100644 include/portable/time.h delete mode 100644 include/portable/wait.h delete mode 100644 include/ppport.h delete mode 100644 innd/Makefile delete mode 100644 innd/art.c delete mode 100644 innd/cc.c delete mode 100644 innd/chan.c delete mode 100644 innd/icd.c delete mode 100644 innd/innd.c delete mode 100644 innd/innd.h delete mode 100644 innd/inndstart.c delete mode 100644 innd/keywords.c delete mode 100644 innd/lc.c delete mode 100644 innd/nc.c delete mode 100644 innd/newsfeeds.c delete mode 100644 innd/ng.c delete mode 100644 innd/perl.c delete mode 100644 innd/proc.c delete mode 100644 innd/python.c delete mode 100644 innd/rc.c delete mode 100644 innd/site.c delete mode 100644 innd/status.c delete mode 100644 innd/tcl.c delete mode 100644 innd/util.c delete mode 100644 innd/wip.c delete mode 100644 innfeed/Makefile delete mode 100644 innfeed/README delete mode 100644 innfeed/article.c delete mode 100644 innfeed/article.h delete mode 100644 innfeed/buffer.c delete mode 100644 innfeed/buffer.h delete mode 100644 innfeed/config_l.c delete mode 100644 innfeed/configfile.h delete mode 100644 innfeed/configfile.l delete mode 100644 innfeed/configfile.y delete mode 100644 innfeed/connection.c delete mode 100644 innfeed/connection.h delete mode 100644 innfeed/endpoint.c delete mode 100644 innfeed/endpoint.h delete mode 100644 innfeed/host.c delete mode 100644 innfeed/host.h delete mode 100644 innfeed/imap_connection.c delete mode 100644 innfeed/innfeed-convcfg.in delete mode 100644 innfeed/innfeed.h delete mode 100644 innfeed/innlistener.c delete mode 100644 innfeed/innlistener.h delete mode 100644 innfeed/main.c delete mode 100644 innfeed/misc.c delete mode 100644 innfeed/misc.h delete mode 100644 innfeed/procbatch.in delete mode 100644 innfeed/startinnfeed.c delete mode 100644 innfeed/tape.c delete mode 100644 innfeed/tape.h delete mode 100644 innfeed/testListener.pl delete mode 100644 lib/Makefile delete mode 100644 lib/buffer.c delete mode 100644 lib/cleanfrom.c delete mode 100644 lib/clientactive.c delete mode 100644 lib/clientlib.c delete mode 100644 lib/concat.c delete mode 100644 lib/conffile.c delete mode 100644 lib/confparse.c delete mode 100644 lib/daemonize.c delete mode 100644 lib/date.c delete mode 100644 lib/dbz.c delete mode 100644 lib/defdist.c delete mode 100644 lib/fdflags.c delete mode 100644 lib/fdlimit.c delete mode 100644 lib/fseeko.c delete mode 100644 lib/ftello.c delete mode 100644 lib/genid.c delete mode 100644 lib/getfqdn.c delete mode 100644 lib/getmodaddr.c delete mode 100644 lib/getpagesize.c delete mode 100644 lib/gettime.c delete mode 100644 lib/hash.c delete mode 100644 lib/hashtab.c delete mode 100644 lib/hstrerror.c delete mode 100644 lib/inet_aton.c delete mode 100644 lib/inet_ntoa.c delete mode 100644 lib/innconf.c delete mode 100644 lib/inndcomm.c delete mode 100644 lib/list.c delete mode 100644 lib/localopen.c delete mode 100644 lib/lockfile.c delete mode 100644 lib/makedir.c delete mode 100644 lib/md5.c delete mode 100644 lib/memcmp.c delete mode 100644 lib/messages.c delete mode 100644 lib/mkstemp.c delete mode 100644 lib/mmap.c delete mode 100644 lib/parsedate.y delete mode 100644 lib/perl.c delete mode 100644 lib/pread.c delete mode 100644 lib/pwrite.c delete mode 100644 lib/qio.c delete mode 100644 lib/radix32.c delete mode 100644 lib/readin.c delete mode 100644 lib/reservedfd.c delete mode 100644 lib/resource.c delete mode 100644 lib/sendarticle.c delete mode 100644 lib/sendpass.c delete mode 100644 lib/sequence.c delete mode 100644 lib/setenv.c delete mode 100644 lib/seteuid.c delete mode 100644 lib/setproctitle.c delete mode 100644 lib/snprintf.c delete mode 100644 lib/sockaddr.c delete mode 100644 lib/strcasecmp.c delete mode 100644 lib/strerror.c delete mode 100644 lib/strlcat.c delete mode 100644 lib/strlcpy.c delete mode 100644 lib/strspn.c delete mode 100644 lib/strtok.c delete mode 100644 lib/timer.c delete mode 100644 lib/tst.c delete mode 100644 lib/uwildmat.c delete mode 100644 lib/vector.c delete mode 100644 lib/version.c delete mode 100644 lib/wire.c delete mode 100644 lib/xfopena.c delete mode 100644 lib/xmalloc.c delete mode 100644 lib/xsignal.c delete mode 100644 lib/xwrite.c delete mode 100644 nnrpd/Makefile delete mode 100644 nnrpd/article.c delete mode 100644 nnrpd/cache.c delete mode 100644 nnrpd/cache.h delete mode 100644 nnrpd/commands.c delete mode 100644 nnrpd/group.c delete mode 100644 nnrpd/line.c delete mode 100644 nnrpd/list.c delete mode 100644 nnrpd/misc.c delete mode 100644 nnrpd/newnews.c delete mode 100644 nnrpd/nnrpd.c delete mode 100644 nnrpd/nnrpd.h delete mode 100644 nnrpd/perl.c delete mode 100644 nnrpd/perm.c delete mode 100644 nnrpd/post.c delete mode 100644 nnrpd/post.h delete mode 100644 nnrpd/python.c delete mode 100644 nnrpd/sasl_config.c delete mode 100644 nnrpd/sasl_config.h delete mode 100644 nnrpd/tls.c delete mode 100644 nnrpd/tls.h delete mode 100644 nnrpd/track.c delete mode 100644 samples/INN.py delete mode 100644 samples/Makefile delete mode 100644 samples/active.minimal delete mode 100644 samples/actsync.cfg delete mode 100644 samples/actsync.ign delete mode 100644 samples/buffindexed.conf delete mode 100644 samples/control.ctl delete mode 100644 samples/cycbuff.conf delete mode 100644 samples/distrib.pats delete mode 100644 samples/expire.ctl delete mode 100644 samples/filter.tcl delete mode 100644 samples/filter_innd.pl delete mode 100644 samples/filter_innd.py delete mode 100644 samples/filter_nnrpd.pl delete mode 100644 samples/incoming.conf delete mode 100644 samples/inn.conf.in delete mode 100644 samples/innfeed.conf delete mode 100644 samples/innreport.conf.in delete mode 100644 samples/innwatch.ctl delete mode 100644 samples/moderators delete mode 100644 samples/motd.news delete mode 100644 samples/news2mail.cf delete mode 100644 samples/newsfeeds.in delete mode 100644 samples/newsgroups.minimal delete mode 100644 samples/nnrpd.py delete mode 100644 samples/nnrpd.track delete mode 100644 samples/nnrpd_access.pl.in delete mode 100644 samples/nnrpd_access.py delete mode 100644 samples/nnrpd_access_wrapper.pl.in delete mode 100644 samples/nnrpd_access_wrapper.py delete mode 100644 samples/nnrpd_auth.pl.in delete mode 100644 samples/nnrpd_auth.py delete mode 100644 samples/nnrpd_auth_wrapper.pl.in delete mode 100644 samples/nnrpd_auth_wrapper.py delete mode 100644 samples/nnrpd_dynamic.py delete mode 100644 samples/nnrpd_dynamic_wrapper.py delete mode 100644 samples/nntpsend.ctl delete mode 100644 samples/ovdb.conf delete mode 100644 samples/overview.fmt delete mode 100644 samples/passwd.nntp delete mode 100644 samples/radius.conf delete mode 100644 samples/readers.conf delete mode 100644 samples/sasl.conf.in delete mode 100644 samples/startup.tcl delete mode 100644 samples/startup_innd.pl delete mode 100644 samples/storage.conf delete mode 100644 samples/subscriptions delete mode 100644 scripts/Makefile delete mode 100644 scripts/inncheck.in delete mode 100644 scripts/innmail.in delete mode 100644 scripts/innreport.in delete mode 100644 scripts/innreport_inn.pm delete mode 100644 scripts/innshellvars.in delete mode 100644 scripts/innshellvars.pl.in delete mode 100644 scripts/innshellvars.tcl.in delete mode 100644 scripts/innstat.in delete mode 100644 scripts/innupgrade.in delete mode 100644 scripts/innwatch.in delete mode 100644 scripts/news.daily.in delete mode 100644 scripts/rc.news.in delete mode 100644 scripts/scanlogs.in delete mode 100644 scripts/simpleftp.in delete mode 100644 scripts/tally.control.in delete mode 100644 scripts/writelog.in delete mode 100644 site/Makefile delete mode 100644 site/getsafe.sh delete mode 100644 storage/Make.methods delete mode 100644 storage/Makefile delete mode 100644 storage/buffindexed/buffindexed.c delete mode 100644 storage/buffindexed/buffindexed.h delete mode 100644 storage/buffindexed/ovmethod.config delete mode 100644 storage/buffindexed/ovmethod.mk delete mode 100644 storage/buildconfig.in delete mode 100644 storage/cnfs/cnfs-private.h delete mode 100644 storage/cnfs/cnfs.c delete mode 100644 storage/cnfs/cnfs.h delete mode 100644 storage/cnfs/method.config delete mode 100644 storage/expire.c delete mode 100644 storage/interface.c delete mode 100644 storage/interface.h delete mode 100644 storage/ov.c delete mode 100644 storage/ovdb/ovdb-private.h delete mode 100644 storage/ovdb/ovdb.c delete mode 100644 storage/ovdb/ovdb.h delete mode 100644 storage/ovdb/ovmethod.config delete mode 100644 storage/overdata.c delete mode 100644 storage/ovinterface.h delete mode 100644 storage/timecaf/README.CAF delete mode 100644 storage/timecaf/caf.c delete mode 100644 storage/timecaf/caf.h delete mode 100644 storage/timecaf/method.config delete mode 100644 storage/timecaf/timecaf.c delete mode 100644 storage/timecaf/timecaf.h delete mode 100644 storage/timehash/method.config delete mode 100644 storage/timehash/timehash.c delete mode 100644 storage/timehash/timehash.h delete mode 100644 storage/tradindexed/ovmethod.config delete mode 100644 storage/tradindexed/ovmethod.mk delete mode 100644 storage/tradindexed/tdx-cache.c delete mode 100644 storage/tradindexed/tdx-data.c delete mode 100644 storage/tradindexed/tdx-group.c delete mode 100644 storage/tradindexed/tdx-private.h delete mode 100644 storage/tradindexed/tdx-structure.h delete mode 100644 storage/tradindexed/tdx-util.c delete mode 100644 storage/tradindexed/tradindexed.c delete mode 100644 storage/tradindexed/tradindexed.h delete mode 100644 storage/tradspool/README.tradspool delete mode 100644 storage/tradspool/method.config delete mode 100644 storage/tradspool/tradspool.c delete mode 100644 storage/tradspool/tradspool.h delete mode 100644 storage/trash/method.config delete mode 100644 storage/trash/trash.c delete mode 100644 storage/trash/trash.h delete mode 100755 support/config.guess delete mode 100755 support/config.sub delete mode 100644 support/fixscript.in delete mode 100755 support/indent delete mode 100755 support/install-sh delete mode 100644 support/ltmain.sh delete mode 100755 support/makedepend delete mode 100755 support/mkchangelog delete mode 100755 support/mkmanifest delete mode 100755 support/mksnapshot delete mode 100755 support/mksystem delete mode 100755 support/mkversion delete mode 100644 tests/Makefile delete mode 100644 tests/TESTS delete mode 100755 tests/authprogs/ckpasswd.t delete mode 100755 tests/authprogs/domain.t delete mode 100644 tests/authprogs/passwd delete mode 100644 tests/lib/articles/no-body delete mode 100644 tests/lib/articles/strange delete mode 100644 tests/lib/articles/truncated delete mode 100644 tests/lib/buffer-t.c delete mode 100644 tests/lib/concat-t.c delete mode 100644 tests/lib/config/errors delete mode 100644 tests/lib/config/line-endings delete mode 100644 tests/lib/config/no-newline delete mode 100644 tests/lib/config/null delete mode 100644 tests/lib/config/simple delete mode 100644 tests/lib/config/valid delete mode 100644 tests/lib/config/warn-bool delete mode 100644 tests/lib/config/warn-int delete mode 100644 tests/lib/config/warnings delete mode 100644 tests/lib/confparse-t.c delete mode 100644 tests/lib/date-t.c delete mode 100644 tests/lib/fakewrite.c delete mode 100644 tests/lib/hash-t.c delete mode 100644 tests/lib/hashtab-t.c delete mode 100644 tests/lib/hstrerror-t.c delete mode 100644 tests/lib/inet_aton-t.c delete mode 100644 tests/lib/inet_ntoa-t.c delete mode 100644 tests/lib/innconf-t.c delete mode 100644 tests/lib/list-t.c delete mode 100644 tests/lib/md5-t.c delete mode 100644 tests/lib/memcmp-t.c delete mode 100644 tests/lib/messages-t.c delete mode 100644 tests/lib/mkstemp-t.c delete mode 100644 tests/lib/pread-t.c delete mode 100644 tests/lib/pwrite-t.c delete mode 100644 tests/lib/qio-t.c delete mode 100644 tests/lib/setenv-t.c delete mode 100755 tests/lib/setenv.t delete mode 100644 tests/lib/snprintf-t.c delete mode 100644 tests/lib/strerror-t.c delete mode 100644 tests/lib/strlcat-t.c delete mode 100644 tests/lib/strlcpy-t.c delete mode 100644 tests/lib/tst-t.c delete mode 100644 tests/lib/uwildmat-t.c delete mode 100644 tests/lib/vector-t.c delete mode 100644 tests/lib/wire-t.c delete mode 100644 tests/lib/xmalloc.c delete mode 100755 tests/lib/xmalloc.t delete mode 100644 tests/lib/xwrite-t.c delete mode 100644 tests/libtest.c delete mode 100644 tests/libtest.h delete mode 100644 tests/overview/data/basic delete mode 100644 tests/overview/data/bogus delete mode 100644 tests/overview/data/high-numbered delete mode 100644 tests/overview/data/reversed delete mode 100755 tests/overview/munge-data delete mode 100644 tests/overview/tradindexed-t.c delete mode 100644 tests/runtests.c delete mode 100755 tests/util/convdate.t diff --git a/CONTRIBUTORS b/CONTRIBUTORS deleted file mode 100644 index 504329f..0000000 --- a/CONTRIBUTORS +++ /dev/null @@ -1,261 +0,0 @@ -The following is a list of the people (in roughly chronological order) -who've helped out. If anyone's name has been left out (probably), or if -something has been incorrectly attributed to you (ditto), please let us -know. - -Rich Salz: - Designed and wrote most of it. - -Bob Halley: - Did the TCL extension. - -Christophe Wolfhugel: - Did the Perl extension and provided several other fixes. - -Doug Needham: - Made nnrpd spool if innd is unavailable. Made nnrpd handle the - LIST SUBSCRIPTIONS command. Added the rebuilding of control - connections to innd (SIGUSR1). Got inews to ask the nntp peer for - moderator info instead of digging it out of a local file. - -David Lawrence: - Did the hooks for PGP verificiation of control messages, added - actived support for syncing against an active file obtained via - ftp. - -John Stapleton: - Wrote the poison newsgroup code ('@') for newsfeeds(5). Wrote the - too-many-connects support ('-X -H -T' flags to innd). - -Landon Curt Noll: - Wrote or co-wrote actsync, nntpsend, shrinkfile, innstat, - news.daily, tally.control and various man pages. He also was the - person originally behind the site directory - configuration/installation process. - -John Levine: - Wrote the '-e' support for expire (expire on shortest time). - -Matthias Urlichs: - Made rnews recognise gzip compression. Made newsfeeds(5) take the - 'Wp' flag. - -Stefan Petri: - Did the original XBATCH support - -Russel Street: - Did more XBATCH support. - -Alan Barrett: - Did the work-limiter in the select loop to stop streaming from - killing performance. - -Greg Patten: - Wrote the perl innlog. - -Clayton O'Neill: - Wrote the articles storage API and implemented the timehash - and regular storage mechanisms with it. He made significant - modifications to dbz. Integrating innfeed, adding Xref slaving, - the history cache, the WIP rewrite and various speedups were - also his doing. Provided the tradindexed overview mechanism. - Implemented the O flag in newsfeeds. Did a bunch of early work on - the CVS repository, reorganization of the code, and committing - patches from others. - -Vincent Archer: - Wrote the initial autoconf scripts. - -Forrest J. Cavalier III: - Provided a lot of bug fixes to 1.5.2. He extended the autoconf - setup a lot to work with version 2.0, and has provided a lot of - valuable design input and testing. - -Scott Fritchie: - Wrote the CNFS storage back end. - -Fabien Tassin: - Wrote the innreport package. Implemented the new incoming.conf - configuration file. Added support for nested profile timers. - -Jeremy Nixon: - Wrote the initial patch for Perl filtering of message IDs on IHAVE - or CHECK and other patches related to the filtering code. - -Karl Kleinpaste: - Wrote the experimental code for automatically generating keywords - from incoming articles and putting those keywords in the overview - for the use of readers. - -Dave Hayes: - Along with some bugfixes, Dave wrote the posting-backoff code for - nnrpd and the patches to the perl hooks to make the headers - modifiable. - -Joe Greco: - Wrote the code for measuring the timing of various parts of innd - and the original actived code. - -Sang-yong Suh: - Provided the fuzzy offset technique to dbz. - -Katsuhiro Kondou: - Provided unified overview, the buffindexed overview method, trash - storage method, spool translation method, traditional expire - policy for articles stored through storage API and expireindex, as - well as hundreds of fixes to clean up defects as changes were - made. Did a large amount of man page documentation and clean up. - Has also been a major force in the CVS pool maintenace. - -Russell Vincent: - Expanded inn.conf to make many of the old compile time options - into run time variables. Numerous bug fixes, small feature - enhancements and man updates. - -Darrell Fuhriman: - Provided various bug fixes and contributed to the pre-SM CNFS - development. - -Steve Carrie: - Modified nnrpd to allow detailed client tracking, added the -R - flag to nnrpd. - -Ed Mooring: - Wrote the first Perl filter callbacks into INN. - -Aidan Cully: - Provided the patches to support the new readers.conf file, and - wrote the initial user authenticators and resolvers for the - readers.conf. Provided the patches to support the new - storage.conf format. Added the option to store articles based on - the Expires header. Also added the '@' article exclusion code to - incoming.conf. - -Andrew Gierth: - Contributed improvements to the nnrpd Perl filtering support to - give access to message bodies and support the DROP and SPOOL - keywords in filter returns. - -Russ Allbery: - Has done large amounts of clean-up on various pieces of the system - (especially the documentation and build system), and has helped - with the CVS pool maintenance. Improved the speed and portability - of the Perl filter. Rewrote the tradindexed overview method for - additional robustness. Has done extensive work on libinn, - breaking out common code from other parts of INN. Lots of other - fixes to various parts of INN. - -Kai Henningsen: - Implemented the C and U flags in newsfeeds. - -Julio Sanchez: - Wrote the initial libtool support for INN. - -Igor Timkin: - Added min-queue-connection support to innfeed, added outgoing - volume logging and reporting, and provided a variety of bug - fixes. - -Heath Kehoe: - Various portability and bug fixes, wrote the ovdb overview - mechanism that uses Berkeley DB. - -Richard Todd: - Implemented the timecaf and tradspool storage mechanisms, as well - as many bug fixes and other contributions. - -Brian Kantor: - Wrote the news2mail gateway. - -Ilya Etingof: - Added Python authentication support for nnrpd. - -Kenichi OKADA: - Added preliminary SSL and SASL support for nnrpd. - -Olaf Titz: - Implemented MODE CANCEL support, as well as other patches and bug - fixes. - -Sven Paulus: - Wrote the support for variables in newsfeeds, contributed various - other patches and bug fixes. - -Krischan Jodies: - Wrote the SMB authenticator. - -Alex Kiernan: - Wrote the history API, generalized the timer code in innd and - innfeed into a generic timer library, reworked the NEWNEWS code - and added a history cache, and contributed various other bug fixes. - -Marco d'Itri: - Wrote gpgverify and overhauled controlchan and its modules. Added - IPv6 support to innd and inndstart. Contributed a rewritten - send-uucp. Has also contributed a variety of bug fixes and helped - with testing. - -Jeffrey M. Vinocur: - Broke parts of the interface with nnrpd for authentication programs - into a separate library, added various features to readers.conf, - and wrote various other fixes and feature improvements, - particularly to nnrpd. - -Erik Klavon: - Significantly reworked nnrpd Perl and Python hooks to be more useful - in combination with the readers.conf mechanism. - -Nathan Lutchansky: - Added IPv6 support to innfeed, nnrpd, and supporting programs. - -Also: - -Dave Barr: - Kept INN alive after Rich Salz didn't have the time any more but - before the ISC took over. He released 4 unofficial versions that - provided a good boost to what the ISC started with. Minor work - on 2.0, mostly with example files and minor code tweaks. - -James Brister: - The chief maintainer of INN from when the ISC took over - maintenance through the 2.2 release, James is also the original - author of innfeed and has made fixes, improvements, and feature - additions all over the code. - -Marc Fournier: - Provided various bug fixes and did a lot of work integrating other - peoples patches and looking after the CVS pool. Helped - significantly with the conversion to autoconf. Added the ability - to set connection limits on a per-host basis. - -Joshua M. Thompson - Wrote the original INSTALL documentation. - -The following people helped above and beyond the call of duty with testing -(provided patches, bug reports, suggestions, documentation improvements, -and lobbying): - -Paul Vixie, Robert Elz, Evan Champion, Robert Keller, Barry Bouwsma, -markd@mira.net.au, Ollivier Robert, Kevin Jameson, Heiko W. Rupp, -Fletcher Mattox, Matus Uhlar, Gabor Kiss, Matthias Scheler, -Richard Michael Todd, Trevor Riley, Alex Bligh, J. Porter Clark, -Alan Brown, Bert Hyman, Petter Nilsen, Gary E. Miller, Kim Culhan, -Marc Baudoin, Neal Becker, Bjorn Knutsson, Stephen Marquard, -Frederick Korz, Benedict Lofstedt, Dan Ellis, Joe Ramey, -Odd Einar Aurbakken, Jon Lewis, Dan Riley, Peter Eriksson, Ken Lalonde, -Koichi Mouri, J. Richard Sladkey, Trine Krogstad, Holger Burbach, -Per Hedeland, Larry Rosenman, Andrew Burgess, Michael Brunnbauer, -Mohan Kokal, Robert R. Collier, Mark Hittinger, Miquel van Smoorenburg, -Boyd Lynn Gerber, Yury B. Razbegin, Joe St. Sauver, Heiko Schlichting, -John P. Speno, Scott Gifford, Steve Parr, Robert Kiessling, -Francis Swasey, Paul Tomblin, Florian La Roche, Curt Welch, -Thomas Mike Michlmayr, KIZU Takashi, Michael Hall, Jeff King, -Edward S. Marshall, Michael Schroeder, George Lindholm, Don Lewis, -Christopher Masto, Hiroaki Sengoku, Yury July, Yar Tikhiy, Kees Bakker, -Peter da Silva, Matt McLeod, Ed Korthof, Jan Rychter, Winfried Magerl, -Andreas Lamrecht, Duane Currie, Ian Dickinson, Bettina Fink, -Jochen Erwied, Rebecca Ore, Felicia Neff, Antonio Querubin, Bear Giles, -Christopher P. Lindsey, Winfried Szukalski, Edvard Tuinder, -Frank McConnell, Ilya Kovalenko, Steve Youngs, Jacek Konieczny, -Ilya Voronin, Sergey Babitch, WATANABE Katsuhiro, Chris Caputo, -Thomas Parmelan diff --git a/ChangeLog b/ChangeLog deleted file mode 100644 index 397156e..0000000 --- a/ChangeLog +++ /dev/null @@ -1,238 +0,0 @@ -2008-06-29 iulius - - * lib/perl.c: Use snprintf instead of asprintf. - - * doc/hook-python, doc/pod/hook-python.pod: Use initial capital - letters for head titles. - - * NEWS, doc/pod/news.pod, lib/perl.c: Fixed a hang in Perl hooks on - (at least) HP/PA since Perl 5.10. On such architectures, - pthread_mutex_lock() hangs inside perl_parse() if - PERL_SYS_INIT3() hasn't been called. - - Also rewrite "do" and "eval" calls to use perl_eval_pv(). - -2008-06-25 iulius - - * samples/innreport.conf.in: For two sections in innreport.conf - there is a mismatch between sort function and sorted hash. - - Thanks to Alexander Bartolich for this patch. - -2008-06-24 iulius - - * NEWS, doc/pod/news.pod, scripts/innreport_inn.pm: Fix another - long-standing bug in innreport which prevented it from correctly - reporting innfeed log messages. - - * scripts/innreport_inn.pm: Suppress a few other nnrpd and - controlchan notices in innreport. - -2008-06-23 iulius - - * NEWS, doc/pod/news.pod: Add changelog for innreport. - - * NEWS, doc/pod/news.pod: Changelog for INN 2.4.5 :-) - - * doc/hook-python: Update the auto-generated documentation for INN - 2.4.5. - - * scripts/innreport_inn.pm: Fix a long-standing bug in innreport - which prevented it from correctly reporting nnrpd log messages. - - * scripts/innreport_inn.pm: Suppress a few warnings in innreport - (especially from Python hooks and nnrpd). Also backport some - other improvements made in TRUNK. - - * site, site/.cvsignore, site/Makefile: Install nnrpd.py which - previously was not. - - * MANIFEST, samples/nnrpd_access.py, samples/nnrpd_auth.py, - samples/nnrpd_dynamic.py, site, site/.cvsignore, site/Makefile: - Update the Python nnrpd filter. New samples for access and - dynamic hooks. - -2008-06-22 iulius - - * samples/filter_innd.py: Update the Python innd filter. - - * doc/pod/hook-python.pod: Typo (canceled -> cancelled). - - * samples/nnrpd_access_wrapper.py, samples/nnrpd_auth_wrapper.py, - samples/nnrpd_dynamic_wrapper.py: Update old Python wrappers. - - * samples/INN.py, samples/nnrpd.py: Update stub Python scripts. Fix - a compilation problem with INN.py (undefined variable) and add - missing methods. - - * doc/hook-python, doc/man/readers.conf.5, doc/pod/hook-python.pod, - doc/pod/readers.conf.pod: Update POD documentation for Python - hooks. It is a complete proof-reading. - - * nnrpd/python.c: No need to check the existence of methods not - used by the hooked script. - - * innd/python.c, nnrpd/python.c: Fix an issue with Python exception - handling. - - * nnrpd/python.c: Fix typos. - - * nnrpd/python.c: Fix a segfault when one closes and then reopens - Python in the same process. files and dynamic_file are still - pointing to the old freed memory and INN blithely tries to write - to it. Thanks to Russ Allbery for the patch. - -2008-06-21 iulius - - * innd/python.c: Better be more careful when decrementing the - reference count for these objects. - -2008-06-16 iulius - - * doc/external-auth, doc/hook-perl, doc/hook-python, - doc/man/active.5, doc/man/active.times.5, doc/man/auth_krb5.8, - doc/man/auth_smb.8, doc/man/ckpasswd.8, doc/man/control.ctl.5, - doc/man/convdate.1, doc/man/cycbuff.conf.5, - doc/man/distrib.pats.5, doc/man/domain.8, doc/man/expire.ctl.5, - doc/man/expireover.8, doc/man/fastrm.1, doc/man/grephistory.1, - doc/man/ident.8, doc/man/inews.1, doc/man/inn.conf.5, - doc/man/innconfval.1, doc/man/innd.8, doc/man/inndf.8, - doc/man/inndstart.8, doc/man/innmail.1, doc/man/innupgrade.8, - doc/man/libauth.3, doc/man/libinnhist.3, doc/man/list.3, - doc/man/mailpost.8, doc/man/makehistory.8, doc/man/motd.news.5, - doc/man/newsfeeds.5, doc/man/ninpaths.8, doc/man/nnrpd.8, - doc/man/ovdb.5, doc/man/ovdb_init.8, doc/man/ovdb_monitor.8, - doc/man/ovdb_server.8, doc/man/ovdb_stat.8, - doc/man/passwd.nntp.5, doc/man/qio.3, doc/man/radius.8, - doc/man/radius.conf.5, doc/man/rc.news.8, doc/man/readers.conf.5, - doc/man/sasl.conf.5, doc/man/sendinpaths.8, doc/man/simpleftp.1, - doc/man/sm.1, doc/man/subscriptions.5, doc/man/tdx-util.8, - doc/man/tst.3, doc/man/uwildmat.3: Update version number for INN - 2.4.5 documentation. - -2008-06-11 iulius - - * support/config.guess, support/config.sub: Update support files - for autoconf to their last stable version. - -2008-06-10 iulius - - * innd/python.c: Fix the name of a variable used in Python filters. - -2008-06-09 iulius - - * innd/python.c: Fix a bug when reloading Python filters. They - might not be correctly reloaded. They must be reimported before - being reloaded. - - * nnrpd/python.c: Fix a segfault when generating access groups with - embedded Python filters for nnrpd. Thanks to David Hlacik for the - bug report. - -2008-06-08 iulius - - * frontends/pullnews.in: Two minor issues resolved with this patch - by Geraint Edwards: * an off-by-one error on the limit to the - amount of articles to get; * when an article is not available, we - may have redundantly retried that article. - -2008-06-07 iulius - - * doc/pod/cycbuff.conf.pod, doc/pod/hook-perl.pod, - doc/pod/hook-python.pod, innd/python.c, samples/filter_innd.pl: - Fix the use of "ctlinnd reload something 'reason'" in - documentation. - -2008-06-05 iulius - - * doc/hook-perl, doc/hook-python, doc/pod/hook-perl.pod, - doc/pod/hook-python.pod, innd/innd.c, innd/innd.h, - samples/filter_innd.py: Add access to several new headers within - Perl and Python hooks for innd. Thanks to Matija Nalis for the - patch. - - Also update the POD documentation and the Python sample. - - * doc/man/pullnews.1, doc/pod/pullnews.pod, frontends/pullnews.in: - A new improved version of pullnews. Great thanks to Geraint A. - Edwards for all his work. He added no more than 16 flags, fixed - some bugs and integrated the backupfeed contrib script by Kai - Henningsen, adding again 6 other flags. - - A long-standing but very minor bug in the -g option was - especially fixed and items from the to-do list implemented. - - From TODO: - - + reset highwater mark to match server (-w) + reset highwater - mark to zero (also -w) + add group to config (-G) + drop articles - with headers matching (or not matching) regexp (-m) - - From backupfeed: - - + pull only a proportion (factor) of articles (-f) + sleeps - between articles/groups (-z/-Z) + Path: fake hop insert (-F) + - NNTP connection timeout (-N) + overall session timeout (-S) - - Other new flags/features: - - -l logfile log to logfile (rather than /dev/null when rnews'ing!) - -s host:port add local port option (can use -p already) -t - retries attempt connect to upstream retries times -T retry_pause - wait between retries -k checkpt checkpoint the config file every - checkpt arts -C width when writing the progress bar - use width - columns -d debug_level self-explanatory -M max_arts only process - max_arts articles per run -H headers remove these headers from - articles -Q quietness set how quiet we are -R be a reader -n - no-op -P paths feed articles depending on number of hops in Path: - -2008-05-25 iulius - - * control/modules/newgroup.pl: Fix a Perl warning. - -2008-05-24 iulius - - * nnrpd/tls.c: When an article of a size greater than remaining - stack is retrieved via SSL, a segmentation fault will occur due - to the use of alloca(). The below patch uses heap based realloc() - instead of stack based alloca(), with a static buffer growing as - needed. It uses realloc() instead of malloc() for performance - reasons since this function is called frequently. The caveat is - that the memory is never free()'ed, so if more correct code is - desired, it should be adjusted. - - Thanks to Chris Caputo for this patch. - -2008-05-19 iulius - - * innd/Makefile, nnrpd/line.c: Implementation of the "alarm signal" - around SSL_read so that to prevent dead connections from leading - nnrpd processes to wait forever in SSL_read(). "clienttimeout" - now also works on SSL connections. - - Thanks to Matija Nalis for the patch. - - * nnrpd/tls.c: Implementation on systems that support it of - SO_KEEPALIVE in SSL TCP connections, allowing system detection - and closing the dead TCP SSL connections automatically after - system-specified time (usually at least 2 hours as recommended by - RFC (on Linux, see /proc/sys/net/ipv4/tcp_keepalive_*). - - Thanks to Matija Nalis for the patch. - -2008-05-18 iulius - - * innfeed/host.c: Fix a problem of undefined constant. - -2008-05-14 iulius - - * innfeed/host.c: Fix a bug in ipAddrs which contained thrice the - same IPs. Rotating the peer IP addresses was a bit slower than it - could be. - - Thanks, D. Stussy, for having seen that. Miquel van Smoorenburg - provided the patch. - - * Makefile.global.in: Bump the revision number to 2.4.5 (in case it - is released one day). - diff --git a/HACKING b/HACKING deleted file mode 100644 index 87a76e3..0000000 --- a/HACKING +++ /dev/null @@ -1,708 +0,0 @@ -Hacking INN - - This file is for people who are interested in making modifications to - INN. Normal users can safely skip reading it. It is intended primarily - as a guide, resource, and accumulation of tips for maintainers and - contributors, and secondarily as documentation of some of INN's - internals. - - This is $Revision: 7736 $ dated $Date: 2006-04-15 04:52:06 +0200 (Sat, - 15 Apr 2006) $. - - First of all, if you plan on working on INN source, please start from - the current development tree. There may be significant changes from the - previous full release, so starting from development sources will make it - considerably easier to integrate your work. You can get nightly - snapshots of the current development source from ftp.isc.org in - /isc/inn/snapshots (the snapshots named inn-CURRENT-*.tar.gz), or you - can get the current CVS tree by using CVSup (see "Using CVSup"). - -Configuring and Portability - - All INN code should be written expecting ANSI C and POSIX. There is no - need to attempt to support pre-ANSI compilers, and ANSI-only features - such as , string concatenation, #elif, and token pasting may - be used freely. So far as possible, INN is written to attempt to be - portable to any system new enough that someone is likely to want to run - a news server on it, but whenever possible this portability should be - provided by checking for standard behavior in configure and supplying - replacements for standard functions that are missing. - - When there is a conflict between ANSI C and C99, INN code should be - written expecting C99 and autoconf used to patch up the differences. - - Try to avoid using #ifdef and the like in the middle of code as much as - possible. Instead, try to isolate the necessary portability bits and - include them in libinn or at least in conditional macros separate from - the code. Trying to read code littered with conditional compilation - directives is much more difficult. - - The shell script configure at the top level of the source tree is - generated by autoconf from configure.in, and include/config.h.in is - generated by autoheader from configure.in and include/acconfig.h. At - configure time, configure generates include/config.h and several other - files based on options it was given and what it discovers about the - target system. - - All modifications to configure should instead be made to configure.in. - Similarly, modifications to include/config.h.in should instead be made - to include/acconfig.h. The autoconf manual (available using info - autoconf if you have autoconf and the GNU info utilities installed on - your system) is a valuable reference when making any modifications. - - To regenerate configure, just run "autoconf". To regenerate - include/config.h.in, run: - - autoheader -l include - - to tell it where to find acconfig.h. Please don't include patches to - either configure or include/config.h.in when sending patches to INN; - instead, note in your patch that those files must be regenerated. - - The generated files are checked into the CVS repository so that people - working on INN don't have to have autoconf on their system, and to make - packaging easier. - - At the time of this writing, autoconf 2.13 is required. - - The supporting files for autoconf are in the support subdirectory, - including the files config.guess and config.sub to determine the system - name and and ltmain.sh for libtool support. The latter file comes from - the libtool distribution; the canonical version of the former two are - available from ftp.gnu.org in /gnu/config. In addition, m4/libtool.m4 - is just a copy of libtool.m4 from the libtool distribution. (Using - libtool without using automake requires a few odd hacks.) These files - used to be on a separate vendor branch so that we could make local - modifications, but local modifications have not been necessary for some - time. Now, new versions can just be checked in like any other file - modifications. - - INN should not compile with libtool by default, only when requested, - since otherwise normal compilations are quite slow. (Using libtool is - not without some cost.) Basic compilation with libtool works fine as of - this writing, with both static and shared compiles, but the dependencies - aren't quite right for make -j using libtool. - -Documentation - - INN's documentation is currently somewhat in a state of flux. The vast - majority is still in the form of man pages written directly in nroff. - Some parts of the documentation have been rewritten in POD; that - documentation can be found in doc/pod. The canonical source for README, - INSTALL, NEWS, doc/hook-perl, doc/hook-python, and this file are also in - POD. - - If you're modifying some part of INN's documentation and see that it has - a POD version in doc/pod, it's preferred if you can make the - modifications to the POD source and then regenerate the derived files. - For a quick introduction to POD, see the perlpod(1) man page on your - system (it should be installed if you have Perl installed). - - When writing new documentation, write in whatever format you care to; if - necessary, we can always convert it to POD or whatever else we want to - use. Having the documentation exist in *some* form is more important - than what language you write it in. If you really don't have any - particular preference, there's a slight preference currently for POD. - - If you use POD or regenerate POD documentation, please install something - close to the latest versions of the POD processing utilities to avoid - changes to the documentation depending on who generated it last. You - can find the latest version on CPAN (ftp.perl.org or another mirror) in - modules/by-module/Pod. You'll need PodParser (for versions of Perl - before 5.6.1; 5.6.1 and later come with a recent enough version) and the - latest version of podlators. For versions of Perl earlier than 5.005, - you'll also need File::Spec in modules/by-module/File. - - podlators 1.25 or later will build INN's documentation without - significant changes from the versions that are checked into the - repository. - - There are Makefile rules in doc/pod/Makefile to build all of the - documentation whose master form is POD; if you add additional - documentation, please add a rule there as well. Documentation should be - generated by cd'ing to doc/pod and typing "make file" where "file" is - the relative path to the documentation file. This will get all of the - various flags right for pod2text or pod2man. - -Error Handling - - INN has a set of generic error handling routines that should be used as - much as possible so that the same syntax can be used for reporting - errors everywhere in INN. The four basic functions are warn, syswarn, - die, and sysdie; warn prints or logs a warning, and die does the same - and then exits the current program. The sys* versions add a colon, a - space, and the value of strerror(errno) to the end of the message, and - should be used to report failing system calls. - - All of the actual error reporting is done via error handlers, and a - program can register its own handlers in addition to or instead of the - default one. The default error handler (error_log_stderr) prints to - stderr, prepending the value of error_program_name if it's set to - something other than NULL. Three other error handlers are available, - error_log_syslog_crit, error_log_syslog_err, and - error_log_syslog_warning, which log the message to syslog at LOG_CRIT, - LOG_ERR, or LOG_WARNING priority, respectively. - - There is a different set of error handlers for warn/syswarn and - die/sysdie. To set them, make calls like: - - warn_set_handlers(2, error_log_stderr, error_log_syslog_warning); - die_set_handlers(2, error_log_stderr, error_log_syslog_err); - - The first argument is the number of handlers, and the remaining - arguments are pointers to functions taking an int (the length of the - formatted message), a const char * (the format), a va_list (the - arguments), and an int that's 0 if warn or die was called and equal to - the value of errno if syswarn or sysdie was called. The length of the - formatted message is obtained by calling vsnprintf with the provided - format and arguments, and therefore is reliable to use as the size of a - buffer to malloc to hold the result of formatting the message provided - that vsnprintf is used to format it (warning: the system vsprintf may - produce more output under some circumstances, so always use vsnprintf). - - The error handler can do anything it wishes; each error handler is - called in the sequence given. Error handlers shouldn't call warn or die - unless great caution is taken to prevent infinite recursion. Also be - aware that sysdie is called if malloc fails in xmalloc, so if the error - handler needs to allocate memory, it must not use xmalloc or a related - function to do so and it shouldn't call die to report failure. The - default syslog handlers report memory allocation failure to stderr and - exit. - - Finally, die and sysdie support an additional handler that's called - immediate before exiting, takes no arguments, and returns an int which - is used as the argument for exit. It can do any necessary global - cleanup, call abort instead to generate a core dump or the like. - - The advantage of using this system everywhere in INN is that library - code can use warn and die to report errors and each calling program can - set up the error handlers as appropriate to make sure the errors go to - the right place. The default handler is fine for interactive programs; - for programs that run from interactive scripts, adding something like: - - error_program_name = "program"; - - to the beginning of main (where program is the name of the program) will - make it easier to figure out which program the script calls is failing. - For programs that may also be called non-interactively, like inndstart, - one may want to set up handlers like: - - warn_set_handlers(2, error_log_stderr, error_log_syslog_warning); - die_set_handlers(2, error_log_stderr, error_log_syslog_err); - - Finally, for daemons and other non-interactive programs, one may want to - do: - - warn_set_handlers(1, error_log_syslog_warning); - die_set_handlers(1, error_log_syslog_err); - - to report errors only via syslog. (Note that if you use syslog error - handlers, the program should call openlog first thing to make sure they - are logged with the right facility.) - - For historical reasons, error messages that are fatal to the news - subsystem are logged at the LOG_CRIT priority, and therefore die in innd - should use error_log_syslog_crit. - -Test Suite - - The test suite for INN is located in the tests directory and is just - getting started. The test suite consists of a set of programs listed in - tests/TESTS and the scaffolding in the runtests program. - - Adding new tests is very straightforward and very flexible. Just write - a program that tests some part of INN, put it in a directory under tests - named after the part of INN it's testing (all the tests so far are in - lib because they're testing libinn routines), and have it output first a - line containing the count of test cases in that file, and then for each - test a line saying "ok n" or "not ok n" where n is the test case number. - (If a test is skipped for some reason, such as a test of an optional - feature that wasn't compiled into INN, the test program should output - "ok n # skip".) Add any rules necessary to build the test to - tests/Makefile (note that for simplicity it doesn't recurse into - subdirectories) and make sure it creates an executable ending in .t. - Then add the name of the test to tests/TESTS, without the .t ending. - - One naming convention: to distinguish more easily between e.g. - lib/error.c (the implementation) and tests/lib/error-t.c (the test - suite), we add -t to the end of the test file names. So - tests/lib/error-t.c is the source that compiles into an executable - tests/lib/error.t which is run by putting a line in tests/TESTS of just - "lib/error". - - Note that tests don't have to be written in C; in fact, lib/xmalloc.t is - just a shell script (that calls a supporting C program). Tests can be - written in shell or Perl (but other languages should be avoided because - someone who wants to run the test suite may not have it) and just have - to follow the above output conventions. - - Additions to the test suite, no matter how simple, are very welcome. - -Makefiles - - All INN makefiles include Makefile.global at the top level, and only - that makefile is a configure substitution target. This has the - disadvantage that configure's normal support for building in a tree - outside of the source tree doesn't work, but it has the significant - advantage of making configure run much faster and allowing one to run - make in any subdirectory and pick up all the definitions and settings - from the top level configuration. - - All INN makefiles should also set $(top) to be the path to the top of - the build directory (usually relative). This path is used to find - various programs like fixscript and libtool so that the same macros (set - in Makefile.global) can be used all over INN. - - The format of INN's makefiles is mostly standardized; the best examples - of the format are probably frontends/Makefile and backends/Makefile, at - least for directories with lots of separate programs. The ALL variable - holds all the files that should be generated, EXTRA those additional - files that were generated by configure, and SOURCES the C source files - for generating tag information. - - There are a set of standard installation commands defined in make - variables by Makefile.global, and these should be used for all file - installations. See the comment blocks in Makefile.global.in for - information on what commands are available and when they should be used. - There are also variables set for each of the installation directories - that INN uses, for use in building the list of installed paths to files. - - Each subdirectory makefile should have the targets all (the default), - clean, clobber, install, tags, and profiled. The tags target generates - vi tags files, and the profiled target generates a profiling version of - the programs (although this hasn't been tested much recently). These - rules should be present and empty in those directories where they don't - apply. - - Be sure to test compiling with both static and dynamic libraries and - make sure that all the libtool support works correctly. All linking - steps, and the compile steps for all library source, should be done - through $(LIBTOOL) (which will be set to empty in Makefile.global if - libtool support isn't desired). - -Scripts - - INN comes with and installs a large number of different scripts, both - Bourne shell and Perl, and also comes with support for Tcl scripts - (although it doesn't come with any). Shell variables containing both - configure-time information and configuration information from inn.conf - are set by the innshellvars support libraries, so the only - system-specific configuration that should have to be done is fixing the - right path to the interpretor and adding a line to load the appropriate - innshellvars. - - support/fixscript, built by configure, does this. It takes a .in file - and generates the final script (removing the .in) by fixing the path to - the interpretor on the first line and replacing the second line, - whatever it is, with code to load the innshellvars appropriate for that - interpretor. (If invoked with -i, it just fixes the interpretor path.) - - Scripts should use innshellvars (via fixscript) to get the right path - and the right variables whenever possible, rather than having configure - substitute values in them. Any values needed at run-time should instead - be available from all of the different innshellvars. - - See the existing scripts for examples of how this is done. - -Include Files - - Include files relevant to all of INN, or relevant to the two libraries - built as part of INN (the utility libinn library and the libstorage - library that contains all storage and overview functions) are found in - the include directory; other include files relevant only to a portion of - INN are found in the relevant directory. - - Practically all INN source files will start with: - - #include "config.h" - #include "clibrary.h" - - The first picks up all defines generated by autoconf and is necessary - for types that may not be present on all systems (uid_t, pid_t, size_t, - int32_t, and the like). It therefore should be included before any - other headers that use those types, as well as to get general - configuration information. - - The second is portably equivalent to: - - #include - #include - #include - #include - #include - #include - #include - #include - - except that it doesn't include headers that are missing on a given - system, replaces functions not found on the system with the INN - equivalents, provides macros that INN assumes are available but which - weren't found, and defines some additional portability things. Even if - this is more headers than the source file actually needs, it's generally - better to just include clibrary.h rather than trying to duplicate the - autoconf-driven hackery that it does to do things portably. The primary - exception is for source files in lib that only define a single function - and are used for portability; those may want to include only config.h so - that they can be easily used in other projects that use autoconf. - config.h is a fairly standard header name for this purpose. - - clibrary.h does also include config.h, but it's somewhat poor form to - rely on this; it's better to explicitly list the header dependencies for - the benefit of someone else reading the code. - - There are portable wrappers around several header files that have known - portability traps or that need some fixing up on some platforms. Look - in include/portable and familiarize yourself with them and use them - where appropriate. - - Another frequently included header file is libinn.h, which among other - things defines xmalloc(), xrealloc(), xstrdup(), and xcalloc(), which - are checked versions of the standard memory allocation routines that - terminate the program if the memory allocation fails. These should - generally always be used instead of the regular C versions. libinn.h - also provides various other utility functions that are frequently used. - - paths.h includes a wide variety of paths determined at configure time, - both default paths to various parts of INN and paths to programs. Don't - just use the default paths, though, if they're also configurable in - inn.conf; instead, call ReadInnConf() and use the global innconf - structure. - - Other files in include are interfaces to particular bits of INN library - functionality or are used for other purposes; see the comments in each - file. - - Eventually, the header files will be separated into installed header - files and uninstalled header files; the latter are those headers that - are used only for compiling INN and aren't useful for users of INN's - libraries (such as clibrary.h). All of the installed headers will live - in include/inn and be installed in a subdirectory named inn in the - configured include directory. This conversion is still in progress. - - When writing header files, remember that C reserves all identifiers - beginning with two underscores and all identifiers beginning with an - underscore and a capital letter for the use of the implementation; don't - use any identifiers with names like that. Additionally, any identifier - beginning with an underscore and a lower-case letter is reserved in file - scope, which means that such identifiers can only be used by INN for the - name of structure members or function arguments in function prototypes. - - Try to pay attention to the impact of a header file on the program - namespace, particularly for installed header files in include/inn. All - symbols defined by a header file should ideally begin with INN_, inn_, - or some other unique prefix indicating the subsystem that symbol is part - of, to avoid accidental conflicts with symbols defined by the program - that uses that header file. - -Coding Style - - INN has quite a variety of coding styles intermixed. As with all - programs, it's preferrable when making minor modifications to keep the - coding style of the code you're modifying. In INN, that will vary by - file. (Over time we're trying to standardize on one coding style, so - changing the region you worked on to fit the general coding style is - also acceptable). - - If you're writing a substantial new piece of code, the prevailing - "standard" INN coding style appears to be something like the following: - - * Write in regular ANSI C whenever possible. Use the normal ANSI and - POSIX constructs and use autoconf or portability wrappers to fix - things up beforehand so that the code itself can read like regular - ANSI or POSIX code. Code should be written so that it works as - expected on a modern platform and is fixed up with portability tricks - for older platforms, not the other way around. You may assume an - ANSI C compiler. - - Try to use const wherever appropriate. Don't use register; modern - compilers will do as good of a job as you will in choosing what to - put into a register. Don't bother with restrict (at least yet). - - * Use string handling functions that take counts for the size of the - buffer whenever possible. This means using snprintf in preference to - sprintf and using strlcpy and strlcat in preference to strcpy and - strcat. Also, use strlcpy and strlcat instead of strncpy and strncat - unless the behavior of the latter is specifically required, as it is - much easier to audit uses of the former than the latter. (strlcpy is - like strncpy except that it always nul-terminates and doesn't fill - the rest of the buffer with nuls, making it more efficient. strlcat - is like strncat except that it always nul-terminates and it takes the - total size of the buffer as its third argument rather than just the - amount of space left.) All of these functions are guaranteed to be - available; there are replacements in lib for systems that don't have - them. - - * Avoid #ifdef and friends whenever possible. Particularly avoid using - them in the middle of code blocks. Try to hide all portability - preprocessor magic in header files or in portability code in lib. - When something just has to be done two completely different ways - depending on the platform or compile options or the like, try to - abstract that functionality out into a generic function and provide - two separate implementations using #ifdef; then the main code can - just call that function. - - If you do have to use preprocessor defines, note that if you always - define them to either 0 or 1 (never use #define without a second - argument), you can use the preprocessor define in a regular if - statement rather than using #if or #ifdef. Make use of this instead - of #ifdef when possible, since that way the compiler will still - syntax-check the other branch for you and it makes it far easier to - convert the code to use a run-time check if necessary. - (Unfortunately, this trick can't be used if one branch may call - functions unavailable on a particular platform.) - - * Avoid uses of fixed-width buffers except in performance-critical - code, as it's harder to be sure that such code is correct and it - tends to be less flexible later on. If you need a reusable, - resizable memory buffer, one is provided in lib/buffer.c. - - * Avoid uses of static variables whenever possible, particularly in - libraries, because it interferes with making the code re-entrant down - the road and makes it harder to follow what's going on. Similarly, - avoid using global variables whenever possible, and if they are - required, try to wrap them into structures that could later be - changed into arguments to the affected functions. - - * Roughly BSD style but with four-space indents. This means no space - before the parens around function arguments, open brace on the same - line as if/while/for, and close and open brace on the same line as - else). - - * Introductory comments for functions or files are generally written - as: - - /* - ** Introductory comment. - */ - - Other multiline comments in the source are generally written as: - - /* This is a - multiline comment. */ - - Comments before functions saying what they do are nice to have. In - general, the RCS/CVS Id tag is on the first line of each source file - since it's useful to know when a file was last modified. - - * Checks for NULL pointers are preferrably written out explicitly; in - other words, use: - - if (p != NULL) - - rather than: - - if (p) - - to make it clearer what the code is assuming. - - * It's better to always put the body of an if statement on a separate - line, even if it's only a single line. In other words, write: - - if (p != NULL) - return p; - - and not: - - if (p != NULL) return p; - - This is in part for a practical reason: some code coverage analysis - tools like purecov will count the second example above as a single - line and won't notice if the condition always evaluates the same way. - - * Plain structs make perfectly reasonable abstract data types; it's not - necessary to typedef the struct to something else. Structs are - actually very useful for opaque data structures, since you can - predeclare them and then manipulate pointers to them without ever - having to know what the contents look like. Please try to avoid - typedefs except for function pointers or other extremely confusing - data types, or for data types where we really gain some significant - data abstraction from hiding the underlying data type. Also avoid - using the _t suffix for any type; all types ending in _t are reserved - by POSIX. For typedefs of function pointer types, a suffix of _func - usually works. - - This style point is currently widely violated inside of INN itself; - INN originally made extensive use of typedefs. - - * When noting something that should be improved later, add a comment - containing "FIXME:" so that one can easily grep for such comments. - - INN's indentation style roughly corresponds to that produced by GNU - indent 2.2.6 with the following options: - - -bad -bap -nsob -fca -lc78 -cd41 -cp1 -br -ce -cdw -cli0 -ss -npcs - -ncs -di1 -nbc -psl -brs -i4 -ci4 -lp -ts8 -nut -ip5 -lps -l78 -bbo - -hnl - - Unfortunately, indent currently doesn't get everything right (it has - problems with spacing around struct pointer arguments in functions, - wants to put in a space between a dereference of a function pointer and - the arguments to the called function, misidentifies some macro calls as - being type declarations, and fouls up long but simple case statements). - It would be excellent if someday we could just run all of INN's code - through indent routinely to enforce a consistant coding style, but - indent isn't quite ready for that. - - For users of emacs cc-mode, use the "bsd" style but with: - - (setq c-basic-offset 4) - - Finally, if possible, please don't use tabs in source files, since they - can expand differently in different environments. In particular, please - try not to use the mix of tabs and spaces that is the default in emacs. - If you use emacs to edit INN code, you may want to put: - - ; Use only spaces when indenting or centering, no tabs. - (setq-default indent-tabs-mode nil) - - in your ~/.emacs file. - - Note that this is only a rough guideline and the maintainers aren't - style nazis; we're more interested in your code contribution than in how - you write it. - -Using CVSup - - If you want to get updated INN source more easily or more quickly than - by downloading nightly snapshots, or if you want to see the full CVS - history, you may want to use CVSup to download the source. CVSup is a - client and server designed for replicating CVS repositories between - sites. - - Unfortunately, CVSup is written in Modula-3, so getting a working binary - can be somewhat difficult. Binaries are available in the *BSD ports - collection or (for a wide variety of different platforms) available from - and its mirrors. - Alternately, you can get a compiler from - (this is more actively maintained than the DEC Modula-3 compiler) and - the source from . - - After you have the CVSup client, you need to have space to download the - INN repository and space for CVSup to store its data files. You also - need to write a configuration file (a supfile) for CVSup. The following - supfile will download the latest versions from the mainline source: - - *default host=inn-cvs.isc.org - *default base= - *default prefix= - *default release=cvs - *default tag=. - *default delete use-rel-suffix - inn - - where should be a directory where CVSup can put its data - files and is where the downloaded source will go (it - will be put into a subdirectory named inn). If you want to pull down - the entire CVS repository instead (warning: this is much larger than - just the latest versions of the source), delete the "*default tag=." - line. The best way to download the CVS repository is to download it - into a portion of a locally-created CVS repository, so that then you can - perform standard CVS operations (like cvs log) against the downloaded - repository. Creating your own local CVS repository is outside the scope - of this document. - - Note that only multiplexed mode is supported (this mode should be the - default). - - For more general information on using CVSup, see the FreeBSD page on it - at . - -Making a Release - - This is a checklist that INN maintainers should go through when - preparing a new release of INN. - - 1. If making a major release, branch the source tree and create a new - STABLE branch tag. This branch will be used for minor releases - based on that major release and can be done a little while before - the .0 release of that major release. At the same time as the - branch is cut, tag the trunk with a STABLE--branch marker - tag so that it's easy to refer to the trunk at the time of the - branch. - - 2. Update doc/pod/news.pod and regenerate NEWS. Be more detailed for a - minor release than for a major release. For a major release, also - add information on how to upgrade from the last major release, - including anything special to be aware of. (Minor releases - shouldn't require any special care when upgrading.) - - 3. Make sure that support/config.sub and support/config.guess are the - latest versions (from ). See the - instructions in "Configuring and Portability" for details on how to - update these files. - - 4. Make sure that samples/control.ctl is in sync with the master - version at . - - 5. Check out a copy of the release branch. It's currently necessary to - run configure to generate Makefile.global. Then run "make - check-manifest". The only differences should be files that are - generated by configure; if there are any other differences, fix the - MANIFEST. - - 6. Run "make release". Note that you need to have a copy of svn2cl - from to do this; at least - version 0.7 is required. Start the ChangeLog at the time of the - previous release. (Eventually, the script will be smart enough to - do this for you.) - - 7. Make the resulting tar file available for testing in a non-listable - directory on ftp.isc.org and announce its availability on - inn-workers. Install it on at least one system and make sure that - system runs fine for at least a few days. This is also a good time - to send out a draft of the release announcement to inn-workers for - proof-reading. - - 8. Generate a diff between this release and the previous release if - feasible (always for minor releases, possibly not a good idea due to - the length of the diff for major releases). - - 9. Move the release into the public area of the ftp site and update the - inn.tar.gz link. Make an MD5 checksum of the release tarball and - put it on the ftp site as well, and update the inn.tar.gz.md5 link. - Put the diff up on the ftp site as well. Contact the ISC folks to - get the release PGP-signed. Possibly move older releases off into - the OLD directory. - - 10. Announce the new release on inn-announce and in news.software.nntp. - - 11. Tag the checked-out tree that was used for generating the release - with a release tag (INN-). - - 12. Bump the revision number in Makefile.global.in. - -References - - Some additional references that may be hard to find and may be of use to - people working on INN: - - - The home page for the IETF NNTP standardization effort, including - links to the IETF NNTP working group archives and copies of the - latest drafts of the new NNTP standard. The old archived mailing - list traffic contains a lot of interesting discussion of why NNTP is - the way it is. - - - The archives for the USEFOR IETF working group, the working group - for the RFC 1036 replacement (the format of Usenet articles). Also - contains a lot of references to other relevant work, such as the RFC - 822 replacement work. - - - Forrest Cavalier provides several tools for following INN - development at this page and elsewhere in the Usenet RKT. Under - here is a web-accessible checked-out copy of the current INN source - tree and pointers to how to use CVSup. - - - The standards for large file support on Unix that are being - generally implemented by vendors. INN sort of partially uses these, - but a good full audit of the code to check them should really be - done and there are occasional problems. - - - A primer on IPv6 with pointers to the appropriate places for more - technical details as needed, useful when working on IPv6 support in - INN. - diff --git a/INSTALL b/INSTALL deleted file mode 100644 index eceb489..0000000 --- a/INSTALL +++ /dev/null @@ -1,1527 +0,0 @@ -Welcome to INN 2.4! - - Please read this document thoroughly before trying to install INN. - You'll be glad you did. - - If you are upgrading from a major release of INN prior to 2.3, it is - recommended that you make copies of your old configuration files and use - them as guides for doing a clean installation and configuration of 2.4. - Many config files have changed, some have been added, and some have been - removed. You'll find it much easier to start with a fresh install than - to try to update your old installation. This is particularly true if - you're upgrading from a version of INN prior to 2.0. - - If you are upgrading from INN 2.3 or later, you may be able to just - update the binaries, scripts, and man pages by running: - - make update - - after building INN and then comparing the new sample configuration files - with your current ones to see if anything has changed. If you take this - route, the old binaries, scripts, and man pages will be saved with an - extension of ".OLD" so that you can easily back out. Be sure to - configure INN with the same options that you used previously if you take - this approach (in particular, INN compiled with --enable-largefiles - can't read the data structures written by INN compiled without that - flag, and vice versa). If you don't remember what options you used but - you have your old build tree, look at the comments at the beginning of - config.status. - - If you made ckpasswd setuid root so that you could use system passwords, - you'll have to do that again after make update. (It's much better to - use PAM instead if you can.) - - If you use "make update" to upgrade from INN 2.3, also look at the new - sample configuration files in samples to see if there are new options of - interest to you. In particular, control.ctl has been updated and - inn.conf has various new options. - - For more information about recent changes, see NEWS. - -Supported Systems - - As much as possible, INN is written in portable C and should work on any - Unix platform. It does, however, make extensive use of mmap(2) and - certain other constructs that may be poorly or incompletely implemented, - particularly on very old operating systems. - - INN has been confirmed to work on the following operating systems: - - AIX 4.3 - FreeBSD 2.2.x and up - HP-UX 10.20 and up - Linux 2.x (tested with libc 5.4, glibc 2.0 and up) - Mac OS X 10.2 and up - NetBSD 1.6 and up - OpenBSD 2.8 and up - SCO 5.0.4 (tested with gcc 2.8.1, cc) - Solaris 2.5.x and up - UnixWare 7.1 - UX/4800 R11 and up - - If you have gotten INN working on an operating system other than the - ones listed above, please let us know at . - -Before You Begin - - INN requires several other packages be installed in order to be fully - functional (or in some cases, to work at all): - - * In order to build INN, you will need a C compiler that understands - ANSI C. If you are trying to install INN on an operating system that - doesn't have an ANSI C compiler (such as SunOS), installing gcc is - recommended. You can get it from or its - mirrors. INN is tested with gcc more thoroughly than with any other - compiler, so even if you have another compiler available, you may wish - to use gcc instead. - - * Currently, in order to build INN, you will need an implementation of - yacc. GNU bison (from or its mirrors) - will work fine. We hope to remove this requirement in the future. - - * INN requires at least Perl 5.004_03 to build and to run several - subsystems. INN is tested primarily with newer versions of Perl, so - it's generally recommended that you install the latest stable - distribution of Perl before compiling INN. For instructions on - obtaining and installing Perl, see - . Note that you - may need to use the same compiler and options (particularly largefile - support) for Perl and INN. - - If you're using a version of Perl prior to 5.6.0, you may need to make - sure that the Perl versions of your system header files have been - generated in order for Sys::Syslog to work properly (used by various - utility programs, including controlchan). To do this, run the - following two commands: - - # cd /usr/include - # h2ph * sys/* - - An even better approach is to install Perl 5.6.1 or later, which have - a fixed version of Sys::Syslog that doesn't require this (as well as - many other improvements over earlier versions of Perl). - - * The INN Makefiles use the syntax "include FILE", rather than the - syntax expected by some BSDish systems of ".include ". If your - system expects the latter syntax, the recommended solution is to - install GNU make from . You may have GNU - make already installed as gmake, in which case using gmake rather than - make to build INN should be sufficient. - - * If you want to enable support for authenticated control messages (this - is not required, but is highly recommended for systems carrying public - Usenet hierarchies) then you will need to install some version of PGP. - The recommended version is GnuPG, since it's actively developed, - supports OpenPGP, is freely available and free to use for any purpose - (in the US and elsewhere), and (as of version 1.0.4 at least) supports - the RSA signatures used by most current control message senders. - - Alternately, you can install PGP from or one of - the international versions of it. Be warned, however, that the - licensing restrictions on PGP inside the United States are extremely - unclear; it's possible that if you are installing INN for a company in - the U.S., even if the news server is not part of the business of that - company, you would need to purchase a commercial license for PGP. For - an educational or non-profit organization, this shouldn't be a - problem. - - * If you want to use either the Python embedded hooks, you'll need to - have a suitable versions of Python installed. See doc/hook-python for - more information. - - * Many of INN's optional features require other packages (primarily - libraries) be installed. If you wish to use any of these optional - features, you will need to install those packages first. Here is a - table of configure options enabling optional features and the software - and versions you'll need: - - --with-perl Perl 5.004_03 or higher, 5.6.1+ recommended - --with-python Python 1.5.2 or higher - --with-berkeleydb BerkeleyDB 2.0 or higher, 4.2+ recommended - --with-openssl OpenSSL 0.9.6 or higher - --with-sasl SASL 2.x or higher - --with-kerberos MIT Kerberos v5 1.2.x or higher - - If any of these libraries (other than Perl or Python) are built shared - and installed in locations where your system doesn't search for shared - libraries by default, you may need to encode the paths to those shared - libraries in the INN binaries. For more information on shared library - paths, see: - - - - For most systems, setting the environment variable LD_RUN_PATH to a - colon-separated list of additional directories in which to look for - shared libraries before building INN will be sufficient. - -Unpacking the Distribution - - Released versions of INN are available from ftp.isc.org in /isc/inn. - New major releases will be announed on (see - README) when they're made. - - If you want more a more cutting-edge version, you can obtain current - snapshots from from ftp.isc.org in directory /isc/inn/snapshots. These - are snapshots of the INN CVS tree taken daily; there are two snapshots - made each night (one of the current development branch, and one of the - stable branch consisting of bug fixes to the previous major release). - They are stored in date format; in other words the snapshots from April - 6th, 2000, would be named inn-CURRENT-20000406.tar.gz and - inn-STABLE-20000406.tar.gz. Choose the newest file of whichever branch - you prefer. (Note that the downloading, configuring, and compiling - steps can be done while logged in as any user.) - - The distribution is in gzip compressed tar archive format. To extract - it, execute: - - gunzip -c | tar -xf - - - Extracting the source distribution will create a directory named - inn- or inn-- where the source resides. - -Installing INN - - Before beginning installation, you should make sure that there is a user - on your system named "news", and that this user's primary group is set - to a group called "news". You can change these with the - --with-news-user and --with-news-group options to configure (see below). - The home directory of this user should be set to the directory under - which you wish to install INN (/usr/local/news is the default and is a - good choice). INN will install itself as this user and group. You can - change these if you want, but these are the defaults and it's easier to - stick with them on a new installation. - - By default, INN sends reports to the user "usenet". This account isn't - used for any other purposes. You can change it with the - --with-news-master option to configure (see below). - - WARNING: By default, INN installs various configuration files as - group-writeable, and in general INN is not hardened from a security - standpoint against an attack by someone who is already in the news - group. In general, you should consider membership in the news group as - equivalent to access to the news account. You should not rely on being - able to keep anyone with access to the news GID from converting that - into access to the news UID. The recommended configuration is to have - the only member of the group "news" be the user "news". - - Installing INN so that all of its files are under a single directory - tree, rather than scattering binaries, libraries, and man pages - throughout the file system, is strongly recommended. It helps keep - everything involved in the operation of INN together as a unit and will - make the installation instructions easier to follow. - - As a side note, whenever doing anything with a running news server, - first log in as this user. That way, you can ensure that all files - created by any commands you run are created with the right ownership to - be readable by the server. Particularly avoid doing anything in the - news spool itself as root, and make sure you fix the ownership of any - created files if you have to. INN doesn't like files in the news spool - owned by a user other than the news user. However, since certain - binaries need to be setuid root, indiscriminate use of "chown news" is - not the solution. (If you don't like to log in to system accounts, - careful use of "chmod g+s" on directories and a umask of 002 or 007 may - suffice.) - - INN uses GNU autoconf and a generated configure script to make - configuration rather painless. Unless you have a rather abnormal setup, - configure should be able to completely configure INN for your system. - If you want to change the defaults, you can invoke the configure script - with one or more command line options. Type: - - ./configure --help - - for a full list of supported options. Some of the most commonly used - options are: - - --prefix=PATH - Sets the installation prefix for INN. The default is - /usr/local/news. All of INN's programs and support files will be - installed under this directory. This should match the home - directory of your news user (it will make installation and - maintenance easier). It is not recommended to set this to /usr; if - you decide to do that anyway, make sure to point INN's temporary - directory at a directory that isn't world-writeable (see - --with-tmp-dir below). - - --with-db-dir=PATH - Sets the prefix for INN database files. The default is PREFIX/db, - where PREFIX is /usr/local/news unless overridden with the option - above. The history and active files will be stored in this - directory, and writes to those files are an appreciable percentage - of INN's disk activity. The history file can also be quite large - (requiring up to 2 GB or more during nightly expire), so this is a - common portion of INN to move to a different file system. - - --with-spool-dir=PATH - Sets the prefix for the news spool (when using any storage method - other than CNFS) and the overview spool. The default is - PREFIX/spool. This is another common portion of INN to move to a - different file system (often /news). - - --with-tmp-dir=PATH - Sets the directory in which INN will create temporary files. This - should under no circumstances be the same as the system temporary - directory or otherwise be set to a world-writeable directory, since - INN doesn't take care to avoid symlink attacks and other security - problems possible with a world-writeable directory. This directory - should be reserved for the exclusive use of INN and only writeable - by the news user. Usage is generally light, so this is unlikely to - need a separate partition. - - It's also possible to set the paths for most other sections of the - INN installation independently; see "./configure --help" and look - for the --with-*-dir=PATH options. - - --enable-largefiles - Enables large file support. This is not enabled by default, even on - platforms that support it, because it changes the format of INN's - on-disk databases (making it difficult to upgrade an earlier INN - installation) and can significantly increase the size of some of the - history database files. Large file support is not necessary unless - your history database is so large that it exceeds 2 GB or you want - to use CNFS buffers larger than 2 GB. - - The history, tradindexed and buffindexed overview, CNFS, and timecaf - databases written by an INN built with this option are incompatible - with those written by an INN without this option. - - --enable-tagged-hash - Use tagged hash table for the history database. The tagged hash - format uses much less memory but is somewhat slower. This option is - recommended if you have less than 256 MB of RAM on your news server. - If you install INN without tagged hash (the default) and expire - takes an excessive amount of time, you should make sure the RAM in - your system satisfies the following formula: - - ram > 10 * tablesize - - ram: Amount of system RAM (in bytes) - tablesize: 3rd field on the 1st line of history.dir (bytes) - - If you don't have at least that much RAM, try rebuilding INN with - tagged hash enabled. - - NOTE: --enable-largefiles cannot be used with --enable-tagged-hash. - - --with-perl - Enables support for embedded Perl, allowing you to install filter - scripts written in Perl. Highly recommended, because many really - good spam filters are written in Perl. See doc/hook-perl for all - the details. - - Even if you do not use this option, INN still requires Perl as - mentioned above. - - --with-python - Enables support for Python, allowing you to install filter and - authentication scripts written in Python. You will need Python - 1.5.2 or later installed on your system to enable this option. See - doc/hook-python for all the details. Note that there is an - incompatibility between INN and Python 2.0 when Python is compiled - with cycle garbage collection; this problem was reported fixed in - Python 2.1a1. - - --with-innd-port=PORT - By default, inndstart(8) refuses to bind to any port under 1024 - other than 119 and 433 for security reasons (to prevent attacks on - rsh(1)-based commands and replacing standard system daemons). If - you want to run innd on a different port under 1024, you'll need to - tell configure what port you intend to use. (You'll also still need - to set the port number in inn.conf or give it to inndstart on the - command line.) - - --with-syslog-facility=FACILITY - Specifies the syslog facility that INN programs should log to. The - default is LOG_NEWS unless configure detects that your system - doesn't understand that facility, in which case it uses LOG_LOCAL1. - This flag overrides the automatic detection. Be sure to specify a - facility not used by anything else on your system (one of LOG_LOCAL0 - through LOG_LOCAL7, for example). - - --enable-libtool - INN has optional support for libtool to generate shared versions of - INN's libraries. This can significantly decrease the size of the - various binaries that come with a complete INN installation. You - can also choose to use libtool even when only building static - libraries; a libtool build may be somewhat more portable on weird - systems. libtool builds aren't the default because they take - somewhat longer. See "./configure --help" for the various available - options related to libtool builds. - - Please note that INN's shared library interface is not stable and - may change drastically in future releases. For this reason, it's - also not properly versioned and won't be until some degree of - stability is guaranteed, and the relevant header files are not - installed. Only INN should use INN's shared libraries, and you - should only use the shared libraries corresponding to the version of - INN that you're installing. - - Also, when updating an existing version of INN, INN tries to save - backup copies of all files so that you can revert to the previous - installed version. Unfortunately, when using shared libraries, this - confuses ldconfig on some systems (such as Linux) and the symbolic - links for the libraries may point to the .OLD versions. If this - happens, you can either fix the links by hand or remove the .OLD - versions and re-run ldconfig. - - --enable-uucp-rnews - If this option is given to configure, rnews will be installed setuid - news, owned by group uucp, and mode 4550. This will allow the UUCP - subsystem to run rnews to process UUCP batches of news articles. - Prior to INN 2.3, installing rnews setuid news was standard; since - most sites no longer use UUCP, it is no longer the default as of INN - 2.3 and must be requested at configure time. You probably don't - want to use this option unless your server accepts UUCP news - batches. - - --enable-setgid-inews - If this option is given to configure, inews will be installed setgid - news and world-executable so that non-privileged users on the news - server machine can use inews to post articles locally (somewhat - faster than opening a new network connection). For standalone news - servers, by far the most common configuration now, there's no need - to use this option; even if you have regular login accounts on your - news server, INN's inews can post fine via a network connection to - your running news server and doesn't need to use the local socket - (which is what setgid enables it to do). Installing inews setgid - was the default prior to INN 2.3. - - --with-berkeleydb=PATH - Enables support for Berkeley DB (2.x or 3.x), which means that it - will then be possible to use the ovdb overview method if you wish. - Enabling this configure option doesn't mean you'll be required to - use ovdb, but it does require that Berkeley DB be installed on your - system (including the header files, not just the runtime libraries). - If a path is given, it sets the installed directory of Berkeley DB - (configure will search for it in some standard locations, but if you - have it installed elsewhere, you may need this option). - - --with-openssl=PATH - Enables support for SSL for news reading, which means it will be - possible to have SSL or TLS encrypted NNTP connections between your - server and newsreaders. This option requires OpenSSL be installed - on your system (including the header files, not just the runtime - libraries). If a path is given, it sets the installed directory of - OpenSSL. After compiling and installing INN with this option, - you'll still need to make a certificate and private key to use SSL. - See below for details on how to do that. - - --enable-ipv6 - Enables support for IPv6 in innd, innfeed, nnrpd, and several of the - supporting programs. This option should be considered developmental - at present. For more information see doc/IPv6-info (and if you have - any particularly good or bad news to report, please let us know at - ). - - For the most common installation, a standalone news server, a suggested - set of options is: - - ./configure --with-perl - - provided that you have the necessary version of Perl installed. - (Compiling with an embedded Perl interpretor will allow you to use one - of the available excellent spam filters if you so choose.) - - If the configure program runs successfully, then you are ready to build - the distribution. From the root of the INN source tree, type: - - make - - At this point you can step away from the computer for a little while and - have a quick snack while INN compiles. On a decently fast system it - should only take five or ten minutes at the most to build. - - Once the build has completed successfully, you are ready to install INN - into its final home. Type: - - make install - - You will need to run this command as root so that INN can create the - directories it needs, change ownerships (if you did not compile as the - news user) and install a couple of setuid wrapper programs needed to - raise resource limits and allow innd to bind to ports under 1024. This - step will install INN under the install directory (/usr/local/news, - unless you specified something else to the configure script). - - If you are configuring SSL support for newsreaders, you must make a - certificate and private key at least once. Type: - - make cert - - as root in order to do this. - - You are now ready for the really fun part: configuring your copy of - INN! - -Choosing an Article Storage Format - - The first thing to decide is how INN should store articles on your - system. There are four different methods for you to choose from, each - of which has its own advantages and disadvantages. INN can support all - four at the same time, so you can store certain newsgroups in one method - and other newsgroups in another method. - - The supported storage formats are: - - tradspool - This is the storage method used by all versions of INN previous to - 2.0. Articles are stored as individual text files whose names are - the same as the article number. The articles are divided up into - directories based on the newsgroup name. For example, article 12345 - in news.software.nntp would be stored as news/software/nntp/12345 - relative to the root of the article spool. - - Advantages: Widely used and well-understood storage mechanism, can - read article spools written by older versions of INN, compatible - with all third-party INN add-ons, provides easy and direct access to - the articles stored on your server and makes writing programs that - fiddle with the news spool very easy, and gives you fine control - over article retention times. - - Disadvantages: Takes a very fast file system and I/O system to keep - up with current Usenet traffic volumes due to file system overhead. - Groups with heavy traffic tend to create a bottleneck because of - inefficiencies in storing large numbers of article files in a single - directory. Requires a nightly expire program to delete old articles - out of the news spool, a process that can slow down the server for - several hours or more. - - timehash - Articles are stored as individual files as in tradspool, but are - divided into directories based on the arrival time to ensure that no - single directory contains so many files as to cause a bottleneck. - - Advantages: Heavy traffic groups do not cause bottlenecks, and fine - control of article retention time is still possible. - - Disadvantages: The ability to easily find all articles in a given - newsgroup and manually fiddle with the article spool is lost, and - INN still suffers from speed degredation due to file system overhead - (creating and deleting individual files is a slow operation). - - timecaf - Similar to timehash, articles are stored by arrival time, but - instead of writing a separate file for each article, multiple - articles are put in the same file. - - Advantages: Roughly four times faster than timehash for article - writes, since much of the file system overhead is bypassed, while - still retaining the same fine control over article retention time. - - Disadvantages: Even worse than timehash, and similar to cnfs - (below), using this method means giving up all but the most careful - manually fiddling with your article spool. As one of the newer and - least widely used storage types, timecaf has not been as thoroughly - tested as the other methods. - - cnfs - CNFS stores articles sequentially in pre-configured buffer files. - When the end of the buffer is reached, new articles are stored from - the beginning of the buffer, overwriting older articles. - - Advantages: Blazingly fast because no file creations or deletions - are necessary to store an article. Unlike all other storage - methods, does not require manual article expiration; old articles - are deleted to make room for new ones when the buffers get too full. - Also, with CNFS your server will never throttle itself due to a full - spool disk, and groups are restricted to just the buffer files you - give them so that they can never use more than the amount of disk - space you allocate to them. - - Disadvantages: Article retention times are more difficult to - control because old articles are overwritten automatically. Attacks - on Usenet, such as flooding or massive amounts of spam, can result - in wanted articles expiring much faster than you intended (with no - warning). - - Some general recommendations: If you are installing a transit news - server (one that just accepts news and sends it out again to other - servers and doesn't support any readers), use CNFS exclusively and don't - worry about any of the other storage methods. Otherwise, put - high-volume groups and groups whose articles you don't need to keep - around very long (binaries groups, *.jobs*, news.lists.filters, etc.) in - CNFS buffers, and use timehash, timecaf, or tradspool (if you have a - fast I/O subsystem or need to be able to go through the spool manually) - for everything else. You'll probably find it most convenient to keep - special hierarchies like local hierarchies and hierarchies that should - never expire in tradspool. - - If your news server will be supporting readers, you'll also need to - choose an overview storage mechanism (by setting *ovmethod* in - inn.conf). There are three overview mechanisms to choose from: - tradindexed, buffindexed, and ovdb. tradindexed is very fast for - readers, but it has to update two files for each incoming article and - can be quite slow to write. buffindexed can keep up with a large feed - more easily, since it uses large buffers to store all overview - information, but it's somewhat slower for readers (although not as slow - as the unified overview in INN 2.2). ovdb stores overview data in a - Berkeley DB database; it's fast and very robust, but requires more disk - space. See the ovdb(5) man page for more information on it. - - Note that ovdb has not been as widely tested as the other overview - mechanisms and should be considered experimental. tradindexed is the - best tested and most widely used of the overview implementations. - - If buffindexed is chosen, you will need to create the buffers for it to - use (very similar to creating CNFS buffers) and list the available - buffers in buffindexed.conf. See buffindexed.conf(5) for more - information. - -Configuring INN - - All documentation from this point on assumes that you have set up the - news user on your system as suggested in "Installing INN" so that the - root of your INN installation is ~news/. If you've moved things around - by using options with "configure", you'll need to adjust the - instructions to account for that. - - All of INN's configuration files are located in ~news/etc. Unless noted - otherwise, any files referred to below are in this directory. When you - first install INN, a sample of each file (containing lots of comments) - is installed in ~news/etc; refer to these for concrete examples of - everything discussed in this section. - - All of INN's configuration files, all of the programs that come with it, - and some of its library routines have documentation in the form of man - pages. These man pages were installed in ~news/man as part of the INN - installation process and are the most complete reference to how INN - works. You're strongly encouraged to refer to the man pages frequently - while configuring INN, and for quick reference afterwards. Any detailed - questions about individual configuration files or the behavior of - specific programs should be answered in them. You may want to add - ~news/man to your MANPATH environment variable; otherwise, you may have - to use a command like: - - man -M ~news/man inn.conf - - to see the inn.conf(5) man page (for example). - - Before we begin, it is worth mentioning the wildmat pattern matching - syntax used in many configuration files. These are simple wildcard - matches using the asterisk ("*") as the wildcard character, much like - the simple wildcard expansion used by Unix shells. - - In many cases, wildmat patterns can be specified in a comma-separated - list to indicate a list of newsgroups. When used in this fashion, each - pattern is checked in turn to see if it matches, and the last pattern in - the line that matches the group name is used. Patterns beginning with - "!" mean to exclude groups matching that pattern. For example: - - *, !comp.*, comp.os.* - - In this case, we're saying we match everything ("*"), except that we - don't match anything under comp ("!comp.*"), unless it is actually under - the comp.os hierarchy ("comp.os.*"). This is because non-comp groups - will match only the first pattern (so we want them), comp.os groups will - match all three patterns (so we want them too, because the third pattern - counts in this case), and all other comp groups will match the first and - second patterns and will be excluded by the second pattern. - - Some uses of wildmat patterns also support "poison" patterns (patterns - starting with "@"). These patterns behave just like "!" patterns when - checked against a single newsgroup name. Where they become special is - for articles crossposted to multiple newsgroups; normally, such an - article will be considered to match a pattern if any of the newsgroups - it is posted to matches the pattern. If any newsgroup the article is - posted to matches an expression beginning with "@", however, that - article will not match the pattern even if other newsgroups to which it - was posted match other expressions. - - See uwildmat(3) for full details on wildmat patterns. - - In all INN configuration files, blank lines and lines beginning with a - "#" symbol are considered comments and are ignored. Be careful, not all - files permit comments to begin in the middle of the line. - - inn.conf - - The first, and most important file is inn.conf. This file is organized - as a series of parameter-value pairs, one per line. The parameter is - first, followed by a colon and one or more whitespace characters, and - then the value itself. For some parameters the value is a string or a - number; for others it is true or false. (True values can be written as - "yes", "true", or "on", whichever you prefer. Similarly, false values - can be written as "no", "false", or "off".) - - inn.conf contains dozens of changeable parameters (see inn.conf(5) for - full details), but only a few really need to be edited during normal - operation: - - allownewnews - If set to true then INN will support the NEWNEWS command for news - readers. While this can be an expensive operation, its speed has - been improved considerably as of INN 2.3 and it's probably safe to - turn on without risking excessive server load. The default is true. - (Note that the *access:* setting in readers.conf overrides this - value; see readers.conf(5) for more details.) - - complaints - Used to set the value of the X-Complaints-To: header, which is added - to all articles posted locally. The usual value would be something - like "abuse@example.com" or "postmaster@example.com". If not - specified, the newsmaster email address will be used. - - hiscachesize - The amount of memory (in kilobytes) to allocate for a cache of - recently used history file entries. Setting this to 0 disables - history caching. History caching can greatly increase the number of - articles per second that your server is capable of processing. A - value of 256 is a good default choice. - - logipaddr - If set to true (the default), INN will log the IP address (or - hostname, if the host is listed in incoming.conf with a hostname) of - the remote host from which it received an article. If set to false, - the trailing Path: header entry is logged instead. If you are using - controlchan (see below) and need to process ihave/sendme control - messages (this is very, very unlikely, so if you don't know what - this means, don't worry about it), make sure you set this to false, - since controlchan needs a site name, not an IP address. - - organization - Set this to the name of your organization as you want it to appear - in the Organization: header of all articles posted locally and not - already containing that header. This will be overridden by the - value of the ORGANIZATION environment variable (if it exists). If - neither this parameter nor the environment variable or set, no - Organization: header will be added to posts which lack one. - - pathhost - This is the name of your news server as you wish it to appear in the - Path: header of all postings which travel through your server (this - includes local posts and incoming posts that you forward out to - other sites). If this parameter is unspecified, the fully-qualified - domain name (FQDN) of the machine will be used instead. Please use - the FQDN of your server or an alias for your server unless you have - a very good reason not to; a future version of the news RFCs may - require this. - - rlimitnofile - If set to a non-negative value (the default is -1), INN (both innd - and innfeed) will try to raise the maximum number of open file - descriptors to this value when it starts. This may be needed if you - have lots of incoming and outgoing feeds. Note that the maximum - value for this setting is very operating-system-dependent, and you - may have to reconfigure your system (possibly even recompile your - kernel) to increase it. See "File Descriptor Limits" for complete - details. - - There are tons of other possible settings; you may want to read through - inn.conf(5) to get a feel for your options. Don't worry if you don't - understand the purpose of most of them right now. Some of the settings - are only needed for very obscure things, and with more experience - running your news server the rest will make more sense. - - newsfeeds - - newsfeeds determines how incoming articles are redistributed to your - peers and to other INN processes. newsfeeds is very versatile and - contains dozens of options; we will touch on just the basics here. The - manpage contains more detailed information. - - newsfeeds is organized as a series of feed entries. Each feed entry is - composed of four fields separated by colons. Entries may span multiple - lines by using a backslash ("\") to indicate that the next line is a - continuation of the current line. (Note that comments don't interact - with backslashes in the way you might expect. A commented-out line - ending in a backslash will still be considered continued on the next - line, possibly resulting in more commented out than you intended or - bizarre syntax errors. In general, it's best to avoid commenting out - lines in the middle of continuation lines.) - - The first field in an entry is the name of the feed. It must be unique, - and for feeds to other news servers it is usually set to the actual - hostname of the remote server (this makes things easier). The name can - optionally be followed by a slash and a comma-separated exclude list. - If the feed name or any of the names in the exclude list appear in the - Path line of an article, then that article will not be forwarded to the - feed as it is assumed that it has passed through that site once already. - The exclude list is useful when a news server's hostname is not the same - as what it puts in the Path header of its articles, or when you don't - want a feed to receive articles from a certain source. - - The second field specifies a set of desired newsgroups and distribution - lists, given as newsgroup-pattern/distribution-list. The distribution - list is not described here; see newsfeeds(5) for information (it's not - used that frequently in practice). The newsgroup pattern is a - wildmat-style pattern list as described above (supporting "@"). - - The third field is a comma-separated list of flags that determine both - the type of feed entry and sets certain parameters for the entry. See - newsfeeds(5) for information on the flag settings; you can do a - surprising amount with them. The three most common patterns, and the - ones mainly used for outgoing news feeds to other sites, are "Tf,Wnm" - (to write out a batch file of articles to be sent, suitable for - processing by nntpsend and innxmit), "Tm" (to send the article to a - funnel feed, used with innfeed), and "Tc,Wnm*" (to collect a funnel feed - and send it via a channel feed to an external program, used to send - articles to innfeed). - - The fourth field is a multi-purpose parameter whose meaning depends on - the settings of the flags in the third field. To get a feel for it - using the examples above, for file feeds ("Tf") it's the name of the - file to write, for funnel feeds ("Tm") it's the name of the feed entry - to funnel into, and for channel feeds ("Tc") it's the name of the - program to run and feed references to articles. - - Now that you have a rough idea of the file layout, we'll begin to add - the actual feed entries. First, we'll set up the special ME entry. - This entry is required and serves two purposes: the newsgroup pattern - specified here is prepended to the newsgroup list of all other feeds, - and the distribution pattern for this entry determines what - distributions (from the Distribution: header of incoming articles) are - accepted from remote sites by your server. The example in the sample - newsfeeds file is a good starting point. If you are going to create a - local hierarchy that should not be distributed off of your system, it - may be useful to exclude it from the default subscription pattern, but - default subscription patterns are somewhat difficult to use right so you - may want to just exclude it specifically from every feed instead. - - The ME entry tends to confuse a lot of people, so this point is worth - repeating: the newsgroup patterns set the default subscription for - *outgoing* feeds, and the distribution patterns set the acceptable - Distribution: header entries for *incoming* articles. This is confusing - enough that it may change in later versions of INN. - - There are two basic ways to feed articles to remote sites. The most - common for large sites and particularly for transit news servers is - innfeed(8), which sends articles to remote sites in real time (the - article goes out to all peers that are supposed to receive it - immediately after your server accepts it). For smaller sites, - particularly sites where the only outgoing messages will be locally - posted articles, it's more common to batch outgoing articles and send - them every ten minutes or so from cron using nntpsend(8) and innxmit(8). - Batching gives you more control and tends to be extremely stable and - reliable, but it's much slower and can't handle high volume very well. - - Batching outgoing posts is easy to set up; for each peer, add an entry - to newsfeeds that looks like: - - remote.example.com/news.example.com\ - :\ - :Tf,Wnm: - - where is the wildmat pattern for the newsgroups that site - wants. In this example, the actual name of the remote site is - "remote.example.com", but it puts "news.example.com" in the Path: - header. If the remote site puts its actual hostname in the Path: - header, you won't need the "/news.example.com" part. - - This entry will cause innd to write out a file in ~news/spool/outgoing - named remote.example.com and containing the Message-ID and storage token - of each message to send to that site. (The storage token is INN's - internal pointer to where an article is stored; to retrieve an article - given its storage token, use sm(8)). innxmit knows how to read files of - this format and send those articles to the remote site. For information - on setting it up to run periodically, see "Setting Up the Cron Jobs" - below. You will also need to set up a config file for nntpsend; see the - man page for nntpsend.ctl(5) for more information. - - If instead you want to use innfeed to send outgoing messages - (recommended for sites with more than a couple of peers), you need some - slightly more complex magic. You still set up a separate entry for each - of your peers, but rather than writing out batch files, they all - "funnel" into a special innfeed entry. That special entry collects all - of the separate funnel feeds and sends the data through a special sort - of feed to an external program (innfeed in this case); this is a - "channel" feed. - - First, the special channel feed entry for innfeed that will collect all - the funnel feeds: - - innfeed!\ - :!*\ - :Tc,Wnm*:/usr/local/news/bin/startinnfeed -y - - (adjust the path to startinnfeed(1) if you installed it elsewhere). - Note that we don't feed this entry any articles directly (its newsgroup - pattern is "!*"). Note also that the name of this entry ends in an - exclamation point. This is a standard convention for all special feeds; - since the delimiter for the Path: header is "!", no site name containing - that character can ever match the name of a real site. - - Next, set up entries for each remote site to which you will be feeding - articles. All of these entries should be of the form: - - remote.example.com/news.example.com\ - :\ - :Tm:innfeed! - - specifying that they funnel into the "innfeed!" feed. As in the - previous example for batching, "remote.example.com" is the actual name - of the remote peer, "news.example.com" is what it puts in the Path: - header (if different than the actual name of the server), and - is the wildmat pattern of newsgroups to be sent. - - As an alternative to NNTP, INN may also feed news out to an IMAP server, - by using imapfeed(8), which is almost identical to innfeed. The - startinnfeed process can be told to start imapfeed instead of innfeed. - The feed entry for this is as follows: - - imapfeed!\ - :!*\ - :Tc,Wnm*,S16384:/usr/local/news/bin/startinnfeed imapfeed - - And set up entries for each remote site like: - - remote.example.com/news.example.com\ - :\ - :Tm:imapfeed! - - For more information on imapfeed, look at the innfeed/imap_connection.c. - For more information on IMAP in general, see RFC 2060. - - Finally, there is a special entry for controlchan(8), which processes - newsgroup control messages, that should always be in newsfeeds unless - you never want to honor any control messages. This entry should look - like: - - controlchan!\ - :!*,control,control.*,!control.cancel\ - :Tc,Wnsm:/usr/local/news/bin/controlchan - - (modified for the actual path to controlchan if you put it somewhere - else). See "Processing Control Messages" for more details. - - For those of you upgrading from earlier versions of INN, note that the - functionality of overchan(8) and crosspost is now incorporated into INN - and neither of those programs is necessary. Unfortunately, crosspost - currently will not work even with the tradspool storage method. You can - still use overchan if you make sure to set *useoverchan* to true in - inn.conf so that innd doesn't write overview data itself, but be - careful: innd may accept articles faster than overchan can process the - data. - - incoming.conf - - incoming.conf file specifies which machines are permitted to connect to - your host and feed it articles. Remote servers you peer with should be - listed here. Connections from hosts not listed in this file will (if - you don't allow readers) be rejected or (if you allow readers) be handed - off to nnrpd and checked against the access restrictions in - readers.conf. - - Start with the sample incoming.conf and, for each remote peer, add an - entry like: - - peer remote.example.com { } - - This uses the default parameters for that feed and allows incoming - connections from a machine named "remote.example.com". If that peer - could be connecting from several different machines, instead use an - entry like: - - peer remote.example.com { - hostname: "remote.example.com, news.example.com" - } - - This will allow either "remote.example.com" or "news.example.com" to - feed articles to you. (In general, you should add new peer lines for - each separate remote site you peer with, and list multiple host names - using the *hostname* key if one particular remote site uses multiple - servers.) - - You can restrict the newsgroups a remote site is allowed to send you, - using the same sort of pattern that newsfeeds(5) uses. For example, if - you want to prevent "example.com" hosts from sending you any articles in - the "local.*" hierarchy (even if they're crossposted to other groups), - change the above to: - - peer remote.example.com { - patterns: "*, @local.*" - hostname: "remote.example.com, news.example.com" - } - - Note, however, that restricting what a remote side can send you will - *not* reduce your incoming bandwidth usage. The remote site will still - send you the entire article; INN will just reject it rather than saving - it to disk. To reduce bandwidth, you have to contact your peers and ask - them not to send you the traffic you don't want. - - There are various other things you can set, including the maximum number - of connections the remote host will be allowed. See incoming.conf(5) - for all the details. - - Note for those familiar with older versions of INN: this file replaces - the old hosts.nntp configuration file. - - cycbuff.conf - - cycbuff.conf is only required if CNFS is used. If you aren't using - CNFS, skip this section. - - CNFS stores articles in logical objects called *metacycbuffs*. Each - metacycbuff is in turn composed of one or more physical buffers called - *cycbuffs*. As articles are written to the metacycbuff, each article is - written to the next cycbuff in the list in a round-robin fashion (unless - "sequential" mode is specified, in which case each cycbuff is filled - before moving on to the next). This is so that you can distribute the - individual cycbuffs across multiple physical disks and balance the load - between them. - - There are two ways to create your cycbuffs: - - 1. Use a block device directly. This will probably give you the most - speed since it avoids the file system overhead of large files, but - it requires your OS support mmap(2) on a block device. Solaris - supports this, as do late Linux 2.4 kernels. FreeBSD does not at - last report. Also on many PC-based Unixes it is difficult to create - more than eight partitions, which may limit your options. - - 2. Use a real file on a filesystem. This will probably be a bit slower - than using a block device directly, but it should work on any Unix - system. - - If you're having doubts, use option #2; it's easier to set up and should - work regardless of your operating system. - - Now you need to decide on the sizes of your cycbuffs and metacycbuffs. - You'll probably want to separate the heavy-traffic groups - ("alt.binaries.*" and maybe a few other things like "*.jobs*" and - "news.lists.filters") into their own metacycbuff so that they don't - overrun the server and push out articles on the more useful groups. If - you have any local groups that you want to stay around for a while then - you should put them in their own metacycbuff as well, so that they don't - get pushed out by other traffic. (Or you might store them in one of the - other storage methods, such as tradspool.) - - For each metacycbuff, you now need to determine how many cycbuffs will - make up the metacycbuff, the size of those cycbuffs, and where they will - be stored. Some OSes do not support files larger than 2 GB, which will - limit the size you can make a single cycbuff, but you can still combine - many cycbuffs into each metacycbuff. Older versions of Linux are known - to have this limitation; FreeBSD does not. Some OSes that support large - files don't support direct access to block devices for large partitions - (Solaris prior to Solaris 7, or not running in 64-bit mode, is in this - category); on those OSes, if you want cycbuffs over 2 GB, you'll have to - use regular files. If in doubt, keep your cycbuffs smaller than 2 GB. - Also, when laying out your cycbuffs, you will want to try to arrange - them across as many physical disks as possible (or use a striped disk - array and put them all on that). - - In order to use any cycbuff larger than 2 GB, you need to build INN with - the --enable-largefiles option. See "Installing INN" for more - information and some caveats. - - For each cycbuff you will be creating, add a line to cycbuff.conf like - the following: - - cycbuff:NAME:/path/to/buffer:SIZE - - NAME must be unique and must be at most seven characters long. - Something simple like "BUFF00", "BUFF01", etc. is a decent choice, or - you may want to use something that includes the SCSI target and slice - number of the partition. SIZE is the buffer size in kilobytes (if - you're trying to stay under 2 GB, keep your sizes below 2097152). - - Now, you need to tell INN how to group your cycbuffs into metacycbuffs. - This is similar to creating cycbuff entries: - - metacycbuff:BUFFNAME:CYCBUFF,CYCBUFF,CYCBUFF - - BUFFNAME is the name of the metacycbuff and must be unique and at most - eight characters long. These should be a bit more meaningful than the - cycbuff names since they will be used in other config files as well. - Try to name them after what will be stored in them; for example, if this - metacycbuff will hold alt.binaries postings, "BINARIES" would be a good - choice. The last part of the entry is a comma-separated list of all of - the cycbuffs that should be used to build this metacycbuff. Each - cycbuff should only appear in one metacycbuff line, and all metacycbuff - lines must occur after all cycbuff lines in the file. - - If you want INN to fill each cycbuff before moving on to the next one - rather than writing to them round-robin, add ":SEQUENTIAL" to the end of - the metacycbuff line. This may give noticeably better performance when - using multiple cycbuffs on the same spindle (such as partitions or - slices of a larger disk), but will probably give worse performance if - your cycbuffs are spread out across a lot of spindles. - - By default, CNFS data is flushed to disk every 25 articles. If you're - running a small server with a light article load, this could mean losing - quite a few articles in a crash. You can change this interval by adding - a cycbuffupdate line to your cycbuff.conf file; see cycbuff.conf(5) for - more details. - - Finally, you have to create the cycbuffs. See "Creating the Article - Spool" for more information on how to do that. - - storage.conf - - storage.conf determines where incoming articles will be stored (what - storage method, and in the case of CNFS, what metacycbuff). Each entry - in the file defines a storage class for articles. The first matching - storage class is used to store the article; if no storage class matches, - INN will reject that article. (This is almost never what you want, so - make sure this file ends in a catch-all entry that will match - everything.) - - A storage class definition looks like this: - - method { - newsgroups: - class: - size: [,] - expires: [,] - options: - } - - is the name of the storage method to use to store articles - in this class ("cnfs", "timehash", "timecaf", "tradspool", or the - special method "trash" that accepts the article and throws it away). - - The first parameter is a wildmat pattern in the same format used by the - newsfeeds(5) file, and determines what newsgroups are accepted by this - storage class. - - The second parameter is a unique number identifying this storage class - and should be between 0 and 255. It can be used to control article - expiration, and for timehash and timecaf will set the top-level - directory in which articles accepted by this storage class are stored. - The easiest way to deal with this parameter is to just number all - storage classes in storage.conf sequentially. The assignment of a - particular number to a storage class is arbitrary but *permanent* (since - it is used in storage tokens). - - The third parameter can be used to accept only articles in a certain - size range into this storage class. A of 0 (or a missing - ) means no upper limit (and of course a of 0 would - mean no lower limit, because all articles are more than zero bytes - long). If you don't want to limit the size of articles accepted by this - storage class, leave this parameter out entirely. - - The fourth parameter you probably don't want to use; it lets you assign - storage classes based on the Expires: header of incoming articles. The - exact details are in storage.conf(5). It's very easy to use this - parameter incorrectly; leave it out entirely unless you've read the man - page and know what you're doing. - - The fifth parameter is the options parameter. Currently only CNFS uses - this field; it should contain the name of the metacycbuff used to store - articles in this storage class. - - If you're using CNFS exclusively, just create one storage class for each - metacycbuff that you have defined in cycbuff.conf and set the newsgroups - pattern according to what newsgroups should be stored in that buffer. - - If you're using timehash or timecaf, the storage class IDs are used to - store articles in separate directory trees, which you can take advantage - of to put particular storage classes on different disks. Also, - currently storage class is the only way to specify expiration time, so - you will need to divide up your newsgroups based on how long you want to - retain articles in those groups and create a storage class for each such - collection of newsgroups. Make note of the storage class IDs you assign - as they will be needed when you edit expire.ctl a bit later. - - expire.ctl - - expire.ctl sets the expiration policy for articles stored on the server. - Be careful, since the default configuration will expire most articles - after 10 days; in most circumstances this deletion is *permanent*, so - read this whole section carefully if you want to keep local hierarchies - forever. (See archive(8) for a way to automate backups of important - articles.) - - Only one entry is required for all storage classes; it looks like: - - /remember/:10 - - This entry says how long to keep the Message-IDs for articles that have - already expired in the history file so that the server doesn't accept - them again. Occasionally, fairly old articles will get regurgitated - somewhere and offered to you again, so even after you've expired - articles from your spool, you want to keep them around in your history - file for a little while to ensure you don't get duplicates. - - INN will reject any articles more than a certain number of days old (the - *artcutoff* parameter in inn.conf, defaulting to 10); the number on the - "/remember/" line should match that. - - CNFS makes no further use of expire.ctl, since articles stored in CNFS - buffers expire automatically when the buffer runs out of free space (but - see the "-N" option in expireover(8) if you really want to expire them - earlier). For other storage methods, there are two different syntaxes - of this file, depending on *groupbaseexpiry* in inn.conf. If it is set - to false, expire.ctl takes entries of the form: - - ::: - - is the number assigned to a storage class in - storage.conf. is the number of days to keep normal articles - in that storage class (decimal values are allowed). For articles that - don't have an Expires: header, those are the only two values that - matter. For articles with an Expires: header, the other two values come - into play; the date given in the Expires: header of an article will be - honored, subject to the contraints set by and . All - articles in this storage class will be kept for at least days, - regardless of their Expires: headers, and all articles in this storage - class will be expired after days, even if their Expires: headers - specify a longer life. - - All three of these fields can also contain the special keyword "never". - If is "never", only articles with explicit Expires: headers - will ever be expired. If is "never", articles with explicit - Expires: headers will be kept forever. Setting to "never" says - to honor Expires: headers even if they specify dates far into the - future. (Note that if is set to "never", all articles with - Expires: headers are kept forever and the value of is not used.) - - If the value of "groupbaseexpiry" is true, expire.ctl takes entries of - the form: - - :::: - - is a wildmat expression ("!" and "@" not permitted, and only a - single expression, not a comma-separated set of them). Each expiration - line applies to groups matching the wildmat expression. is "M" - for moderated groups, "U" for unmoderated groups, and "A" for groups - with any moderation status; the line only matches groups with the - indicated expiration status. All of the other fields have the same - meaning as above. - - readers.conf - - Provided that *noreader* is set to false in inn.conf, any connection - from a host that doesn't match an entry in incoming.conf (as well as any - connection from a host that does match such an entry, but has issued a - MODE READER command) will be handed off to nnrpd(8), the part of INN - that supports newsreading clients. nnrpd uses readers.conf to determine - whether a given connection is allowed to read news, and if so what - newsgroups the client can read and post to. - - There are a variety of fairly complicated things that one can do with - readers.conf, things like run external authentication programs that can - query RADIUS servers. See readers.conf(5) and the example file for all - the gory details. Here's an example of probably the simplest reasonable - configuration, one that only allows clients in the example.com domain to - read from the server and allows any host in that domain to read and post - to all groups: - - auth "example.com" { - hosts: "example.com, *.example.com" - default: "" - default-domain: "example.com" - } - - access "all" { - users: "*@example.com" - newsgroups: "*" - } - - If you're running a server for one particular domain, want to allow all - hosts within that domain to read and post to any group on the server, - and want to deny access to anyone outside that domain, just use the - above and change "example.com" in the above to your domain and you're - all set. Lots of examples of more complicated things are in the sample - file. - -Creating the Article Spool (CNFS only) - - If you are using actual files as your CNFS buffers, you will need to - pre-create those files, ensuring they're the right size. The easiest - way to do this is with dd. For each cycbuff in cycbuff.conf, create the - buffer with the following commands (as the news user): - - dd if=/dev/zero of=/path/to/buffer bs=1k count=BUFFERSIZE - chmod 664 /path/to/buffer - - Substitute the correct path to the buffer and the size of the buffer as - specified in cycbuff.conf. This will create a zero-filled file of the - correct size; it may take a while, so be prepared to wait. - - Here's a command that will print out the dd(1) commands that you should - run: - - awk -F: \ - '/^cy/ { printf "dd if=/dev/zero of=%s bs=1k count=%s\n", $3, $4 }' \ - ~news/etc/cycbuff.conf - - If you are using block devices, you don't technically have to do - anything at all (since INN is capable of using the devices in /dev), but - you probably want to create special device files for those devices - somewhere for INN's private use. It s more convenient to keep all of - INN's stuff together, but more importantly, the device files used by INN - really should be owned by the news user and group, and you may not want - to do that with the files in /dev. - - To create the device files for INN, use mknod(8) with a type of "b", - getting the major and minor device numbers from the existing devices in - /dev. There's a small shell script in cycbuff.conf(5) that may help - with this. Make sure to create the device files in the location INN - expects them (specified in cycbuff.conf). - - Solaris users please note: on Solaris, do not use block devices that - include the first cylinder of the disk. Solaris doesn't protect the - superblock from being overwritten by an application writing to block - devices and includes it in the first cylinder of the disk, so unless you - use a slice that starts with cylinder 1 instead of 0, INN will - invalidate the partition table when it tries to initialize the cycbuff - and all further accesses will fail until you repartition. - -Creating the Database Files - - At this point, you need to set up the news database directory - (~news/db). This directory will hold the active(5) file (the list of - newsgroups you carry), the active.times(5) file (the creator and - creation time of newsgroups created since the server was initialized), - the newsgroups(5) file (descriptions for all the newsgroups you carry), - and the history(5) file (a record of every article the server currently - has or has seen in the past few days, used to decide whether to accept - or refuse new incoming messages). - - Before starting to work on this, make sure you're logged on as the news - user, since all of these files need to be owned by that user. This is a - good policy to always follow; if you are doing any maintenance work on - your news server, log on as the news user. Don't do maintenance work as - root. Also make sure that ~news/bin is in the default path of the news - user (and while you're at it, make sure ~news/man is in the default - MANPATH) so that you can run INN maintenance commands without having to - type the full path. - - If you already have a server set up (if you're upgrading, or setting up - a new server based on an existing server), copy active and newsgroups - from that server into ~news/db. Otherwise, you'll need to figure out - what newsgroups you want to carry and create new active and newsgroups - files for them. If you plan to carry a full feed, or something close to - that, go to and download active - and newsgroups from there; that will start you off with reasonably - complete files. If you plan to only carry a small set of groups, the - default minimal active file installed by INN is a good place to start; - you can create additional groups after the server is running by using - "ctlinnd newgroup". (Another option is to use actsync(8) to synchronize - your newsgroup list to that of another server.) - - "control" and "junk" must exist as newsgroups in your active file for - INN to start, and creating pseudogroups for the major types of control - messages is strongly encouraged for all servers that aren't standalone. - If you don't want these groups to be visible to clients, do *not* delete - them; simply hide them in readers.conf. "to" must also exist as a - newsgroup if you have mergetogroups set in inn.conf. - - Next, you need to create an empty history database. To do this, type: - - cd ~news/db - touch history - makedbz -i - - When it finishes, rename the files it created to remove the ".n" in the - file names and then make sure the file permissions are correct on all - the files you've just created: - - chmod 644 * - - Your news database files are now ready to go. - -Configuring syslog - - While some logs are handled internally, INN also logs a wide variety of - information via syslog. INN's nightly report programs know how to roll - and summarize those syslog log files, but when you first install INN you - need to set them up. - - If your system understands the "news" syslog facility, INN will use it; - otherwise, it will log to "local1". Nearly every modern system has a - "news" syslog facility so you can safely assume that yours does, but if - in doubt take a look at the output from running "configure". You should - see a line that looks like: - - checking log level for news... LOG_NEWS - - If that says LOG_LOCAL1 instead, change the below instructions to use - "local1" instead of "news". - - Edit /etc/syslog.conf on your system and add lines that look like the - following: - - news.crit /usr/local/news/log/news.crit - news.err /usr/local/news/log/news.err - news.notice /usr/local/news/log/news.notice - - (Change the path names as necessary if you installed INN in a different - location than /usr/local/news.) These lines *must* be tab-delimited, so - don't copy and paste from these instructions. Type it in by hand and - make sure you use a tab, or you'll get mysterious failures. You'll also - want to make sure that news log messages don't fill your other log files - (INN generates a lot of log traffic); so for every entry in - /etc/syslog.conf that starts with "*", add ";news.none" to the end of - the first column. For example, if you have a line like: - - *.err /dev/console - - change it to: - - *.err;news.none /dev/console - - (You can choose not to do this for the higher priority log messages, if - you want to make sure they go to your normal high-priority log files as - well as INN's. Don't bother with anything lower priority than "crit", - though. "news.err" isn't interesting enough to want to see all the - time.) Now, make sure that the news log files exist; syslog generally - won't create files automatically. Enter the following commands: - - touch /usr/local/news/log/news.crit - touch /usr/local/news/log/news.err - touch /usr/local/news/log/news.notice - chown news /usr/local/news/log/news.* - chgrp news /usr/local/news/log/news.* - - (again adjusting the paths if necessary for your installation). - Finally, send a HUP signal to syslogd to make it re-read its - configuration file. - -Setting Up the Cron Jobs - - INN requires a special cron job to be set up on your system to run - news.daily(8) which performs daily server maintenance tasks such as - article expiration and the processing and rotation of the server logs. - Since it will slow the server down while it is running, it should be run - during periods of low server usage, such as in the middle of the night. - To run it at 3am, for example, add the following entry to the news - user's crontab file: - - 0 3 * * * /usr/local/news/bin/news.daily expireover lowmark - - or, if your system does not have per-user crontabs, put the following - line into your system crontab instead: - - 0 3 * * * su -c "/usr/local/news/bin/news.daily expireover lowmark" news - - If you're using any non-CNFS storage methods, add "delayrm" to the above - option list for news.daily. - - The news user obviously must be able to run cron jobs. On Solaris, this - means that it must have a valid /etc/shadow entry and must not be locked - (although it may be a non-login account). There may be similar - restrictions with other operating systems. - - If you use the batching method to send news, also set up a cron job to - run nntpsend(8) every ten minutes. nntpsend will run innxmit for all - non-empty pending batch files to send pending news to your peers. That - cron entry should look something like: - - 0,10,20,30,40,50 * * * * /usr/local/news/bin/nntpsend - - The pathnames and user ID used above are the installation defaults; - change them to match your installation if you used something other than - the defaults. - - The parameters passed to news.daily in the above example are the most - common (and usually the most efficient) ones to use. More information - on what these parameters do can be found in the news.daily(8) man page. - -File Descriptor Limits - - INN likes to use a lot of file descriptors, particularly if you have a - lot of peers. Depending on what your system defaults are, you may need - to make sure the default limit is increased for INN (particularly for - innd and innfeed). This is vital on Solaris, which defaults (at least - as of 2.6) to an absurdly low limit of 64 file descriptors per process. - - One way to increase the number of file descriptors is to set - *rlimitnofile* in inn.conf to a higher value. This will cause both - startinnfeed and inndstart (the setuid root wrapper scripts that start - innfeed and innd, respectively) to increase the file descriptor limits - before they run the regular INN programs. Note, however, that INN won't - be able to increase the limits above the hard limits set by your - operating system; on some systems, that hard limit is normally 256 file - descriptors (Linux, for example). On others, like Solaris, it's 1024. - Increasing the limit beyond that value may require serious system - configuration work. (On some operating systems, it requires patching - and recompiling the kernel. On Solaris it can be changed in - /etc/system, but for 2.6 or earlier the limit cannot be increased beyond - 1024 without breaking select(2) and thereby breaking all of INN. For - current versions of Linux, you may be able to change the maximum by - writing to /proc/sys/fs/file-max.) - - 256 file descriptors will probably be enough for all but the largest - sites. There is no harm in setting the limits higher than you actually - need (provided they're set to something lower than or equal to your - system hard limit). 256 is therefore a reasonable value to try. - - If you're installing INN on a Solaris system, particularly if you're - installing it on a dedicated news server machine, it may be easier to - just increase the default file descriptor limit across the board for all - processes. You can do that by putting the line: - - set rlim_fd_cur = 256 - - in /etc/system and rebooting. You can increase it all the way to 1024 - (and may need to if you have a particularly large site), but that can - cause RPC and some stdio applications to break. It therefore probably - isn't a good idea on a machine that isn't dedicated to INN. - -Starting and Stopping the System - - INN is started via the shell script rc.news. This must be run as the - news user and not as root. To start INN on system boot, you therefore - want to put something like: - - su - news -c /usr/local/news/bin/rc.news - - in the system boot scripts. If innd is stopped or killed, you can - restart it by running rc.news by hand as the news user. - - The rc.news script may also be used to shut down INN, with the "stop" - option: - - su - news -c '/usr/local/news/bin/rc.news stop' - - In the contrib directory of this source tree is a sample init script for - people using System V-style init.d directories. - -Processing Newsgroup Control Messages - - Control messages are specially-formatted messages that tell news servers - to take various actions. Cancels (commands to delete messages) are - handled internally by INN, and all other control messages are processed - by controlchan. controlchan should be run out of newsfeeds if you want - your news server to process any control messages; see "Configuring INN" - for specific instructions. - - The actions of controlchan are determined by control.ctl, which lists - who can perform what actions. The primary control messages to be - concerned with are "newgroup" (to create a newsgroup), "rmgroup" (to - remove a newsgroup), and "checkgroups" (to compare the list of groups - carried in a hierarchy to a canonical list). INN comes with a - control.ctl file that processes control messages in most major public - hierarchies; if you don't want to act on all those control messages, you - should remove from that file all entries for hierarchies you don't want - to carry. - - You can tell INN to just authenticate control messages based on the From - header of the message, but this is obviously perilous and control - messages are widely forged. Many hierarchies sign all of their control - messages with PGP, allowing news servers to verify their authenticity, - and checking those signatures for hierarchies that use them is highly - recommended. controlchan knows how to do this (using pgpverify) without - additional configuration, but you do have to provide it with a public - key ring containing the public keys of all of the hierarchy - administrators whose control messages you want to check. - - INN expects the public key ring to either be in the default location for - a PGP public key ring for the news user (generally ~news/.gnupg for - GnuPG and ~news/.pgp for old PGP implementations), or in pathetc/pgp - (/usr/local/news/etc/pgp by default). The latter is the recommended - path. To add a key to that key ring, use: - - gpg --import --homedir=/usr/local/news/etc/pgp - - where is a file containing the hierarchy key. Change the homedir - setting to point to pathetc/pgp if you have INN installed in a - non-default location. If you're using the old-style PGP program, an - equivalent command is: - - env PGPPATH=/usr/local/news/etc/pgp pgp - - You can safely answer "no" to questions about whether you want to sign, - trust, or certify keys. - - The URLs from which you can get hierarchy keys are noted in comments in - control.ctl. tries to - collect the major hierarchy keys. - - If you are using GnuPG, please note that the first user ID on the key - will be the one that's used by INN for verification and must match the - key listed in control.ctl. If a hierarchy key has multiple user IDs, - you may have to remove all the user IDs except the one that matches the - control.ctl entry using "gpg --edit-key" and the "delkey" command. - diff --git a/LICENSE b/LICENSE deleted file mode 100644 index 4d0fec5..0000000 --- a/LICENSE +++ /dev/null @@ -1,87 +0,0 @@ -INN as a whole and all code contained in it not otherwise marked with -different licenses and/or copyrights is covered by the following copyright -and license: - - Copyright (c) 2004, 2005, 2006, 2007, 2008 - by Internet Systems Consortium, Inc. ("ISC") - Copyright (c) 1991, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, - 2002, 2003 by The Internet Software Consortium and Rich Salz - - This code is derived from software contributed to the Internet Software - Consortium by Rich Salz. - - Permission to use, copy, modify, and distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH - REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY - SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -Some specific portions of INN are covered by different licenses. Those -licenses, if present, will be noted prominantly at the top of those source -files. Specifically (but possibly not comprehensively): - - authprogs/smbval/*, backends/send-uucp.in, and control/perl-nocem.in - are under the GNU General Public License. See doc/GPL for a copy of - this license. - - backends/shrinkfile.c, frontends/scanspool.in, lib/concat.c, - lib/hstrerror.c, lib/inet_aton.c, lib/inet_ntoa.c, lib/memcmp.c, - lib/parsedate.y, lib/pread.c, lib/pwrite.c, lib/setenv.c, lib/seteuid.c, - lib/strerror.c, lib/strlcat.c and lib/strlcpy.c are in the public - domain. - - lib/snprintf.c may be used for any purpose as long as the author's - notice remains intact in all source code distributions. - - control/gpgverify.in, control/pgpverify.in and control/signcontrol.in - are under a BSD-style license (with the advertising clause) with UUNET - Technologies, Inc. as the copyright holder. See the end of those files - for details. - - control/controlchan.in and control/modules/*.pl are covered by a - two-clause BSD-style license (no advertising clause). See the - beginning of those files for details. - - lib/strcasecmp.c, lib/strspn.c, and lib/strtok.c are taken from BSD - sources and are covered by the standard BSD license. See those files - for more details. - - lib/md5.c is covered under the standard free MD5 license from RSA Data - Security. See the file for more details. A clarification is also - provided here: . - - "Implementations of these message-digest algorithms, including - implementations derived from the reference C code in RFC-1319, - RFC-1320, and RFC-1321, may be made, used, and sold without - license from RSA for any purpose." - - history/his.c and history/hisv6/hisv6.c are under a license very - similar to the new BSD license (no advertising clause) but with Thus - plc as the copyright holder. See those files for details. - - lib/tst.c, include/inn/tst.h and doc/pod/tst.pod are derived from - and are under the new BSD - license (no advertising clause), but with Peter A. Friend as the - copyright holder. - - tests/runtests.c is covered under a license very similar to the MIT/X - Consortium license. See the beginning of the file for details. - -Note that all portions of INN that link with core INN code have to be -covered by licenses compatible with the license at the top of this file, -and since INN links with several external libraries if so configured (such -as OpenSSL), should also be compatible with the licenses of those external -libraries to be safe. Some portions of this distribution are covered by -more restrictive licenses, but all of that code is completely stand-alone, -either as a standalone script or as code that compiles into a separate -executable. - -Please note that the files in the contrib directory are not properly part -of INN and may be under widely varying licenses. Please see each file -and/or its documentation for license information. diff --git a/MANIFEST b/MANIFEST deleted file mode 100644 index d93dada..0000000 --- a/MANIFEST +++ /dev/null @@ -1,745 +0,0 @@ -File Name Description -------------------------------------------------------------------------------- -CONTRIBUTORS List of contributors -HACKING Docs for INN coders and maintainers -INSTALL INN installation instructions -LICENSE Legal mumbo-jumbo -MANIFEST This shipping list -Makefile Top-level makefile -Makefile.global.in Make variables for all Makefiles -NEWS Changes since last version -README Introduction to the INN package -TODO The list of pending INN projects -aclocal.m4 M4 macro for libtool -authprogs The authentication programs (Directory) -authprogs/Makefile Makefile for auth programs -authprogs/auth_krb5.c Authenticator against Kerberos v5 -authprogs/auth_smb.c Authenticator against Samba servers -authprogs/ckpasswd.c Check password -authprogs/domain.c Get username from remote user's hostname -authprogs/ident.c Get username from ident -authprogs/libauth.c Library for talking to nnrpd -authprogs/libauth.h Interface for libauth -authprogs/radius.c Authenticator against RADIUS servers -authprogs/smbval The smb auth libraries (Directory) -authprogs/smbval/Makefile Libraries for smb auth -authprogs/smbval/byteorder.h Libraries for smb auth -authprogs/smbval/rfcnb-common.h Libraries for smb auth -authprogs/smbval/rfcnb-error.h Libraries for smb auth -authprogs/smbval/rfcnb-io.c Libraries for smb auth -authprogs/smbval/rfcnb-io.h Libraries for smb auth -authprogs/smbval/rfcnb-priv.h Libraries for smb auth -authprogs/smbval/rfcnb-util.c Libraries for smb auth -authprogs/smbval/rfcnb-util.h Libraries for smb auth -authprogs/smbval/rfcnb.h Libraries for smb auth -authprogs/smbval/session.c Libraries for smb auth -authprogs/smbval/smbdes.c Libraries for smb auth -authprogs/smbval/smbencrypt.c Libraries for smb auth -authprogs/smbval/smblib-common.h Libraries for smb auth -authprogs/smbval/smblib-priv.h Libraries for smb auth -authprogs/smbval/smblib-util.c Libraries for smb auth -authprogs/smbval/smblib.c Libraries for smb auth -authprogs/smbval/smblib.h Libraries for smb auth -authprogs/smbval/valid.c Libraries for smb auth -authprogs/smbval/valid.h Libraries for smb auth -backends Outgoing feed programs (Directory) -backends/Makefile Makefile for outgoing feed programs -backends/actmerge.in Merge two active files to stdout -backends/actsync.c Poll remote(s) for active file & merge -backends/actsyncd.in Daemon to run actsync periodically -backends/archive.c Simple article archiver -backends/batcher.c Make news batches -backends/buffchan.c Buffered funnel to file splitter -backends/crosspost.c Create links for crossposts (obselete) -backends/cvtbatch.c Add fields to simple batchfile -backends/filechan.c Split a funnel into separate files -backends/inndf.c df used for innwatch -backends/innxbatch.c Send batches using XBATCH to remote -backends/innxmit.c Send articles to remote site -backends/map.c Site name to filename mapping routines -backends/map.h Headers for backends/map.c -backends/mod-active.in Batch do active file modifications -backends/news2mail.in News to mail gateway -backends/ninpaths.c Path statistics accumulation program -backends/nntpget.c Get articles from remote site -backends/nntpsend.in Invoke all innxmit's at once -backends/overchan.c Update news overview database -backends/send-ihave.in Script to post ihave messages -backends/send-nntp.in Shell script to call innxmit -backends/send-uucp.in Script to call batcher -backends/sendinpaths.in Send accumulated Path statistics -backends/sendxbatches.in Shell wrapper around innxbatch -backends/shlock.c Program to make lockfiles in scripts -backends/shrinkfile.c Shrink file from beginning -configure Script to configure INN -configure.in Source file for configure -contrib External contributions (Directory) -contrib/Makefile Makefile for contrib programs -contrib/README Contents of the contrib directory -contrib/archivegz.in Compressing version of archive -contrib/auth_pass.README README corresponding to auth_pass.c -contrib/auth_pass.c Sample for use with AUTHINFO GENERIC -contrib/backlogstat.in Analyze innfeed's backlog status -contrib/backupfeed.in Suck down news via a reading connection -contrib/cleannewsgroups.in Script to clean newsgroups file -contrib/count_overview.pl Count overview entries -contrib/delayer.in Delay data in a pipe, for innfeed -contrib/expirectl.c Generate expire.ctl from template -contrib/findreadgroups.in Track which groups are being read -contrib/fixhist Script to clean history -contrib/innconfcheck Merge inn.conf with its man page -contrib/makeexpctl.in Create expire.ctl from read groups -contrib/makestorconf.in Create storage.conf from read groups -contrib/mkbuf Create cycbuff for HP-UX -contrib/mlockfile.c Lock files into memory using mlock -contrib/newsresp.c Measure responsiveness of remote server -contrib/pullart.c Recover articles from cyclic buffers -contrib/reset-cnfs.c Reset the state parts of a CNFS buffer -contrib/respool.c Respool articles in the storage manager -contrib/sample.init.script Example SysV-style init.d script -contrib/showtoken.in Decode storage API tokens -contrib/stathist.in Parse history statistics -contrib/thdexpire.in Dynamic expire for timehash and timecaf -contrib/tunefeed.in Tune a feed by comparing active files -control Control message handling (Directory) -control/Makefile Makefile for control programs -control/controlbatch.in Batch program for controlchan -control/controlchan.in Channel program for control messages -control/docheckgroups.in Script to execute checkgroups -control/gpgverify.in Verify control messages with GnuPG -control/modules Modules for controlchan (Directory) -control/modules/checkgroups.pl checkgroups controlchan handler -control/modules/ihave.pl ihave controlchan handler -control/modules/newgroup.pl newgroup controlchan handler -control/modules/rmgroup.pl rmgroup controlchan handler -control/modules/sendme.pl sendme controlchan handler -control/modules/sendsys.pl sendsys controlchan handler -control/modules/senduuname.pl senduuname controlchan handler -control/modules/version.pl version controlchan handler -control/perl-nocem.in NoCeM on spool implementation -control/pgpverify.in Verify control messages with PGP -control/signcontrol.in PGP control message signing program -doc Documentation (Directory) -doc/GPL The GNU General Public License 2.0 -doc/IPv6-info Nathan Lutchansky's IPv6 notes -doc/Makefile Makefile for documentation -doc/checklist Checklist for installing INN -doc/compliance-nntp INN compliance with the NNTP standard -doc/config-design Configuration parser design principles -doc/config-semantics Configuration file semantics -doc/config-syntax Configuration file syntax -doc/external-auth readers.conf external interface notes -doc/history Messages of historical significance -doc/hook-perl Christophe Wolfhugel's Perl hook notes -doc/hook-python Python hook notes -doc/hook-tcl Bob Halley's TCL hook notes -doc/man nroff documentation (Directory) -doc/man/Makefile Makefile for nroff documentation -doc/man/active.5 Manpage for active database -doc/man/active.times.5 Manpage for active.times file -doc/man/actsync.8 Manpage for active file synch program -doc/man/actsyncd.8 Manpage for active synch daemon -doc/man/archive.8 Manpage for archive backend -doc/man/auth_krb5.8 Manpage for auth_krb5 authenticator -doc/man/auth_smb.8 Manpage for auth_smb authenticator -doc/man/batcher.8 Manpage for batcher -doc/man/buffchan.8 Manpage for buffchan backend -doc/man/buffindexed.conf.5 Manpage for buffindexed.conf config file -doc/man/ckpasswd.8 Manpage for ckpasswd authenticator -doc/man/clientlib.3 Manpage for C News library interface -doc/man/cnfsheadconf.8 Manpage for cnfsheadconf -doc/man/cnfsstat.8 Manpage for cnfsstat -doc/man/control.ctl.5 Manpage for control.ctl config file -doc/man/controlchan.8 Manpage for controlchan backend -doc/man/convdate.1 Manpage for convdate utility -doc/man/ctlinnd.8 Manpage for ctlinnd frontend -doc/man/cvtbatch.8 Manpage for cvtbatch utility -doc/man/cycbuff.conf.5 Manpage for cycbuff.conf config file -doc/man/dbz.3 Manpage for DBZ database interface -doc/man/distrib.pats.5 Manpage for distrib.pats config file -doc/man/domain.8 Manpage for domain resolver -doc/man/expire.8 Manpage for expire -doc/man/expire.ctl.5 Manpage for expire.ctl config file -doc/man/expireover.8 Manpage for expireover -doc/man/expirerm.8 Manpage for expirerm -doc/man/fastrm.1 Manpage for fastrm utility -doc/man/filechan.8 Manpage for filechan backend -doc/man/getlist.1 Manpage for getlist frontend -doc/man/grephistory.1 Manpage for grephistory -doc/man/history.5 Manpage for history database -doc/man/ident.8 Manpage for ident resolver -doc/man/incoming.conf.5 Manpage for incoming.conf config file -doc/man/inews.1 Manpage for inews frontend -doc/man/inn.conf.5 Manpage for inn.conf config file -doc/man/inncheck.8 Manpage for inncheck utility -doc/man/innconfval.1 Manpage for innconfval -doc/man/innd.8 Manpage for innd server -doc/man/inndcomm.3 Manpage for part of INN library -doc/man/inndf.8 Manpage for inndf utility -doc/man/inndstart.8 Manpage for inndstart -doc/man/innfeed.1 Manpage for innfeed backend -doc/man/innfeed.conf.5 Manpage for innfeed.conf config file -doc/man/innmail.1 Manpage for innmail utility -doc/man/innreport.8 Manpage for innreport -doc/man/innstat.8 Manpage for innstat utility -doc/man/innupgrade.8 Manpage for innupgrade utility -doc/man/innwatch.8 Manpage for innwatch -doc/man/innwatch.ctl.5 Manpage for innwatch.ctl config file -doc/man/innxbatch.8 Manpage for innxbatch -doc/man/innxmit.8 Manpage for innxmit -doc/man/libauth.3 Manpage for authprogs utilty routines -doc/man/libinn.3 Manpage for INN library routines -doc/man/libinnhist.3 Manpage for history API library routines -doc/man/libstorage.3 Manpage for storage API library routines -doc/man/list.3 Manpage for list routines -doc/man/mailpost.8 Manpage for mailpost frontend -doc/man/makeactive.8 Manpage for makeactive -doc/man/makedbz.8 Manpage for makedbz -doc/man/makehistory.8 Manpage for makehistory -doc/man/mod-active.8 Manpage for mod-active -doc/man/moderators.5 Manpage for moderators config file -doc/man/motd.news.5 Manpage for motd.news config file -doc/man/news.daily.8 Manpage for news.daily -doc/man/news2mail.8 Manpage for news2mail -doc/man/newsfeeds.5 Manpage for newsfeeds config file -doc/man/newslog.5 Manpage for log files -doc/man/ninpaths.8 Manpage for ninpaths -doc/man/nnrpd.8 Manpage for nnrpd daemon -doc/man/nnrpd.track.5 Manpage for nnrpd.track config file -doc/man/nntpget.1 Manpage for nntpget frontend -doc/man/nntpsend.8 Manpage for nntpsend -doc/man/nntpsend.ctl.5 Manpage for nntpsend.ctl config file -doc/man/ovdb.5 Manpage for the ovdb storage module -doc/man/ovdb_init.8 Manpage for ovdb_init -doc/man/ovdb_monitor.8 Manpage for ovdb_monitor -doc/man/ovdb_server.8 Manpage for ovdb_server -doc/man/ovdb_stat.8 Manpage for ovdb_stat -doc/man/overchan.8 Manpage for overchan backend -doc/man/overview.fmt.5 Manpage for overview.fmt config file -doc/man/parsedate.3 Manpage for parsedate library routine -doc/man/passwd.nntp.5 Manpage for passwd.nntp config file -doc/man/perl-nocem.8 Manpage for perl-nocem -doc/man/pgpverify.1 Manpage for pgpverify -doc/man/prunehistory.8 Manpage for prunehistory -doc/man/pullnews.1 Manpage for pullnews -doc/man/putman.sh Install a manpage -doc/man/qio.3 Manpage for fast I/O file routines -doc/man/radius.8 Manpage for radius authenticator -doc/man/radius.conf.5 Manpage for radius.conf config file -doc/man/rc.news.8 Manpage for rc.news -doc/man/readers.conf.5 Manpage for readers.conf config file -doc/man/rnews.1 Manpage for rnews frontend -doc/man/sasl.conf.5 Manpage for sasl.conf config file -doc/man/scanlogs.8 Manpage for scanlogs -doc/man/send-nntp.8 Manpage for send-nntp and send-ihave -doc/man/send-uucp.8 Manpage for send-uucp -doc/man/sendinpaths.8 Manpage for sendinpaths -doc/man/shlock.1 Manpage for shlock backend utility -doc/man/shrinkfile.1 Manpage for shrinkfile utility -doc/man/simpleftp.1 Manpage for simpleftp utility -doc/man/sm.1 Manpage for sm -doc/man/startinnfeed.1 Manpage for startinnfeed -doc/man/storage.conf.5 Manpage for storage.conf config file -doc/man/subscriptions.5 Manpage for subscriptions list -doc/man/tally.control.8 Manpage for tally.control -doc/man/tdx-util.8 Manpage for tdx-util -doc/man/tst.3 Manpage for ternary search tree routines -doc/man/uwildmat.3 Manpage for uwildmat library routine -doc/man/writelog.8 Manpage for writelog -doc/pod POD documentation (Directory) -doc/pod/Makefile Maintainer rules for derived files -doc/pod/active.pod Master file for active.5 -doc/pod/active.times.pod Master file for active.times.5 -doc/pod/auth_krb5.pod Master file for auth_krb5.8 -doc/pod/auth_smb.pod Master file for auth_smb.8 -doc/pod/checklist.pod Master file for doc/checklist -doc/pod/ckpasswd.pod Master file for ckpasswd.8 -doc/pod/control.ctl.pod Master file for control.ctl.5 -doc/pod/convdate.pod Master file for convdate.1 -doc/pod/cycbuff.conf.pod Master file for cycbuff.conf.5 -doc/pod/distrib.pats.pod Master file for distrib.pats.5 -doc/pod/domain.pod Master file for domain.8 -doc/pod/expire.ctl.pod Master file for expire.ctl.5 -doc/pod/expireover.pod Master file for expireover.8 -doc/pod/external-auth.pod Master file for doc/external-auth -doc/pod/fastrm.pod Master file for fastrm.1 -doc/pod/grephistory.pod Master file for grephistory.1 -doc/pod/hacking.pod Master file for HACKING -doc/pod/hook-perl.pod Master file for doc/hook-perl -doc/pod/hook-python.pod Master file for doc/hook-python -doc/pod/ident.pod Master file for ident.8 -doc/pod/inews.pod Master file for inews.1 -doc/pod/inn.conf.pod Master file for inn.conf.5 -doc/pod/innconfval.pod Master file for innconfval.1 -doc/pod/innd.pod Master file for innd.8 -doc/pod/inndf.pod Master file for inndf.8 -doc/pod/inndstart.pod Master file for inndstart.8 -doc/pod/innmail.pod Master file for innmail.1 -doc/pod/innupgrade.pod Master file for innupgrade.8 -doc/pod/install.pod Master file for INSTALL -doc/pod/libauth.pod Master file for libauth.3 -doc/pod/libinnhist.pod Master file for libinnhist.3 -doc/pod/list.pod Master file for list.3 -doc/pod/mailpost.pod Master file for mailpost.8 -doc/pod/makehistory.pod Master file for makehistory.8 -doc/pod/motd.news.pod Master file for motd.news.5 -doc/pod/news.pod Master file for NEWS -doc/pod/newsfeeds.pod Master file for newsfeeds.5 -doc/pod/ninpaths.pod Master file for ninpaths.8 -doc/pod/nnrpd.pod Master file for nnrpd.8 -doc/pod/ovdb.pod Master file for ovdb.5 -doc/pod/ovdb_init.pod Master file for ovdb_init.8 -doc/pod/ovdb_monitor.pod Master file for ovdb_monitor.8 -doc/pod/ovdb_server.pod Master file for ovdb_server.8 -doc/pod/ovdb_stat.pod Master file for ovdb_stat.8 -doc/pod/passwd.nntp.pod Master file for passwd.nntp.5 -doc/pod/pullnews.pod Master file for pullnews.1 -doc/pod/qio.pod Master file for qio.3 -doc/pod/radius.conf.pod Master file for radius.conf.5 -doc/pod/radius.pod Master file for radius.8 -doc/pod/rc.news.pod Master file for rc.news.8 -doc/pod/readers.conf.pod Master file for readers.conf.5 -doc/pod/readme.pod Master file for README -doc/pod/sasl.conf.pod Master file for sasl.conf.5 -doc/pod/sendinpaths.pod Master file for sendinpaths.8 -doc/pod/simpleftp.pod Master file for simpleftp.1 -doc/pod/sm.pod Master file for sm.1 -doc/pod/subscriptions.pod Master file for subscriptions.5 -doc/pod/tdx-util.pod Master file for tdx-util.8 -doc/pod/tst.pod Master file for tst.3 -doc/pod/uwildmat.pod Master file for uwildmat.3 -doc/sample-control Sample PGP-signed control message -expire Expiration and recovery (Directory) -expire/Makefile Makefile for expiration -expire/convdate.c Date string conversions -expire/expire.c Expire old articles and history lines -expire/expireover.c Expire news overview data -expire/expirerm.in Remove articles from expire -z -expire/fastrm.c Remove list of files -expire/grephistory.c Find entries in history database -expire/makedbz.c Recover dbz -expire/makehistory.c Recover the history database -expire/prunehistory.c Prune file names from history file -frontends inews, rnews, ctlinnd (Directory) -frontends/Makefile Makefile for frontends -frontends/cnfsheadconf.in Setup cycbuff header -frontends/cnfsstat.in Show cycbuff status -frontends/ctlinnd.c Send control request to innd -frontends/decode.c Decode 7-bit data into binary file -frontends/encode.c Encode binary file into 7-bit data -frontends/feedone.c Test rig to feed a single NNTP article -frontends/getlist.c Get active or other list from server -frontends/inews.c Send article to local NNTP server -frontends/innconfval.c Get an INN configuration parameter -frontends/mailpost.in Mail to news gateway -frontends/ovdb_init.c Prepare ovdb database for use -frontends/ovdb_monitor.c Database maintainance for ovdb -frontends/ovdb_server.c Helper server for ovdb -frontends/ovdb_stat.c Display information from ovdb database -frontends/pullnews.in Sucking news feeder -frontends/rnews.c UUCP unbatcher -frontends/scanspool.in Scan spool directory for trash -frontends/sm.c Get article or overview data from token -frontends/sys2nf.c Sys file to newsfeeds conversion aid -history History library routines (Directory) -history/Make.methods Makefile for history methods -history/Makefile Makefile for history library -history/buildconfig.in Construct history interface -history/his.c History API glue implementation -history/hisinterface.h History API interface -history/hisv6 History v6 method (Directory) -history/hisv6/hismethod.config hisbuildconfig definition -history/hisv6/hisv6-private.h Private header file for hisv6 -history/hisv6/hisv6.c hisv6 history method -history/hisv6/hisv6.h Header for hisv6 history -include Header files (Directory) -include/Makefile Makefile for header files -include/acconfig.h Master file for config.h.in -include/clibrary.h C library portability -include/conffile.h Header file for reading *.conf files -include/config.h.in Template configuration data -include/dbz.h Header file for DBZ -include/inn Installed header files (Directory) -include/inn/buffer.h Header file for reusable counted buffers -include/inn/confparse.h Header file for configuration parser -include/inn/defines.h Portable defs for installed headers -include/inn/hashtab.h Header file for generic hash table -include/inn/history.h Header file for the history API -include/inn/innconf.h Header file for the innconf struct -include/inn/list.h Header file for list routines -include/inn/md5.h Header file for MD5 digests -include/inn/messages.h Header file for message functions -include/inn/mmap.h Header file for mmap() functions -include/inn/qio.h Header file for quick I/O package -include/inn/sequence.h Header file for sequence space arithmetic -include/inn/timer.h Header file for generic timers -include/inn/tst.h Header file for ternary search tries -include/inn/vector.h Header file for vectors of strings -include/inn/wire.h Header file for wire-format functions -include/inndcomm.h innd control channel commands -include/innperl.h Header file for embedded Perl -include/libinn.h INN library declarations -include/nntp.h NNTP command and reply codes -include/ov.h Header file for overview -include/paths.h.in Paths to common programs and files -include/portable Portability wrappers (Directory) -include/portable/mmap.h Wrapper for -include/portable/setproctitle.h Portable setup for setproctitle -include/portable/socket.h Wrapper for and friends -include/portable/time.h Wrapper for and -include/portable/wait.h Wrapper for -include/ppport.h Header file for Perl support -include/storage.h Header file for storage API -innd Server (Directory) -innd/Makefile Makefile for server -innd/art.c Process a received article -innd/cc.c Control channel routines -innd/chan.c I/O channel routines -innd/icd.c Read and write the active file -innd/innd.c Main and utility routines -innd/innd.h Header file for server -innd/inndstart.c Open the NNTP port, then exec innd -innd/keywords.c Generate article keywords -innd/lc.c Local NNTP channel routines -innd/nc.c NNTP channel routines -innd/newsfeeds.c Routines to parse the newsfeeds file -innd/ng.c Newsgroup routines -innd/perl.c Perl routines for innd -innd/proc.c Process routines -innd/python.c Python routines for innd -innd/rc.c Remote channel accepting routines -innd/site.c Site feeding routines -innd/status.c Status routines for innd -innd/tcl.c Bob Halley's Tcl hook -innd/util.c Utility functions for innd -innd/wip.c Work-in-progress routines for innd -innfeed innfeed (Directory) -innfeed/Makefile Makefile for innfeed -innfeed/README Assorted notes -innfeed/article.c Implementation of the Article class -innfeed/article.h Public interface to Articles -innfeed/buffer.c Implementation of the Buffer class -innfeed/buffer.h Public interface to the Buffer class -innfeed/config_l.c Lexer for the innfeed config file -innfeed/configfile.h Header file for configfile.y -innfeed/configfile.l Master file for config_l.c -innfeed/configfile.y Parser for innfeed config file -innfeed/connection.c Implementation of the Connection class -innfeed/connection.h Public interface to the Connection class -innfeed/endpoint.c Implementation of the EndPoint class -innfeed/endpoint.h Public interface to the EndPoint class -innfeed/host.c Implementation of the Host class -innfeed/host.h Public interface to the Host class -innfeed/imap_connection.c Implementation of IMAP Connection class -innfeed/innfeed-convcfg.in Script to convert old innfeed.conf -innfeed/innfeed.h Application configuration values -innfeed/innlistener.c Implementation of the InnListener class -innfeed/innlistener.h Public interface of InnListener class -innfeed/main.c Main routines for the innfeed program -innfeed/misc.c Miscelloneous routines for innfeed -innfeed/misc.h Header file for misc.c -innfeed/procbatch.in Script to process dropped articles -innfeed/startinnfeed.c Start innfeed -innfeed/tape.c Implementation of the Tape class -innfeed/tape.h Public interface to the Tape class -innfeed/testListener.pl Script to hand articles to innfeed -lib INN library routines (Directory) -lib/Makefile Makefile for library -lib/buffer.c Reusable counted buffer -lib/cleanfrom.c Clean out a From line -lib/clientactive.c Client access to the active file -lib/clientlib.c Replacement for C News library routine -lib/concat.c Concatenate strings with dynamic memory -lib/conffile.c Routines for reading *.conf files -lib/confparse.c Generic configuration file parser -lib/daemonize.c Code necessary to become a daemon -lib/date.c Date parsing and conversion routines -lib/dbz.c DBZ database library -lib/defdist.c Determine default Distribution header -lib/fdflags.c Set or clear file descriptor flags -lib/fdlimit.c File descriptor limits -lib/fseeko.c fseeko replacement -lib/ftello.c ftello replacement -lib/genid.c Generate a message ID -lib/getfqdn.c Get FQDN of local host -lib/getmodaddr.c Get a moderator's address -lib/getpagesize.c getpagesize replacement -lib/gettime.c Get time and timezone info -lib/hash.c Create hash from message ID -lib/hashtab.c Generic hash table -lib/hstrerror.c Error reporting for resolver -lib/inet_aton.c Extra source for inet_aton routine -lib/inet_ntoa.c Convert inaddr to string (BSD) -lib/innconf.c Parsing and manipulation of inn.conf -lib/inndcomm.c Library routines to talk to innd -lib/list.c List routines -lib/localopen.c Open a local NNTP connection -lib/lockfile.c Try to lock a file descriptor -lib/makedir.c Make directory recursively -lib/md5.c MD5 checksum calculation -lib/memcmp.c memcmp replacement -lib/messages.c Error reporting and debug output -lib/mkstemp.c mkstemp replacement -lib/mmap.c mmap manipulation routines -lib/parsedate.y Date parsing -lib/perl.c Perl hook support for nnrpd and innd -lib/pread.c pread replacement -lib/pwrite.c pwrite replacement -lib/qio.c Quick I/O package -lib/radix32.c Encode a number as a radix-32 string -lib/readin.c Read file into memory -lib/remopen.c Open a remote NNTP connection -lib/reservedfd.c File descriptor reservation -lib/resource.c Get process CPU usage -lib/sendarticle.c Send an article, NNTP style -lib/sendpass.c Send NNTP authentication -lib/sequence.c Sequence space arithmetic routines -lib/setenv.c setenv replacement -lib/seteuid.c seteuid replacement -lib/setproctitle.c setproctitle replacement -lib/snprintf.c snprintf and vsnprintf replacement -lib/sockaddr.c Manipulation of sockaddr structs -lib/strcasecmp.c Case-insenstive string comparison (BSD) -lib/strerror.c String representation of errno -lib/strlcat.c strlcat replacement -lib/strlcpy.c strlcpy replacement -lib/strspn.c Skip bytes in a string (BSD) -lib/strtok.c Split a string into tokens (BSD) -lib/timer.c Generic profile timer -lib/tst.c Ternary search trie implementation -lib/uwildmat.c Pattern match routine -lib/vector.c Manipulate vectors of strings -lib/version.c INN version constants -lib/wire.c Manipulate wire-format articles -lib/xfopena.c Open a FILE in append mode -lib/xmalloc.c Failsafe memory allocation wrapper -lib/xsignal.c signal() wrapper using sigaction -lib/xwrite.c write that handles partial transfers -nnrpd Reader server (Directory) -nnrpd/Makefile Makefile for nnrpd -nnrpd/article.c Article-related routines -nnrpd/cache.c MessageID cache routines -nnrpd/cache.h MessageID cache interfaces -nnrpd/commands.c Assorted server commands -nnrpd/group.c Group-related routines -nnrpd/line.c Long line-by-line reading routines -nnrpd/list.c The LIST commands -nnrpd/misc.c Miscellaneous support routines -nnrpd/newnews.c The NEWNEWS command -nnrpd/nnrpd.c Main and some utility routines -nnrpd/nnrpd.h Header file for nnrpd -nnrpd/perl.c Perl routines for nnrpd -nnrpd/perm.c Reading readers.conf -nnrpd/post.c Article processing and posting -nnrpd/post.h Article data types -nnrpd/python.c Python routines for nnrpd -nnrpd/sasl_config.c Configuration for SASL -nnrpd/sasl_config.h SASL data types -nnrpd/tls.c Transport layer security -nnrpd/tls.h Transport layer security data types -nnrpd/track.c Track client behavior -samples Prototype INN config files (Directory) -samples/INN.py Stub Python functions -samples/Makefile Makefile for samples -samples/active.minimal Minimal starting active file -samples/actsync.cfg Config file for actsync -samples/actsync.ign Ignore file for actsync -samples/buffindexed.conf Buffindexed overview config file -samples/control.ctl Access control for control messages -samples/cycbuff.conf Sample cycbuff.conf file -samples/distrib.pats Default values for Distribution header -samples/expire.ctl Expiration config file -samples/filter.tcl Sample Tcl filter for innd -samples/filter_innd.pl Sample Perl filter for innd -samples/filter_innd.py Sample Python filter for innd -samples/filter_nnrpd.pl Sample Perl filter for nnrpd -samples/incoming.conf Permissions for incoming feeds -samples/inn.conf.in General INN configuration -samples/innfeed.conf Outgoing feed configuration -samples/innreport.conf.in Log summary configuration -samples/innwatch.ctl INN monitoring configuration -samples/moderators Moderation submission addresses -samples/motd.news Sample MOTD file -samples/news2mail.cf news2mail config file -samples/newsfeeds.in innd feed configuration -samples/newsgroups.minimal Minimal starting newsgroups file -samples/nnrpd.py Python hooks for nnrpd -samples/nnrpd.track Reader tracking configuration -samples/nnrpd_access.pl.in Sample nnrpd Perl access hooks -samples/nnrpd_access.py Sample nnrpd Python access hooks -samples/nnrpd_access_wrapper.pl.in Wrapper around old Perl access hooks -samples/nnrpd_access_wrapper.py Wrapper around old Python access hooks -samples/nnrpd_auth.pl.in Sample nnrpd Perl authorization hooks -samples/nnrpd_auth.py Sample nnrpd Python authorization hooks -samples/nnrpd_auth_wrapper.pl.in Wrapper around old Perl auth hooks -samples/nnrpd_auth_wrapper.py Wrapper around old Python auth hooks -samples/nnrpd_dynamic.py Sample nnrpd Python dynamic access hooks -samples/nnrpd_dynamic_wrapper.py Wrapper around old Python dynamic hooks -samples/nntpsend.ctl Outgoing nntpsend feed configuration -samples/ovdb.conf Berkeley DB overview configuration -samples/overview.fmt Format of news overview database -samples/passwd.nntp Passwords for remote connections -samples/radius.conf Sample config for RADIUS authentication -samples/readers.conf Reader connection configuration -samples/sasl.conf.in SASL configuration -samples/startup.tcl Tcl startup code for innd -samples/startup_innd.pl Perl startup code for innd -samples/storage.conf Sample storage configuration -samples/subscriptions Sample default subscriptions list -scripts Various utilities (Directory) -scripts/Makefile Makefile for script files -scripts/inncheck.in Syntax-check INN config files -scripts/innmail.in Perl front-end to sendmail -scripts/innreport.in Script to analyze INN logs -scripts/innreport_inn.pm Config file for innreport -scripts/innshellvars.in Config parameters for shell scripts -scripts/innshellvars.pl.in Config parameters for Perl scripts -scripts/innshellvars.tcl.in Config parameters for Tcl scripts -scripts/innstat.in Display INN status snapshot -scripts/innupgrade.in Upgrade INN configuration files -scripts/innwatch.in Throttle innd based on load and space -scripts/news.daily.in Front-end script to run expire, etc. -scripts/rc.news.in News boot script -scripts/scanlogs.in Summarize log files -scripts/simpleftp.in Rudimentary ftp client -scripts/tally.control.in Count newgroup/rmgroup messages -scripts/writelog.in Write a log entry or mail it -site Site-local files (Directory) -site/Makefile Makefile for site-local files -site/getsafe.sh Safely get config file from samples -storage Storage library (Directory) -storage/Make.methods Makefile for storage methods -storage/Makefile Makefile for storage library -storage/buffindexed buffindexed overview method (Directory) -storage/buffindexed/buffindexed.c buffindexed overview routines -storage/buffindexed/buffindexed.h Header file for buffindexed overview -storage/buffindexed/ovmethod.config buildconfig definition -storage/buffindexed/ovmethod.mk Make rules for buffindexed overview -storage/buildconfig.in Construct method interface -storage/cnfs CNFS storage method (Directory) -storage/cnfs/cnfs-private.h Private header file for CNFS -storage/cnfs/cnfs.c CNFS storage routines -storage/cnfs/cnfs.h Header file for CNFS -storage/cnfs/method.config buildconfig definition -storage/expire.c Overview-drive expire implementation -storage/interface.c Storage API glue implementation -storage/interface.h Storage API interface -storage/ov.c Overview API glue implementation -storage/ovdb ovdb overview method (Directory) -storage/ovdb/ovdb-private.h Private header file for ovdb -storage/ovdb/ovdb.c ovdb (Berkeley DB) overview method -storage/ovdb/ovdb.h Header for ovdb (Berkeley DB) overview -storage/ovdb/ovmethod.config buildconfig definition -storage/overdata.c Overview data manipulation -storage/ovinterface.h Overview API interface -storage/timecaf timecaf storage method (Directory) -storage/timecaf/README.CAF README the CAF file format -storage/timecaf/caf.c CAF file implementation -storage/timecaf/caf.h Header for CAF files -storage/timecaf/method.config buildconfig definition -storage/timecaf/timecaf.c timecaf storage routines -storage/timecaf/timecaf.h Header file for timecaf -storage/timehash timehash storage method (Directory) -storage/timehash/method.config buildconfig definition -storage/timehash/timehash.c timehash storage routines -storage/timehash/timehash.h Header for timehash -storage/tradindexed tradindexed overview method (Directory) -storage/tradindexed/ovmethod.config buildconfig definition -storage/tradindexed/ovmethod.mk Make rules for tradindexed overview -storage/tradindexed/tdx-cache.c Data file cache handling for tradindexed -storage/tradindexed/tdx-data.c Data file handling for tradindexed -storage/tradindexed/tdx-group.c Group index handling for tradindexed -storage/tradindexed/tdx-private.h Private header file for tradindexed -storage/tradindexed/tdx-structure.h On disk layout of tradindexed files -storage/tradindexed/tdx-util.c Utility program for tradindexed -storage/tradindexed/tradindexed.c Interface code for the overview API -storage/tradindexed/tradindexed.h Interface for tradindexed -storage/tradspool tradspool storage method (Directory) -storage/tradspool/README.tradspool Docs for tradspool storage method -storage/tradspool/method.config buildconfig definition -storage/tradspool/tradspool.c tradspool storage routines -storage/tradspool/tradspool.h Header for tradspool -storage/trash Trash storage method (Directory) -storage/trash/method.config buildconfig definition -storage/trash/trash.c Trash storage routines -storage/trash/trash.h Header file for trash storage -support Tools for building INN (Directory) -support/config.guess Determine system type for libtool -support/config.sub Canonicalize system type for libtool -support/fixscript.in Interpreter path fixup script -support/indent A mostly working wrapper around indent -support/install-sh Installation utility -support/ltmain.sh Source for libtool utility -support/makedepend Generate dependencies for C files -support/mkchangelog Generate ChangeLog from CVS -support/mkmanifest Generate a list of files for the manifest -support/mksnapshot Generate a snapshot of the tree -support/mksystem Generate from config.h -support/mkversion Generate with INN version -tests Test suite for INN (Directory) -tests/Makefile Makefile for test suite -tests/TESTS List of tests to run -tests/authprogs Test suite for auth programs (Directory) -tests/authprogs/ckpasswd.t Tests for authprogs/ckpasswd -tests/authprogs/domain.t Tests for authprogs/domain -tests/authprogs/passwd Password data for ckpasswd tests -tests/lib Test suite for libinn (Directory) -tests/lib/articles Testing news articles (Directory) -tests/lib/articles/no-body An article without a body -tests/lib/articles/strange An article with CR and LF in headers -tests/lib/articles/truncated An article truncated in the headers -tests/lib/buffer-t.c Tests for lib/buffer.c -tests/lib/concat-t.c Tests for lib/concat.c -tests/lib/config Testing config files (Directory) -tests/lib/config/errors Various config files with errors -tests/lib/config/line-endings A config file with varied line endings -tests/lib/config/no-newline A config file without an ending newline -tests/lib/config/null A config file containing a nul character -tests/lib/config/simple A simple config file -tests/lib/config/valid Various valid config parameters -tests/lib/config/warn-bool Invalid boolean parameters -tests/lib/config/warn-int Invalid integer parameters -tests/lib/config/warnings Various config files with warnings -tests/lib/confparse-t.c Tests for lib/confparse.c -tests/lib/date-t.c Tests for lib/date.c -tests/lib/fakewrite.c Helper functions for xwrite tests -tests/lib/hash-t.c Tests for lib/hash.c -tests/lib/hashtab-t.c Tests for lib/hashtab.c -tests/lib/hstrerror-t.c Tests for lib/hstrerror.c -tests/lib/inet_aton-t.c Tests for lib/inet_aton.c -tests/lib/inet_ntoa-t.c Tests for lib/inet_ntoa.c -tests/lib/innconf-t.c Tests for lib/innconf.c -tests/lib/list-t.c Tests for lib/list.c -tests/lib/md5-t.c Tests for lib/md5.c -tests/lib/memcmp-t.c Tests for lib/memcmp.c -tests/lib/messages-t.c Tests for lib/messages.c -tests/lib/mkstemp-t.c Tests for lib/mkstemp.c -tests/lib/pread-t.c Tests for lib/pread.c -tests/lib/pwrite-t.c Tests for lib/pwrite.c -tests/lib/qio-t.c Tests for lib/qio.c -tests/lib/setenv-t.c Tests for lib/setenv.c -tests/lib/setenv.t Wrapper for setenv tests -tests/lib/snprintf-t.c Tests for lib/snprintf.c -tests/lib/strerror-t.c Tests for lib/strerror.c -tests/lib/strlcat-t.c Tests for lib/strlcat.c -tests/lib/strlcpy-t.c Tests for lib/strlcpy.c -tests/lib/tst-t.c Tests for lib/tst.c -tests/lib/uwildmat-t.c Tests for lib/uwildmat.c -tests/lib/vector-t.c Tests for lib/vector.c -tests/lib/wire-t.c Tests for lib/wire.c -tests/lib/xmalloc.c Helper program for xmalloc tests -tests/lib/xmalloc.t Tests for lib/xmalloc.c -tests/lib/xwrite-t.c Tests for lib/xwrite.c -tests/libtest.c Helper library for writing tests -tests/libtest.h Interface to libtest -tests/overview Test suite for overview (Directory) -tests/overview/data Test overview data (Directory) -tests/overview/data/basic Basic set of overview test data -tests/overview/data/bogus Bad newsgroup name test data -tests/overview/data/high-numbered High-numbered article test data -tests/overview/data/reversed Same as basic, but in reverse order -tests/overview/munge-data Support script to generate test data -tests/overview/tradindexed-t.c Tests for storage/tradindexed/* -tests/runtests.c The test suite driver program -tests/util Test suite for utilities (Directory) -tests/util/convdate.t Tests for expire/convdate diff --git a/NEWS b/NEWS deleted file mode 100644 index 2ad3e94..0000000 --- a/NEWS +++ /dev/null @@ -1,860 +0,0 @@ -Changes in 2.4.5 - - * Fixed the "alarm signal" around "SSL_read" in nnrpd: it allows a - proper disconnection of news clients which were previously hanging - when posting an article through a SSL connection. Moreover, the - *clienttimeout* parameter now works on SSL connections. Thanks to - Matija Nalis for the patch. - - * SO_KEEPALIVE is now implemented for SSL TCP connections on systems - which support it, allowing system detection and closing the dead TCP - SSL connections automatically after system-specified time. Thanks to - Matija Nalis for the patch. - - * Fixed a segmentation fault when an article of a size greater than - remaining stack is retrieved via SSL. Thanks to Chris Caputo for this - patch. - - * Fixed a few segfaults and bugs which affected both Python innd and - nnrpd hooks. They no longer check the existence of methods not used - by the hooked script. An issue with Python exception handling was - also fixed, as well as a segfault fixed by Russ Allbery which happened - whenever one closes and then reopens Python in the same process. - Julien Elie also fixed a bug when reloading Python filters (they were - not always correctly reloaded) and a segfault when generating access - groups with embedded Python filters for nnrpd. Many thanks to David - Hlacik for its bug reports. - - * The nnrpd.py stub file in order to test Python nnrpd hooks, as - mentioned in their documentation, is now installed; only INN.py was - previously installed in *pathfilter*. Also fixed a bug in INN.py and - add missing methods to it. - - * Fixed a long-standing bug in innreport which prevented it from - correctly reporting nnrpd and innfeed log messages. - - * Fixed a hang in Perl hooks on (at least) HP/PA since Perl 5.10. - - * Fixed a compilation problem on some platforms because of AF_INET6 - which was not inside a HAVE_INET6 block in innfeed. - - * Fixed a bug in innfeed which contained thrice the same IPs for each - peer; it unnecessarily slowed the peer IP rotation for innfeed. - Thanks, D. Stussy, for having seen that. Miquel van Smoorenburg - provided the patch. - - * A new *heavily* improved version of pullnews is shipped with this INN - release. This new version is provided by Geraint Edwards. He added - no more than 16 flags, fixed some bugs and integrated the backupfeed - contrib script by Kai Henningsen, adding again 6 other flags. A - long-standing but very minor bug in the -g option was especially fixed - and items from the to-do list implemented. Many thanks again to - Geraint Edwards. - - * New headers are accessible through Perl and Python innd filtering - hooks. You will find the exact list in the INN Python Filtering and - Authentication Hooks documentation (doc/hook-python) and in Python - samples. Thanks to Matija Nalis for this addition of new useful - headers. - - * New samples for Python nnrpd hooks are shipped with INN: - nnrpd_access.py for access control and nnrpd_dynamic.py for dynamic - access control. The nnrpd_auth.py script is now only used for - authorization control. See the readers.conf man page for more - information (especially the *python_auth*, *python_access* and - *python_dynamic* parameters). The documention about INN Python - Filtering and Authentication Hooks has also been improved by Julien - Elie. - -Changes in 2.4.4 - - * Fixed incomplete checking of packet sizes in the ctlinnd interface in - the no-Unix-domain-sockets case. This is a potential buffer overflow - in dead code since basically all systems INN builds on support Unix - domain sockets these days. Also track the buffer size more correctly - in the client side of this interface for the Unix domain socket case. - - * Group blocks in incoming.conf are now correctly parsed and no longer - cause segfaults when loading this file. - - * Fixed a problem with innfeed continuously segfaulting on amd64 - hardware (and possibly on lots of 64-bit platforms). Many thanks to - Ollivier Robert for his patch and also to Kai Gallasch for having - reported the problem and provided the FreeBSD server to debug it. - - * scanlogs now rotates innfeed's log file, which prevents innfeed from - silently dying when its log file reaches 2 GB. - - * Perl 5.10 support has been added to INN thanks to Jakub Bogusz. - - * Some news clients hang when posting an article through a SSL - connection: it seems that nnrpd's SSL routines make it wrongly wait - for data completion. In order to fix the problem, the select() wait - is now just bypassed. However, the IDLE timer stat is currently not - collected for such connections. Thanks to Kachun Lee for this - workaround. - - * Fixed a bug in the display of the used compressor ("cunbatch" was used - if arguments were passed to gzip or bzip2). - - * Fixed a bug in mailpost and pullnews which prevented useful error - messages to be seen. Also add the -x flag to pullnews in order to - insert Xref: headers in articles which lack one. - - * If compiling with Berkeley DB, use its ndbm compatibility layer for - ckpasswd in preference to searching for a traditional dbm library. - INN also supports Berkeley DB 4.4, 4.5 and 4.6 thanks to Marco d'Itri. - - * ovdb_init now properly closes stdin/out/err when it becomes a daemon. - The issue was reported by Viktor Pilpenok and fixed by Marco d'Itri. - - * Added support for Diablo quickhash and hashfeed algorithms. It allows - to distribute the messages among several peers (new Q flag for - newsfeeds). Thanks to Miquel van Smoorenburg for this implementation - in INN. - - * innd now listen on separate sockets for IPv4 and IPv6 connections if - the IPV6_V6ONLY socket option is available. There might also be - operating systems that still have separate IPv4 and IPv6 TCP - implementations, and advanced features like TCP SACK might not be - available on v6 sockets. Thanks to Miquel van Smoorenburg for this - patch. - - * The two configuration options *bindaddress* and *bindaddress6* can now - be set on a per-peer basis for innfeed. Setting *bindaddress6* to - "none" tells innfeed to never attempt an IPv6 connection to that host. - Thanks to Miquel van Smoorenburg for this patch. - - * Added a *nnrpdflags* parameter to inn.conf (modeled on the concept of - *innflags*) to permit passing of command line arguments to instances - of nnrpd spawned from innd. - - * A new inn.conf parameter called *pathcluster* has been added: it - allows to append a common name to the Path: header on all incoming - articles. *pathhost* and *pathalias* (if set) are still appended to - the path as usual, but *pathcluster* is always appended as the last - element (e.g. on the leftmost side of the Path: header). Thanks to - Miquel van Smoorenburg for this feature. - - * simpleftp has been rewritten to use "Net::FTP". Indeed, ftp.pl is no - longer shipped with Perl 5 and the script did not work. - - * perl-nocem will now check for a timeout and re-open the socket if - required. Additionally, perl-nocem will switch to cancel_ctlinnd in - case cancel_nntp fails after sending the Message-ID. Thanks to - Christoph Biedl for the patch. A more detailed documentation has also - been written for perl-nocem(8). - - * The RADIUS configuration is now wrapped in a "server {}" block in - radius.conf. - - * Checkgroups when there is nothing to change no longer result in - sending a blank mail to administrators. Besides, no mail is sent by - controlchan for the creation of a newsgroup when the action is "no - change". - - * Checkgroups are now properly propagated even though the news server - does not carry the groups they are posted to. - - * controlchan and docheckgroups now handle wire format messages so that - articles from the spool can be directly fed to them. - - * Newgroup control messages for existing groups now change their - description. If a mail is sent to administrators, it reminds them to - update their newsgroups file. It also warns when there are missing or - obsolete descriptions. Furthermore, the newsgroups file is now - written prettier (from one to three tabulations between the name of - the group and its short description) and to.* groups cannot be - created. - - * The sample control.ctl file has been extensively updated. - - * Fixed empty LISTGROUP replies which were not terminated. Thanks to - David Canzi for the patch. - - * In response to a LIST [file] command, if the file does not exist, we - assume it is not maintained and return 503 instead of 215 and an empty - file. Moreover, capability to LIST ACTIVE.TIMES for a wildmat pattern - as its third argument has been added in order to select wanted - newsgroups. - - * inews now tries to authenticate if it does not receive a 200 return - code after MODE READER. Indeed, it might be able to post even with a - 201 return code and also with another codes like 440 or 480. - - * If creating a new history file, set the ownership and mode - appropriately. inncheck also expects fewer things to be private to - the news user. Most of the configuration files will never contain - private information like passwords. - - * Other minor bug fixes and documentation improvements. - -Changes in 2.4.3 - - * Previous versions of INN had an optimization for handling XHDR - Newsgroups that used the Xref: header from overview. While this does - make the command much faster, it doesn't produce accurate results and - breaks the NNTP protocol, so this optimization has been removed. - - * Fixed a bug in innd that allowed it to accept articles with duplicated - headers if the header occurred an odd number of times. Modified the - programs for rebuilding overview to use the last Xref: header if there - are multiple ones to avoid problems with spools that contain such - invalid articles. - - * Fixed yet another problem with verifying that a user has permissions - to approve posts to a moderated group. Thanks, Jens Schlegel. - - * Increase the send and receive buffer on the Unix domain socket used by - ctlinnd. This should allow longer replies (particularly for innstat) - on platforms with very low default Unix domain socket buffer sizes. - - * rnews's handling of articles with nul characters, NNTP errors, header - problems, and deferrals has been significantly improved. - - * Thomas Parmelan added support to send-uucp for specifying the funnel - or exploder site to flush for feeds managed through one and fixed a - problem with picking up old stranded work files. - - * Many other more minor bug fixes, optimization improvements, and - documentation fixes. - -Changes in 2.4.2 - - * INN is now licensed under a less restrictive license (about as - minimally restrictive as possible shy of public domain), and the - clause similar to the old BSD advertising clause has been dropped. - - * "make install" and "make update" now always install the newly built - binaries, rather than only installing them if the modification times - are newer. This is the behavior that people expect. "make install" - now also automatically builds a new (empty) history database if one - doesn't already exist. - - * The embedded Tcl filter code has been disabled (and will be removed - entirely in the next major release of INN). It hasn't worked for some - time and causes innd crashes if compiled in (even if not used). If - someone wants to step forward and maintain it, I recommend starting - from scratch and emulating the Perl and Python filters. - - * ctlinnd should now successfully handle messages from INN up to the - maximum allowable packet size in the protocol, fixing problems sites - with many active peers were having with innstat output. - - * Overview generation has been fixed in both makehistory and innd to - follow the rules in the latest NNTP draft rather than just replacing - special characters with spaces. This means that the unfolding of - folded header lines will not introduce additional, incorrect - whitespace in the overview data. - - * nnrpd now uniformly responds with a 480 or 502 status code to attempts - to read a newsgroup to which the user does not have access, depending - on whether the user has authenticated. Previously, it returned a 411 - status code, claiming the group didn't exist, which confuses the - reactive authentication capability of news readers. - - * If a user is not authorized to approve articles (using the "A" - *access* control in readers.conf), articles that include Approved: - headers will be rejected even if posted to unmoderated groups. Some - other site may consider that group to be moderated. - - * The configuration parser used for readers.conf and others now - correctly handles "#" inside quoted strings and is more robust against - unmatched double quotes. - - * Messages mailed to moderators had two spaces after the colons in the - headers, rather than one. This bug has been fixed. - - * A bug that could cause heap corruption and random crashes in innd if - INN were compiled with Python support has been fixed. - - * Some problems with innd's tracking of article size and enforcement of - the configured maximum article size have been fixed. - - * pgpverify will now correctly verify signatures generated by GnuPG and - better supports GnuPG as the PGP implementation. - - * INN's code should now be more 64-bit clean in its handling of size_t, - pointer differences, and casting of pointers, correcting problems that - showed up on 64-bit platforms like AMD64. - - * Improved the error reporting in the history database code, in inews, - in controlchan, and in expire. - - * Many other, more minor bugs have also been fixed. - -Changes in 2.4.1 - - * SECURITY: Handle the special filing of control messages into per-type - newsgroups more robustly. This closes a potentially exploitable - buffer overflow. Thanks to Dan Riley for his excellent bug report. - - * Fixed article handling in innd so that articles without a Path: header - (arising from peers sending malformatted articles or injecting - malformatted articles through rnews) would not cause innd to crash. - (This was not exploitable.) - - * Fixed a serious bug in XPAT handling, thanks to Tommy van Leeuwen. - - * "configure" now looks for sendmail only in /usr/sbin and /usr/lib, not - on the user's path. This should reduce the need for --with-sendmail - if your preferred sendmail is in a standard location. - - * The robustness of the tradindexed overview method has been further - increased, handling more edge cases arising from corrupted databases - and oddly-named newsgroups. - - * innd now never decreases the high water mark of a newsgroup when - renumbering, which should help ameliorate overview and active file - synchronization problems. - - * Do not close and reopen the history file on ctlinnd reload when the - server is paused or throttled. This was breaking ctlinnd reload all - during a server pause. - - * Various minor portability and compilation issues fixed. Substantial - numbers of compiler warnings have been cleaned up, thanks largely to - work by Ilya Kovalenko. - - * Multiple other more minor bugs have been fixed. - - * Documentation and man pages have been clarified and updated. - -Upgrading from 2.3 to 2.4 - - The inn.conf parser has changed between INN 2.3 and 2.4. Due to that - change, options in inn.conf that contain whitespace or a few other - special characters must be quoted with double quotes, and empty - parameters (parameters with no value) are not allowed. INN 2.4 comes - with a script, innupgrade, run automatically during "make update", that - will attempt to fix any problems that it finds with your inn.conf file, - saving the original as inn.conf.OLD. - - This change is the beginning of standardization of parsing and syntax - across all of INN's configuration files. - - The history subsystem now has a standard API that allows other backends - to be used. Because of this, you now need to specify the history method - in inn.conf. Adding: - - hismethod: hisv6 - - will tell INN to use the same history backend as was used in previous - versions. innupgrade should take care of this for you. - - ovdb is known to have some locking and timing issues related to how - nnrpd shuts down (or fails to shut down) the overview databases. If you - have stability problems with ovdb, try setting *readserver* to "true" in - ovdb.conf. This will funnel all ovdb reads through a single process - with a cleaner interface to the underlying Berkeley DB database. - - If you use Perl authentication for nnrpd (if *nnrpdperlauth* in inn.conf - is "true"), there have been major changes. See "Changes to Perl - Authentication Support for nnrpd" in doc/hook-perl for details. - - Similarly, if you use Python authentication for nnrpd (if - *nnrpdpythonauth* in inn.conf is "true"), there have been major changes. - See "Changes to Python Authentication and Access Control Support for - nnrpd" in doc/hook-python for details. - - If you use send-uucp, it has been completely rewritten and now takes a - configuration file to specify its behavior. See its man page for more - information. If you use sendbatch, it is no longer included in INN - since the new send-uucp can handle all of the same functionality. - - The wildmat API has been renamed (to uwildmat and friends; see - uwildmat(3) for the interfaces) to distinguish it from Rich $alz's - original version, since it now supports UTF-8. This may require changes - in other software packages that link against INN's libraries. - - If you are upgrading from a version prior to INN 2.3, see "Upgrading - from 2.2 to 2.3". - -Changes in 2.4.0 - - * IPv6 support has been added, disabled by default. If you have IPv6 - connectivity, build with --enable-ipv6 to try it. There are no known - bugs, but please report any problems you find (or even successes, if - you use an unusual platform). There are a few changes of interest; - further information is available in doc/IPv6-info. - - * The tradindexed overview method has been completely rewritten and - should be considerably more robust in the face of system crashes. A - new utility, tdx-util, is provided to examine the contents of the - overview database, repair inconsistencies, and rebuild the overview - for particular groups from a tradspool news spool. See tdx-util(8) - for more details. - - * The Perl and Python authentication hooks for readers have been - extensively overhauled and integrated better with readers.conf. See - the Changes sections in doc/hook-perl and doc/hook-python for more - details. - - * nnrpd now optionally supports article injection via IHAVE, see - readers.conf(5). Any articles injected this way must have Date, From, - Message-ID, Newsgroups, Path, and Subject headers. X-Trace and - X-Complaints-To headers will be added if the appropriate options are - set in readers.conf, but other headers will not be modified/inserted - (e.g. NNTP-Posting-Host, NNTP-Posting-Date, Organization, Lines, Cc, - Bcc, and To headers). - - * nnrpd now handles arbitrarily long lines in POST and IHAVE; - administrators who want to limit the length of lines in locally posted - articles will need to add this to their local filters instead. - - * nnrpd no longer handles the poorly-specified RFC 977 optional fourth - argument to the NEWGROUPS command specifying the "distributions" that - the command was supposed to apply to. - - Clients that use that argument will break. There are not believed to - be any such clients, and it's easy enough to just filter the returned - list of newsgroups (which is generally fairly short) to achieve the - same results. - - * nnrpd no longer accepts UTC as a synonym for GMT for NEWGROUPS or - NEWNEWS. This usage was never portable, and was rejected by the NNTP - working group. It is being removed now in the hope that it will be - caught before anyone starts to rely on it. - - * innfeed supports a new peer parameter, *backlog-feed-first*, that if - set to "true" feeds any backlog to a peer before new articles, see - innfeed.conf(5). When used in combination with *max-connections* set - to 1, this can be used to enforce in-order delivery of messages to a - peer that is doing Xref slaving, avoiding cases where a - higher-numbered message is received before a lower-numbered message in - the same group. - - * Several other, more minor protocol issues have been fixed: - connections rejected due to the connection rate limiting in innd - receive 400 replies instead of 504 or 505, and ARTICLE without an - argument will always either retrieve the current article or return a - 423 error, never advance the current article number to the next valid - article. - - See doc/compliance-nntp for all of the known issues with INN's - compliance with the current NNTP draft. - - * All accesses to the history file for all parts of INN now go through a - generic API like the storage and overview subsystems do. This will - eventually allow new history implementations to be dropped in without - affecting the rest of INN, and will significantly improve the - encapsulation of the history subsystem. See the libinnhist(3) man - page for the details of the interface. - - * INN now uses a new parser for the inn.conf file. This means that - parameters containing whitespace or other special characters must now - be quoted; see inn.conf(5). It fixes the long-standing bug that - certain values must be included in inn.conf even if using the defaults - for the use of shell or Perl scripts, and it will serve as the basis - for standardizing and cleaning up the configuration file parsing in - other parts of INN. innupgrade is run during "make update" and should - convert an existing inn.conf file for you. - - * send-uucp has been replaced by a completely rewritten version from - Marco d'Itri, Edvard Tuinder, and Miquel van Smoorenburg, which uses a - configuration file that specifies batch sizes, compression methods, - and hours during which batches should be generated. The old sendbatch - script has been retired, since send-uucp can now handle everything - that it did. - - * Two "configure" options have changed names: --with-tmp-path is now - --with-tmp-dir, and --with-largefiles is now --enable-largefiles, to - improve consistency and better match the "autoconf" option guidelines. - - * Variables can now be used in the newsfeeds file to make it easier to - specify many similar feeds or feed patterns. See the newsfeeds(5) man - page for details. - - * Local connections to INN support a new special mode, MODE CANCEL, that - allows efficient batch cancellation of messages. This is intended to - be the preferred interface for external spam and abuse filters like - NoCeM. See "CANCEL FEEDS" in innd(8) for details. - - * Two new options, *nfsreader* and *nfswriter*, have been added to - inn.conf to aid in building NFS based shared reader/writer platforms. - On the writer server configure *nfswriter* to "true" and on all of the - readers configure *nfsreader* to "true"; these options add calls to - force data out to the NFS server and force it to be read directly from - the NFS server at the appropriate moments. Note that it has only been - tested on Solaris 8, using CNFS as the storage mechanism and - tradindexed as the overview method. - - * A new option, *tradindexedmmap*, has been added to inn.conf. If set - to "true" (the default), then the tradindexed overview method will use - mmap() to access its overview data (in 2.3 you couldn't control this; - it always used mmap). - - * Thanks to code contributed by CMU, innfeed can now feed an IMAP server - as well as other NNTP servers. See the man page for innfeed(8) for - more information. - - * An authenticator, auth_smb, that checks a username and password - against a remote Samba server is now included. See auth_smb(8) for - details. - - * The wildmat functions in INN now support UTF-8, in a way that should - allow them to still work with most simple 8-bit character sets in - widespread use. As part of this change, some additional wildmat - interfaces are now available and the names have changed (to uwildmat, - where "u" is for Unicode). See uwildmat(3) for the details. - - * The interface between external authenticators and nnrpd is now - properly documented, in doc/external-auth. A library implementing - this interface in C is provided, which should make it easier to write - additional authenticators resolvers. See libauth(3) for details, and - any of the existing programs in authprogs/ for examples. - - * Most (if not all) of the temporary file creation in INN now uses - functions that create temporary files properly and safely. - -Changes in 2.3.5 - - * Clients using POST are no longer permitted to provide an - Injector-Info: header. - - * Fixed a bug causing posts with Followup-To: set to a moderated group - to be rejected if the posting user didn't have permission to approve - postings. - - * Fixed bugs in inncheck with setuid rnews or setgid inews, in - *innconfval* with inn.conf parameters containing shell metacharacters - but no spaces, and in parsedate.y with some versions of yacc. Fixed a - variety of size-related printf format warnings (e.g., %d vs. %ld) - thanks to the work of Winfried Szukalski. - -Changes in 2.3.4 - - * LIST ACTIVE no longer returns data when given a single group argument - if the client is not authorized to read that group. - - * XHDR and XPAT weren't correctly parsing article headers, resulting in - searches for the header "newsgroup" matching the header "newsgroups". - - * Made CNFS more robust against crashes by actually syncing the cycbuff - headers to disk as was originally intended. Fixed a memory leak in - the tradspool code. - - * Two bugs in pgpverify when using GnuPG were fixed: it now correctly - checks for gpgv (rather than pgp) when told to use GnuPG and expects - the keyring to be pubring.gpg (not pubring.pgp). - - * Substantial updates to the sample provided control.ctl file. - - * Compilation fixes with Perl 5.8.0, Berkeley DB 4.x, current versions - of Linux (including with large file support), and Tru64. inndf fixes - for ReiserFS. - - * Various bugs in the header handling in nnrpd have been fixed, - including hangs when using virtual domains and improper processing of - folded headers under certain circumstances. - - * Other minor bug fixes and documentation improvements. - -Changes in 2.3.3 - - * pgpverify now supports using GnuPG to check signatures (rather than - PGP) without the pgpgpg wrapper. GnuPG can check both old-style RSA - signatures and new OpenPGP signatures and is recommended over PGP 2.6. - If you have GnuPG installed, pgpverify will use it rather than PGP, - which means that you may have to create a new key ring for GnuPG to - use to verify signatures if you were previously using PGP. - - * Users can no longer post articles containing Approved: headers to - moderated groups by default; they must be specifically given that - permission with the *access* parameter in readers.conf. See the man - page for more details. - - * Two bugs in repacking overview index files and a reliability bug with - writing overview data were all fixed in the tradindexed overview - method, hopefully making it somewhat more reliable, particularly for - makehistory. - - * If rc.news.local exists in the INN binary directory, it will be run - with the start or stop argument whenever rc.news is run. This is - available as a hook for local startup and shutdown code. - - * The default history table hash sizes were increased because a - too-small value can cause serious performance problems (whereas a - too-large hash just wastes a bit of disk space). - - * The sample control.ctl file has been extensively updated. - - * Wildmat exclusions ("@" and "!") should now work properly in - storage.conf newsgroup patterns. - - * The implementation of the -w flag for expireover was fixed; - previously, the value given to -w to change expireover's notion of the - current time was scaled by too much. - - * Various other more minor bug fixes, standards compliance fixes, and - documentation improvements. - -Changes in 2.3.2 - - * innxmit can again handle regular filenames as input as well as storage - API tokens (allowing it to be used to import an old traditional - spool). - - * Several problems with tagged-hash history files have been fixed thanks - to the debugging efforts of Andrew Gierth and Sang-yong Suh. - - * A very long-standing (since INN 1.0!) NNTP protocol bug in nnrpd was - fixed. The response to an ARTICLE command retrieving a message by - Message-ID should have the Message-ID as the third word of the - response, not the fourth. Fixing this is reported to *possibly* cause - problems with some Netscape browsers, but other news servers correctly - follow the protocol. - - * Some serious performance problems with expiration of tradspool should - now be at least somewhat alleviated. tradspool and timehash now know - how to output file names for removal rather than tokens, and fastrm's - ability to remove regular files has been restored. This should bring - expiration times for tradspool back to within a factor of two of - pre-storage-API expiration times. - - * Added a sample subscriptions file and documentation for it and - innmail. - -Changes in 2.3.1 - - * inews no longer downloads the active file, no longer tries to send - postings to moderated groups to the moderator directly, and in general - duplicates less of the functionality of nnrpd, instead letting nnrpd - handle it. This fixes the problem of inews not working properly for - users other than news without being setgid. - - * Added a man page for ckpasswd. - - * A serious bug in the embedded Perl authentication hooks was fixed, - thanks to Jan Rychter. - - * The annoying compilation problem with embedded Perl filtering on Linux - systems without libgdbm installed should be fixed. - - * INN now complains loudly at "configure" time if the configured path - for temporary files is world-writeable, since this configuration can - be a security hole. - - * Many other varied bug fixes and documentation fixes of all sorts. - -Upgrading from 2.2 to 2.3 - - There may be additional things to watch out for not listed here; if you - run across any, please let know about them. - - Simply doing a "make update" is not sufficient to upgrade; the history - and overview information will also have to be regenerated, since the - formats of both files have changed between 2.2 and 2.3. Regardless of - whether you were using the storage API or traditional spool under 2.2, - you'll need to rebuild your overview and history files. You will also - need to add a storage.conf file, if you weren't using the storage API - under INN 2.2. A good default storage.conf file for 2.2 users would be: - - method tradspool { - newsgroups: * - class: 0 - } - - Create this storage.conf file before rebuilding history or overview. - - If you want to allow readers, or if you want to expire based on - newsgroup name, you need to tell INN to generate overview data and pick - an overview method by setting *ovmethod* in inn.conf. See INSTALL and - inn.conf(5) for more details. - - The code that generates the dbz index files has been split into a - separate program, makedbz. makehistory still generates the base history - file and the overview information, but some of its options have been - changed. To rebuild the history and overview files, use something like: - - makehistory -b -f history.n -O -T /usr/local/news/tmp -l 600000 - - (change the /usr/local/news/tmp path to some directory that has plenty - of temporary space, and leave off -O if you're running a transit-only - server and don't intend to expire based on group name, and therefore - don't need overview.) Or if your overview is buffindexed, use: - - makehistory -b -f history.n -O -F - - Both will generate a new history file as history.n and rebuild overview - at the same time. If you want to preseve a record of expired - Message-IDs in the history file, run: - - awk 'NF==2 { print; }' < history >> history.n - - to append them to the new history file you created above. Look over the - new history file and make sure it looks right, then generate the new - index files and move them into place: - - makedbz -s `wc -l < history.n` -f history.n - mv history.n history - mv history.n.dir history.dir - mv history.n.hash history.hash - mv history.n.index history.index - - (Rather than .hash and .index files, you may have a .pag file if you're - using tagged hash.) - - For reader machines, nnrp.access has been replaced by readers.conf. - There currently isn't a program to convert between the old format and - the new format (if you'd like to contribute one, it would be welcomed - gratefully). The new file is unfortunately considerably more complex as - a result of its new capabilities; please carefully read the example - readers.conf provided and the man page when setting up your initial - configuration. The provided commented-out examples cover the most - common installation (IP-based authentication for all machines on the - local network). - - INN makes extensive use of mmap(2) for the new overview mechanisms, so - at the present time NFS-mounting the spool and overview on multiple - reader machines from one central server probably isn't feasible in this - version. mmap tends to interact poorly with NFS (at the least, NFS - clients won't see updates to the mapped files in situations where they - should). (The preferred way to fix this would, rather than backing out - the use of mmap or making it optional, to add support for Diablo-style - header feeds and pull-on-demand of articles from a master server.) - - The flags for overchan have changed, plus you probably don't want to run - overchan at all any more. Letting innd write overview data itself - results in somewhat slower performance, but is more reliable and has a - better failure mode under high loads. Writing overview data directly is - the default, so in a normal upgrade from 2.2 to 2.3 you'll want to - comment out or remove your overchan entry in newsfeeds and set - *useoverchan* to "false" in inn.conf. - - crosspost is no longer installed, and no longer works (even with - traditional spool). If you have an entry for crosspost in newsfeeds, - remove it. - - If you're importing a traditional spool from a pre-storage API INN - server, it's strongly recommended that you use NNTP to feed the articles - to your new server rather than trying to build overview and history - directly from the old spool. It's more reliable and ensures that - everything gets put into the right place. The easiest way to do this is - to generate, on your old server, a list of all of your existing article - files and then feed that list to innxmit. Further details can be found - in the FAQ at . - - If you are using a version of Cleanfeed that still has a line in it - like: - - $lines = $hdr{'__BODY__'} =~ tr/\n/\n/; - - you will need to change this line to: - - $lines = $hdr{'__LINES__'}; - - to work with INN 2.3 or later. This is due to an internal optimization - of the interface to embedded filters that's new in INN 2.3. - -Changes in 2.3.0 - - * New readers.conf file (replaces nnrp.access) which allows more - flexible specification of access restrictions. Included in the sample - implementations is a RADIUS-based authenticator. - - * Unified overview has been replaced with an overview API, and there are - now three separate overview implementations to choose from. One - (tradindexed) is very like traditional overview but uses an additional - index file. The second (buffindexed) uses large buffers rather than - separate files for each group and can handle a higher incoming article - rate while still being fast for readers. The third (ovdb) uses - Berkeley DB to store overview information (so you need to have - Berkeley DB installed to use it). The *ovmethod* key in inn.conf - chooses the overview method to use. - - Note that ovdb has not been as widely tested as the other overview - mechanisms and should be considered experimental. - - * All article storage and retrieval is now done via the storage API. - Traditional spool is now available as a storage type under the storage - API. (Note that the current traditional spool implementation causes - nightly expire to be extremely slow for a large number of articles, so - it's not recommended that you use the tradspool storage method for the - majority of a large spool.) - - * The timecaf storage method has been added, similar to timehash but - storing multiple articles in a single file. See INSTALL for details - on it. - - * INN now supports embedded Python filters as well as Perl and Tcl - filters, and supports Python authentication hooks. - - * There is preliminary support for news reading over SSL, using OpenSSL. - - * To simplify anti-abuse filtering, and to be more compliant with news - standards and proposed standards, INN now treats as control messages - only articles containing a Control: header. A Subject: line beginning - with "cmsg " is no longer sufficient for a message to be considered a - control message, and the Also-Control: header is no longer supported. - - * The INN build system no longer uses subst. (This will be transparent - to most users; it's an improvement and modernization of how INN is - configured.) - - * The build and installation system has been substantially overhauled. - "make update" now updates scripts as well as binaries and - documentation, there is better support for parallel builds ("make - -j"), there is less "make" recursion, and far more of the - system-dependent configuration is handled directly by "autoconf". - libtool build support (including shared library support) should be - better than previous releases. - -Changes in 2.2.3 - - * inews is not installed setgid news and rnews is not installed setuid - root by default any more. If you need the old permissions, you have - to give a flag to configure. See INSTALL for more details. - - * Fixed a security hole when *verifycancels* was enabled in inn.conf - (not the default). - - * Message-IDs are now limited to 250 octets to prevent interoperability - problems with other servers. - - * Embedded Perl filters now work with Perl 5.6.0. - - * Lots of bug fixes and changes for security paranoia. - -Changes in 2.2.2 - - * Various minor bug fixes and a Y2K bug fix. The Y2K bug is in version - version 2.2.1 only and will show up after Jan 1st, 2000 when a news - reader issues a NEWNEWS command for a date prior to the year 2000. - -Changes in 2.2.1 - - * Various bug fixes, mostly notably fixes for potential buffer overflow - security vulnerabilities. - -Changes in 2.2.0 - - * New storage.conf file (replaces storage.ctl). - - * New (optional) way of handling non-cancel control messages - (controlchan) that serializes them and prevents server overload from - control message storms. - - * Support for actsyncd to fetch active file with ftp; configured by - default to use if you - run actsyncd. Be sure to read the manual page for actsync to - configure an actsync.ign file for your site, and test simpleftp if you - do not "configure" with wget or ncftp. Also see - . - - * Some options to "configure" are now moved to inn.conf - (*merge-to-groups* and *pgp-verify*, without the hyphen). - - * inndf, a portable version of df(1), is supplied. - - * New cnfsstat program to show stats of CNFS buffers. - - * news2mail and mailpost programs for gatewaying news to mail and mail - to news are supplied. - - * pullnews program for doing a sucking feed is provided (not meant for - large feeds). - - * The innshellvars.csh.in script is obsolete (and lives in the obsolete - directory, for now). - diff --git a/README b/README deleted file mode 100644 index 722abc5..0000000 --- a/README +++ /dev/null @@ -1,288 +0,0 @@ -Welcome to INN 2.4! - - This work is sponsored by Internet Systems Consortium. - - Please see INSTALL for installation instructions, NEWS for what's - changed from the previous release, and LICENSE for the copyright, - license, and distribution terms. - -What is INN? - - INN (InterNetNews), originally written by Rich Salz, is an extremely - flexible and configurable Usenet / netnews news server. For a complete - description of the protocols behind Usenet and netnews, see RFC 1036 and - RFC 977 (or their replacements). In brief, netnews is a set of - protocols for exchanging messages between a decentralized network of - news servers. News articles are organized into newsgroups, which are - themselves organized into hierarchies. Each individual news server - stores locally all articles it has received for a given newsgroup, - making access to stored articles extremely fast. Netnews does not - require any central server; instead, each news server passes along - articles it receives to all of the news servers it peers with, those - servers pass the articles along to their peers, and so on, resulting in - "flood fill" propagation of news articles. - - A news server performs three basic functions: it accepts articles from - other servers and stores them on disk, sends articles it has received - out to other servers, and offers stored news articles to readers on - demand. It additionally has to perform some periodic maintenance tasks, - such as deleting older articles to make room for new ones. - - Originally, a news server would just store all of the news articles it - had received in a file system. Users could then read news by reading - the article files on disk (or more commonly using news reading software - that did this efficiently). These days, news servers are almost always - stand-alone systems and news reading is supported via network - connections. A user who wants to read a newsgroup opens that newsgroup - in their newsreader software, which opens a network connection to the - news server and sends requests for articles and related information. - The protocol that a newsreader uses to talk to a news server and that a - news server uses to talk to another news server over TCP/IP is called - NNTP (Network News Transport Protocol). - - INN supports accepting articles via either NNTP connections or via UUCP. - innd, the heart of INN, handles NNTP feeding connections directly; UUCP - newsfeeds use rnews (included in INN) to hand articles off to innd. - Other parts of INN handle feeding articles out to other news servers, - most commonly innfeed (for real-time outgoing feeds) or nntpsend and - innxmit (used to send batches of news created by innd to a remote site - via TCP/IP). INN can also handle outgoing UUCP feeds. - - The part of INN that handles connections from newsreaders is nnrpd. - - Also included in INN are a wide variety of supporting programs to handle - periodic maintenance and recovery from crashes, process special control - messages, maintain the list of active newsgroups, and generate and - record a staggering variety of statistics and summary information on the - usage and performance of the server. - - INN also supports an extremely powerful filtering system that allows the - server administrator to reject unwanted articles (such as spam and other - abuses of Usenet). - - INN is free software, supported by Internet Systems Consortium and - volunteers around the world. See "Supporting the INN Effort" below. - -Prerequisites - - Compiling INN requires an ANSI C compiler (gcc is recommended). INN was - originally written in K&R C, but supporting pre-ANSI compilers has - become enough of a headache that a lot of the newer parts of INN will no - longer compile with a non-ANSI compiler. gcc itself will compile with - most vendor non-ANSI compilers, however, so if you're stuck with one, - installing gcc is highly recommended. Not only will it let you build - INN, it will make installing lots of other software much easier. You - may also need GNU make (particularly if your system make is - BSD-derived), although most SysV make programs should work fine. - Compiling INN also currently requires a yacc implementation (bison will - do fine). - - INN uses GNU autoconf to probe the capabilities of your system, and - therefore should compile on nearly any Unix system. It does, however, - make extensive use of mmap(), which can cause problems on some older - operating systems. See INSTALL for a list of systems it is known to - work on. If you encounter problems compiling or running INN, or if you - successfully run INN on a platform that isn't listed in INSTALL, please - let us know (see "Reporting Bugs" below). - - Perl 5.003 or later is required to build INN. Perl 5.004 is required if - you want the embedded Perl filter support (which is highly recommended; - some excellent spam filters have been written for INN). Since all - versions of Perl previous to 5.004 are buggy (including security - problems) and have fewer features, installing Perl 5.004 or later is - recommended. - - If you want to enable PGP verification of control messages (highly - recommended), you will need to have a PGP implementation installed. See - INSTALL for more details. - -Getting Started - - A news server can be a fairly complicated piece of software to set up - just because of the wide variety of pieces that have to be configured - (who is authorized to read from the server, what newsgroups it carries, - and how the articles are stored on disk at a bare minimum, and if the - server isn't completely stand-alone -- and very few servers are -- both - incoming and outgoing feeds have to be set up and tested). Be prepared - to take some time to understand what's going on and how all the pieces - fit together. If you have any specific suggestions for documentation, - or comments about things that are unclear, please send them to the INN - maintainers (see "Reporting Bugs" below). - - See INSTALL for step-by-step instructions for setting up and configuring - a news server. - - INN also comes with a very complete set of man pages; there is a man - page for every configuration file and program that comes with INN. (If - you find one that doesn't have a man page, that's a bug. Please do - report it.) When trying to figure out some specific problem, reading - the man pages for all of the configuration files involved is a very good - start. - -Reporting Bugs - - We're interested in all bug reports. Not just on the programs, but on - the documentation too. Please send *all* such reports to - - inn-bugs@isc.org - - (patches are certainly welcome, see below). Even if you post to Usenet, - please CC the above address. All other INN mail should go to - - inn@isc.org - - (please do *not* send bug reports to this address). - - If you have general "how do I do this" questions or problems configuring - your server that you don't believe are due to a bug in INN, you should - post them to news.software.nntp. A lot of experienced INN users, - including several of the INN maintainers, read that newsgroup regularly. - Please don't send general questions to the above addresses; those - addresses are specifically for INN, and the INN maintainers usually - won't have time to answer general questions. - -Contributing Code - - If you have a patch or a utility that you'd like to be considered for - inclusion into INN, please mail it to - - inn-patches@isc.org - - in the body of the message (not as an attachment), or put it on a - webpage and send a link. Patches included with a bug report as - described above should follow the same procedure, but need not be sent - to both addresses (either will do). - - Have fun! - -Mailing Lists - - There are various INN-related mailing lists you can join or send - messages to if you like. Some of them you must be a member of before - you can send mail to them (thank the spammers for that policy), and one - of them is read-only (no postings allowed). - - inn-announce@isc.org Where announcements about INN are set (only - maintainers may post). - - inn-workers@isc.org Discussion of INN development (postings by - members only). - - inn-patches@isc.org Where to send patches for consideration for - inclusion into INN (open posting). - - inn-committers@isc.org CVS commit messages for INN are sent to this - list (only the automated messages are sent here, - no regular posting). - - inn-bugs@isc.org Where to send bug reports (open posting). If - you're an INN expert and have the time to help - out other users, we encourage you to join this - mailing list to answer questions. (You may also - want to read the newsgroup news.software.nntp, - which gets a lot of INN-related questions.) - - To join these lists, send a subscription request to the "-request" - address. The addresses for the above lists are: - - inn-announce-request@isc.org - inn-workers-request@isc.org - inn-patches-request@isc.org - inn-committers-request@isc.org - inn-bugs-request@isc.org - -Who's Responsible / Who to Thank - - See CONTRIBUTORS for a long list of past contributors as well as people - from the inn-workers mailing list who have dedicated a lot of time and - effort to getting this new version together. They deserve a big round - of applause. They've certainly got our thanks. - - This product includes software developed by UUNET Technologies, Inc. and - by the University of California, Berkeley and its contributors. - - Last, but certainly not least, Rich Salz, the original author of INN - deserves a lion's share of the credit for writing INN in the first place - and making it the most popular news server software on the planet (no - NNTP yet to the moon, but we plan to be there first). - -Related Packages - - INN users may also be interested in the following software packages that - work with INN or are based on it. Please note that none of this - software is developed or maintained by ISC; we don't support it and - generally can't answer questions about it. - - CleanFeed - URL: - - CleanFeed is an extremely powerful spam filter, probably the most - widely used spam filter on Usenet currently. It catches excessive - multiposting and a host of other things, and is highly configurable. - Note that it requires that INN be built with Perl support (the - --with-perl option to configure). - - GUP (Group Update Program) - URL: - - GUP provides a way for your peers to update their newsfeeds entries - as they want without having to ask you to edit the configuration - file all the time. It's useful when feeding peers who take limited - and very specific feeds that change periodically. - - inflow - URL: - - inflow generates graphs of news flow statistics in real time from - INN's logs (things like articles accepted per peer, volume accepted - per peer, and the like). - - News-Portal - URL: - - A PHP-based web news reader that works as a front-end to a regular - news server such as INN and lets people read and post without - learning a news reader. - - PersonalINN - URL: - - PersonalINN is a version of INN modified for personal use and with a - friendly GUI built on top of it. It is available for NeXTSTEP or - OPENSTEP only, unfortunately. - - suck - URL: - - suck is a separate package for downloading a news feed via a reading - connection (rather than via a direct NNTP or UUCP feed) and sending - outgoing local posts via POST. It's intended primarily for personal - or small-organization news servers who get their news via an ISP and - are too small to warrant setting up a regular news feed. - - newsx - URL: - - Serving the same purpose as suck, newsx is a separate package for - downloading a news feed via a reading connectino and sending - outgoing local posts via POST. Some people find suck easier to - configure and use, and some people find newsx easier. If you have - problems with one, try the other. - -Supporting the INN Effort - - Note that INN is supported by Internet Systems Consortium, and although - it is free for use and redistribution and incorporation into vendor - products and export and anything else you can think of, it costs money - to produce. That money comes from ISPs, hardware and software vendors, - companies who make extensive use of the software, and generally - kind-hearted folk such as yourself. - - Internet Systems Consortium has also commissioned a DHCP server - implementation and handles the official support/release of BIND. You - can learn more about the ISC's goals and accomplishments from the web - page at . - - Russ Allbery - Katsuhiro Kondou - diff --git a/TODO b/TODO deleted file mode 100644 index 28b655b..0000000 --- a/TODO +++ /dev/null @@ -1,847 +0,0 @@ -This is a rough and informal list of suggested improvements to INN, parts -of INN that need work, and other tasks yet undone. Some of these may be -in progress, in which case the person working on them will be noted in -square brackets and should be contacted if you want to help. Otherwise, -let inn-workers@isc.org know if you'd like to work on any item listed -below. - -The list is divided into changes already tentatively scheduled for a -particular release, higher priority changes that will hopefully be done in -the near future, small or medium-scale projects for the future, and -long-term, large-scale problems. Note that just because a particular -feature is scheduled for a later release doesn't mean it can't be -completed earlier if someone decides to take it on. The association of -features with releases is intended to be a rough guide for prioritization -and a set of milestones to use to judge when a new major release is -justified. - -Also, one major thing that is *always* welcome is additions to the test -suite, which is currently very minimal. Any work done on the test suite -to allow more portions of INN to be automatically tested will make all -changes easier and will be *greatly* appreciated. - -Last modified $Id: TODO 7575 2006-09-11 22:59:38Z eagle $. - - -Scheduled for INN 2.5 - -* Rewrite configure, breaking all of the tests out into separate files - using the new capabilities in autoconf 2.5x. Replace our local macros - with the more general features provided by autoconf. At the same time, - configure.in and Makefile.global.in should be fixed to use the same - names as each other for various parameters. [Russ plans to work on - this.] - -* Add support for groups, nesting, and vectors to the new configuration - parsing code. [Russ plans on doing this.] - -* Convert readers.conf and storage.conf (and related configuration files) - to use the new parsing system and break out program-specific sections - of inn.conf into their own groups. - -* The current WIP cache and history cache should be integrated into the - history API, things like message ID hashing should become a selectable - property of the history file, and the history API should support - multiple backend storage formats and automatically select the right one - for an existing history file based on stored metainformation. - -* The interface to embedded filters needs to be reworked. The information - about which filters are enabled should be isolated in the filtering API, - and there should be standard API calls for filtering message IDs, remote - posts, and local posts. As part of this revision, all of the Perl - callbacks should be defined before any of the user code is loaded, and - the Perl loading code needs considerable cleanup. At the same time as - this is done, the implementation should really be documented; we do some - interesting things with embedded filters and it would be nice to have a - general document describing how we do it. [Russ is planning on working - on this at some point, but won't get upset if someone starts first.] - -* All of INN's documentation should be written in POD, with text and man - pages generated from the POD source. Anyone is encouraged to work on - this by just taking any existing documentation in man format and convert - it to POD while checking that it's still accurate and adding any - additional useful information that was missed. - -* Replace the current innshellvars.pl file with a real INN Perl module for - Perl programs, and include the necessary glue so that other Perl modules - can be added to INN's build tree and installed with INN, allowing their - capabilities to be available to the portions of INN written in Perl. - -* Switch nnrpd over to using the new wildmat routines rather than breaking - apart strings on commas and matching each expression separately. This - involves a lot of surgery, since PERMmatch is used all over the place, - and may change the interpretation of ! and @ in group permission - wildmats. - -* Rework and clean up the storage API. The major change is that the - initialization function should return a pointer to an opaque struct - which stores all of the state of the storage subsystem, rather than all - of that being stored in static variables, and then all other functions - should take that pointer. More of the structures should also be opaque, - all-caps structure names should be avoided in favor of named structures, - SMsetup and SMinit should be combined into one function that takes - flags, SMerrno and SMerrorstr should be replaced with functions that - return that information, and the wire format utilities should be moved - into libinn. - -* Rework and clean up the overview API. The major change is that the - initialization function should return a pointer to an opaque struct - which stores all of the state of the overview subsystem, rather than all - of that being stored in static variables, and then all other functions - should take that pointer. OVctl possibly should instead take and return - a struct rather than using an ioctl-style interface. Currently, the - overview functions do a lot of breaking apart of Xref headers and - parsing them, which is very ugly; consider having the overview interface - always key off a newsgroup name and article number, even for storing. - OVadd should probably take a structure and OVsearch should probably - return a structure. - - -Scheduled for INN 2.6 - -* Add a generic, modular anti-spam and anti-abuse filter, off by default, - but coming with INN and prominently mentioned in the INSTALL - documentation. [Andrew Gierth has work in progress that may be usable - for this.] - -* A unified configuration file combining the facilities of newsfeeds, - incoming.conf, and innfeed.conf, but hopefully more readable and easier - for new INN users to edit. This should have all of the capabilities of - the existing configuration files, but specifying common things (such as - file feeds or innfeed feeds) should be very simple and straightforward. - This configuration file should use the new parsing infrastructure. - -* Convert all remaining INN configuration files to the new parsing - infrastructure. - -* INN really should be capable of both sending and receiving a - headers-only feed (or even an overview-only feed) similar to Diablo and - using it for the same things that Diablo does, namely clustering, - pull-on-demand for articles, and the like. This should be implementable - as a new backend, although the API may need a few more hooks. Both a - straight headers-only feed that only pulls articles down via NNTP from a - remote server and a caching feed where some articles are pre-fed, some - articles are pulled down at first read, and some articles are never - stored locally should be possible. [Patches for a header-only feed have - already been written and submitted to inn-workers.] - -* The libinn, libstorage, and other library interfaces should be treated - as stable libraries and properly versioned using libtool's - recommendation for library versioning when changes are made so that they - can be installed as shared libraries and work properly through releases - of INN. This is currently waiting on a systematic review of the - interface and removal of things that we don't want to support long-term. - -* The include files necessary to use libinn, libstorage, and other - libraries should be installed in a suitable directory so that other - programs can link against them. All such include files should be under - include/inn and included with . All such include files - should only depend on other inn/* header files and not on, e.g., - config.h. All such include files should be careful about namespace to - avoid conflicts with other include files used by applications. - - -High Priority Projects - -* Modulo warnings from system headers and warnings where the compiler is - simply wrong and there's no equally readable way to rewrite the code, - INN should compile cleanly under "make warnings". It should be possible - for maintainers to routinely compile INN with make warnings to catch - problems. Note that -Wcast-qual warnings cannot be avoided entirely - because we don't want to write redundant functions for regular and const - strings and because of such things as struct iovec; -Wcast-qual will be - removed from make warnings when this task is reasonably complete. - -* INN shouldn't flush all feeds (particularly all program feeds) on - newgroup or rmgroup. Currently it reloads newsfeeds to reparse all of - the wildmat patterns and rebuild the peer lists associated with the - active file on group changes, and this forces a flush of all feeds. - The best fix is probably to stash the wildmat pattern (and flags) for - each peer when newsfeeds is read and then just using the stashed copy on - newgroup or rmgroup, since otherwise the newsfeeds loading code would - need significant modification. But in general, innd is too - reload-happy; it should be better at making incremental changes without - reloading everything. - -* Add authenticated Path support, based on the current USEFOR draft or the - behavior of some other servers (such as Diablo). [Andrew Gierth wrote a - patch for part of this a while back, which Russ has. Marco d'Itri - expressed some interest in working on this.] - -* Various parts of INN are using write or writev; they should all use - xwrite or xwritev instead. Even for writes that are unlikely to ever be - partial, on some systems system calls aren't restartable and xwrite and - xwritev properly handle EINTR returns. - -* Apparently on Solaris open can also be interrupted by a signal; we may - need to have an xopen wrapper that checks for EINTR and retries. - -* tradspool has a few annoying problems. Deleted newsgroups never have - their last articles expired, and there is no way of forcibly - resynchronizing the articles stored on disk with what overview knows - about unless tradindexed is used. Some sort of utility program to take - care of these and to do things like analyze the tradspool.map file - should be provided. - -* Rewrite inndstart as a helper program that only binds the relevant - sockets and then returns them to innd. Since file descriptors are - shared by child processes, this can be done with a program spawned by - innd. This may have gotten more complicated with IPv6. Drop - startinnfeed entirely in favor of recommending people use ulimit in the - news init script. - -* contrib/mkbuf and contrib/reset-cnfs.c should be combined into a utility - for creating and clearing cycbuffs, perhaps combined with cnfsheadconf, - and the whole thing moved into storage/cnfs rather than frontends (along - with cnfsstat). pullart.c may also stand to be merged into the same - utility (cnfs-util might not be a bad name). - - -Documentation Projects - -* Add man pages for all libinn interfaces. There should be a subdirectory - of doc/pod for this since there will be a lot of them; installing them - as libinn_
.3 seems to make the most sense (so, for example, - error handling routines would be documented in libinn_error.3). - -* Better documentation of and support for UUCP feeds. send-uucp is now - easier to use, but there's still a paucity of documentation covering the - whole theory and mechanisms of UUCP feeding. - -* Everything installed by INN should have a man page. Currently, there - are several binaries and configuration files that don't have man pages. - (In some cases, the best thing to do with the configuration file may be - to merge it into another one or find a way to eliminate it.) - -* Document the internal formats of the various overview methods, CNFS, - timehash, and timecaf. A lot of this documentation already exists in - various forms, but it needs to be cleaned up and collected in one place - for each format, preferrably as a man page. - -* Add documentation for slave servers. [Russ has articles from - inn-workers that can be used as a beginning.] - -* Write complete documentation for all of our extensions to RFC 977 or RFC - 1036, preferrably in a format that could be suitable for future - inclusion into new revisions of the RFCs. - -* Audit readers.conf.5 against perm.c for missing options ("include" at - least is missing from the documentation). - -* The distributions file is undocumented. - - -Code Cleanup Projects - -* Eliminate everything in the LEGACY section of config.h. - -* Move all compile-time configuration in config.h either into a separate - header (such as inn/options.h) or turn it into a configuration file - directive or a command-line option. In particular, the rnews - configuration should probably be an rnews-specific section of inn.conf. - -* Move include/paths.h to include/inn/paths.h and change _PATH as a prefix - to INN_PATH to move the identifiers out of the C reserved namespace. - Check to be sure we still need all of the #defines and look at adding - anything needed by innfeed (and eliminating the separate innfeed header - serving the same purpose). - -* Move include/nntp.h to include/inn/nntp.h and at the same time look at - standardizing the names of all of the #defines it provides, including - the message class. [Russ has a start on this.] - -* Get rid of GetTimeInfo and TIMEINFO. All the struct is is a struct - timeval plus time zone information. All of the parts of INN that deal - with time zone information are isolated in lib/date.c. The rest of INN - uses GetTimeInfo where a plain call to time would often work fine, or - at most gettimeofday, and there's no reason to compute the time zone - everywhere. Plus, it makes the code more readable to use standard - functions and data types. - -* putman.sh should be merged into support/install-sh (which would mean - giving up any pretext of using the standard install-sh script, but that - should be fine). - -* Use vectors or cvectors everywhere that argify and friends are currently - used and eliminate the separate implementation in nnrpd/misc.c. - -* Break up the remainder of libinn.h into multiple inn/* include files for - specific functions (such as memory management, wildmat, date handling, - NNTP commands, etc.), with an inn/util.h header to collect the remaining - random utilities. Consider adding some sort of prefix, like inn_, to all - functions that aren't part of some other logical set with its own prefix. - -* Break the CNFS and tradspool code into multiple source files to make it - easier to understand the logical divisions of the code and consider - doing the same with the other overview and storage methods. - -* Examine the (mostly socket) code that currently should probably be - compiled with -fno-strict-aliasing on gcc and move the relevant casts - to within function calls. [Russ knows about this.] - -* Clean up the use of #ifdef for sockets and IPv6, perhaps involving - addition of more to include/portable/socket.h. - - -Needed Bug Fixes - -* tradspool currently uses stdio to write out tradspool.map, which can - cause problems if more than 256 file descriptors are in use for other - things (such as incoming connections or tradindexed overview cache). - It should use write() instead. - -* LIST NEWSGROUPS should probably only list newsgroups that are marked in - the active file as valid groups. - -* INN's startup script should be sure to clean out old lock files and PID - files for innfeed. Be careful, though, since innfeed may still be - running, spawned from a previous innd. - -* makedbz should be more robust in the presence of malformed history - lines, discarding with them or otherwise dealing with them. - -* CNFS, if the cycbuff is larger than 2GB and it doesn't have large file - support, reports a mysterious file not found error because it assumes - all errors from stat are the result of the cycbuff not being found. - -* Some servers reject some IHAVE, TAKETHIS, or CHECK commands with 500 - syntax errors (particularly for long message IDs), and innfeed doesn't - handle this particularly well at the moment. It really should have an - error handler for this case. [Sven Paulus has a preliminary patch that - needs testing.] - -* Editing the active file by hand can currently munge it fairly badly even - if the server is throttled unless you reload active before restarting - the server. This could be avoidable for at least that particular case - by checking the mtime of active before and after the server was - throttled. - -* innreport silently discards news.notice entries about most of the errors - innfeed generates. It should ideally generate some summary, or at least - note that some error has occurred and the logs should be examined. - -* INN's message ID parser should be more forgiving about surrounding - whitespace. Right now, it will reject messages with a trailing space in - the Message-ID header. - -* nnrpd doesn't check the message ID of a posted article for syntactic - validity before remailing it to the moderator, since normally it relies - on innd to check the message ID. The message ID checking code from - innd/art.c should be moved into lib so that nnrpd can use it as well. - -* Currently, if the list of newsgroups on an Xref slave is out of sync - with the newsgroups on the master, receiving an article crossposted to - one of the groups that doesn't exist on the slave will cause the slave - to throttle. This isn't the best behavior; the server should either - optionally create the missing newsgroup or just ignore that crossposted - group (and modify Xref accordingly?). - -* Handling of compressed batches needs to be thoroughly reviewed by - someone who understands how they're supposed to work. It's not clear - that _PATH_GZIP is being used correctly at the moment and that - compressed batch handling will work right now on systems that don't have - gzip installed (but that do have uncompress). - -* innfeed's statistics don't add up properly all the time. All of the - article dispositions don't add up to the offered count like they should. - Some article handling must not be recorded properly. - -* innd's counting of article size doesn't always work properly, and it can - accept articles that are larger than its configured limit. It's not - clear exactly where this is happening. - -* If a channel feed exits immediately, innd respawns it immediately, - causing thrashing of the system and a huge spew of errors in syslog. It - should mark the channel as dormant for some period of time before - respawning it, perhaps only if it's already died multiple times in a - short interval. - -* ctlinnd begin was causing innd to core dump. - -* Handling of innfeed's dropped batches needs looking at. There are three - places where articles can fall between the cracks: an innfeed.togo file - written by innd when the feed can't be spawned, a batch file named after - the feed name which can be created under similar circumstances, and the - dropped files written by innfeed itself. procbatch can clean these up, - but has to be run by hand. - -* When using tradspool, groups are not immediately added to tradspool.map - when created, making innfeed unable to find the articles until after - some period of time. Part of the problem here is that tradspool only - updates tradspool.map on a lazy basis, when it sees an article in that - group, since there is no storage hook for creation of a new group. - -* nntpget doesn't handle long lines in messages. - -* WP feeds break if there are spaces in the Path header, and the inn.conf - parser doesn't check for this case and will allow people to configure - their server that way. (It's not clear that the latter is actually a - bug, given the new USEFOR attempt to allow folding of Path headers, but - the space needs to be removed for WP feeds.) - -* Error handling in the history backend needs to be reviewed, since it - currently is always printing out errno regardless of whether it's - meaningful. The error handling needs to record errno if it's useful and - the reporting function should only print it out if it's useful for that - error. - -* innd returns 437 for articles that were accepted but filed in the junk - group. It should probably return the appropriate 2xx status code in - that case instead. - -* Someone should go through the BUGS sections of all of the manpages and - fix those for which the current behavior is unacceptable. - - -Requested New Features - -* Consider implementing the HEADERS command as discussed rather - extensively in news.software.nntp. [Greg Andruk has a preliminary - patch.] - -* There have been a few requests for the ability to programmatically set - the subject of the report generated by news.daily, with escapes that are - filled in by the various pieces of information that might be useful. - -* A bulk cancel command using the MODE CANCEL interface. Possibly through - ctlinnd, although it may be a bit afield of what ctlinnd is currently - for. - -* Sven Paulus's patch for nnrpd volume reports should be integrated. See - . - -* Lots of people encrypt X-Trace in various ways. Should that be offered - as a standard option? The first data element should probably remain - unencrypted so that the O flag in newsfeeds doesn't break. - - Should there also be an option not to generate X-Trace? And this whole - area may change if USEFOR ever standardizes poster trace information; - it's been proposed to put it in the path tail instead. The current - USEFOR trend as of January, 2001 appears to be towards an Injector-Info - header with this information, allowing a token or an injecting hostname. - For a token, one really wants it to be hierarchically structured for - spam filtering even if it's encrypted (in other words, to get a "group" - of clients, one could just match the first n bytes of the token instead - of the whole thing). - - Olaf Titz suggests: - - This can be done by formatting the (rest of) the header in a way - that fields are always a multiple of 8 bytes and applying a 64 bit - block cipher in ECB mode on it. But then we would be better off - using binary fields, as the timestamp is 9 bytes and an IP address - 10-12 bytes. - - Combining the timestamp and PID into one block, adding an - authenticated user field and omitting the redundant formatted time - would give the following format: - - X-Trace: g212.hadiko.de [395109AA000016FF] [AC14302A00000000] [...] - time | pid ip |reserved user - -* ctlinnd flushlogs currently renames all of the log files. It would be - nice to support the method of log rotation that most other daemons - support, namely to move the logs aside and then tell innd to reopen its - log files. Ideally, that behavior would be triggered with a SIGHUP. - scanlogs would have to be modified to handle this. - - The best way to support this seems to be to leave scanlogs as is by - default, but also add two additional modes. One would flush all the - logs and prepare for the syslog logs to be rotated, and the other would - do all the work needed after the logs have been rotated. That way, if - someone wanted to plug in a separate log rotation handler, they could do - so and just call scanlogs on either side of it. The reporting portions - of scanlogs should be in a separate program. - -* Several people have Perl interfaces to pieces of INN that should ideally - be part of the INN source tree in some fashion. Greg Andruk has a bunch - of stuff that Russ has copies of, for example. - -* Investigate using the new, stricter date parsing code in libinn for - nnrpd rather than the extremely lenient parsedate routine. - -* There are various available patches for Cancel-Lock and an Internet - draft; support should be added to INN for both generation and - verification (definitely optional and not on by default at this point). - -* It would be nice to be able to reload inn.conf (although difficult, due - to the amount of data that's generated from it and stashed in various - places). This will need to wait for the new configuration parsing - library and an inn.conf parser that uses it. - -* remembertrash currently rejects and remembers articles with syntax - errors as well as things like unwanted newsgroups and unwanted - distributions, which means that if a peer sends you a bunch of mangled - articles, you'll then also reject the correct versions of the articles - from other peers. This should probably be rethought. - -* Additional limits for readers.conf: Limit on concurrent parallel reader - streams, limit on KB/second download (preliminary support for this is - already in), and a limit on maximum posted articles per day (tied in - with the backoff stuff?). These should be per-IP or per-user, but - possibly also per-access group. (Consider pulling the -H, -T, -X, and - -i code out from innd and using it here.) - -* timecaf should have more configurable parameters (at the least, how - frequently to switch to a new CAF file should be an option). - storage.conf should really be extended to allow method-specific - configuration for things like this (and to allow the cycbuff.conf file - to be merged into storage.conf). - -* Allow generation of arbitrary additional information that could go in - overview by using embedded Perl or Python code. This might be a cleaner - way to do the keywords code, which really wants Perl's regex engine - ideally. It would also let one do something like doing MD5 hashes of - each article and putting that in the overview if you care a lot about - making sure that articles aren't corrupted. - -* Allow some way of accepting articles regardless of the Date header, even - if it's far into the future. Some people are running into articles that - are dated years into the future for some reason that they still want to - store on the server. - -* There was a request to make --program-suffix and the other name - transformation options to autoconf work. The standard GNU package does - this with really ugly sed commands in the Makefile rules; we could - probably do better, perhaps by substituting the autoconf results into - support/install-sh. - -* INN currently uses hash tables to store the active file internally. It - would be worth trying ternary search trees to see if they're faster; the - data structure is simpler, performance may be comparable for hits and - significantly better for misses, sizing and resizing becomes a non-issue, - and the space penalty isn't too bad. A generic implementation is already - available in libinn. (An even better place to use ternary search trees - may be the configuration parser.) - -* Provide an innshellvars equivalent for Python. - -* inncheck should check the syntax of all the various files that are - returned by LIST commands, since having those files present with the - wrong syntax could result in non-compliant responses from the server. - Possibly the server should also refuse to send malformatted lines to - the client. - -* ctlinnd reload incoming.conf could return a count of the hosts that - failed, or even better a list of them. This would make pruning old - stuff out of incoming.conf much easier. - -* nnrpd could use sendfile(2), if available, to send articles directly - to the socket (for those storage methods where to-wire conversion is - not needed). This would need to be added to the storage API. - -* Somebody should look at keeping the "newsgroups" file more accurate - (e.g. newgroups for existing groups should change description, better - checkgroups handling, checking for duplicates) - -* The by-domain statistics innreport generates for nnrpd count all local - connections (those with no "." in the hostname) in with the errors as - just "?". The host2dom function could be updated to group these as - something like "Local". - -* news.daily could detect if expire segfaults and unpause the server. - -* When using SSL, track the amount of data that's been transferred to the - client and periodically renegotiate the session key. - -* When using SSL, use SSL_get_peer to get a verified client certificate, - if available, and use it to create an additional header line when - posting articles (X-Auth-Poster?). This header could use: - - X509_NAME_oneline(X509_get_subject_name(peer),...) - - for the full distinguished name, or - - X509_name_get_text_by_NID(X509_get_subject_name(peer), - NID_commonName, ...) - - for the client's "common name" alone. - -* When using SSL, use the server's key to generate an HMAC of the body of - the message (and most headers?), then include that digest in the - headers. This allows a news administrator to determine if a complaint - about the content of a message is fradulent since the message was - changed after transmission. - - -General Projects - -* All the old packages in unoff-contrib should be reviewed for integration - into INN. - -* It may be better for INN on SysV-derived systems to use poll rather than - select. The semantics are better, and on some systems (such as Solaris) - select is limited to 1024 file descriptors whereas poll can handle any - number. Unfortunately, the API is drastically different between the - two and poll isn't portable, so supporting both cleanly would require a - bit of thought. - -* Currently only innd and innfeed increase their file descriptor limits. - Other parts of INN, notably makehistory, may benefit from doing the same - thing if they can without root privileges. - -* The Tcl filtering support code has undergone serious bitrot and needs - some work to fix it and make it work with modern versions of Tcl and the - current version of INN. It also lacks a lot of the functionality of the - Perl and Python filters, if anyone cares. - -* Revisit support for aliased groups and what nnrpd does with them. - Should posts to the alias automatically be redirected to the real group? - Regardless, the error return should provide useful information about - where to post instead. Also, the new overview API, for at least some of - the overview methods, truncated the group status at one character and - lost the name of the group to which a group is aliased; that needs to be - fixed. - -* More details as to why a message ID is bad would be useful to return to - the user, particularly for rnews, inews, etc. innd also rejects message - IDs with trailing spaces, which can be hard to check. - -* Support putting the active file and history file in different - directories without hand-editing a bunch of files. - -* nnrpd's NNTP command parsing interacts poorly with AUTHINFO and - passwords containing spaces. The correct solution isn't clear; check - with the current NNTP RFC draft and how existing clients handle it? - -* frontends/pullnews and contrib/backupfeed solve the same problem; the - best ideas of both should be unified into one script. - -* actsyncd could stand a rewrite and cleaner handling of both - configuration and syncing against multiple sources which are canonical - for different sets of groups. - -* send-nntp and nntpsend basically do the same thing; send-nntp could - probably be removed (possibly with some extra support in nntpsend for - doing simpler things). - - -Long-Term Projects - -* Look at turning header parsing into a library of some sort. Lots of INN - does this, but different parts of INN need subtly different things, so - the best best API is unclear. - -* INN's header handling needs to be checked against the current USEFOR - draft. This may want wait until after we have a header parsing library. - -* The innd filter should be able to specify additional or replacement - groups into which an article should be filed, or even spool the article - to a local disk file rather than storing it. (See the stuff that the - nnrpd filter can already do.) - -* Add authentication via SASL to nnrpd. This is a boatload of additional - issues, particularly if we want to add authentication methods like - Kerberos that require their own separate libraries (although we should - use Cyrus's SASL libraries, which will simplify a lot of that). - [Jeffrey Vinocur is working on a standard for this.] - -* When articles expire out of a storage method with self-expire - functionality, the overview and history entries for those articles - should also be expired immediately. Otherwise, things like the GROUP - command don't give the correct results. This will likely require a - callback that can be passed to CNFS that is called to do the overview - and history cleanup for each article overwritten. It will also require - the new history API. - -* Feed control, namely allowing your peers to set policy on what articles - you feed them (not just newsgroups but max article size and perhaps even - filter properties like "non-binary"). Every site does this a bit - differently. Some people have web interfaces, some people use GUP, some - people roll their own alternate things. It would really be nice to have - some good way of doing this as part of INN. It's worth considering an - NNTP extension for this purpose, although the first step is to build a - generic interface that an NNTP extension, a web page, etc. could all - use. (An alternate way of doing this would be to extend IHAVE to pass - the list of newsgroups as part of the command, although this doesn't - seem as generally useful.) - -* Traffic classification as an extension of filtering. The filter should - be able to label traffic as binary (e.g.) without rejecting it, and - newsfeeds should be extended to allow feeding only non-binary articles - (e.g.) to a peer. - -* External authenticators should also be able to do things like return a - list of groups that a person is allowed to read or post to. Currently, - maintaining a set of users and a set of groups, each of which some - subset of the users is allowed to access, is far too difficult. For a - good starting list of additional functionality that should be made - available, look at everything the Perl authentication hooks can do. - This should probably wait for the configuration file parsing rewrite. - -* Allow nnrpd to spawn long-running helper processes. Not only would this - be useful for handling authentication (so that the auth hooks could work - without execing a program on every connection), but it may allow for - other architectures for handling requests (such as a pool of helpers - that deal only with overview requests). More than that, nnrpd should - *be* a long-running helper process that innd can feed open file - descriptors to. [Aidan Culley has ideas along these lines.] - -* The tradspool storage method requires assigning a number to every - newsgroup (for use in a token). Currently this is maintained in a - separate tradspool.map file, but it would be much better to keep that - information in the active file where it can't drop out of sync. A code - assigned to each newsgroup would be useful for other things as well, - such as hashing the directories for the tradindexed overview. For use - for that purpose, though, the active file would have to be extended to - include removed groups, since they'd need to be kept in the active file - to reserve their numbers until the last articles expired. - -* The locking of the active file leaves something to be desired; in - general, the locking in INN (for the active file, the history file, - spool updates, overview updates, and the like) needs a thorough - inspection and some cleanup. A good place to start would be tracing - through the pause and throttle code and write up a clear description of - what gets locked where and what is safely restarted and what isn't. - Long term, there needs to be a library locking routine used by - *everything* that needs to write to the history file, active file, etc. - and that keeps track of the PID of the process locking things and is - accessible via ctlinnd. - -* There is a fundamental problem with the current design of the - control.ctl file. It combines two things: A database of hierarchies, - their maintainers, and related information, and a list of which - hierarchies the local server should honor. These should be separated - out into the database (which could mostly be updated from a remote - source like ftp.isc.org and then combined with local additions) and a - configured list of hierarchies (or sub-hierarchies within hierarchies) - that control messages should be honored for. This should be reasonably - simple although correct handling of checkgroups could get a mite tricky. - -* Possible NNTP extension: Compression of the protocol, using gzip, - bzip2, or some other technique. Particularly useful for long lists like - the active file information or the overview information, but possibly - useful in general for other things. - -* Install wizards. Configuring INN is currently very complex even for an - experienced news admin, and there are several fairly standard - configurations that shouldn't be nearly that complicated to get running - out of the box. A little interactive Perl script asking some simple - questions could probably get a lot of cases easily right. - -* One ideally wants to be able to easily convert between different - overview formats or storage methods, refiling articles in place. This - should be possible once we have a history API that allows changing the - storage location of an article in-place. - -* Set up the infrastructure required so that INN can use alloca. This - would significantly decrease the number of calls to malloc needed and - would be a lot more convenient. - -* A serious investigation into whether INN could use a garbage collector - is probably a good idea. The network buffers probably need to be - handled with decidated code, but there are a lot of other incidental - allocations and deallocations that may be much more efficient and safer - using a garbage collector. - -* Look at integrating asprintf and vasprintf. Russ already tried this - once and couldn't see a good way of doing it (particularly vasprintf) - without hooking deep into an sprintf implementation, because the simple - hack of calling vsnprintf first, allocating that much memory, and then - calling it again on the new buffer doesn't work for vasprintf (you can't - reprocess the arguments). - -* Support building in a separate directory than the source tree. It may - be best to just support this via lndir rather than try to do it in - configure, but it would be ideal to add support for this to the autoconf - system. Unfortunately, the standard method requires letting configure - generate all of the makefiles, which would make running configure and - config.status take much longer than it does currently. - -* Look at adding some kind of support for MODE CANCEL via network sockets - and fixing up the protocol so that it could possibly be standardized - (the easiest thing to do would probably be to change it into a CANCEL - command). If we want to get to the point where INN can accept and even - propagate such feeds from dedicated spam filters or the like, there must - also be some mechanism of negotiating policy in order to decide what - cancels the server wants to be fed. - -* The "possibly signed" char data type is one of the inherent flaws of C. - Some other projects have successfully gotten completely away from this - by declaring all of their strings to be unsigned char, defining a macro - like U that casts strings to unsigned char for use with literal strings, - and always using unsigned char everywhere. Unfortunately, this also - requires wrappering all of the standard libc string functions, since - they're prototyped as taking char rather than unsigned char. The - benefits include cleaner and consistent handling of characters over 127, - better warnings from the compiler, consistent behavior across platforms - with different notions about the signedness of char, and the elimination - of warnings from the macros on platforms like Solaris where - those macros can't handle signed characters. We should look at doing - this for INN. - -* It would clean up a lot of code considerably if we could just use mmap - semantics regardless of whether the system has mmap. It may be possible - to emulate mmap on systems that don't have it by reading the entirety of - the file into memory and setting the flags that require things to call - mmap_flush and mmap_invalidate on a regular basis, but it's not clear - where to stash the file descriptor that corresponds to the mapped file. - -* Figure out some Samba library that we can link against for the Samba - authenticator so that we can get all the Samba code back out of INN's - source tree; we don't want to maintain it. - -* Consider replacing the awkward access: parameter in readers.conf with - separate commands (e.g. "allow_newnews: true") or otherwise cleaning up - the interaction between access: and read:/post:. Note that at least - allownewnews: can be treated as a setting for overriding inn.conf and - should be very easy to add. - -* Add a localport: parameter (similar to localaddress:) to readers.conf - auth groups. With those two parameters (and ssl_required:) we - essentially eliminate the need to run multiple instances of nnrpd just to - use different configurations. - -* Various things may break when trying to use data written while compiled - with large file support using a server that wasn't so compiled (and vice - versa). The main one is the history file, but tradindexed is also - affected and buffindexed has been reported to have problems with this - as well. Ideally, all of INN's data files should be as portable as - possible. - - -Complete Code Reorganization - -At some point, we should probably abandon and archive the current CVS -repository, reimport all of the current source files, and start with a -fresh repository with a better revision control system such as Subversion. -A better revision control system would let us rename and move things -around arbitrarily, something CVS doesn't handle at all well. Should this -ever be done, we should consider doing all of the following at the same -time: - -* Don't include any generated files in the CVS tree. Maintainers should - have autoconf and friends, pod2text and pod2man, and bison around anyway. - This would save a bunch of extra check-ins, remove the danger of the - generated files getting out of sync, and drastically reduce the - repository size in the case of configure. - -* Don't include any of the generated man pages in the CVS tree, as an - additional case of the above. All of the documentation should be in POD - and we can generate the man pages as part of the snapshot process. - -* storage should be reserved just for article storage; the overview - methods should be in a separate overview tree. - -* The split between frontends and backends is highly non-intuitive. Some - better organization scheme should be arrived at. Perhaps something - related to incoming and outgoing, with programs like cnfsstat moved into - the storage directory with the other storage-related code? - -* Add a separate utils directory for things like convdate, shlock, - shrinkfile, and the like. Some of the scripts may possibly want to go - into that directory too. - -* The lib directory possibly should be split so that it contains only code - always compiled and part of INN, and the various replacements for - possibly missing system routines are in a separate directory (such as - replace). These should possibly be separate libraries; there are things - that currently link against libinn that only need the portability - pieces. - -* The doc directory really should be broken down further by type of - documentation or section or something; it's getting a bit unwieldy. - -* Untabify and reformat all of the code according to a consistent coding - style which would then be enforced for all future check-ins. diff --git a/authprogs/Makefile b/authprogs/Makefile deleted file mode 100644 index efb2751..0000000 --- a/authprogs/Makefile +++ /dev/null @@ -1,115 +0,0 @@ -## $Id: Makefile 7727 2008-04-06 07:59:46Z iulius $ - -include ../Makefile.global - -top = .. -CFLAGS = $(GCFLAGS) - -ALL = auth_smb ckpasswd domain ident radius $(KRB5_AUTH) - -LIBSMB = smbval/smbvalid.a - -LIBAUTH = libauth.o - -SOURCES = auth_krb5.c auth_smb.c ckpasswd.c domain.c ident.c libauth.c \ - radius.c - -all: $(ALL) - -warnings: - $(MAKE) COPT='$(WARNINGS)' all - -install: all - if [ x"$(KRB5_AUTH)" != x ] ; then \ - $(LI_XPUB) auth_krb5 $(D)$(PATHAUTHPASSWD)/auth_krb5 ; \ - fi - for F in auth_smb ckpasswd radius ; do \ - $(LI_XPUB) $$F $D$(PATHAUTHPASSWD)/$$F ; \ - done - for F in domain ident ; do \ - $(LI_XPUB) $$F $D$(PATHAUTHRESOLV)/$$F ; \ - done - -clobber clean distclean: - rm -f *.o $(ALL) - rm -rf .libs - cd smbval && $(MAKE) clean - -tags ctags: $(SOURCES) - $(CTAGS) $(SOURCES) ../lib/*.c ../include/*.h - -profiled: - $(MAKEPROFILING) all - - -## Compilation rules. - -LINK = $(LIBLD) $(LDFLAGS) -o $@ -CKLIBS = $(CRYPTLIB) $(SHADOWLIB) $(PAMLIB) $(DBMLIB) - -auth_krb5: auth_krb5.o $(LIBAUTH) $(LIBINN) - $(LINK) auth_krb5.o $(LIBAUTH) $(KRB5LIB) $(LIBINN) $(LIBS) - -auth_smb: auth_smb.o $(LIBSMB) $(LIBAUTH) $(LIBINN) - $(LINK) auth_smb.o $(LIBSMB) $(LIBAUTH) $(LIBINN) $(LIBS) - -ckpasswd: ckpasswd.o $(LIBAUTH) $(LIBINN) - $(LINK) ckpasswd.o $(LIBAUTH) $(CKLIBS) $(LIBINN) $(LIBS) - -domain: domain.o $(LIBAUTH) $(LIBINN) - $(LINK) domain.o $(LIBAUTH) $(LIBINN) $(LIBS) - -ident: ident.o $(LIBAUTH) $(LIBINN) - $(LINK) ident.o $(LIBAUTH) $(LIBINN) $(LIBS) - -radius: radius.o $(LIBAUTH) $(LIBINN) - $(LINK) radius.o $(LIBAUTH) $(LIBINN) $(LIBS) - -auth_krb5.o: auth_krb5.c - $(CC) $(CFLAGS) $(KRB5INC) -c auth_krb5.c - -ckpasswd.o: ckpasswd.c - $(CC) $(CFLAGS) $(DBMINC) -c ckpasswd.c - -$(LIBINN): ; (cd ../lib ; $(MAKE)) -$(LIBSMB): ; (cd smbval ; $(MAKE)) -$(LIBAUTH): libauth.h libauth.c - - -## Dependencies. Default list, below, is probably good enough. - -depend: Makefile $(SOURCES) - $(MAKEDEPEND) '$(CFLAGS)' $(SOURCES) - -# DO NOT DELETE THIS LINE -- make depend depends on it. -auth_krb5.o: auth_krb5.c ../include/config.h ../include/inn/defines.h \ - ../include/inn/system.h ../include/clibrary.h ../include/config.h \ - libauth.h ../include/portable/socket.h ../include/config.h \ - ../include/inn/messages.h ../include/inn/defines.h ../include/libinn.h -auth_smb.o: auth_smb.c ../include/config.h ../include/inn/defines.h \ - ../include/inn/system.h ../include/clibrary.h ../include/config.h \ - ../include/inn/messages.h ../include/inn/defines.h libauth.h \ - ../include/portable/socket.h ../include/config.h smbval/valid.h -ckpasswd.o: ckpasswd.c ../include/config.h ../include/inn/defines.h \ - ../include/inn/system.h ../include/clibrary.h ../include/config.h \ - ../include/inn/messages.h ../include/inn/defines.h ../include/inn/qio.h \ - ../include/inn/vector.h ../include/libinn.h libauth.h \ - ../include/portable/socket.h ../include/config.h -domain.o: domain.c ../include/config.h ../include/inn/defines.h \ - ../include/inn/system.h ../include/clibrary.h ../include/config.h \ - ../include/inn/messages.h ../include/inn/defines.h ../include/libinn.h \ - libauth.h ../include/portable/socket.h ../include/config.h -ident.o: ident.c ../include/config.h ../include/inn/defines.h \ - ../include/inn/system.h ../include/clibrary.h ../include/config.h \ - ../include/inn/messages.h ../include/inn/defines.h ../include/libinn.h \ - libauth.h ../include/portable/socket.h ../include/config.h -libauth.o: libauth.c ../include/config.h ../include/inn/defines.h \ - ../include/inn/system.h ../include/clibrary.h ../include/config.h \ - ../include/libinn.h libauth.h ../include/portable/socket.h \ - ../include/config.h ../include/inn/messages.h ../include/inn/defines.h -radius.o: radius.c ../include/config.h ../include/inn/defines.h \ - ../include/inn/system.h ../include/clibrary.h ../include/config.h \ - ../include/portable/time.h ../include/config.h ../include/inn/innconf.h \ - ../include/inn/defines.h ../include/inn/md5.h ../include/inn/messages.h \ - ../include/libinn.h ../include/nntp.h ../include/paths.h \ - ../include/conffile.h libauth.h ../include/portable/socket.h diff --git a/authprogs/auth_krb5.c b/authprogs/auth_krb5.c deleted file mode 100644 index 1088b8b..0000000 --- a/authprogs/auth_krb5.c +++ /dev/null @@ -1,217 +0,0 @@ -/* $Id: auth_krb5.c 7462 2005-12-12 01:06:54Z eagle $ -** -** Check an username and password against Kerberos v5. -** -** Based on nnrpkrb5auth by Christopher P. Lindsey -** See -** -** This program takes a username and password pair from nnrpd and checks -** checks their validity against a Kerberos v5 KDC by attempting to obtain a -** TGT. With the -i command line option, appends / to -** the username prior to authentication. -** -** Special thanks to Von Welch for giving me the initial -** code on which the Kerberos V authentication is based many years ago, and -** for introducing me to Kerberos back in '96. -** -** Also, thanks to Graeme Mathieson for his inspiration -** through the pamckpasswd program. -*/ - -#include "config.h" -#include "clibrary.h" -#include "libauth.h" -#ifdef HAVE_ET_COM_ERR_H -# include -#else -# include -#endif - -/* krb5_get_in_tkt_with_password is deprecated. */ -#define KRB5_DEPRECATED 1 -#include - -#include "inn/messages.h" -#include "libinn.h" - -/* - * Default life of the ticket we are getting. Since we are just checking - * to see if the user can get one, it doesn't need a long lifetime. - */ -#define KRB5_DEFAULT_LIFE 60 * 5 /* 5 minutes */ - - -/* -** Check the username and password by attempting to get a TGT. Returns 1 on -** success and 0 on failure. Errors are reported via com_err. -*/ -static int -krb5_check_password (char *principal_name, char *password) -{ - krb5_context kcontext; - krb5_creds creds; - krb5_principal user_principal; - krb5_data *user_realm; - krb5_principal service_principal; - krb5_timestamp now; - krb5_address **addrs = (krb5_address **) NULL; /* Use default */ - long lifetime = KRB5_DEFAULT_LIFE; - int options = 0; - - /* TGT service name for convenience */ - krb5_data tgtname = { 0, KRB5_TGS_NAME_SIZE, KRB5_TGS_NAME }; - - krb5_preauthtype *preauth = NULL; - - krb5_error_code code; - - /* Our return code - 1 is success */ - int result = 0; - - /* Initialize our Kerberos state */ - code = krb5_init_context (&kcontext); - if (code) { - com_err (message_program_name, code, "initializing krb5 context"); - return 0; - } - -#ifdef HAVE_KRB5_INIT_ETS - /* Initialize krb5 error tables */ - krb5_init_ets (kcontext); -#endif - - /* Get current time */ - code = krb5_timeofday (kcontext, &now); - if (code) { - com_err (message_program_name, code, "getting time of day"); - return 0; - } - - /* Set up credentials to be filled in */ - memset (&creds, 0, sizeof(creds)); - - /* From here on, goto cleanup to exit */ - - /* Parse the username into a krb5 principal */ - if (!principal_name) { - com_err (message_program_name, 0, "passed NULL principal name"); - goto cleanup; - } - - code = krb5_parse_name (kcontext, principal_name, &user_principal); - if (code) { - com_err (message_program_name, code, - "parsing user principal name %.100s", principal_name); - goto cleanup; - } - - creds.client = user_principal; - - /* Get the user's realm for building service principal */ - user_realm = krb5_princ_realm (kcontext, user_principal); - - /* - * Build the service name into a principal. Right now this is - * a TGT for the user's realm. - */ - code = krb5_build_principal_ext (kcontext, - &service_principal, - user_realm->length, - user_realm->data, - tgtname.length, - tgtname.data, - user_realm->length, - user_realm->data, - 0 /* terminator */); - if (code) { - com_err(message_program_name, code, "building service principal name"); - goto cleanup; - } - - creds.server = service_principal; - - creds.times.starttime = 0; /* Now */ - creds.times.endtime = now + lifetime; - creds.times.renew_till = 0; /* Unrenewable */ - - /* DO IT */ - code = krb5_get_in_tkt_with_password (kcontext, - options, - addrs, - NULL, - preauth, - password, - 0, - &creds, - 0); - - /* We are done with password at this point... */ - - if (code) { - /* FAILURE - Parse a few common errors here */ - switch (code) { - case KRB5KRB_AP_ERR_BAD_INTEGRITY: - com_err (message_program_name, 0, "bad password for %.100s", - principal_name); - break; - case KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN: - com_err (message_program_name, 0, "unknown user \"%.100s\"", - principal_name); - break; - default: - com_err (message_program_name, code, - "checking Kerberos password for %.100s", principal_name); - } - result = 0; - } else { - /* SUCCESS */ - result = 1; - } - - /* Cleanup */ - cleanup: - krb5_free_cred_contents (kcontext, &creds); - - return result; -} - -int -main (int argc, char *argv[]) -{ - struct auth_info *authinfo; - char *new_user; - - message_program_name = "auth_krb5"; - - /* Retrieve the username and passwd from nnrpd. */ - authinfo = get_auth_info(stdin); - - /* Must have a username/password, and no '@' in the address. @ checking - is there to prevent authentication against another Kerberos realm; there - should be a -r commandline option to make this check unnecessary - in the future. */ - if (authinfo == NULL) - die("no authentication information from nnrpd"); - if (authinfo->username[0] == '\0') - die("null username"); - if (strchr(authinfo->username, '@') != NULL) - die("username contains @, not allowed"); - - /* May need to prepend instance name if -i option was given. */ - if (argc > 1) { - if (argc == 3 && strcmp(argv[1], "-i") == 0) { - new_user = concat(authinfo->username, "/", argv[2], (char *) 0); - free(authinfo->username); - authinfo->username = new_user; - } else { - die("error parsing command-line options"); - } - } - - if (krb5_check_password(authinfo->username, authinfo->password)) { - printf("User:%s\r\n", authinfo->username); - exit(0); - } else { - die("failure validating password"); - } -} diff --git a/authprogs/auth_smb.c b/authprogs/auth_smb.c deleted file mode 100644 index 34fcc55..0000000 --- a/authprogs/auth_smb.c +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Samba authenticator. - * usage: auth_smb [] - * - * Heavily based on: - * pam_smb -- David Airlie 1998-2000 v1.1.6 - * http://www.csn.ul.ie/~airlied - * - * Written 2000 October by Krischan Jodies - * - */ - -#include "config.h" -#include "clibrary.h" -#include "inn/messages.h" - -#include "libauth.h" -#include "smbval/valid.h" - -int -main(int argc, char *argv[]) -{ - struct auth_info *authinfo; - int result; - char *server, *backup, *domain; - - message_program_name = "auth_smb"; - - if ((argc > 4) || (argc < 3)) - die("wrong number of arguments" - " (auth_smb [] "); - - authinfo = get_auth_info(stdin); - if (authinfo == NULL) - die("no user information provided by nnrpd"); - - /* Got a username and password. Now check to see if they're valid. */ - server = argv[1]; - backup = (argc > 3) ? argv[2] : argv[1]; - domain = (argc > 3) ? argv[3] : argv[2]; - result = Valid_User(authinfo->username, authinfo->password, server, - backup, domain); - - /* Analyze the result. */ - switch (result) { - case NTV_NO_ERROR: - printf("User:%s\n", authinfo->username); - exit(0); - break; - case NTV_SERVER_ERROR: - die("server error"); - break; - case NTV_PROTOCOL_ERROR: - die("protocol error"); - break; - case NTV_LOGON_ERROR: - die("logon error"); - break; - default: - die("unknown error"); - break; - } - - /* Never reached. */ - return 1; -} diff --git a/authprogs/ckpasswd.c b/authprogs/ckpasswd.c deleted file mode 100644 index e8f1db1..0000000 --- a/authprogs/ckpasswd.c +++ /dev/null @@ -1,411 +0,0 @@ -/* $Id: ckpasswd.c 7565 2006-08-28 02:42:54Z eagle $ -** -** The default username/password authenticator. -** -** This program is intended to be run by nnrpd and handle usernames and -** passwords. It can authenticate against a regular flat file (the type -** managed by htpasswd), a DBM file, the system password file or shadow file, -** or PAM. -*/ - -#include "config.h" -#include "clibrary.h" - -#include "inn/messages.h" -#include "inn/qio.h" -#include "inn/vector.h" -#include "libinn.h" - -#include "libauth.h" - -#if HAVE_CRYPT_H -# include -#endif -#include -#include -#include - -#if defined(HAVE_DBM) || defined(HAVE_BDB_DBM) -# if HAVE_NDBM_H -# include -# elif HAVE_BDB_DBM -# define DB_DBM_HSEARCH 1 -# include -# elif HAVE_GDBM_NDBM_H -# include -# elif HAVE_DB1_NDBM_H -# include -# endif -# define OPT_DBM "d:" -#else -# define OPT_DBM "" -#endif - -#if HAVE_GETSPNAM -# include -# define OPT_SHADOW "s" -#else -# define OPT_SHADOW "" -#endif - -#if HAVE_PAM -# if HAVE_PAM_PAM_APPL_H -# include -# else -# include -# endif -#endif - - -/* -** The PAM conversation function. -** -** Since we already have all the information and can't ask the user -** questions, we can't quite follow the real PAM protocol. Instead, we just -** return the password in response to every question that PAM asks. There -** appears to be no generic way to determine whether the message in question -** is indeed asking for the password.... -** -** This function allocates an array of struct pam_response to return to the -** PAM libraries that's never freed. For this program, this isn't much of an -** issue, since it will likely only be called once and then the program will -** exit. This function uses malloc and strdup instead of xmalloc and xstrdup -** intentionally so that the PAM conversation will be closed cleanly if we -** run out of memory rather than simply terminated. -** -** appdata_ptr contains the password we were given. -*/ -#if HAVE_PAM -static int -pass_conv(int num_msg, const struct pam_message **msgm UNUSED, - struct pam_response **response, void *appdata_ptr) -{ - int i; - - *response = malloc(num_msg * sizeof(struct pam_response)); - if (*response == NULL) - return PAM_CONV_ERR; - for (i = 0; i < num_msg; i++) { - (*response)[i].resp = strdup((char *)appdata_ptr); - (*response)[i].resp_retcode = 0; - } - return PAM_SUCCESS; -} -#endif /* HAVE_PAM */ - - -/* -** Authenticate a user via PAM. -** -** Attempts to authenticate a user with PAM, returning true if the user -** successfully authenticates and false otherwise. Note that this function -** doesn't attempt to handle any remapping of the authenticated user by the -** PAM stack, but just assumes that the authenticated user was the same as -** the username given. -** -** Right now, all failures are handled via die. This may be worth revisiting -** in case we want to try other authentication methods if this fails for a -** reason other than the system not having PAM support. -*/ -#if !HAVE_PAM -static bool -auth_pam(char *username UNUSED, char *password UNUSED) -{ - return false; -} -#else -static bool -auth_pam(const char *username, char *password) -{ - pam_handle_t *pamh; - struct pam_conv conv; - int status; - - conv.conv = pass_conv; - conv.appdata_ptr = password; - status = pam_start("nnrpd", username, &conv, &pamh); - if (status != PAM_SUCCESS) - die("pam_start failed: %s", pam_strerror(pamh, status)); - status = pam_authenticate(pamh, PAM_SILENT); - if (status != PAM_SUCCESS) - die("pam_authenticate failed: %s", pam_strerror(pamh, status)); - status = pam_acct_mgmt(pamh, PAM_SILENT); - if (status != PAM_SUCCESS) - die("pam_acct_mgmt failed: %s", pam_strerror(pamh, status)); - status = pam_end(pamh, status); - if (status != PAM_SUCCESS) - die("pam_end failed: %s", pam_strerror(pamh, status)); - - /* If we get to here, the user successfully authenticated. */ - return true; -} -#endif /* HAVE_PAM */ - - -/* -** Try to get a password out of a dbm file. The dbm file should have the -** username for the key and the crypted password as the value. The crypted -** password, if found, is returned as a newly allocated string; otherwise, -** NULL is returned. -*/ -#if !(defined(HAVE_DBM) || defined(HAVE_BDB_DBM)) -static char * -password_dbm(char *user UNUSED, const char *file UNUSED) -{ - return NULL; -} -#else -static char * -password_dbm(char *name, const char *file) -{ - datum key, value; - DBM *database; - char *password; - - database = dbm_open(file, O_RDONLY, 0600); - if (database == NULL) - return NULL; - key.dptr = name; - key.dsize = strlen(name); - value = dbm_fetch(database, key); - if (value.dptr == NULL) { - dbm_close(database); - return NULL; - } - password = xmalloc(value.dsize + 1); - strlcpy(password, value.dptr, value.dsize + 1); - dbm_close(database); - return password; -} -#endif /* HAVE_DBM || HAVE_BDB_DBM */ - - -/* -** Try to get a password out of the system /etc/shadow file. The crypted -** password, if found, is returned as a newly allocated string; otherwise, -** NULL is returned. -*/ -#if !HAVE_GETSPNAM -static char * -password_shadow(const char *user UNUSED) -{ - return NULL; -} -#else -static char * -password_shadow(const char *user) -{ - struct spwd *spwd; - - spwd = getspnam(user); - if (spwd != NULL) - return xstrdup(spwd->sp_pwdp); - return NULL; -} -#endif /* HAVE_GETSPNAM */ - - -/* -** Try to get a password out of a file. The crypted password, if found, is -** returned as a newly allocated string; otherwise, NULL is returned. -*/ -static char * -password_file(const char *username, const char *file) -{ - QIOSTATE *qp; - char *line, *password; - struct cvector *info = NULL; - - qp = QIOopen(file); - if (qp == NULL) - return NULL; - for (line = QIOread(qp); line != NULL; line = QIOread(qp)) { - if (*line == '#' || *line == '\n') - continue; - info = cvector_split(line, ':', info); - if (info->count < 2 || strcmp(info->strings[0], username) != 0) - continue; - password = xstrdup(info->strings[1]); - QIOclose(qp); - cvector_free(info); - return password; - } - if (QIOtoolong(qp)) - die("line too long in %s", file); - if (QIOerror(qp)) - sysdie("error reading %s", file); - QIOclose(qp); - cvector_free(info); - return NULL; -} - - -/* -** Try to get a password out of the system password file. The crypted -** password, if found, is returned as a newly allocated string; otherwise, -** NULL is returned. -*/ -static char * -password_system(const char *username) -{ - struct passwd *pwd; - - pwd = getpwnam(username); - if (pwd != NULL) - return xstrdup(pwd->pw_passwd); - return NULL; -} - - -/* -** Try to get the name of a user's primary group out of the system group -** file. The group, if found, is returned as a newly allocated string; -** otherwise, NULL is returned. If the username is not found, NULL is -** returned. -*/ -static char * -group_system(const char *username) -{ - struct passwd *pwd; - struct group *gr; - - pwd = getpwnam(username); - if (pwd == NULL) - return NULL; - gr = getgrgid(pwd->pw_gid); - if (gr == NULL) - return NULL; - return xstrdup(gr->gr_name); -} - - -/* -** Output username (and group, if desired) in correct return format. -*/ -static void -output_user(const char *username, bool wantgroup) -{ - if (wantgroup) { - char *group = group_system(username); - if (group == NULL) - die("group info for user %s not available", username); - printf("User:%s@%s\n", username, group); - } - else - printf("User:%s\n", username); -} - - -/* -** Main routine. -** -** We handle the variences between systems with #if blocks above, so that -** this code can look fairly clean. -*/ -int -main(int argc, char *argv[]) -{ - enum authtype { AUTH_NONE, AUTH_SHADOW, AUTH_FILE, AUTH_DBM }; - - int opt; - enum authtype type = AUTH_NONE; - bool wantgroup = false; - const char *filename = NULL; - struct auth_info *authinfo = NULL; - char *password = NULL; - - message_program_name = "ckpasswd"; - - while ((opt = getopt(argc, argv, "gf:u:p:" OPT_DBM OPT_SHADOW)) != -1) { - switch (opt) { - case 'g': - if (type == AUTH_DBM || type == AUTH_FILE) - die("-g option is incompatible with -d or -f"); - wantgroup = true; - break; - case 'd': - if (type != AUTH_NONE) - die("only one of -s, -f, or -d allowed"); - if (wantgroup) - die("-g option is incompatible with -d or -f"); - type = AUTH_DBM; - filename = optarg; - break; - case 'f': - if (type != AUTH_NONE) - die("only one of -s, -f, or -d allowed"); - if (wantgroup) - die("-g option is incompatible with -d or -f"); - type = AUTH_FILE; - filename = optarg; - break; - case 's': - if (type != AUTH_NONE) - die("only one of -s, -f, or -d allowed"); - type = AUTH_SHADOW; - break; - case 'u': - if (authinfo == NULL) { - authinfo = xmalloc(sizeof(struct auth_info)); - authinfo->password = NULL; - } - authinfo->username = optarg; - break; - case 'p': - if (authinfo == NULL) { - authinfo = xmalloc(sizeof(struct auth_info)); - authinfo->username = NULL; - } - authinfo->password = optarg; - break; - default: - exit(1); - } - } - if (argc != optind) - die("extra arguments given"); - if (authinfo != NULL && authinfo->username == NULL) - die("-u option is required if -p option is given"); - if (authinfo != NULL && authinfo->password == NULL) - die("-p option is required if -u option is given"); - - /* Unless a username or password was given on the command line, assume - we're being run by nnrpd. */ - if (authinfo == NULL) - authinfo = get_auth_info(stdin); - if (authinfo == NULL) - die("no authentication information from nnrpd"); - if (authinfo->username[0] == '\0') - die("null username"); - - /* Run the appropriate authentication routines. */ - switch (type) { - case AUTH_SHADOW: - password = password_shadow(authinfo->username); - if (password == NULL) - password = password_system(authinfo->username); - break; - case AUTH_FILE: - password = password_file(authinfo->username, filename); - break; - case AUTH_DBM: - password = password_dbm(authinfo->username, filename); - break; - case AUTH_NONE: - if (auth_pam(authinfo->username, authinfo->password)) { - output_user(authinfo->username, wantgroup); - exit(0); - } - password = password_system(authinfo->username); - break; - } - - if (password == NULL) - die("user %s unknown", authinfo->username); - if (strcmp(password, crypt(authinfo->password, password)) != 0) - die("invalid password for user %s", authinfo->username); - - /* The password matched. */ - output_user(authinfo->username, wantgroup); - exit(0); -} diff --git a/authprogs/domain.c b/authprogs/domain.c deleted file mode 100644 index e4e0f4f..0000000 --- a/authprogs/domain.c +++ /dev/null @@ -1,49 +0,0 @@ -/* $Id: domain.c 7141 2005-03-17 11:42:46Z vinocur $ -** -** Domain authenticator. -** -** Compares the domain of the client connection to the first argument given -** on the command line, and returns the host portion of the connecting host -** as the user if it matches. -*/ - -#include "config.h" -#include "clibrary.h" - -#include "inn/messages.h" -#include "libinn.h" -#include "libauth.h" - -int -main(int argc, char *argv[]) -{ - char *p, *host; - struct res_info *res; - - if (argc != 2) - die("Usage: domain "); - message_program_name = "domain"; - - /* Read the connection information from stdin. */ - res = get_res_info(stdin); - if (res == NULL) - die("did not get ClientHost data from nnrpd"); - host = res->clienthostname; - - /* Check the host against the provided domain. Allow the domain to be - specified both with and without a leading period; if without, make sure - that there is a period right before where it matches in the host. */ - p = strstr(host, argv[1]); - if (p == host) - die("host %s matches the domain exactly", host); - if (p == NULL || (argv[1][0] != '.' && p != host && *(p - 1) != '.')) - die("host %s didn't match domain %s", host, argv[1]); - - /* Peel off the portion of the host before where the provided domain - matches and return it as the user. */ - if (argv[1][0] != '.') - p--; - *p = '\0'; - printf("User:%s\n", host); - return 0; -} diff --git a/authprogs/ident.c b/authprogs/ident.c deleted file mode 100644 index ac728e1..0000000 --- a/authprogs/ident.c +++ /dev/null @@ -1,179 +0,0 @@ -/* $Id: ident.c 6135 2003-01-19 01:15:40Z rra $ -** -** Ident authenticator. -*/ - -#include "config.h" -#include "clibrary.h" -#include -#include -#include -#include - -#include "inn/messages.h" -#include "libinn.h" - -#include "libauth.h" - -#define IDENT_PORT 113 - -static void out(int sig UNUSED) { - exit(1); -} - -int main(int argc, char *argv[]) -{ - struct servent *s; - char buf[2048]; - struct res_info *res; - struct sockaddr_in *lsin, *csin; -#ifdef HAVE_INET6 - struct sockaddr_storage *lss; - struct sockaddr_in6 *lsin6, *csin6; -#endif - int sock; - int opt; - int truncate_domain = 0; - char *iter; - char *p; - unsigned int got; - int lport, cport, identport; - char *endstr; - - message_program_name = "ident"; - - xsignal_norestart(SIGALRM,out); - alarm(15); - - s = getservbyname("ident", "tcp"); - if (!s) - identport = IDENT_PORT; - else - identport = ntohs(s->s_port); - - while ((opt = getopt(argc, argv, "p:t")) != -1) { - switch (opt) { - case 'p': - for (iter = optarg; *iter; iter++) - if (*iter < '0' || *iter > '9') - break; - if (*iter) { - /* not entirely numeric */ - s = getservbyname(optarg, "tcp"); - if (s == NULL) - die("cannot getsrvbyname(%s, tcp)", optarg); - identport = s->s_port; - } else - identport = atoi(optarg); - break; - case 't': - truncate_domain = 1; - break; - } - } - - /* read the connection info from stdin */ - res = get_res_info(stdin); - if (res == NULL) - die("did not get client information from nnrpd"); - -#ifdef HAVE_INET6 - lss = (struct sockaddr_storage *)(res->local); - lsin6 = (struct sockaddr_in6 *)(res->local); - csin6 = (struct sockaddr_in6 *)(res->client); - if( lss->ss_family == AF_INET6 ) - { - lport = ntohs( lsin6->sin6_port ); - lsin6->sin6_port = 0; - cport = ntohs( csin6->sin6_port ); - csin6->sin6_port = htons( identport ); - sock = socket(PF_INET6, SOCK_STREAM, 0); - } else -#endif - { - lsin = (struct sockaddr_in *)(res->local); - lport = htons( lsin->sin_port ); - lsin->sin_port = 0; - csin = (struct sockaddr_in *)(res->client); - cport = htons( csin->sin_port ); - csin->sin_port = htons( identport ); - sock = socket(PF_INET, SOCK_STREAM, 0); - } - if (sock < 0) - sysdie("cannot create socket"); - if (bind(sock, res->local, SA_LEN(res->local)) < 0) - sysdie("cannot bind socket"); - if (connect(sock, res->client, SA_LEN(res->local)) < 0) { - if (errno != ECONNREFUSED) - sysdie("cannot connect to ident server"); - else - sysdie("client host does not accept ident connections"); - } - free_res_info(res); - - /* send the request out */ - snprintf(buf, sizeof(buf), "%d , %d\r\n", cport, lport); - opt = xwrite(sock, buf, strlen(buf)); - if (opt < 0) - sysdie("cannot write to ident server"); - - /* get the answer back */ - got = 0; - do { - opt = read(sock, buf+got, sizeof(buf)-got); - if (opt < 0) - sysdie("cannot read from ident server"); - else if (!opt) - die("end of file from ident server before response"); - while (opt--) - if (buf[got] != '\n') - got++; - } while (buf[got] != '\n'); - buf[got] = '\0'; - if (buf[got-1] == '\r') - buf[got-1] = '\0'; - - /* buf now contains the entire ident response. */ - if (!(iter = strchr(buf, ':'))) - /* malformed response */ - die("malformed response \"%s\" from ident server", buf); - iter++; - - while (*iter && ISWHITE(*iter)) - iter++; - endstr = iter; - while (*endstr && *endstr != ':' && !ISWHITE(*endstr)) - endstr++; - if (!*endstr) - /* malformed response */ - die("malformed response \"%s\" from ident server", buf); - if (*endstr != ':') { - *endstr++ = '\0'; - while (*endstr != ':') - endstr++; - } - - *endstr = '\0'; - - if (strcmp(iter, "ERROR") == 0) - die("ident server reported an error"); - else if (strcmp(iter, "USERID") != 0) - die("ident server returned \"%s\", not USERID", iter); - - /* skip the operating system */ - if (!(iter = strchr(endstr+1, ':'))) - exit(1); - - /* everything else is username */ - iter++; - while (*iter && ISWHITE(*iter)) - iter++; - if (!*iter || *iter == '[') - /* null, or encrypted response */ - die("ident response is null or encrypted"); - if ((truncate_domain == 1) && ((p = strchr(iter, '@')) != NULL)) - *p = '\0'; - printf("User:%s\n", iter); - - exit(0); -} diff --git a/authprogs/libauth.c b/authprogs/libauth.c deleted file mode 100644 index c99dcd9..0000000 --- a/authprogs/libauth.c +++ /dev/null @@ -1,216 +0,0 @@ -/* $Id: libauth.c 7500 2006-03-20 01:52:44Z eagle $ -** -** Common code for authenticators and resolvers. -** -** Collects common code to read information from nnrpd that should be done -** the same for all authenticators, and common code to get information about -** the incoming connection. -*/ - -#include "config.h" -#include "clibrary.h" -#include "libinn.h" - -#include "libauth.h" -#include "inn/messages.h" - -#define NAMESTR "ClientAuthname: " -#define PASSSTR "ClientPassword: " - -#define CLIHOST "ClientHost: " -#define CLIIP "ClientIP: " -#define CLIPORT "ClientPort: " -#define LOCIP "LocalIP: " -#define LOCPORT "LocalPort: " - -#ifdef HAVE_INET6 -# include -#endif - -/* Main loop. If res != NULL, expects to get resolver info from nnrpd, and - writes it into the struct. If auth != NULL, expects to get authentication - info from nnrpd, and writes it into the struct. */ - -static bool -get_connection_info(FILE *stream, struct res_info *res, struct auth_info *auth) -{ - char buff[SMBUF]; - size_t length; - char *cip = NULL, *sip = NULL, *cport = NULL, *sport = NULL; -#ifdef HAVE_INET6 - struct addrinfo *r, hints; -#else - struct sockaddr_in *loc_sin, *cli_sin; -#endif - - /* Zero fields first (anything remaining NULL after is missing data) */ - if (res != NULL) { - res->clienthostname = NULL; - res->client = NULL; - res->local = NULL; - } - if (auth != NULL) { - auth->username = NULL; - auth->password = NULL; - } - - /* Read input from nnrpd a line at a time, stripping \r\n. */ - while (fgets(buff, sizeof(buff), stream) != NULL) { - length = strlen(buff); - if (length == 0 || buff[length - 1] != '\n') - goto error; - buff[length - 1] = '\0'; - if (length > 1 && buff[length - 2] == '\r') - buff[length - 2] = '\0'; - - /* Parse */ - if (strncmp(buff, ".", 2) == 0) - break; - else if (auth != NULL && strncmp(buff, NAMESTR, strlen(NAMESTR)) == 0) - auth->username = xstrdup(buff + strlen(NAMESTR)); - else if (auth != NULL && strncmp(buff, PASSSTR, strlen(PASSSTR)) == 0) - auth->password = xstrdup(buff + strlen(PASSSTR)); - else if (res != NULL && strncmp(buff, CLIHOST, strlen(CLIHOST)) == 0) - res->clienthostname = xstrdup(buff + strlen(CLIHOST)); - else if (res != NULL && strncmp(buff, CLIIP, strlen(CLIIP)) == 0) - cip = xstrdup(buff + strlen(CLIIP)); - else if (res != NULL && strncmp(buff, CLIPORT, strlen(CLIPORT)) == 0) - cport = xstrdup(buff + strlen(CLIPORT)); - else if (res != NULL && strncmp(buff, LOCIP, strlen(LOCIP)) == 0) - sip = xstrdup(buff + strlen(LOCIP)); - else if (res != NULL && strncmp(buff, LOCPORT, strlen(LOCPORT)) == 0) - sport = xstrdup(buff + strlen(LOCPORT)); - else { - /**** We just ignore excess fields for now ****/ - - /* warn("libauth: unexpected data from nnrpd: \"%s\"", buff); */ - /* goto error; */ - } - } - - /* If some field is missing, free the rest and error out. */ - if (auth != NULL && (auth->username == NULL || auth->password == NULL)) { - warn("libauth: requested authenticator data not sent by nnrpd"); - goto error; - } - if (res != NULL && (res->clienthostname == NULL || cip == NULL || - cport == NULL || sip == NULL || sport == NULL)) { - warn("libauth: requested resolver data not sent by nnrpd"); - goto error; - } - - /* Generate sockaddrs from IP and port strings */ - if (res != NULL) { -#ifdef HAVE_INET6 - /* sockaddr_in6 may be overkill for PF_INET case, but oh well */ - res->client = xcalloc(1, sizeof(struct sockaddr_in6)); - res->local = xcalloc(1, sizeof(struct sockaddr_in6)); - - memset( &hints, 0, sizeof( hints ) ); - hints.ai_flags = AI_NUMERICHOST; - hints.ai_socktype = SOCK_STREAM; - - hints.ai_family = strchr( cip, ':' ) != NULL ? PF_INET6 : PF_INET; - if( getaddrinfo( cip, cport, &hints, &r ) != 0) - goto error; - if( r->ai_addrlen > sizeof(struct sockaddr_in6) ) - goto error; - memcpy( res->client, r->ai_addr, r->ai_addrlen ); - freeaddrinfo( r ); - - hints.ai_family = strchr( sip, ':' ) != NULL ? PF_INET6 : PF_INET; - if( getaddrinfo( sip, sport, &hints, &r ) != 0) - goto error; - if( r->ai_addrlen > sizeof(struct sockaddr_in6) ) - goto error; - memcpy( res->local, r->ai_addr, r->ai_addrlen ); - freeaddrinfo( r ); -#else - res->client = xcalloc(1, sizeof(struct sockaddr_in)); - res->local = xcalloc(1, sizeof(struct sockaddr_in)); - - cli_sin = (struct sockaddr_in *)(res->client); - loc_sin = (struct sockaddr_in *)(res->local); - cli_sin->sin_family = AF_INET; - if (!inet_aton(cip, &cli_sin->sin_addr)) - goto error; - cli_sin->sin_port = htons( atoi(cport) ); - - loc_sin->sin_family = AF_INET; - if (!inet_aton(sip, &loc_sin->sin_addr)) - goto error; - loc_sin->sin_port = htons( atoi(sport) ); - -# ifdef HAVE_SOCKADDR_LEN - cli_sin->sin_len = sizeof(struct sockaddr_in); - loc_sin->sin_len = sizeof(struct sockaddr_in); -# endif -#endif - - free(sip); - free(sport); - free(cip); - free(cport); - } - - return true; - -error: - if (auth != NULL && auth->username != NULL) free(auth->username); - if (auth != NULL && auth->password != NULL) free(auth->password); - if (res != NULL && res->clienthostname != NULL) free(res->clienthostname); - if (res != NULL && res->client != NULL) free(res->client); - if (res != NULL && res->local != NULL) free(res->local); - if (sip != NULL) free(sip); - if (sport != NULL) free(sport); - if (cip != NULL) free(cip); - if (cport != NULL) free(cport); - return false; -} - - -/* Wrappers to read information from nnrpd, returning an allocated struct on - success. */ - -struct res_info * -get_res_info(FILE *stream) { - struct res_info *res = xmalloc(sizeof(struct res_info)); - - if(get_connection_info(stream, res, NULL)) - return res; - - free(res); - return NULL; -} - - -struct auth_info * -get_auth_info(FILE *stream) { - struct auth_info *auth = xmalloc(sizeof(struct auth_info)); - - if(get_connection_info(stream, NULL, auth)) - return auth; - - free(auth); - return NULL; -} - -void -free_res_info(struct res_info *res) { - if(res == NULL) - return; - if(res->client != NULL) free(res->client); - if(res->local != NULL) free(res->local); - if(res->clienthostname != NULL) free(res->clienthostname); - free(res); -} - -void -free_auth_info(struct auth_info *auth) { - if(auth == NULL) - return; - if(auth->username != NULL) free(auth->username); - if(auth->password != NULL) free(auth->password); - free(auth); -} - diff --git a/authprogs/libauth.h b/authprogs/libauth.h deleted file mode 100644 index faa6520..0000000 --- a/authprogs/libauth.h +++ /dev/null @@ -1,39 +0,0 @@ -/* -** -** Common headers for authenticators and resolvers. -** -*/ - -#include "config.h" -#include "portable/socket.h" - -/* Holds the resolver information from nnrpd. */ -struct res_info { - struct sockaddr *client; - struct sockaddr *local; - char *clienthostname; -}; - -/* Holds the authentication information from nnrpd. */ -struct auth_info { - char *username; - char *password; -}; - -/* - * Reads connection information from a file descriptor (normally stdin, when - * talking to nnrpd) and returns a new res_info or auth_info struct, or - * returns NULL on failure. Note that the fields will never be NULL; if the - * corresponding information is missing, it is an error (which will be - * logged and NULL will be returned). The client is responsible for freeing - * the struct and its fields; this can be done by calling the appropriate - * destruction function below. - */ - -extern struct auth_info *get_auth_info(FILE *); -extern struct res_info *get_res_info (FILE *); - -extern void free_auth_info(struct auth_info*); -extern void free_res_info (struct res_info*); - - diff --git a/authprogs/radius.c b/authprogs/radius.c deleted file mode 100644 index e6da348..0000000 --- a/authprogs/radius.c +++ /dev/null @@ -1,564 +0,0 @@ -/* $Id: radius.c 7745 2008-04-06 10:18:54Z iulius $ -** -** Authenticate a user against a remote radius server. -*/ - -#include "config.h" -#include "clibrary.h" -#include "portable/time.h" -#include -#include -#include -#include -#include - -/* Needed on AIX 4.1 to get fd_set and friends. */ -#if HAVE_SYS_SELECT_H -# include -#endif - -#include "inn/innconf.h" -#include "inn/md5.h" -#include "inn/messages.h" -#include "libinn.h" -#include "nntp.h" -#include "paths.h" -#include "conffile.h" - -#include "libauth.h" - -#define RADIUS_LOCAL_PORT NNTP_PORT - -#define AUTH_VECTOR_LEN 16 - -typedef struct _auth_req { - unsigned char code; - unsigned char id; - unsigned short length; - unsigned char vector[AUTH_VECTOR_LEN]; - unsigned char data[NNTP_STRLEN*2]; - int datalen; -} auth_req; - -typedef struct _rad_config_t { - char *secret; /* pseudo encryption thingy secret that radius uses */ - - char *radhost; /* parameters for talking to the remote radius sever */ - int radport; - char *lochost; - int locport; - - char *prefix, *suffix; /* futz with the username, if necessary */ - int ignore_source; - - struct _rad_config_t *next; /* point to any additional servers */ -} rad_config_t; - -typedef struct _sending_t { - auth_req req; - int reqlen; - struct sockaddr_in sinr; - struct _sending_t *next; -} sending_t; - -#define RADlbrace 1 -#define RADrbrace 2 -#define RADserver 10 -#define RADhost 11 -#define RADsecret 12 -#define RADport 13 -#define RADlochost 14 -#define RADlocport 15 -#define RADprefix 16 -#define RADsuffix 17 -#define RADsource 18 - -static CONFTOKEN radtoks[] = { - { RADlbrace, "{" }, - { RADrbrace, "}" }, - { RADserver, "server" }, - { RADhost, "radhost:" }, - { RADsecret, "secret:" }, - { RADport, "radport:" }, - { RADlochost, "lochost:" }, - { RADlocport, "locport:" }, - { RADprefix, "prefix:" }, - { RADsuffix, "suffix:" }, - { RADsource, "ignore-source:" }, - { 0, 0 } -}; - -static rad_config_t *get_radconf(void) -{ - rad_config_t *new; - - new = xcalloc(1, sizeof(rad_config_t)); - new->next = NULL; - - return new; -} - -static int read_config(char *authfile, rad_config_t *radconf) -{ - int inbrace; - rad_config_t *radconfig=NULL; - CONFFILE *file; - CONFTOKEN *token; - char *server; - int type; - char *iter; - - if ((file = CONFfopen(authfile)) == NULL) - sysdie("cannot open config file %s", authfile); - - inbrace = 0; - while ((token = CONFgettoken(radtoks, file)) != NULL) { - if (!inbrace) { - if (token->type != RADserver) - die("expected server keyword on line %d", file->lineno); - if ((token = CONFgettoken(0, file)) == NULL) - die("expected server name on line %d", file->lineno); - server = xstrdup(token->name); - if ((token = CONFgettoken(radtoks, file)) == NULL - || token->type != RADlbrace) - die("expected { on line %d", file->lineno); - inbrace = 1; - - if (radconfig == NULL) - radconfig = radconf; - else { - radconfig->next = get_radconf(); - radconfig = radconfig->next; - } - } - else { - type = token->type; - if (type == RADrbrace) - inbrace = 0; - else { - if ((token = CONFgettoken(0, file)) == NULL) - die("keyword with no value on line %d", file->lineno); - iter = token->name; - - /* what are we setting? */ - switch(type) { - case RADsecret: - if (radconfig->secret) continue; - radconfig->secret = xstrdup(iter); - break; - case RADhost: - if (radconfig->radhost) continue; - radconfig->radhost = xstrdup(iter); - break; - case RADport: - if (radconfig->radport) continue; - radconfig->radport = atoi(iter); - break; - case RADlochost: - if (radconfig->lochost) continue; - radconfig->lochost = xstrdup(iter); - break; - case RADlocport: - if (radconfig->locport) continue; - radconfig->locport = atoi(iter); - break; - case RADprefix: - if (radconfig->prefix) continue; - radconfig->prefix = xstrdup(iter); - break; - case RADsuffix: - if (radconfig->suffix) continue; - radconfig->suffix = xstrdup(iter); - break; - case RADsource: - if (!strcasecmp(iter, "true")) - radconfig->ignore_source = 1; - else if (!strcasecmp(iter, "false")) - radconfig->ignore_source = 0; - else - die("expected true or false after ignore-source on line %d", - file->lineno); - break; - default: - die("unknown keyword on line %d", file->lineno); - } - } - } - } - - CONFfclose(file); - - if (!radconf->radhost) - die("no radius host specified"); - else if (!radconf->secret) - die("no shared secret with radius host specified"); - - return(0); -} - -#define PW_AUTH_UDP_PORT 1645 - -#define PW_AUTHENTICATION_REQUEST 1 -#define PW_AUTHENTICATION_ACK 2 -#define PW_AUTHENTICATION_REJECT 3 - -#define PW_USER_NAME 1 -#define PW_PASSWORD 2 - -#define PW_SERVICE_TYPE 6 -#define PW_SERVICE_AUTH_ONLY 8 - -#define RAD_NAS_IP_ADDRESS 4 /* IP address */ -#define RAD_NAS_PORT 5 /* Integer */ - -static void req_copyto (auth_req to, sending_t *from) -{ - to = from->req; -} - -static void req_copyfrom (sending_t *to, auth_req from) -{ - to->req = from; -} - -static int rad_auth(rad_config_t *radconfig, char *uname, char *pass) -{ - auth_req req; - int i, j, jlen, passstart; - unsigned char secbuf[128]; - char hostname[SMBUF]; - unsigned char digest[MD5_DIGESTSIZE]; - struct timeval seed; - struct sockaddr_in sinl; - int sock; - struct hostent *hent; - int passlen; - time_t now, end; - struct timeval tmout; - int got; - fd_set rdfds; - uint32_t nvalue; - socklen_t slen; - int authtries= 3; /* number of times to try reaching the radius server */ - rad_config_t *config; - sending_t *reqtop, *sreq, *new; - int done; - - /* set up the linked list */ - config = radconfig; - - if (config == NULL) { - warn("no configuration file"); - return(-2); - } else { - /* setting sreq to NULL guarantees reqtop will be properly set later */ - sreq = NULL; - reqtop = NULL; - } - - while (config != NULL){ - new = xmalloc(sizeof(sending_t)); - new->next = NULL; - - if (sreq == NULL){ - reqtop = new; - sreq = new; - } else { - sreq->next = new; - sreq = sreq->next; - } - req_copyto(req, sreq); - - /* first, build the sockaddrs */ - memset(&sinl, '\0', sizeof(sinl)); - memset(&sreq->sinr, '\0', sizeof(sreq->sinr)); - sinl.sin_family = AF_INET; - sreq->sinr.sin_family = AF_INET; - if (config->lochost == NULL) { - if (gethostname(hostname, sizeof(hostname)) != 0) { - syswarn("cannot get local hostname"); - return(-2); - } - config->lochost = xstrdup(hostname); - } - if (config->lochost) { - if (inet_aton(config->lochost, &sinl.sin_addr) != 1) { - if ((hent = gethostbyname(config->lochost)) == NULL) { - warn("cannot gethostbyname lochost %s", config->lochost); - return(-2); - } - memcpy(&sinl.sin_addr.s_addr, hent->h_addr, - sizeof(struct in_addr)); - } - } - if (inet_aton(config->radhost, &sreq->sinr.sin_addr) != 1) { - if ((hent = gethostbyname(config->radhost)) == NULL) { - warn("cannot gethostbyname radhost %s", config->radhost); - return(-2); - } - memcpy(&sreq->sinr.sin_addr.s_addr, hent->h_addr_list[0], - sizeof(struct in_addr)); - } - - if (config->radport) - sreq->sinr.sin_port = htons(config->radport); - else - sreq->sinr.sin_port = htons(PW_AUTH_UDP_PORT); - - /* seed the random number generator for the auth vector */ - gettimeofday(&seed, 0); - srandom((unsigned) seed.tv_sec+seed.tv_usec); - /* build the visible part of the auth vector randomly */ - for (i = 0; i < AUTH_VECTOR_LEN; i++) - req.vector[i] = random() % 256; - strlcpy((char *) secbuf, config->secret, sizeof(secbuf)); - memcpy(secbuf+strlen(config->secret), req.vector, AUTH_VECTOR_LEN); - md5_hash(secbuf, strlen(config->secret)+AUTH_VECTOR_LEN, digest); - /* fill in the auth_req data */ - req.code = PW_AUTHENTICATION_REQUEST; - req.id = 0; - - /* bracket the username in the configured prefix/suffix */ - req.data[0] = PW_USER_NAME; - req.data[1] = 2; - req.data[2] = '\0'; - if (config->prefix) { - req.data[1] += strlen(config->prefix); - strlcat((char *) &req.data[2], config->prefix, sizeof(req.data) - 2); - } - req.data[1] += strlen(uname); - strlcat((char *)&req.data[2], uname, sizeof(req.data) - 2); - if (!strchr(uname, '@') && config->suffix) { - req.data[1] += strlen(config->suffix); - strlcat((char *)&req.data[2], config->suffix, sizeof(req.data) - 2); - } - req.datalen = req.data[1]; - - /* set the password */ - passstart = req.datalen; - req.data[req.datalen] = PW_PASSWORD; - /* Null pad the password */ - passlen = (strlen(pass) + 15) / 16; - passlen *= 16; - req.data[req.datalen+1] = passlen+2; - strlcpy((char *)&req.data[req.datalen+2], pass, - sizeof(req.data) - req.datalen - 2); - passlen -= strlen(pass); - while (passlen--) - req.data[req.datalen+passlen+2+strlen(pass)] = '\0'; - req.datalen += req.data[req.datalen+1]; - - /* Add NAS_PORT and NAS_IP_ADDRESS into request */ - if ((nvalue = config->locport) == 0) - nvalue = RADIUS_LOCAL_PORT; - req.data[req.datalen++] = RAD_NAS_PORT; - req.data[req.datalen++] = sizeof(nvalue) + 2; - nvalue = htonl(nvalue); - memcpy(req.data + req.datalen, &nvalue, sizeof(nvalue)); - req.datalen += sizeof(nvalue); - req.data[req.datalen++] = RAD_NAS_IP_ADDRESS; - req.data[req.datalen++] = sizeof(struct in_addr) + 2; - memcpy(req.data + req.datalen, &sinl.sin_addr.s_addr, - sizeof(struct in_addr)); - req.datalen += sizeof(struct in_addr); - - /* we're only doing authentication */ - req.data[req.datalen] = PW_SERVICE_TYPE; - req.data[req.datalen+1] = 6; - req.data[req.datalen+2] = (PW_SERVICE_AUTH_ONLY >> 24) & 0x000000ff; - req.data[req.datalen+3] = (PW_SERVICE_AUTH_ONLY >> 16) & 0x000000ff; - req.data[req.datalen+4] = (PW_SERVICE_AUTH_ONLY >> 8) & 0x000000ff; - req.data[req.datalen+5] = PW_SERVICE_AUTH_ONLY & 0x000000ff; - req.datalen += req.data[req.datalen+1]; - - /* filled in the data, now we know what the actual length is. */ - req.length = 4+AUTH_VECTOR_LEN+req.datalen; - - /* "encrypt" the password */ - for (i = 0; i < req.data[passstart+1]-2; i += sizeof(HASH)) { - jlen = sizeof(HASH); - if (req.data[passstart+1]-(unsigned)i-2 < sizeof(HASH)) - jlen = req.data[passstart+1]-i-2; - for (j = 0; j < jlen; j++) - req.data[passstart+2+i+j] ^= digest[j]; - if (jlen == sizeof(HASH)) { - /* Recalculate the digest from the HASHed previous */ - strlcpy((char *) secbuf, config->secret, sizeof(secbuf)); - memcpy(secbuf+strlen(config->secret), &req.data[passstart+2+i], - sizeof(HASH)); - md5_hash(secbuf, strlen(config->secret)+sizeof(HASH), digest); - } - } - sreq->reqlen = req.length; - req.length = htons(req.length); - - req_copyfrom(sreq, req); - - /* Go to the next record in the list */ - config = config->next; - } - - /* YAYY! The auth_req is ready to go! Build the reply socket and send out - * the message. */ - - /* now, build the sockets */ - if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { - syswarn("cannot build reply socket"); - return(-1); - } - if (bind(sock, (struct sockaddr*) &sinl, sizeof(sinl)) < 0) { - syswarn("cannot bind reply socket"); - close(sock); - return(-1); - } - - for(done = 0; authtries > 0 && !done; authtries--) { - for (config = radconfig, sreq = reqtop; sreq != NULL && !done; - config = config->next, sreq = sreq->next){ - req_copyto(req, sreq); - - /* send out the packet and wait for reply. */ - if (sendto(sock, (char *)&req, sreq->reqlen, 0, - (struct sockaddr*) &sreq->sinr, - sizeof (struct sockaddr_in)) < 0) { - syswarn("cannot send auth_reg"); - close(sock); - return(-1); - } - - /* wait 5 seconds maximum for a radius reply. */ - now = time(0); - end = now+5; - tmout.tv_sec = 6; - tmout.tv_usec = 0; - FD_ZERO(&rdfds); - /* store the old vector to verify next checksum */ - memcpy(secbuf+sizeof(req.vector), req.vector, sizeof(req.vector)); - FD_SET(sock, &rdfds); - got = select(sock+1, &rdfds, 0, 0, &tmout); - if (got < 0) { - syswarn("cannot not select"); - break; - } else if (got == 0) { - /* timer ran out */ - now = time(0); - tmout.tv_sec = end - now + 1; - tmout.tv_usec = 0; - continue; - } - slen = sizeof(sinl); - if ((jlen = recvfrom(sock, (char *)&req, sizeof(req)-sizeof(int), 0, - (struct sockaddr*) &sinl, &slen)) < 0) { - syswarn("cannot recvfrom"); - break; - } - if (!config->ignore_source) { - if (sinl.sin_addr.s_addr != sreq->sinr.sin_addr.s_addr || - (sinl.sin_port != sreq->sinr.sin_port)) { - warn("received unexpected UDP packet from %s:%d", - inet_ntoa(sinl.sin_addr), ntohs(sinl.sin_port)); - continue; - } - } - sreq->reqlen = ntohs(req.length); - if (jlen < 4+AUTH_VECTOR_LEN || jlen != sreq->reqlen) { - warn("received badly-sized packet"); - continue; - } - /* verify the checksum */ - memcpy(((char*)&req)+sreq->reqlen, config->secret, strlen(config->secret)); - memcpy(secbuf, req.vector, sizeof(req.vector)); - memcpy(req.vector, secbuf+sizeof(req.vector), sizeof(req.vector)); - md5_hash((unsigned char *)&req, strlen(config->secret)+sreq->reqlen, - digest); - if (memcmp(digest, secbuf, sizeof(HASH)) != 0) { - warn("checksum didn't match"); - continue; - } - /* FINALLY! Got back a known-good packet. See if we're in. */ - close(sock); - return (req.code == PW_AUTHENTICATION_ACK) ? 0 : -1; - done = 1; - req_copyfrom(sreq, req); - break; - } - } - if (authtries == 0) - warn("cannot talk to remote radius server %s:%d", - inet_ntoa(sreq->sinr.sin_addr), ntohs(sreq->sinr.sin_port)); - return(-2); -} - -#define RAD_HAVE_HOST 1 -#define RAD_HAVE_PORT 2 -#define RAD_HAVE_PREFIX 4 -#define RAD_HAVE_SUFFIX 8 -#define RAD_HAVE_LOCHOST 16 -#define RAD_HAVE_LOCPORT 32 - -int main(int argc, char *argv[]) -{ - int opt; - int havefile, haveother; - struct auth_info *authinfo; - rad_config_t radconfig; - int retval; - char *radius_config; - - message_program_name = "radius"; - - if (!innconf_read(NULL)) - exit(1); - - memset(&radconfig, '\0', sizeof(rad_config_t)); - haveother = havefile = 0; - - while ((opt = getopt(argc, argv, "f:h")) != -1) { - switch (opt) { - case 'f': - if (haveother) - die("-f flag after another flag"); - if (!havefile) { - /* override the standard config completely if the user - * specifies an alternate config file */ - memset(&radconfig, '\0', sizeof(rad_config_t)); - havefile = 1; - } - read_config(optarg, &radconfig); - break; - case 'h': - printf("Usage: radius [-f config]\n"); - exit(0); - } - } - if (argc != optind) - exit(2); - if (!havefile) { - radius_config = concatpath(innconf->pathetc, _PATH_RADIUS_CONFIG); - read_config(radius_config, &radconfig); - - free(radius_config); - } - - authinfo = get_auth_info(stdin); - if (authinfo == NULL) - die("failed getting auth info"); - if (authinfo->username[0] == '\0') - die("empty username"); - - /* got username and password, check that they're valid */ - - retval = rad_auth(&radconfig, authinfo->username, authinfo->password); - if (retval == -1) - die("user %s password doesn't match", authinfo->username); - else if (retval == -2) - /* couldn't talk to the radius server.. output logged above. */ - exit(1); - else if (retval != 0) - die("unexpected return code from authentication function: %d", - retval); - - /* radius password matches! */ - printf("User:%s\n", authinfo->username); - exit(0); -} diff --git a/authprogs/smbval/Makefile b/authprogs/smbval/Makefile deleted file mode 100644 index 6bb6ef1..0000000 --- a/authprogs/smbval/Makefile +++ /dev/null @@ -1,51 +0,0 @@ -## $Id: Makefile 5789 2002-09-29 23:34:26Z rra $ - -include ../../Makefile.global - -top = ../.. -CFLAGS = $(GCFLAGS) - -ALL = smbvalid.a - -SOURCES = rfcnb-io.c rfcnb-util.c session.c smbdes.c \ - smbencrypt.c smblib-util.c smblib.c valid.c - -OBJECTS = $(SOURCES:.c=.o) - -all: $(ALL) - -warnings: - $(MAKE) COPT='$(WARNINGS)' all - -smbvalid.a: $(OBJECTS) - ar rc $@ $(OBJECTS) - $(RANLIB) $@ - -clobber clean distclean: - rm -f *.o smbvalid.a - -depend: Makefile $(SOURCES) - $(MAKEDEPEND) '$(CFLAGS)' $(SOURCES) - -# DO NOT DELETE THIS LINE -- make depend depends on it. -rfcnb-io.o: rfcnb-io.c ../../include/config.h \ - ../../include/inn/defines.h ../../include/clibrary.h rfcnb-priv.h \ - rfcnb-error.h rfcnb-common.h byteorder.h rfcnb-util.h rfcnb-io.h -rfcnb-util.o: rfcnb-util.c ../../include/config.h \ - ../../include/inn/defines.h ../../include/clibrary.h rfcnb-priv.h \ - rfcnb-error.h rfcnb-common.h byteorder.h rfcnb-util.h rfcnb-io.h -session.o: session.c ../../include/config.h \ - ../../include/inn/defines.h ../../include/clibrary.h rfcnb-priv.h \ - rfcnb-error.h rfcnb-common.h byteorder.h rfcnb-util.h -smbdes.o: smbdes.c -smbencrypt.o: smbencrypt.c ../../include/config.h \ - ../../include/inn/defines.h ../../include/clibrary.h smblib-priv.h \ - smblib-common.h byteorder.h -smblib-util.o: smblib-util.c ../../include/config.h \ - ../../include/inn/defines.h ../../include/clibrary.h smblib-priv.h \ - smblib-common.h byteorder.h rfcnb.h rfcnb-error.h rfcnb-common.h -smblib.o: smblib.c ../../include/config.h ../../include/inn/defines.h \ - ../../include/clibrary.h smblib-priv.h smblib-common.h byteorder.h \ - rfcnb.h rfcnb-error.h rfcnb-common.h -valid.o: valid.c ../../include/config.h ../../include/inn/defines.h \ - smblib-priv.h smblib-common.h byteorder.h valid.h diff --git a/authprogs/smbval/byteorder.h b/authprogs/smbval/byteorder.h deleted file mode 100644 index 9bea2b2..0000000 --- a/authprogs/smbval/byteorder.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - Unix SMB/Netbios implementation. - Version 1.9. - SMB Byte handling - Copyright (C) Andrew Tridgell 1992-1995 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -/* - This file implements macros for machine independent short and - int manipulation -*/ - -#undef CAREFUL_ALIGNMENT - -/* we know that the 386 can handle misalignment and has the "right" - byteorder */ -#ifdef __i386__ -#define CAREFUL_ALIGNMENT 0 -#endif - -#ifndef CAREFUL_ALIGNMENT -#define CAREFUL_ALIGNMENT 1 -#endif - -#define CVAL(buf,pos) (((unsigned char *)(buf))[pos]) -#define PVAL(buf,pos) ((unsigned)CVAL(buf,pos)) -#define SCVAL(buf,pos,val) (CVAL(buf,pos) = (val)) - - -#if CAREFUL_ALIGNMENT -#define SVAL(buf,pos) (PVAL(buf,pos)|PVAL(buf,(pos)+1)<<8) -#define IVAL(buf,pos) (SVAL(buf,pos)|SVAL(buf,(pos)+2)<<16) -#define SSVALX(buf,pos,val) (CVAL(buf,pos)=(val)&0xFF,CVAL(buf,pos+1)=(val)>>8) -#define SIVALX(buf,pos,val) (SSVALX(buf,pos,val&0xFFFF),SSVALX(buf,pos+2,val>>16)) -#define SVALS(buf,pos) ((int16)SVAL(buf,pos)) -#define IVALS(buf,pos) ((int32)IVAL(buf,pos)) -#define SSVAL(buf,pos,val) SSVALX((buf),(pos),((uint16)(val))) -#define SIVAL(buf,pos,val) SIVALX((buf),(pos),((uint32)(val))) -#define SSVALS(buf,pos,val) SSVALX((buf),(pos),((int16)(val))) -#define SIVALS(buf,pos,val) SIVALX((buf),(pos),((int32)(val))) -#else -/* this handles things for architectures like the 386 that can handle - alignment errors */ -/* - WARNING: This section is dependent on the length of int16 and int32 - being correct -*/ -#define SVAL(buf,pos) (*(uint16 *)((char *)(buf) + (pos))) -#define IVAL(buf,pos) (*(uint32 *)((char *)(buf) + (pos))) -#define SVALS(buf,pos) (*(int16 *)((char *)(buf) + (pos))) -#define IVALS(buf,pos) (*(int32 *)((char *)(buf) + (pos))) -#define SSVAL(buf,pos,val) SVAL(buf,pos)=((uint16)(val)) -#define SIVAL(buf,pos,val) IVAL(buf,pos)=((uint32)(val)) -#define SSVALS(buf,pos,val) SVALS(buf,pos)=((int16)(val)) -#define SIVALS(buf,pos,val) IVALS(buf,pos)=((int32)(val)) -#endif diff --git a/authprogs/smbval/rfcnb-common.h b/authprogs/smbval/rfcnb-common.h deleted file mode 100644 index ba09d7c..0000000 --- a/authprogs/smbval/rfcnb-common.h +++ /dev/null @@ -1,36 +0,0 @@ -/* UNIX RFCNB (RFC1001/RFC1002) NetBIOS implementation - - Version 1.0 - RFCNB Common Structures etc Defines - - Copyright (C) Richard Sharpe 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 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -/* A data structure we need */ - -typedef struct RFCNB_Pkt { - - char * data; /* The data in this portion */ - int len; - struct RFCNB_Pkt *next; - -} RFCNB_Pkt; - -void RFCNB_Free_Pkt(struct RFCNB_Pkt *pkt); diff --git a/authprogs/smbval/rfcnb-error.h b/authprogs/smbval/rfcnb-error.h deleted file mode 100644 index afa1328..0000000 --- a/authprogs/smbval/rfcnb-error.h +++ /dev/null @@ -1,48 +0,0 @@ -/* UNIX RFCNB (RFC1001/RFC1002) NetBIOS implementation - - Version 1.0 - RFCNB Error Response Defines - - Copyright (C) Richard Sharpe 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 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -/* Error responses */ - -#define RFCNBE_Bad -1 /* Bad response */ -#define RFCNBE_OK 0 - -/* these should follow the spec ... is there one ?*/ - -#define RFCNBE_NoSpace 1 /* Could not allocate space for a struct */ -#define RFCNBE_BadName 2 /* Could not translate a name */ -#define RFCNBE_BadRead 3 /* Read sys call failed */ -#define RFCNBE_BadWrite 4 /* Write Sys call failed */ -#define RFCNBE_ProtErr 5 /* Protocol Error */ -#define RFCNBE_ConGone 6 /* Connection dropped */ -#define RFCNBE_BadHandle 7 /* Handle passed was bad */ -#define RFCNBE_BadSocket 8 /* Problems creating socket */ -#define RFCNBE_ConnectFailed 9 /* Connect failed */ -#define RFCNBE_CallRejNLOCN 10 /* Call rejected, not listening on CN */ -#define RFCNBE_CallRejNLFCN 11 /* Call rejected, not listening for CN */ -#define RFCNBE_CallRejCNNP 12 /* Call rejected, called name not present */ -#define RFCNBE_CallRejInfRes 13/* Call rejetced, name ok, no resources */ -#define RFCNBE_CallRejUnSpec 14/* Call rejected, unspecified error */ -#define RFCNBE_BadParam 15/* Bad parameters passed ... */ -#define RFCNBE_Timeout 16/* IO Timed out */ diff --git a/authprogs/smbval/rfcnb-io.c b/authprogs/smbval/rfcnb-io.c deleted file mode 100644 index 3f030fa..0000000 --- a/authprogs/smbval/rfcnb-io.c +++ /dev/null @@ -1,310 +0,0 @@ -/* UNIX RFCNB (RFC1001/RFC1002) NEtBIOS implementation - - Version 1.0 - RFCNB IO Routines ... - - Copyright (C) Richard Sharpe 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 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include "config.h" -#include "clibrary.h" -#include -#include - -#include "rfcnb-priv.h" -#include "rfcnb-util.h" -#include "rfcnb-io.h" - -int RFCNB_Timeout = 0; /* Timeout in seconds ... */ - -/* Discard the rest of an incoming packet as we do not have space for it - in the buffer we allocated or were passed ... */ - -int RFCNB_Discard_Rest(struct RFCNB_Con *con, int len) - -{ char temp[100]; /* Read into here */ - int rest, this_read, bytes_read; - - /* len is the amount we should read */ - - rest = len; - - while (rest > 0) { - - this_read = (rest > sizeof(temp)?sizeof(temp):rest); - - bytes_read = read(con -> fd, temp, this_read); - - if (bytes_read <= 0) { /* Error so return */ - - if (bytes_read < 0) - RFCNB_errno = RFCNBE_BadRead; - else - RFCNB_errno = RFCNBE_ConGone; - - RFCNB_saved_errno = errno; - return(RFCNBE_Bad); - - } - - rest = rest - bytes_read; - - } - - return(0); - -} - - -/* Send an RFCNB packet to the connection. - - We just send each of the blocks linked together ... - - If we can, try to send it as one iovec ... - -*/ - -int RFCNB_Put_Pkt(struct RFCNB_Con *con, struct RFCNB_Pkt *pkt, int len) - -{ int len_sent, tot_sent, this_len; - struct RFCNB_Pkt *pkt_ptr; - char *this_data; - int i; - struct iovec io_list[10]; /* We should never have more */ - /* If we do, this will blow up ...*/ - - /* Try to send the data ... We only send as many bytes as len claims */ - /* We should try to stuff it into an IOVEC and send as one write */ - - - pkt_ptr = pkt; - len_sent = tot_sent = 0; /* Nothing sent so far */ - i = 0; - - while ((pkt_ptr != NULL) & (i < 10)) { /* Watch that magic number! */ - - this_len = pkt_ptr -> len; - this_data = pkt_ptr -> data; - if ((tot_sent + this_len) > len) - this_len = len - tot_sent; /* Adjust so we don't send too much */ - - /* Now plug into the iovec ... */ - - io_list[i].iov_len = this_len; - io_list[i].iov_base = this_data; - i++; - - tot_sent += this_len; - - if (tot_sent == len) break; /* Let's not send too much */ - - pkt_ptr = pkt_ptr -> next; - - } - - /* Set up an alarm if timeouts are set ... */ - - if (RFCNB_Timeout > 0) - alarm(RFCNB_Timeout); - - if ((len_sent = writev(con -> fd, io_list, i)) < 0) { /* An error */ - - con -> rfc_errno = errno; - if (errno == EINTR) /* We were interrupted ... */ - RFCNB_errno = RFCNBE_Timeout; - else - RFCNB_errno = RFCNBE_BadWrite; - RFCNB_saved_errno = errno; - return(RFCNBE_Bad); - - } - - if (len_sent < tot_sent) { /* Less than we wanted */ - if (errno == EINTR) /* We were interrupted */ - RFCNB_errno = RFCNBE_Timeout; - else - RFCNB_errno = RFCNBE_BadWrite; - RFCNB_saved_errno = errno; - return(RFCNBE_Bad); - } - - if (RFCNB_Timeout > 0) - alarm(0); /* Reset that sucker */ - - return(len_sent); - -} - -/* Read an RFCNB packet off the connection. - - We read the first 4 bytes, that tells us the length, then read the - rest. We should implement a timeout, but we don't just yet - -*/ - - -int RFCNB_Get_Pkt(struct RFCNB_Con *con, struct RFCNB_Pkt *pkt, int len) - -{ int read_len, pkt_len; - char hdr[RFCNB_Pkt_Hdr_Len]; /* Local space for the header */ - struct RFCNB_Pkt *pkt_frag; - int more, this_time, offset, frag_len, this_len; - bool seen_keep_alive = true; - - /* Read that header straight into the buffer */ - - if (len < RFCNB_Pkt_Hdr_Len) { /* What a bozo */ - - RFCNB_errno = RFCNBE_BadParam; - return(RFCNBE_Bad); - - } - - /* We discard keep alives here ... */ - - if (RFCNB_Timeout > 0) - alarm(RFCNB_Timeout); - - while (seen_keep_alive) { - - if ((read_len = read(con -> fd, hdr, sizeof(hdr))) < 0) { /* Problems */ - if (errno == EINTR) - RFCNB_errno = RFCNBE_Timeout; - else - RFCNB_errno = RFCNBE_BadRead; - RFCNB_saved_errno = errno; - return(RFCNBE_Bad); - - } - - /* Now we check out what we got */ - - if (read_len == 0) { /* Connection closed, send back eof? */ - - if (errno == EINTR) - RFCNB_errno = RFCNBE_Timeout; - else - RFCNB_errno = RFCNBE_ConGone; - RFCNB_saved_errno = errno; - return(RFCNBE_Bad); - - } - - if (RFCNB_Pkt_Type(hdr) != RFCNB_SESSION_KEEP_ALIVE) { - seen_keep_alive = false; - } - - } - - /* What if we got less than or equal to a hdr size in bytes? */ - - if (read_len < sizeof(hdr)) { /* We got a small packet */ - - /* Now we need to copy the hdr portion we got into the supplied packet */ - - memcpy(pkt -> data, hdr, read_len); /*Copy data */ - - return(read_len); - - } - - /* Now, if we got at least a hdr size, alloc space for rest, if we need it */ - - pkt_len = RFCNB_Pkt_Len(hdr); - - /* Now copy in the hdr */ - - memcpy(pkt -> data, hdr, sizeof(hdr)); - - /* Get the rest of the packet ... first figure out how big our buf is? */ - /* And make sure that we handle the fragments properly ... Sure should */ - /* use an iovec ... */ - - if (len < pkt_len) /* Only get as much as we have space for */ - more = len - RFCNB_Pkt_Hdr_Len; - else - more = pkt_len; - - this_time = 0; - - /* We read for each fragment ... */ - - if (pkt -> len == read_len){ /* If this frag was exact size */ - pkt_frag = pkt -> next; /* Stick next lot in next frag */ - offset = 0; /* then we start at 0 in next */ - } - else { - pkt_frag = pkt; /* Otherwise use rest of this frag */ - offset = RFCNB_Pkt_Hdr_Len; /* Otherwise skip the header */ - } - - frag_len = pkt_frag -> len; - - if (more <= frag_len) /* If len left to get less than frag space */ - this_len = more; /* Get the rest ... */ - else - this_len = frag_len - offset; - - while (more > 0) { - - if ((this_time = read(con -> fd, (pkt_frag -> data) + offset, this_len)) <= 0) { /* Problems */ - - if (errno == EINTR) { - - RFCNB_errno = RFCNB_Timeout; - - } - else { - if (this_time < 0) - RFCNB_errno = RFCNBE_BadRead; - else - RFCNB_errno = RFCNBE_ConGone; - } - - RFCNB_saved_errno = errno; - return(RFCNBE_Bad); - - } - - read_len = read_len + this_time; /* How much have we read ... */ - - /* Now set up the next part */ - - if (pkt_frag -> next == NULL) break; /* That's it here */ - - pkt_frag = pkt_frag -> next; - this_len = pkt_frag -> len; - offset = 0; - - more = more - this_time; - - } - - if (read_len < (pkt_len + sizeof(hdr))) { /* Discard the rest */ - - return(RFCNB_Discard_Rest(con, (pkt_len + sizeof(hdr)) - read_len)); - - } - - if (RFCNB_Timeout > 0) - alarm(0); /* Reset that sucker */ - - return(read_len + sizeof(RFCNB_Hdr)); -} diff --git a/authprogs/smbval/rfcnb-io.h b/authprogs/smbval/rfcnb-io.h deleted file mode 100644 index 753c7ae..0000000 --- a/authprogs/smbval/rfcnb-io.h +++ /dev/null @@ -1,28 +0,0 @@ -/* UNIX RFCNB (RFC1001/RFC1002) NetBIOS implementation - - Version 1.0 - RFCNB IO Routines Defines - - Copyright (C) Richard Sharpe 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 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -int RFCNB_Put_Pkt(struct RFCNB_Con *con, struct RFCNB_Pkt *pkt, int len); - -int RFCNB_Get_Pkt(struct RFCNB_Con *con, struct RFCNB_Pkt *pkt, int len); diff --git a/authprogs/smbval/rfcnb-priv.h b/authprogs/smbval/rfcnb-priv.h deleted file mode 100644 index a6b9da8..0000000 --- a/authprogs/smbval/rfcnb-priv.h +++ /dev/null @@ -1,115 +0,0 @@ -/* UNIX RFCNB (RFC1001/RFC1002) NetBIOS implementation - - Version 1.0 - RFCNB Defines - - Copyright (C) Richard Sharpe 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 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -/* Defines we need */ - -typedef unsigned short uint16; - -#define GLOBAL extern - -#include - -#include "rfcnb-error.h" -#include "rfcnb-common.h" -#include "byteorder.h" - -#define RFCNB_Default_Port 139 - -#define RFCNB_MAX_STATS 1 - -/* Protocol defines we need */ - -#define RFCNB_SESSION_MESSAGE 0 -#define RFCNB_SESSION_REQUEST 0x81 -#define RFCNB_SESSION_ACK 0x82 -#define RFCNB_SESSION_REJ 0x83 -#define RFCNB_SESSION_RETARGET 0x84 -#define RFCNB_SESSION_KEEP_ALIVE 0x85 - -/* Structures */ - -typedef struct redirect_addr * redirect_ptr; - -struct redirect_addr { - - struct in_addr ip_addr; - int port; - redirect_ptr next; - -}; - -typedef struct RFCNB_Con { - - int fd; /* File descripter for TCP/IP connection */ - int rfc_errno; /* last error */ - int timeout; /* How many milli-secs before IO times out */ - int redirects; /* How many times we were redirected */ - struct redirect_addr *redirect_list; /* First is first address */ - struct redirect_addr *last_addr; - -} RFCNB_Con; - -typedef char RFCNB_Hdr[4]; /* The header is 4 bytes long with */ - /* char[0] as the type, char[1] the */ - /* flags, and char[2..3] the length */ - -/* Macros to extract things from the header. These are for portability - between architecture types where we are worried about byte order */ - -#define RFCNB_Pkt_Hdr_Len 4 -#define RFCNB_Pkt_Sess_Len 72 -#define RFCNB_Pkt_Retarg_Len 10 -#define RFCNB_Pkt_Nack_Len 5 -#define RFCNB_Pkt_Type_Offset 0 -#define RFCNB_Pkt_Flags_Offset 1 -#define RFCNB_Pkt_Len_Offset 2 /* Length is 2 bytes plus a flag bit */ -#define RFCNB_Pkt_N1Len_Offset 4 -#define RFCNB_Pkt_Called_Offset 5 -#define RFCNB_Pkt_N2Len_Offset 38 -#define RFCNB_Pkt_Calling_Offset 39 -#define RFCNB_Pkt_Error_Offset 4 -#define RFCNB_Pkt_IP_Offset 4 -#define RFCNB_Pkt_Port_Offset 8 - -/* The next macro isolates the length of a packet, including the bit in the - flags */ - -#define RFCNB_Pkt_Len(p) (PVAL(p, 3) | (PVAL(p, 2) << 8) | \ - ((PVAL(p, RFCNB_Pkt_Flags_Offset) & 0x01) << 16)) - -#define RFCNB_Put_Pkt_Len(p, v) ((p)[1] = (((v) >> 16) & 1)); \ - ((p)[2] = (((v) >> 8) & 0xFF)); \ - ((p)[3] = ((v) & 0xFF)); - -#define RFCNB_Pkt_Type(p) (CVAL(p, RFCNB_Pkt_Type_Offset)) - -/* Static variables */ - -/* Only declare this if not defined */ - -#ifndef RFCNB_ERRNO -extern int RFCNB_errno; -extern int RFCNB_saved_errno; /* Save this from point of error */ -#endif diff --git a/authprogs/smbval/rfcnb-util.c b/authprogs/smbval/rfcnb-util.c deleted file mode 100644 index 9e57e4e..0000000 --- a/authprogs/smbval/rfcnb-util.c +++ /dev/null @@ -1,331 +0,0 @@ -/* UNIX RFCNB (RFC1001/RFC1002) NetBIOS implementation - - Version 1.0 - RFCNB Utility Routines ... - - Copyright (C) Richard Sharpe 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 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include "config.h" -#include "clibrary.h" -#include "portable/socket.h" -#include -#include - -#include "rfcnb-priv.h" -#include "rfcnb-util.h" -#include "rfcnb-io.h" - -#ifndef INADDR_NONE -# define INADDR_NONE -1 -#endif - -extern void (*Prot_Print_Routine)(); /* Pointer to protocol print routine */ - -/* Convert name and pad to 16 chars as needed */ -/* Name 1 is a C string with null termination, name 2 may not be */ -/* If SysName is true, then put a <00> on end, else space> */ - -void RFCNB_CvtPad_Name(char *name1, char *name2) - -{ char c, c1, c2; - int i, len; - - len = strlen(name1); - - for (i = 0; i < 16; i++) { - - if (i >= len) { - - c1 = 'C'; c2 = 'A'; /* CA is a space */ - - } else { - - c = name1[i]; - c1 = (char)((int)c/16 + (int)'A'); - c2 = (char)((int)c%16 + (int)'A'); - } - - name2[i*2] = c1; - name2[i*2+1] = c2; - - } - - name2[32] = 0; /* Put in the nll ...*/ - -} - -/* Get a packet of size n */ - -struct RFCNB_Pkt *RFCNB_Alloc_Pkt(int n) - -{ RFCNB_Pkt *pkt; - - if ((pkt = (struct RFCNB_Pkt *)malloc(sizeof(struct RFCNB_Pkt))) == NULL) { - - RFCNB_errno = RFCNBE_NoSpace; - RFCNB_saved_errno = errno; - return(NULL); - - } - - pkt -> next = NULL; - pkt -> len = n; - - if (n == 0) return(pkt); - - if ((pkt -> data = (char *)malloc(n)) == NULL) { - - RFCNB_errno = RFCNBE_NoSpace; - RFCNB_saved_errno = errno; - free(pkt); - return(NULL); - - } - - return(pkt); - -} - -/* Free up a packet */ - -void RFCNB_Free_Pkt(struct RFCNB_Pkt *pkt) - -{ struct RFCNB_Pkt *pkt_next; char *data_ptr; - - while (pkt != NULL) { - - pkt_next = pkt -> next; - - data_ptr = pkt -> data; - - if (data_ptr != NULL) - free(data_ptr); - - free(pkt); - - pkt = pkt_next; - - } - -} - -/* Resolve a name into an address */ - -int RFCNB_Name_To_IP(char *host, struct in_addr *Dest_IP) - -{ int addr; /* Assumes IP4, 32 bit network addresses */ - struct hostent *hp; - - /* Use inet_addr to try to convert the address */ - - if ((addr = inet_addr(host)) == INADDR_NONE) { /* Oh well, a good try :-) */ - - /* Now try a name look up with gethostbyname */ - - if ((hp = gethostbyname(host)) == NULL) { /* Not in DNS */ - - /* Try NetBIOS name lookup, how the hell do we do that? */ - - RFCNB_errno = RFCNBE_BadName; /* Is this right? */ - RFCNB_saved_errno = errno; - return(RFCNBE_Bad); - - } - else { /* We got a name */ - - memcpy((void *)Dest_IP, (void *)hp -> h_addr_list[0], sizeof(struct in_addr)); - - } - } - else { /* It was an IP address */ - - memcpy((void *)Dest_IP, (void *)&addr, sizeof(struct in_addr)); - - } - - return 0; - -} - -/* Disconnect the TCP connection to the server */ - -int RFCNB_Close(int socket) - -{ - - close(socket); - - /* If we want to do error recovery, here is where we put it */ - - return 0; - -} - -/* Connect to the server specified in the IP address. - Not sure how to handle socket options etc. */ - -int RFCNB_IP_Connect(struct in_addr Dest_IP, int port) - -{ struct sockaddr_in Socket; - int fd; - - /* Create a socket */ - - if ((fd = socket(PF_INET, SOCK_STREAM, 0)) < 0) { /* Handle the error */ - - RFCNB_errno = RFCNBE_BadSocket; - RFCNB_saved_errno = errno; - return(RFCNBE_Bad); - } - - memset(&Socket, 0, sizeof(Socket)); - memcpy((char *)&Socket.sin_addr, (char *)&Dest_IP, sizeof(Dest_IP)); - - Socket.sin_port = htons(port); - Socket.sin_family = PF_INET; - - /* Now connect to the destination */ - - if (connect(fd, (struct sockaddr *)&Socket, sizeof(Socket)) < 0) { /* Error */ - - close(fd); - RFCNB_errno = RFCNBE_ConnectFailed; - RFCNB_saved_errno = errno; - return(RFCNBE_Bad); - } - - return(fd); - -} - -/* handle the details of establishing the RFCNB session with remote - end - -*/ - -int RFCNB_Session_Req(struct RFCNB_Con *con, - char *Called_Name, - char *Calling_Name, - bool *redirect, - struct in_addr *Dest_IP, - int * port) - -{ char *sess_pkt; - - /* Response packet should be no more than 9 bytes, make 16 jic */ - - char resp[16]; - int len; - struct RFCNB_Pkt *pkt, res_pkt; - - /* We build and send the session request, then read the response */ - - pkt = RFCNB_Alloc_Pkt(RFCNB_Pkt_Sess_Len); - - if (pkt == NULL) { - - return(RFCNBE_Bad); /* Leave the error that RFCNB_Alloc_Pkt gives) */ - - } - - sess_pkt = pkt -> data; /* Get pointer to packet proper */ - - sess_pkt[RFCNB_Pkt_Type_Offset] = RFCNB_SESSION_REQUEST; - RFCNB_Put_Pkt_Len(sess_pkt, RFCNB_Pkt_Sess_Len-RFCNB_Pkt_Hdr_Len); - sess_pkt[RFCNB_Pkt_N1Len_Offset] = 32; - sess_pkt[RFCNB_Pkt_N2Len_Offset] = 32; - - RFCNB_CvtPad_Name(Called_Name, (sess_pkt + RFCNB_Pkt_Called_Offset)); - RFCNB_CvtPad_Name(Calling_Name, (sess_pkt + RFCNB_Pkt_Calling_Offset)); - - /* Now send the packet */ - - if ((len = RFCNB_Put_Pkt(con, pkt, RFCNB_Pkt_Sess_Len)) < 0) { - - return(RFCNBE_Bad); /* Should be able to write that lot ... */ - - } - - res_pkt.data = resp; - res_pkt.len = sizeof(resp); - res_pkt.next = NULL; - - if ((len = RFCNB_Get_Pkt(con, &res_pkt, sizeof(resp))) < 0) { - - return(RFCNBE_Bad); - - } - - /* Now analyze the packet ... */ - - switch (RFCNB_Pkt_Type(resp)) { - - case RFCNB_SESSION_REJ: /* Didnt like us ... too bad */ - - /* Why did we get rejected ? */ - - switch (CVAL(resp,RFCNB_Pkt_Error_Offset)) { - - case 0x80: - RFCNB_errno = RFCNBE_CallRejNLOCN; - break; - case 0x81: - RFCNB_errno = RFCNBE_CallRejNLFCN; - break; - case 0x82: - RFCNB_errno = RFCNBE_CallRejCNNP; - break; - case 0x83: - RFCNB_errno = RFCNBE_CallRejInfRes; - break; - case 0x8F: - RFCNB_errno = RFCNBE_CallRejUnSpec; - break; - default: - RFCNB_errno = RFCNBE_ProtErr; - break; - } - - return(RFCNBE_Bad); - break; - - case RFCNB_SESSION_ACK: /* Got what we wanted ... */ - - return(0); - break; - - case RFCNB_SESSION_RETARGET: /* Go elsewhere */ - - *redirect = true; /* Copy port and ip addr */ - - memcpy(Dest_IP, (resp + RFCNB_Pkt_IP_Offset), sizeof(struct in_addr)); - *port = SVAL(resp, RFCNB_Pkt_Port_Offset); - - return(0); - break; - - default: /* A protocol error */ - - RFCNB_errno = RFCNBE_ProtErr; - return(RFCNBE_Bad); - break; - } -} diff --git a/authprogs/smbval/rfcnb-util.h b/authprogs/smbval/rfcnb-util.h deleted file mode 100644 index 1af7e5e..0000000 --- a/authprogs/smbval/rfcnb-util.h +++ /dev/null @@ -1,42 +0,0 @@ -/* UNIX RFCNB (RFC1001/RFC1002) NetBIOS implementation - - Version 1.0 - RFCNB Utility Defines - - Copyright (C) Richard Sharpe 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 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -void RFCNB_CvtPad_Name(char *name1, char *name2); - -struct RFCNB_Pkt *RFCNB_Alloc_Pkt(int n); - -int RFCNB_Name_To_IP(char *host, struct in_addr *Dest_IP); - -int RFCNB_Close(int socket); - -int RFCNB_IP_Connect(struct in_addr Dest_IP, int port); - -int RFCNB_Session_Req(struct RFCNB_Con *con, - char *Called_Name, - char *Calling_Name, - bool *redirect, - struct in_addr *Dest_IP, - int * port); - diff --git a/authprogs/smbval/rfcnb.h b/authprogs/smbval/rfcnb.h deleted file mode 100644 index 8c2ea1c..0000000 --- a/authprogs/smbval/rfcnb.h +++ /dev/null @@ -1,48 +0,0 @@ -/* UNIX RFCNB (RFC1001/RFC1002) NetBIOS implementation - - Version 1.0 - RFCNB Defines - - Copyright (C) Richard Sharpe 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 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -/* Error responses */ - -#include "rfcnb-error.h" -#include "rfcnb-common.h" - -/* Defines we need */ - -#define RFCNB_Default_Port 139 - -/* Definition of routines we define */ - -void *RFCNB_Call(char *Called_Name, char *Calling_Name, char *Called_Address, - int port); - -int RFCNB_Send(void *Con_Handle, struct RFCNB_Pkt *Data, int Length); - -int RFCNB_Recv(void *Con_Handle, struct RFCNB_Pkt *Data, int Length); - -int RFCNB_Hangup(void *con_Handle); - -void *RFCNB_Listen(); - -struct RFCNB_Pkt *RFCNB_Alloc_Pkt(int n); diff --git a/authprogs/smbval/session.c b/authprogs/smbval/session.c deleted file mode 100644 index ec35bcd..0000000 --- a/authprogs/smbval/session.c +++ /dev/null @@ -1,304 +0,0 @@ -/* UNIX RFCNB (RFC1001/RFC1002) NetBIOS implementation - - Version 1.0 - Session Routines ... - - Copyright (C) Richard Sharpe 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 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include "config.h" -#include "clibrary.h" -#include -#include -#include -#include - -int RFCNB_errno = 0; -int RFCNB_saved_errno = 0; -#define RFCNB_ERRNO - -#include "rfcnb-priv.h" -#include "rfcnb-io.h" -#include "rfcnb-util.h" - -int RFCNB_Stats[RFCNB_MAX_STATS]; - -void (*Prot_Print_Routine)() = NULL; /* Pointer to print routine */ - -/* Set up a session with a remote name. We are passed Called_Name as a - string which we convert to a NetBIOS name, ie space terminated, up to - 16 characters only if we need to. If Called_Address is not empty, then - we use it to connect to the remote end, but put in Called_Name ... Called - Address can be a DNS based name, or a TCP/IP address ... -*/ - -void *RFCNB_Call(char *Called_Name, char *Calling_Name, char *Called_Address, - int port) - -{ struct RFCNB_Con *con; - struct in_addr Dest_IP; - int Client; - bool redirect; struct redirect_addr *redir_addr; - char *Service_Address; - - /* Now, we really should look up the port in /etc/services ... */ - - if (port == 0) port = RFCNB_Default_Port; - - /* Create a connection structure first */ - - if ((con = (struct RFCNB_Con *)malloc(sizeof(struct RFCNB_Con))) == NULL) { /* Error in size */ - - RFCNB_errno = RFCNBE_NoSpace; - RFCNB_saved_errno = errno; - return(NULL); - - } - - con -> fd = -0; /* no descriptor yet */ - con -> rfc_errno = 0; /* no error yet */ - con -> timeout = 0; /* no timeout */ - con -> redirects = 0; - con -> redirect_list = NULL; /* Fix bug still in version 0.50 */ - - /* Resolve that name into an IP address */ - - Service_Address = Called_Name; - if (strcmp(Called_Address, "") != 0) { /* If the Called Address = "" */ - Service_Address = Called_Address; - } - - if ((errno = RFCNB_Name_To_IP(Service_Address, &Dest_IP)) < 0) { /* Error */ - - /* No need to modify RFCNB_errno as it was done by RFCNB_Name_To_IP */ - - return(NULL); - - } - - /* Now connect to the remote end */ - - redirect = true; /* Fudge this one so we go once through */ - - while (redirect) { /* Connect and get session info etc */ - - redirect = false; /* Assume all OK */ - - /* Build the redirect info. First one is first addr called */ - /* And tack it onto the list of addresses we called */ - - if ((redir_addr = (struct redirect_addr *)malloc(sizeof(struct redirect_addr))) == NULL) { /* Could not get space */ - - RFCNB_errno = RFCNBE_NoSpace; - RFCNB_saved_errno = errno; - return(NULL); - - } - - memcpy((char *)&(redir_addr -> ip_addr), (char *)&Dest_IP, sizeof(Dest_IP)); - redir_addr -> port = port; - redir_addr -> next = NULL; - - if (con -> redirect_list == NULL) { /* Stick on head */ - - con -> redirect_list = con -> last_addr = redir_addr; - - } else { - - con -> last_addr -> next = redir_addr; - con -> last_addr = redir_addr; - - } - - /* Now, make that connection */ - - if ((Client = RFCNB_IP_Connect(Dest_IP, port)) < 0) { /* Error */ - - /* No need to modify RFCNB_errno as it was done by RFCNB_IP_Connect */ - - return(NULL); - - } - - con -> fd = Client; - - /* Now send and handle the RFCNB session request */ - /* If we get a redirect, we will comeback with redirect true - and a new IP address in DEST_IP */ - - if ((errno = RFCNB_Session_Req(con, - Called_Name, - Calling_Name, - &redirect, &Dest_IP, &port)) < 0) { - - /* No need to modify RFCNB_errno as it was done by RFCNB_Session.. */ - - return(NULL); - - } - - if (redirect) { - - /* We have to close the connection, and then try again */ - - (con -> redirects)++; - - RFCNB_Close(con -> fd); /* Close it */ - - } - } - - return(con); - -} - -/* We send a packet to the other end ... for the moment, we treat the - data as a series of pointers to blocks of data ... we should check the - length ... */ - -int RFCNB_Send(struct RFCNB_Con *Con_Handle, struct RFCNB_Pkt *udata, int Length) - -{ struct RFCNB_Pkt *pkt; char *hdr; - int len; - - /* Plug in the header and send the data */ - - pkt = RFCNB_Alloc_Pkt(RFCNB_Pkt_Hdr_Len); - - if (pkt == NULL) { - - RFCNB_errno = RFCNBE_NoSpace; - RFCNB_saved_errno = errno; - return(RFCNBE_Bad); - - } - - pkt -> next = udata; /* The user data we want to send */ - - hdr = pkt -> data; - - /* Following crap is for portability across multiple UNIX machines */ - - *(hdr + RFCNB_Pkt_Type_Offset) = RFCNB_SESSION_MESSAGE; - RFCNB_Put_Pkt_Len(hdr, Length); - -#ifdef RFCNB_DEBUG - - fprintf(stderr, "Sending packet: "); - -#endif - - if ((len = RFCNB_Put_Pkt(Con_Handle, pkt, Length + RFCNB_Pkt_Hdr_Len)) < 0) { - - /* No need to change RFCNB_errno as it was done by put_pkt ... */ - - return(RFCNBE_Bad); /* Should be able to write that lot ... */ - - } - - /* Now we have sent that lot, let's get rid of the RFCNB Header and return */ - - pkt -> next = NULL; - - RFCNB_Free_Pkt(pkt); - - return(len); - -} - -/* We pick up a message from the internet ... We have to worry about - non-message packets ... */ - -int RFCNB_Recv(void *con_Handle, struct RFCNB_Pkt *Data, int Length) - -{ struct RFCNB_Pkt *pkt; - int ret_len; - - if (con_Handle == NULL){ - - RFCNB_errno = RFCNBE_BadHandle; - RFCNB_saved_errno = errno; - return(RFCNBE_Bad); - - } - - /* Now get a packet from below. We allocate a header first */ - - /* Plug in the header and send the data */ - - pkt = RFCNB_Alloc_Pkt(RFCNB_Pkt_Hdr_Len); - - if (pkt == NULL) { - - RFCNB_errno = RFCNBE_NoSpace; - RFCNB_saved_errno = errno; - return(RFCNBE_Bad); - - } - - pkt -> next = Data; /* Plug in the data portion */ - - if ((ret_len = RFCNB_Get_Pkt(con_Handle, pkt, Length + RFCNB_Pkt_Hdr_Len)) < 0) { - -#ifdef RFCNB_DEBUG - fprintf(stderr, "Bad packet return in RFCNB_Recv... \n"); -#endif - - return(RFCNBE_Bad); - - } - - /* We should check that we go a message and not a keep alive */ - - pkt -> next = NULL; - - RFCNB_Free_Pkt(pkt); - - return(ret_len); - -} - -/* We just disconnect from the other end, as there is nothing in the RFCNB */ -/* protocol that specifies any exchange as far as I can see */ - -int RFCNB_Hangup(struct RFCNB_Con *con_Handle) - -{ - - if (con_Handle != NULL) { - RFCNB_Close(con_Handle -> fd); /* Could this fail? */ - free(con_Handle); - } - - return 0; - - -} - -/* Set TCP_NODELAY on the socket */ - -int RFCNB_Set_Sock_NoDelay(struct RFCNB_Con *con_Handle, bool yn) - -{ - - return(setsockopt(con_Handle -> fd, IPPROTO_TCP, TCP_NODELAY, - (char *)&yn, sizeof(yn))); - -} diff --git a/authprogs/smbval/smbdes.c b/authprogs/smbval/smbdes.c deleted file mode 100644 index e4f8280..0000000 --- a/authprogs/smbval/smbdes.c +++ /dev/null @@ -1,337 +0,0 @@ -/* - Unix SMB/Netbios implementation. - Version 1.9. - - a partial implementation of DES designed for use in the - SMB authentication protocol - - Copyright (C) Andrew Tridgell 1997 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - - -/* NOTES: - - This code makes no attempt to be fast! In fact, it is a very - slow implementation - - This code is NOT a complete DES implementation. It implements only - the minimum necessary for SMB authentication, as used by all SMB - products (including every copy of Microsoft Windows95 ever sold) - - In particular, it can only do a unchained forward DES pass. This - means it is not possible to use this code for encryption/decryption - of data, instead it is only useful as a "hash" algorithm. - - There is no entry point into this code that allows normal DES operation. - - I believe this means that this code does not come under ITAR - regulations but this is NOT a legal opinion. If you are concerned - about the applicability of ITAR regulations to this code then you - should confirm it for yourself (and maybe let me know if you come - up with a different answer to the one above) -*/ - - - -static int perm1[56] = {57, 49, 41, 33, 25, 17, 9, - 1, 58, 50, 42, 34, 26, 18, - 10, 2, 59, 51, 43, 35, 27, - 19, 11, 3, 60, 52, 44, 36, - 63, 55, 47, 39, 31, 23, 15, - 7, 62, 54, 46, 38, 30, 22, - 14, 6, 61, 53, 45, 37, 29, - 21, 13, 5, 28, 20, 12, 4}; - -static int perm2[48] = {14, 17, 11, 24, 1, 5, - 3, 28, 15, 6, 21, 10, - 23, 19, 12, 4, 26, 8, - 16, 7, 27, 20, 13, 2, - 41, 52, 31, 37, 47, 55, - 30, 40, 51, 45, 33, 48, - 44, 49, 39, 56, 34, 53, - 46, 42, 50, 36, 29, 32}; - -static int perm3[64] = {58, 50, 42, 34, 26, 18, 10, 2, - 60, 52, 44, 36, 28, 20, 12, 4, - 62, 54, 46, 38, 30, 22, 14, 6, - 64, 56, 48, 40, 32, 24, 16, 8, - 57, 49, 41, 33, 25, 17, 9, 1, - 59, 51, 43, 35, 27, 19, 11, 3, - 61, 53, 45, 37, 29, 21, 13, 5, - 63, 55, 47, 39, 31, 23, 15, 7}; - -static int perm4[48] = { 32, 1, 2, 3, 4, 5, - 4, 5, 6, 7, 8, 9, - 8, 9, 10, 11, 12, 13, - 12, 13, 14, 15, 16, 17, - 16, 17, 18, 19, 20, 21, - 20, 21, 22, 23, 24, 25, - 24, 25, 26, 27, 28, 29, - 28, 29, 30, 31, 32, 1}; - -static int perm5[32] = { 16, 7, 20, 21, - 29, 12, 28, 17, - 1, 15, 23, 26, - 5, 18, 31, 10, - 2, 8, 24, 14, - 32, 27, 3, 9, - 19, 13, 30, 6, - 22, 11, 4, 25}; - - -static int perm6[64] ={ 40, 8, 48, 16, 56, 24, 64, 32, - 39, 7, 47, 15, 55, 23, 63, 31, - 38, 6, 46, 14, 54, 22, 62, 30, - 37, 5, 45, 13, 53, 21, 61, 29, - 36, 4, 44, 12, 52, 20, 60, 28, - 35, 3, 43, 11, 51, 19, 59, 27, - 34, 2, 42, 10, 50, 18, 58, 26, - 33, 1, 41, 9, 49, 17, 57, 25}; - - -static int sc[16] = {1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1}; - -static int sbox[8][4][16] = { - {{14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7}, - {0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8}, - {4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0}, - {15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13}}, - - {{15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10}, - {3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5}, - {0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15}, - {13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9}}, - - {{10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8}, - {13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1}, - {13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7}, - {1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12}}, - - {{7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15}, - {13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9}, - {10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4}, - {3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14}}, - - {{2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9}, - {14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6}, - {4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14}, - {11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3}}, - - {{12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11}, - {10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8}, - {9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6}, - {4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13}}, - - {{4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1}, - {13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6}, - {1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2}, - {6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12}}, - - {{13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7}, - {1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2}, - {7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8}, - {2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11}}}; - -static void permute(char *out, char *in, int *p, int n) -{ - int i; - for (i=0;i>1; - key[1] = ((str[0]&0x01)<<6) | (str[1]>>2); - key[2] = ((str[1]&0x03)<<5) | (str[2]>>3); - key[3] = ((str[2]&0x07)<<4) | (str[3]>>4); - key[4] = ((str[3]&0x0F)<<3) | (str[4]>>5); - key[5] = ((str[4]&0x1F)<<2) | (str[5]>>6); - key[6] = ((str[5]&0x3F)<<1) | (str[6]>>7); - key[7] = str[6]&0x7F; - for (i=0;i<8;i++) { - key[i] = (key[i]<<1); - } -} - - -static void smbhash(unsigned char *out, unsigned char *in, unsigned char *key) -{ - int i; - char outb[64]; - char inb[64]; - char keyb[64]; - unsigned char key2[8]; - - str_to_key(key, key2); - - for (i=0;i<64;i++) { - inb[i] = (in[i/8] & (1<<(7-(i%8)))) ? 1 : 0; - keyb[i] = (key2[i/8] & (1<<(7-(i%8)))) ? 1 : 0; - outb[i] = 0; - } - - dohash(outb, inb, keyb); - - for (i=0;i<8;i++) { - out[i] = 0; - } - - for (i=0;i<64;i++) { - if (outb[i]) - out[i/8] |= (1<<(7-(i%8))); - } -} - -void E_P16(unsigned char *p14,unsigned char *p16) -{ - unsigned char sp8[8] = {0x4b, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25}; - smbhash(p16, sp8, p14); - smbhash(p16+8, sp8, p14+7); -} - -void E_P24(unsigned char *p21, unsigned char *c8, unsigned char *p24) -{ - smbhash(p24, c8, p21); - smbhash(p24+8, c8, p21+7); - smbhash(p24+16, c8, p21+14); -} - -void cred_hash1(unsigned char *out,unsigned char *in,unsigned char *key) -{ - unsigned char buf[8]; - - smbhash(buf, in, key); - smbhash(out, buf, key+9); -} - -void cred_hash2(unsigned char *out,unsigned char *in,unsigned char *key) -{ - unsigned char buf[8]; - static unsigned char key2[8]; - - smbhash(buf, in, key); - key2[0] = key[7]; - smbhash(out, buf, key2); -} - diff --git a/authprogs/smbval/smbencrypt.c b/authprogs/smbval/smbencrypt.c deleted file mode 100644 index 4cae973..0000000 --- a/authprogs/smbval/smbencrypt.c +++ /dev/null @@ -1,60 +0,0 @@ -/* - Unix SMB/Netbios implementation. - Version 1.9. - SMB parameters and setup - Copyright (C) Andrew Tridgell 1992-1997 - Modified by Jeremy Allison 1995. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include "config.h" -#include "clibrary.h" -#include - -#include "smblib-priv.h" - -typedef unsigned char uchar; - -void strupper(char *s); - -/* - This implements the X/Open SMB password encryption - It takes a password, a 8 byte "crypt key" and puts 24 bytes of - encrypted password into p24 */ -void SMBencrypt(uchar *passwd, uchar *c8, uchar *p24) -{ - uchar p14[15], p21[21]; - - memset(p21,'\0',21); - memset(p14,'\0',14); - strlcpy((char *) p14, (char *) passwd, sizeof(p14)); - - strupper((char *)p14); - E_P16(p14, p21); - E_P24(p21, c8, p24); -} - -void strupper(char *s) -{ - while (*s) - { - { - if (CTYPE(islower, *s)) - *s = toupper(*s); - s++; - } - } -} diff --git a/authprogs/smbval/smblib-common.h b/authprogs/smbval/smblib-common.h deleted file mode 100644 index b8441e0..0000000 --- a/authprogs/smbval/smblib-common.h +++ /dev/null @@ -1,69 +0,0 @@ -/* UNIX SMBlib NetBIOS implementation - - Version 1.0 - SMBlib Common Defines - - Copyright (C) Richard Sharpe 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 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -/* Error CLASS codes and etc ... */ - -#define SMBC_SUCCESS 0 -#define SMBC_ERRDOS 0x01 -#define SMBC_ERRSRV 0x02 -#define SMBC_ERRHRD 0x03 -#define SMBC_ERRCMD 0xFF - -/* Define the protocol types ... */ - -#define SMB_P_Unknown -1 /* Hmmm, is this smart? */ -#define SMB_P_Core 0 -#define SMB_P_CorePlus 1 -#define SMB_P_DOSLanMan1 2 -#define SMB_P_LanMan1 3 -#define SMB_P_DOSLanMan2 4 -#define SMB_P_LanMan2 5 -#define SMB_P_DOSLanMan2_1 6 -#define SMB_P_LanMan2_1 7 -#define SMB_P_NT1 8 - -/* SMBlib return codes */ -/* We want something that indicates whether or not the return code was a */ -/* remote error, a local error in SMBlib or returned from lower layer ... */ -/* Wonder if this will work ... */ -/* SMBlibE_Remote = 1 indicates remote error */ -/* SMBlibE_ values < 0 indicate local error with more info available */ -/* SMBlibE_ values >1 indicate local from SMBlib code errors? */ - -#define SMBlibE_Success 0 -#define SMBlibE_Remote 1 /* Remote error, get more info from con */ -#define SMBlibE_BAD -1 -#define SMBlibE_LowerLayer 2 /* Lower layer error */ -#define SMBlibE_NotImpl 3 /* Function not yet implemented */ -#define SMBlibE_ProtLow 4 /* Protocol negotiated does not support req */ -#define SMBlibE_NoSpace 5 /* No space to allocate a structure */ -#define SMBlibE_BadParam 6 /* Bad parameters */ -#define SMBlibE_NegNoProt 7 /* None of our protocols was liked */ -#define SMBlibE_SendFailed 8 /* Sending an SMB failed */ -#define SMBlibE_RecvFailed 9 /* Receiving an SMB failed */ -#define SMBlibE_GuestOnly 10 /* Logged in as guest */ -#define SMBlibE_CallFailed 11 /* Call remote end failed */ -#define SMBlibE_ProtUnknown 12 /* Protocol unknown */ -#define SMBlibE_NoSuchMsg 13 /* Keep this up to date */ diff --git a/authprogs/smbval/smblib-priv.h b/authprogs/smbval/smblib-priv.h deleted file mode 100644 index 155b66b..0000000 --- a/authprogs/smbval/smblib-priv.h +++ /dev/null @@ -1,249 +0,0 @@ -/* UNIX SMBlib NetBIOS implementation - - Version 1.0 - SMBlib private Defines - - Copyright (C) Richard Sharpe 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 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include "smblib-common.h" -#include -#include - -typedef unsigned short uint16; -typedef unsigned int uint32; - -#include "byteorder.h" /* Hmmm ... hot good */ - -#define SMB_DEF_IDF 0x424D53FF /* "\377SMB" */ - -/* The protocol commands and constants we need */ -#define SMBnegprot 0x72 /* negotiate protocol */ -#define SMBsesssetupX 0x73 /* Session Set Up & X (including User Logon) */ -#define SMBdialectID 0x02 /* a dialect id */ - -typedef unsigned short WORD; -typedef unsigned short UWORD; -typedef unsigned int ULONG; -typedef unsigned char BYTE; -typedef unsigned char UCHAR; - -/* Some macros to allow access to actual packet data so that we */ -/* can change the underlying representation of packets. */ -/* */ -/* The current formats vying for attention are a fragment */ -/* approach where the SMB header is a fragment linked to the */ -/* data portion with the transport protocol (rfcnb or whatever) */ -/* being linked on the front. */ -/* */ -/* The other approach is where the whole packet is one array */ -/* of bytes with space allowed on the front for the packet */ -/* headers. */ - -#define SMB_Hdr(p) (char *)(p -> data) - -/* SMB Hdr def for File Sharing Protocol? From MS and Intel, */ -/* Intel PN 138446 Doc Version 2.0, Nov 7, 1988. This def also */ -/* applies to LANMAN1.0 as well as the Core Protocol */ -/* The spec states that wct and bcc must be present, even if 0 */ - -/* We define these as offsets into a char SMB[] array for the */ -/* sake of portability */ - -/* NOTE!. Some of the lenght defines, SMB__len do not include */ -/* the data that follows in the SMB packet, so the code will have to */ -/* take that into account. */ - -#define SMB_hdr_idf_offset 0 /* 0xFF,'SMB' 0-3 */ -#define SMB_hdr_com_offset 4 /* BYTE 4 */ -#define SMB_hdr_rcls_offset 5 /* BYTE 5 */ -#define SMB_hdr_reh_offset 6 /* BYTE 6 */ -#define SMB_hdr_err_offset 7 /* WORD 7 */ -#define SMB_hdr_reb_offset 9 /* BYTE 9 */ -#define SMB_hdr_flg_offset 9 /* same as reb ...*/ -#define SMB_hdr_res_offset 10 /* 7 WORDs 10 */ -#define SMB_hdr_res0_offset 10 /* WORD 10 */ -#define SMB_hdr_flg2_offset 10 /* WORD */ -#define SMB_hdr_res1_offset 12 /* WORD 12 */ -#define SMB_hdr_res2_offset 14 -#define SMB_hdr_res3_offset 16 -#define SMB_hdr_res4_offset 18 -#define SMB_hdr_res5_offset 20 -#define SMB_hdr_res6_offset 22 -#define SMB_hdr_tid_offset 24 -#define SMB_hdr_pid_offset 26 -#define SMB_hdr_uid_offset 28 -#define SMB_hdr_mid_offset 30 -#define SMB_hdr_wct_offset 32 - -#define SMB_hdr_len 33 /* 33 byte header? */ - -#define SMB_hdr_axc_offset 33 /* AndX Command */ -#define SMB_hdr_axr_offset 34 /* AndX Reserved */ -#define SMB_hdr_axo_offset 35 /* Offset from start to WCT of AndX cmd */ - -/* Format of the Negotiate Protocol SMB */ - -#define SMB_negp_bcc_offset 33 -#define SMB_negp_buf_offset 35 /* Where the buffer starts */ -#define SMB_negp_len 35 /* plus the data */ - -/* Format of the Negotiate Response SMB, for CoreProtocol, LM1.2 and */ -/* NT LM 0.12. wct will be 1 for CoreProtocol, 13 for LM 1.2, and 17 */ -/* for NT LM 0.12 */ - -#define SMB_negrCP_idx_offset 33 /* Response to the neg req */ -#define SMB_negrCP_bcc_offset 35 -#define SMB_negrLM_idx_offset 33 /* dialect index */ -#define SMB_negrLM_sec_offset 35 /* Security mode */ -#define SMB_sec_user_mask 0x01 /* 0 = share, 1 = user */ -#define SMB_sec_encrypt_mask 0x02 /* pick out encrypt */ -#define SMB_negrLM_mbs_offset 37 /* max buffer size */ -#define SMB_negrLM_mmc_offset 39 /* max mpx count */ -#define SMB_negrLM_mnv_offset 41 /* max number of VCs */ -#define SMB_negrLM_rm_offset 43 /* raw mode support bit vec*/ -#define SMB_negrLM_sk_offset 45 /* session key, 32 bits */ -#define SMB_negrLM_st_offset 49 /* Current server time */ -#define SMB_negrLM_sd_offset 51 /* Current server date */ -#define SMB_negrLM_stz_offset 53 /* Server Time Zone */ -#define SMB_negrLM_ekl_offset 55 /* encryption key length */ -#define SMB_negrLM_res_offset 57 /* reserved */ -#define SMB_negrLM_bcc_offset 59 /* bcc */ -#define SMB_negrLM_len 61 /* 61 bytes ? */ -#define SMB_negrLM_buf_offset 61 /* Where the fun begins */ - -#define SMB_negrNTLM_idx_offset 33 /* Selected protocol */ -#define SMB_negrNTLM_sec_offset 35 /* Security more */ -#define SMB_negrNTLM_mmc_offset 36 /* Different format above */ -#define SMB_negrNTLM_mnv_offset 38 /* Max VCs */ -#define SMB_negrNTLM_mbs_offset 40 /* MBS now a long */ -#define SMB_negrNTLM_mrs_offset 44 /* Max raw size */ -#define SMB_negrNTLM_sk_offset 48 /* Session Key */ -#define SMB_negrNTLM_cap_offset 52 /* Capabilities */ -#define SMB_negrNTLM_stl_offset 56 /* Server time low */ -#define SMB_negrNTLM_sth_offset 60 /* Server time high */ -#define SMB_negrNTLM_stz_offset 64 /* Server time zone */ -#define SMB_negrNTLM_ekl_offset 66 /* Encrypt key len */ -#define SMB_negrNTLM_bcc_offset 67 /* Bcc */ -#define SMB_negrNTLM_len 69 -#define SMB_negrNTLM_buf_offset 69 - -/* Offsets for Delete file */ - -#define SMB_delet_sat_offset 33 /* search attribites */ -#define SMB_delet_bcc_offset 35 /* bcc */ -#define SMB_delet_buf_offset 37 -#define SMB_delet_len 37 - -/* Offsets for SESSION_SETUP_ANDX for both LM and NT LM protocols */ - -#define SMB_ssetpLM_mbs_offset 37 /* Max buffer Size, allow for AndX */ -#define SMB_ssetpLM_mmc_offset 39 /* max multiplex count */ -#define SMB_ssetpLM_vcn_offset 41 /* VC number if new VC */ -#define SMB_ssetpLM_snk_offset 43 /* Session Key */ -#define SMB_ssetpLM_pwl_offset 47 /* password length */ -#define SMB_ssetpLM_res_offset 49 /* reserved */ -#define SMB_ssetpLM_bcc_offset 53 /* bcc */ -#define SMB_ssetpLM_len 55 /* before data ... */ -#define SMB_ssetpLM_buf_offset 55 - -#define SMB_ssetpNTLM_mbs_offset 37 /* Max Buffer Size for NT LM 0.12 */ - /* and above */ -#define SMB_ssetpNTLM_mmc_offset 39 /* Max Multiplex count */ -#define SMB_ssetpNTLM_vcn_offset 41 /* VC Number */ -#define SMB_ssetpNTLM_snk_offset 43 /* Session key */ -#define SMB_ssetpNTLM_cipl_offset 47 /* Case Insensitive PW Len */ -#define SMB_ssetpNTLM_cspl_offset 49 /* Unicode pw len */ -#define SMB_ssetpNTLM_res_offset 51 /* reserved */ -#define SMB_ssetpNTLM_cap_offset 55 /* server capabilities */ -#define SMB_ssetpNTLM_bcc_offset 59 /* bcc */ -#define SMB_ssetpNTLM_len 61 /* before data */ -#define SMB_ssetpNTLM_buf_offset 61 - -#define SMB_ssetpr_axo_offset 35 /* Offset of next response ... */ -#define SMB_ssetpr_act_offset 37 /* action, bit 0 = 1 => guest */ -#define SMB_ssetpr_bcc_offset 39 /* bcc */ -#define SMB_ssetpr_buf_offset 41 /* Native OS etc */ - -/* The following two arrays need to be in step! */ -/* We must make it possible for callers to specify these ... */ - -extern const char *SMB_Prots[]; -extern int SMB_Types[]; - -typedef struct SMB_Connect_Def * SMB_Handle_Type; - -struct SMB_Connect_Def { - - SMB_Handle_Type Next_Con, Prev_Con; /* Next and previous conn */ - int protocol; /* What is the protocol */ - int prot_IDX; /* And what is the index */ - void *Trans_Connect; /* The connection */ - - /* All these strings should be malloc'd */ - - char service[80], username[80], password[80], desthost[80], sock_options[80]; - char address[80], myname[80]; - - int gid; /* Group ID, do we need it? */ - int mid; /* Multiplex ID? We might need one per con */ - int pid; /* Process ID */ - - int uid; /* Authenticated user id. */ - - /* It is pretty clear that we need to bust some of */ - /* these out into a per TCon record, as there may */ - /* be multiple TCon's per server, etc ... later */ - - int port; /* port to use in case not default, this is a TCPism! */ - - int max_xmit; /* Max xmit permitted by server */ - int Security; /* 0 = share, 1 = user */ - int Raw_Support; /* bit 0 = 1 = Read Raw supported, 1 = 1 Write raw */ - bool encrypt_passwords; /* false = don't */ - int MaxMPX, MaxVC, MaxRaw; - unsigned int SessionKey, Capabilities; - int SvrTZ; /* Server Time Zone */ - int Encrypt_Key_Len; - char Encrypt_Key[80], Domain[80], PDomain[80], OSName[80], LMType[40]; - char Svr_OS[80], Svr_LMType[80], Svr_PDom[80]; - -}; - -#define SMBLIB_DEFAULT_OSNAME "UNIX of some type" -#define SMBLIB_DEFAULT_LMTYPE "SMBlib LM2.1 minus a bit" -#define SMBLIB_MAX_XMIT 65535 - -/* global Variables for the library */ - -#ifndef SMBLIB_ERRNO -extern int SMBlib_errno; -extern int SMBlib_SMB_Error; /* last Error */ -#endif - -/* From smbdes.c. */ -void E_P16(unsigned char *, unsigned char *); -void E_P24(unsigned char *, unsigned char *, unsigned char *); - -/* From smblib-util.c. */ -void SMB_Get_My_Name(char *name, int len); - -/* From smbencrypt.c. */ -void SMBencrypt(unsigned char *passwd, unsigned char *, unsigned char *); diff --git a/authprogs/smbval/smblib-util.c b/authprogs/smbval/smblib-util.c deleted file mode 100644 index 27f5619..0000000 --- a/authprogs/smbval/smblib-util.c +++ /dev/null @@ -1,332 +0,0 @@ -/* UNIX SMBlib NetBIOS implementation - - Version 1.0 - SMBlib Utility Routines - - Copyright (C) Richard Sharpe 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 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include "config.h" -#include "clibrary.h" - -#include "smblib-priv.h" -#include "rfcnb.h" - -/* The following two arrays need to be in step! */ -/* We must make it possible for callers to specify these ... */ - -const char *SMB_Prots[] = {"PC NETWORK PROGRAM 1.0", - "MICROSOFT NETWORKS 1.03", - "MICROSOFT NETWORKS 3.0", - "DOS LANMAN1.0", - "LANMAN1.0", - "DOS LM1.2X002", - "LM1.2X002", - "DOS LANMAN2.1", - "LANMAN2.1", - "Samba", - "NT LM 0.12", - "NT LANMAN 1.0", - NULL}; - -int SMB_Types[] = {SMB_P_Core, - SMB_P_CorePlus, - SMB_P_DOSLanMan1, - SMB_P_DOSLanMan1, - SMB_P_LanMan1, - SMB_P_DOSLanMan2, - SMB_P_LanMan2, - SMB_P_LanMan2_1, - SMB_P_LanMan2_1, - SMB_P_NT1, - SMB_P_NT1, - SMB_P_NT1, - -1}; - -/* Figure out what protocol was accepted, given the list of dialect strings */ -/* We offered, and the index back from the server. We allow for a user */ -/* supplied list, and assume that it is a subset of our list */ - -int SMB_Figure_Protocol(const char *dialects[], int prot_index) - -{ int i; - - if (dialects == SMB_Prots) { /* The jobs is easy, just index into table */ - - return(SMB_Types[prot_index]); - } - else { /* Search through SMB_Prots looking for a match */ - - for (i = 0; SMB_Prots[i] != NULL; i++) { - - if (strcmp(dialects[prot_index], SMB_Prots[i]) == 0) { /* A match */ - - return(SMB_Types[i]); - - } - - } - - /* If we got here, then we are in trouble, because the protocol was not */ - /* One we understand ... */ - - return(SMB_P_Unknown); - - } - -} - - -/* Negotiate the protocol we will use from the list passed in Prots */ -/* we return the index of the accepted protocol in NegProt, -1 indicates */ -/* none acceptible, and our return value is 0 if ok, <0 if problems */ - -int SMB_Negotiate(SMB_Handle_Type Con_Handle, const char *Prots[]) -{ - struct RFCNB_Pkt *pkt; - int prots_len, i, pkt_len, prot, alloc_len; - char *p; - - /* Figure out how long the prot list will be and allocate space for it */ - - prots_len = 0; - - for (i = 0; Prots[i] != NULL; i++) { - - prots_len = prots_len + strlen(Prots[i]) + 2; /* Account for null etc */ - - } - - /* The -1 accounts for the one byte smb_buf we have because some systems */ - /* don't like char msg_buf[] */ - - pkt_len = SMB_negp_len + prots_len; - - /* Make sure that the pkt len is long enough for the max response ... */ - /* Which is a problem, because the encryption key len eec may be long */ - - if (pkt_len < (SMB_hdr_wct_offset + (19 * 2) + 40)) { - - alloc_len = SMB_hdr_wct_offset + (19 * 2) + 40; - - } - else { - - alloc_len = pkt_len; - - } - - pkt = (struct RFCNB_Pkt *)RFCNB_Alloc_Pkt(alloc_len); - - if (pkt == NULL) { - - SMBlib_errno = SMBlibE_NoSpace; - return(SMBlibE_BAD); - - } - - /* Now plug in the bits we need */ - - memset(SMB_Hdr(pkt), 0, SMB_negp_len); - SIVAL(SMB_Hdr(pkt), SMB_hdr_idf_offset, SMB_DEF_IDF); /* Plunk in IDF */ - *(SMB_Hdr(pkt) + SMB_hdr_com_offset) = SMBnegprot; - SSVAL(SMB_Hdr(pkt), SMB_hdr_pid_offset, Con_Handle -> pid); - SSVAL(SMB_Hdr(pkt), SMB_hdr_tid_offset, 0); - SSVAL(SMB_Hdr(pkt), SMB_hdr_mid_offset, Con_Handle -> mid); - SSVAL(SMB_Hdr(pkt), SMB_hdr_uid_offset, Con_Handle -> uid); - *(SMB_Hdr(pkt) + SMB_hdr_wct_offset) = 0; - - SSVAL(SMB_Hdr(pkt), SMB_negp_bcc_offset, prots_len); - - /* Now copy the prot strings in with the right stuff */ - - p = (char *)(SMB_Hdr(pkt) + SMB_negp_buf_offset); - - for (i = 0; Prots[i] != NULL; i++) { - - *p = SMBdialectID; - strcpy(p + 1, Prots[i]); - p = p + strlen(Prots[i]) + 2; /* Adjust len of p for null plus dialectID */ - - } - - /* Now send the packet and sit back ... */ - - if (RFCNB_Send(Con_Handle -> Trans_Connect, pkt, pkt_len) < 0){ - - -#ifdef DEBUG - fprintf(stderr, "Error sending negotiate protocol\n"); -#endif - - RFCNB_Free_Pkt(pkt); - SMBlib_errno = -SMBlibE_SendFailed; /* Failed, check lower layer errno */ - return(SMBlibE_BAD); - - } - - /* Now get the response ... */ - - if (RFCNB_Recv(Con_Handle -> Trans_Connect, pkt, alloc_len) < 0) { - -#ifdef DEBUG - fprintf(stderr, "Error receiving response to negotiate\n"); -#endif - - RFCNB_Free_Pkt(pkt); - SMBlib_errno = -SMBlibE_RecvFailed; /* Failed, check lower layer errno */ - return(SMBlibE_BAD); - - } - - if (CVAL(SMB_Hdr(pkt), SMB_hdr_rcls_offset) != SMBC_SUCCESS) { /* Process error */ - -#ifdef DEBUG - fprintf(stderr, "SMB_Negotiate failed with errorclass = %i, Error Code = %i\n", - CVAL(SMB_Hdr(pkt), SMB_hdr_rcls_offset), - SVAL(SMB_Hdr(pkt), SMB_hdr_err_offset)); -#endif - - SMBlib_SMB_Error = IVAL(SMB_Hdr(pkt), SMB_hdr_rcls_offset); - RFCNB_Free_Pkt(pkt); - SMBlib_errno = SMBlibE_Remote; - return(SMBlibE_BAD); - - } - - if (SVAL(SMB_Hdr(pkt), SMB_negrCP_idx_offset) == 0xFFFF) { - -#ifdef DEBUG - fprintf(stderr, "None of our protocols was accepted ... "); -#endif - - RFCNB_Free_Pkt(pkt); - SMBlib_errno = SMBlibE_NegNoProt; - return(SMBlibE_BAD); - - } - - /* Now, unpack the info from the response, if any and evaluate the proto */ - /* selected. We must make sure it is one we like ... */ - - Con_Handle -> prot_IDX = prot = SVAL(SMB_Hdr(pkt), SMB_negrCP_idx_offset); - Con_Handle -> protocol = SMB_Figure_Protocol(Prots, prot); - - if (Con_Handle -> protocol == SMB_P_Unknown) { /* No good ... */ - - RFCNB_Free_Pkt(pkt); - SMBlib_errno = SMBlibE_ProtUnknown; - return(SMBlibE_BAD); - - } - - switch (CVAL(SMB_Hdr(pkt), SMB_hdr_wct_offset)) { - - case 0x01: /* No more info ... */ - - break; - - case 13: /* Up to and including LanMan 2.1 */ - - Con_Handle -> Security = SVAL(SMB_Hdr(pkt), SMB_negrLM_sec_offset); - Con_Handle -> encrypt_passwords = ((Con_Handle -> Security & SMB_sec_encrypt_mask) != 0x00); - Con_Handle -> Security = Con_Handle -> Security & SMB_sec_user_mask; - - Con_Handle -> max_xmit = SVAL(SMB_Hdr(pkt), SMB_negrLM_mbs_offset); - Con_Handle -> MaxMPX = SVAL(SMB_Hdr(pkt), SMB_negrLM_mmc_offset); - Con_Handle -> MaxVC = SVAL(SMB_Hdr(pkt), SMB_negrLM_mnv_offset); - Con_Handle -> Raw_Support = SVAL(SMB_Hdr(pkt), SMB_negrLM_rm_offset); - Con_Handle -> SessionKey = IVAL(SMB_Hdr(pkt), SMB_negrLM_sk_offset); - Con_Handle -> SvrTZ = SVAL(SMB_Hdr(pkt), SMB_negrLM_stz_offset); - Con_Handle -> Encrypt_Key_Len = SVAL(SMB_Hdr(pkt), SMB_negrLM_ekl_offset); - - p = (SMB_Hdr(pkt) + SMB_negrLM_buf_offset); - fprintf(stderr, "%p", (char *)(SMB_Hdr(pkt) + SMB_negrLM_buf_offset)); - memcpy(Con_Handle->Encrypt_Key, p, 8); - - p = (SMB_Hdr(pkt) + SMB_negrLM_buf_offset + Con_Handle -> Encrypt_Key_Len); - - strncpy(p, Con_Handle -> Svr_PDom, sizeof(Con_Handle -> Svr_PDom) - 1); - - break; - - case 17: /* NT LM 0.12 and LN LM 1.0 */ - - Con_Handle -> Security = SVAL(SMB_Hdr(pkt), SMB_negrNTLM_sec_offset); - Con_Handle -> encrypt_passwords = ((Con_Handle -> Security & SMB_sec_encrypt_mask) != 0x00); - Con_Handle -> Security = Con_Handle -> Security & SMB_sec_user_mask; - - Con_Handle -> max_xmit = IVAL(SMB_Hdr(pkt), SMB_negrNTLM_mbs_offset); - Con_Handle -> MaxMPX = SVAL(SMB_Hdr(pkt), SMB_negrNTLM_mmc_offset); - Con_Handle -> MaxVC = SVAL(SMB_Hdr(pkt), SMB_negrNTLM_mnv_offset); - Con_Handle -> MaxRaw = IVAL(SMB_Hdr(pkt), SMB_negrNTLM_mrs_offset); - Con_Handle -> SessionKey = IVAL(SMB_Hdr(pkt), SMB_negrNTLM_sk_offset); - Con_Handle -> SvrTZ = SVAL(SMB_Hdr(pkt), SMB_negrNTLM_stz_offset); - Con_Handle -> Encrypt_Key_Len = CVAL(SMB_Hdr(pkt), SMB_negrNTLM_ekl_offset); - - p = (SMB_Hdr(pkt) + SMB_negrNTLM_buf_offset ); - memcpy(Con_Handle -> Encrypt_Key, p, 8); - p = (SMB_Hdr(pkt) + SMB_negrNTLM_buf_offset + Con_Handle -> Encrypt_Key_Len); - - strncpy(p, Con_Handle -> Svr_PDom, sizeof(Con_Handle -> Svr_PDom) - 1); - - break; - - default: - -#ifdef DEBUG - fprintf(stderr, "Unknown NegProt response format ... Ignored\n"); - fprintf(stderr, " wct = %i\n", CVAL(SMB_Hdr(pkt), SMB_hdr_wct_offset)); -#endif - - break; - } - -#ifdef DEBUG - fprintf(stderr, "Protocol selected is: %i:%s\n", prot, Prots[prot]); -#endif - - RFCNB_Free_Pkt(pkt); - return(0); - -} - -/* Get our hostname */ - -void SMB_Get_My_Name(char *name, int len) - -{ - if (gethostname(name, len) < 0) { /* Error getting name */ - - strncpy(name, "unknown", len); - - /* Should check the error */ - -#ifdef DEBUG - fprintf(stderr, "gethostname in SMB_Get_My_Name returned error:"); - perror(""); -#endif - - } - - /* only keep the portion up to the first "." */ - - -} diff --git a/authprogs/smbval/smblib.c b/authprogs/smbval/smblib.c deleted file mode 100644 index 06c8509..0000000 --- a/authprogs/smbval/smblib.c +++ /dev/null @@ -1,379 +0,0 @@ -/* UNIX SMBlib NetBIOS implementation - - Version 1.0 - SMBlib Routines - - Copyright (C) Richard Sharpe 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 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include "config.h" -#include "clibrary.h" -#include -#include - -int SMBlib_errno; -int SMBlib_SMB_Error; -#define SMBLIB_ERRNO -typedef unsigned char uchar; -#include "smblib-priv.h" - -#include "rfcnb.h" - -/* Initialize the SMBlib package */ - -int SMB_Init() - -{ - signal(SIGPIPE, SIG_IGN); /* Ignore these ... */ - - return 0; - -} - -int SMB_Term() - -{ - - return 0; - -} - -/* SMB_Connect_Server: Connect to a server, but don't negotiate protocol */ -/* or anything else ... */ - -SMB_Handle_Type SMB_Connect_Server(SMB_Handle_Type Con_Handle, - char *server, char *NTdomain) - -{ SMB_Handle_Type con; - char called[80], calling[80], *address; - int i; - - /* Get a connection structure if one does not exist */ - - con = Con_Handle; - - if (Con_Handle == NULL) { - - if ((con = (struct SMB_Connect_Def *)malloc(sizeof(struct SMB_Connect_Def))) == NULL) { - - - SMBlib_errno = SMBlibE_NoSpace; - return NULL; - } - - } - - /* Init some things ... */ - - strlcpy(con->service, "", sizeof(con->service)); - strlcpy(con->username, "", sizeof(con->username)); - strlcpy(con->password, "", sizeof(con->password)); - strlcpy(con->sock_options, "", sizeof(con->sock_options)); - strlcpy(con->address, "", sizeof(con->address)); - strlcpy(con->desthost, server, sizeof(con->desthost)); - strlcpy(con->PDomain, NTdomain, sizeof(con->PDomain)); - strlcpy(con->OSName, SMBLIB_DEFAULT_OSNAME, sizeof(con->OSName)); - strlcpy(con->LMType, SMBLIB_DEFAULT_LMTYPE, sizeof(con->LMType)); - - SMB_Get_My_Name(con -> myname, sizeof(con -> myname)); - - con -> port = 0; /* No port selected */ - - /* Get some things we need for the SMB Header */ - - con -> pid = getpid(); - con -> mid = con -> pid; /* This will do for now ... */ - con -> uid = 0; /* Until we have done a logon, no uid ... */ - con -> gid = getgid(); - - /* Now connect to the remote end, but first upper case the name of the - service we are going to call, sine some servers want it in uppercase */ - - for (i=0; i < strlen(server); i++) - called[i] = toupper(server[i]); - - called[strlen(server)] = 0; /* Make it a string */ - - for (i=0; i < strlen(con -> myname); i++) - calling[i] = toupper(con -> myname[i]); - - calling[strlen(con -> myname)] = 0; /* Make it a string */ - - if (strcmp(con -> address, "") == 0) - address = con -> desthost; - else - address = con -> address; - - con -> Trans_Connect = RFCNB_Call(called, - calling, - address, /* Protocol specific */ - con -> port); - - /* Did we get one? */ - - if (con -> Trans_Connect == NULL) { - - if (Con_Handle == NULL) { - Con_Handle = NULL; - free(con); - } - SMBlib_errno = -SMBlibE_CallFailed; - return NULL; - - } - - return(con); - -} - -/* Logon to the server. That is, do a session setup if we can. We do not do */ -/* Unicode yet! */ - -int SMB_Logon_Server(SMB_Handle_Type Con_Handle, char *UserName, - char *PassWord) - -{ struct RFCNB_Pkt *pkt; - int param_len, pkt_len, pass_len; - char *p, pword[128]; - - /* First we need a packet etc ... but we need to know what protocol has */ - /* been negotiated to figure out if we can do it and what SMB format to */ - /* use ... */ - - if (Con_Handle -> protocol < SMB_P_LanMan1) { - - SMBlib_errno = SMBlibE_ProtLow; - return(SMBlibE_BAD); - - } - - strlcpy(pword, PassWord, sizeof(pword)); - if (Con_Handle -> encrypt_passwords) - { - pass_len=24; - SMBencrypt((uchar *) PassWord, (uchar *)Con_Handle -> Encrypt_Key,(uchar *)pword); - } - else - pass_len=strlen(pword); - - - /* Now build the correct structure */ - - if (Con_Handle -> protocol < SMB_P_NT1) { - - param_len = strlen(UserName) + 1 + pass_len + 1 + - strlen(Con_Handle -> PDomain) + 1 + - strlen(Con_Handle -> OSName) + 1; - - pkt_len = SMB_ssetpLM_len + param_len; - - pkt = (struct RFCNB_Pkt *)RFCNB_Alloc_Pkt(pkt_len); - - if (pkt == NULL) { - - SMBlib_errno = SMBlibE_NoSpace; - return(SMBlibE_BAD); /* Should handle the error */ - - } - - memset(SMB_Hdr(pkt), 0, SMB_ssetpLM_len); - SIVAL(SMB_Hdr(pkt), SMB_hdr_idf_offset, SMB_DEF_IDF); /* Plunk in IDF */ - *(SMB_Hdr(pkt) + SMB_hdr_com_offset) = SMBsesssetupX; - SSVAL(SMB_Hdr(pkt), SMB_hdr_pid_offset, Con_Handle -> pid); - SSVAL(SMB_Hdr(pkt), SMB_hdr_tid_offset, 0); - SSVAL(SMB_Hdr(pkt), SMB_hdr_mid_offset, Con_Handle -> mid); - SSVAL(SMB_Hdr(pkt), SMB_hdr_uid_offset, Con_Handle -> uid); - *(SMB_Hdr(pkt) + SMB_hdr_wct_offset) = 10; - *(SMB_Hdr(pkt) + SMB_hdr_axc_offset) = 0xFF; /* No extra command */ - SSVAL(SMB_Hdr(pkt), SMB_hdr_axo_offset, 0); - - SSVAL(SMB_Hdr(pkt), SMB_ssetpLM_mbs_offset, SMBLIB_MAX_XMIT); - SSVAL(SMB_Hdr(pkt), SMB_ssetpLM_mmc_offset, 2); - SSVAL(SMB_Hdr(pkt), SMB_ssetpLM_vcn_offset, Con_Handle -> pid); - SIVAL(SMB_Hdr(pkt), SMB_ssetpLM_snk_offset, 0); - SSVAL(SMB_Hdr(pkt), SMB_ssetpLM_pwl_offset, pass_len + 1); - SIVAL(SMB_Hdr(pkt), SMB_ssetpLM_res_offset, 0); - SSVAL(SMB_Hdr(pkt), SMB_ssetpLM_bcc_offset, param_len); - - /* Now copy the param strings in with the right stuff */ - - p = (char *)(SMB_Hdr(pkt) + SMB_ssetpLM_buf_offset); - - /* Copy in password, then the rest. Password has a null at end */ - - memcpy(p, pword, pass_len); - - p = p + pass_len + 1; - - strcpy(p, UserName); - p = p + strlen(UserName); - *p = 0; - - p = p + 1; - - strcpy(p, Con_Handle -> PDomain); - p = p + strlen(Con_Handle -> PDomain); - *p = 0; - p = p + 1; - - strcpy(p, Con_Handle -> OSName); - p = p + strlen(Con_Handle -> OSName); - *p = 0; - - } - else { - - /* We don't admit to UNICODE support ... */ - - param_len = strlen(UserName) + 1 + pass_len + - strlen(Con_Handle -> PDomain) + 1 + - strlen(Con_Handle -> OSName) + 1 + - strlen(Con_Handle -> LMType) + 1; - - pkt_len = SMB_ssetpNTLM_len + param_len; - - pkt = (struct RFCNB_Pkt *)RFCNB_Alloc_Pkt(pkt_len); - - if (pkt == NULL) { - - SMBlib_errno = SMBlibE_NoSpace; - return(-1); /* Should handle the error */ - - } - - memset(SMB_Hdr(pkt), 0, SMB_ssetpNTLM_len); - SIVAL(SMB_Hdr(pkt), SMB_hdr_idf_offset, SMB_DEF_IDF); /* Plunk in IDF */ - *(SMB_Hdr(pkt) + SMB_hdr_com_offset) = SMBsesssetupX; - SSVAL(SMB_Hdr(pkt), SMB_hdr_pid_offset, Con_Handle -> pid); - SSVAL(SMB_Hdr(pkt), SMB_hdr_tid_offset, 0); - SSVAL(SMB_Hdr(pkt), SMB_hdr_mid_offset, Con_Handle -> mid); - SSVAL(SMB_Hdr(pkt), SMB_hdr_uid_offset, Con_Handle -> uid); - *(SMB_Hdr(pkt) + SMB_hdr_wct_offset) = 13; - *(SMB_Hdr(pkt) + SMB_hdr_axc_offset) = 0xFF; /* No extra command */ - SSVAL(SMB_Hdr(pkt), SMB_hdr_axo_offset, 0); - - SSVAL(SMB_Hdr(pkt), SMB_ssetpNTLM_mbs_offset, SMBLIB_MAX_XMIT); - SSVAL(SMB_Hdr(pkt), SMB_ssetpNTLM_mmc_offset, 0); - SSVAL(SMB_Hdr(pkt), SMB_ssetpNTLM_vcn_offset, 0); - SIVAL(SMB_Hdr(pkt), SMB_ssetpNTLM_snk_offset, 0); - SSVAL(SMB_Hdr(pkt), SMB_ssetpNTLM_cipl_offset, pass_len); - SSVAL(SMB_Hdr(pkt), SMB_ssetpNTLM_cspl_offset, 0); - SIVAL(SMB_Hdr(pkt), SMB_ssetpNTLM_res_offset, 0); - SIVAL(SMB_Hdr(pkt), SMB_ssetpNTLM_cap_offset, 0); - SSVAL(SMB_Hdr(pkt), SMB_ssetpNTLM_bcc_offset, param_len); - - /* Now copy the param strings in with the right stuff */ - - p = (char *)(SMB_Hdr(pkt) + SMB_ssetpNTLM_buf_offset); - - /* Copy in password, then the rest. Password has no null at end */ - - memcpy(p, pword, pass_len); - - p = p + pass_len; - - strcpy(p, UserName); - p = p + strlen(UserName); - *p = 0; - - p = p + 1; - - strcpy(p, Con_Handle -> PDomain); - p = p + strlen(Con_Handle -> PDomain); - *p = 0; - p = p + 1; - - strcpy(p, Con_Handle -> OSName); - p = p + strlen(Con_Handle -> OSName); - *p = 0; - p = p + 1; - - strcpy(p, Con_Handle -> LMType); - p = p + strlen(Con_Handle -> LMType); - *p = 0; - - } - - /* Now send it and get a response */ - - if (RFCNB_Send(Con_Handle -> Trans_Connect, pkt, pkt_len) < 0){ - - RFCNB_Free_Pkt(pkt); - SMBlib_errno = SMBlibE_SendFailed; - return(SMBlibE_BAD); - - } - - /* Now get the response ... */ - - if (RFCNB_Recv(Con_Handle -> Trans_Connect, pkt, pkt_len) < 0) { - - RFCNB_Free_Pkt(pkt); - SMBlib_errno = SMBlibE_RecvFailed; - return(SMBlibE_BAD); - - } - - /* Check out the response type ... */ - - if (CVAL(SMB_Hdr(pkt), SMB_hdr_rcls_offset) != SMBC_SUCCESS) { /* Process error */ - - SMBlib_SMB_Error = IVAL(SMB_Hdr(pkt), SMB_hdr_rcls_offset); - RFCNB_Free_Pkt(pkt); - SMBlib_errno = SMBlibE_Remote; - return(SMBlibE_BAD); - - } -/** @@@ mdz: check for guest login { **/ - if (SVAL(SMB_Hdr(pkt), SMB_ssetpr_act_offset) & 0x1) - { - /* do we allow guest login? NO! */ - return(SMBlibE_BAD); - - } - /** @@@ mdz: } **/ - - - /* Now pick up the UID for future reference ... */ - - Con_Handle -> uid = SVAL(SMB_Hdr(pkt), SMB_hdr_uid_offset); - RFCNB_Free_Pkt(pkt); - - return(0); - -} - - -/* Disconnect from the server, and disconnect all tree connects */ - -int SMB_Discon(SMB_Handle_Type Con_Handle, bool KeepHandle) - -{ - - /* We just disconnect the connection for now ... */ - - RFCNB_Hangup(Con_Handle -> Trans_Connect); - - if (!KeepHandle) - free(Con_Handle); - - return(0); - -} diff --git a/authprogs/smbval/smblib.h b/authprogs/smbval/smblib.h deleted file mode 100644 index a93255f..0000000 --- a/authprogs/smbval/smblib.h +++ /dev/null @@ -1,50 +0,0 @@ -/* UNIX SMBlib NetBIOS implementation - - Version 1.0 - SMBlib Defines - - Copyright (C) Richard Sharpe 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 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include "smblib-common.h" - -/* Just define all the entry points */ - -/* Initialize the library. */ - -int SMB_Init(void); - -/* Connect to a server, but do not do a tree con etc ... */ - -void *SMB_Connect_Server(void *Con, char *server, char *NTdomain); - -/* Negotiate a protocol */ - -int SMB_Negotiate(void *Con_Handle, char *Prots[]); - -/* Disconnect from server. Has flag to specify whether or not we keep the */ -/* handle. */ - -int SMB_Discon(void *Con, bool KeepHandle); - -/* Log on to a server. */ - -int SMB_Logon_Server(SMB_Handle_Type Con_Handle, char *UserName, - char *PassWord); diff --git a/authprogs/smbval/valid.c b/authprogs/smbval/valid.c deleted file mode 100644 index 425b14f..0000000 --- a/authprogs/smbval/valid.c +++ /dev/null @@ -1,48 +0,0 @@ -#include -#include -#include -#include "config.h" -#include "smblib-priv.h" -#include "smblib.h" -#include "valid.h" - -int Valid_User(char *USERNAME,char *PASSWORD,char *SERVER,char *BACKUP, char *DOMAIN) -{ - char *SMB_Prots[] = {"PC NETWORK PROGRAM 1.0", - "MICROSOFT NETWORKS 1.03", - "MICROSOFT NETWORKS 3.0", - "LANMAN1.0", - "LM1.2X002", - "Samba", - "NT LM 0.12", - "NT LANMAN 1.0", - NULL}; - SMB_Handle_Type con; - - SMB_Init(); - con = SMB_Connect_Server(NULL, SERVER, DOMAIN); - if (con == NULL) { /* Error ... */ - con = SMB_Connect_Server(NULL, BACKUP, DOMAIN); - if (con == NULL) { - return(NTV_SERVER_ERROR); - } - } - if (SMB_Negotiate(con, SMB_Prots) < 0) { /* An error */ - SMB_Discon(con,0); - return(NTV_PROTOCOL_ERROR); - } - /* Test for a server in share level mode do not authenticate against it */ - if (con -> Security == 0) - { - SMB_Discon(con,0); - return(NTV_PROTOCOL_ERROR); - } - - if (SMB_Logon_Server(con, USERNAME, PASSWORD) < 0) { - SMB_Discon(con,0); - return(NTV_LOGON_ERROR); - } - - SMB_Discon(con,0); - return(NTV_NO_ERROR); -} diff --git a/authprogs/smbval/valid.h b/authprogs/smbval/valid.h deleted file mode 100644 index 00d068b..0000000 --- a/authprogs/smbval/valid.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef _VALID_H_ -#define _VALID_H_ -/* SMB User verification function */ - -#define NTV_NO_ERROR 0 -#define NTV_SERVER_ERROR 1 -#define NTV_PROTOCOL_ERROR 2 -#define NTV_LOGON_ERROR 3 - -int Valid_User(char *USERNAME,char *PASSWORD,char *SERVER, char *BACKUP, char *DOMAIN); - -#endif diff --git a/backends/actmerge.in b/backends/actmerge.in deleted file mode 100644 index 237a332..0000000 --- a/backends/actmerge.in +++ /dev/null @@ -1,216 +0,0 @@ -#! /bin/sh -# fixscript will replace this line with code to load innshellvars - -# @(#) $Id: actmerge.in 2674 1999-11-15 06:28:29Z rra $ -# @(#) Under RCS control in /usr/local/news/src/inn/local/RCS/actmerge.sh,v -# -# actmerge - merge two active files -# -# usage: -# actmerge [-s] ign1 ign2 host1 host2 -# -# -s - write status on stderr even if no fatal error -# ign1 - ignore file for host1 -# ign2 - ignore file for host2 -# host1 - 1st active file or host -# host2 - 2nd active file or host -# -# The merge of two active files are sent to stdout. The status is -# written to stderr. - -# By: Landon Curt Noll chongo@toad.com (chongo was here /\../\) -# -# Copyright (c) Landon Curt Noll, 1996. -# All rights reserved. -# -# Permission to use and modify is hereby granted so long as this -# notice remains. Use at your own risk. No warranty is implied. - -# preset vars -# - -# Our lock file -LOCK=${LOCKS}/LOCK.actmerge -# where actsync is located -ACTSYNC=${PATHBIN}/actsync -# exit value of actsync if unable to get an active file -NOSYNC=127 -# args used by actsync a fetch of an active file -FETCH="-b 0 -d 0 -g 0 -o aK -p 0 -q 12 -s 0 -t 0 -v 2" -# args used to merge two active files -MERGE="-b 0 -d 0 -g 0 -m -o aK -p 0 -q 12 -s 0 -t 0 -v 3" -# unless -q -QUIET=true - -# parse args -# -if [ $# -gt 1 ]; then - if [ X"-s" = X"$1" ]; then - QUIET= - shift - fi -fi -if [ $# -ne 4 ]; then - echo "usage: $0 ign1 ign2 host1 host2" 1>&2 - exit 1 -fi -ign1="$1" -if [ ! -s "$ign1" ]; then - echo "$0: host1 ignore file not found or empty: $ign1" 1>&2 - exit 2 -fi -ign2="$2" -if [ ! -s "$ign2" ]; then - echo "$0: host2 ignore file not found or empty: $ign2" 1>&2 - exit 3 -fi -host1="$3" -host2="$4" - - -# Lock out others -# -trap 'rm -f ${LOCK}; exit 1' 0 1 2 3 15 -shlock -p $$ -f ${LOCK} || { - echo "$0: Locked by `cat ${LOCK}`" 1>&2 - exit 4 -} - -# setup -# -tmp="$TMPDIR/.merge$$" -act1="$TMPDIR/.act1$$" -act2="$TMPDIR/.act2$$" -trap "rm -f $tmp ${LOCK} $act1 $act2; exit" 0 1 2 3 15 -rm -f "$tmp" -touch "$tmp" -chmod 0600 "$tmp" -rm -f "$act1" -touch "$act1" -chmod 0600 "$act1" -rm -f "$act2" -touch "$act2" -chmod 0600 "$act2" - -# try to fetch the first active file -# -echo "=-= fetching $host1" >>$tmp -eval "$ACTSYNC -i $ign1 $FETCH /dev/null $host1 > $act1 2>>$tmp" -status=$? -if [ "$status" -ne 0 ]; then - - # We failed on our first try, so we will trice knock 3 times after - # waiting 5 minutes. - # - for loop in 1 2 3; do - - # wait 5 minutes - sleep 300 - - # try #1 - eval "$ACTSYNC -i $ign1 $FETCH /dev/null $host1 > $act1 2>>$tmp" - status=$? - if [ "$status" -eq "$NOSYNC" ]; then - break; - fi - - # try #2 - eval "$ACTSYNC -i $ign1 $FETCH /dev/null $host1 > $act1 2>>$tmp" - status=$? - if [ "$status" -eq "$NOSYNC" ]; then - break; - fi - - # try #3 - eval "$ACTSYNC -i $ign1 $FETCH /dev/null $host1 > $act1 2>>$tmp" - status=$? - if [ "$status" -eq "$NOSYNC" ]; then - break; - fi - done - - # give up - # - if [ "$status" -ne 0 ]; then - echo "=-= `date` merge $host1 $host2 exit $status" 1>&2 - sed -e 's/^/ /' < "$tmp" 1>&2 - exit "$status" - fi -fi -if [ ! -s "$act1" ]; then - echo "$0: host1 active file not found or empty: $act1" 1>&2 - exit 5 -fi - -# try to fetch the second active file -# -echo "=-= fetching $host2" >>$tmp -eval "$ACTSYNC -i $ign2 $FETCH /dev/null $host2 > $act2 2>>$tmp" -status=$? -if [ "$status" -ne 0 ]; then - - # We failed on our first try, so we will trice knock 3 times after - # waiting 5 minutes. - # - for loop in 1 2 3; do - - # wait 5 minutes - sleep 300 - - # try #1 - eval "$ACTSYNC -i $ign2 $FETCH /dev/null $host2 > $act2 2>>$tmp" - status=$? - if [ "$status" -eq "$NOSYNC" ]; then - break; - fi - - # try #2 - eval "$ACTSYNC -i $ign2 $FETCH /dev/null $host2 > $act2 2>>$tmp" - status=$? - if [ "$status" -eq "$NOSYNC" ]; then - break; - fi - - # try #3 - eval "$ACTSYNC -i $ign2 $FETCH /dev/null $host2 > $act2 2>>$tmp" - status=$? - if [ "$status" -eq "$NOSYNC" ]; then - break; - fi - done - - # give up - # - if [ "$status" -ne 0 ]; then - echo "=-= `date` merge $host1 $host2 exit $status" 1>&2 - sed -e 's/^/ /' < "$tmp" 1>&2 - exit "$status" - fi -fi -if [ ! -s "$act2" ]; then - echo "$0: host2 active file not found or empty: $act2" 1>&2 - exit 6 -fi - -# merge the 2 active files to stdout -# -echo "=-= merging $host1 and $host2" >>$tmp -eval "$ACTSYNC $MERGE $act1 $act2" 2>>$tmp -status=$? -if [ "$status" -ne 0 ]; then - echo "=-= `date` merge $host1 $host2 exit $status" 1>&2 - sed -e 's/^/ /' < "$tmp" 1>&2 - exit "$status" -fi - -# if not -q, send status to stderr -# -if [ -z "$QUIET" ]; then - echo "=-= `date` merge $host1 $host2 successful" 1>&2 - sed -e 's/^/ /' < "$tmp" 1>&2 -fi - -# all done -# -rm -f "${LOCK}" -exit 0 diff --git a/backends/actsync.c b/backends/actsync.c deleted file mode 100644 index 41c35e0..0000000 --- a/backends/actsync.c +++ /dev/null @@ -1,2766 +0,0 @@ -/* @(#) $Id: actsync.c 6372 2003-05-31 19:48:28Z rra $ */ -/* @(#) Under RCS control in /usr/local/news/src/inn/local/RCS/actsync.c,v */ -/* - * actsync - sync or merge two active files - * - * usage: - * actsync [-b hostid][-d hostid][-g max][-i ignore_file][-I][-k][-l hostid] - * [-m][-n name][-o fmt][-p %][-q hostid][-s size] - * [-t hostid][-T][-v verbose_lvl][-z sec] - * [host1] host2 - * - * -A use authentication to server - * -b hostid ignore *.bork.bork.bork groups from: (def: -b 0) - * 0 from neither host - * 1 from host1 - * 2 from host2 - * 12 from host1 and host2 - * 21 from host1 and host2 - * -d hostid ignore groups with all numeric components (def: -d 0) - * -g max ignore group >max levels (0=dont ignore) (def: -g 0) - * -i ignore_file file with list/types of groups to ignore (def: no file) - * -I hostid ignore_file applies only to hostid (def: -I 12) - * -k keep host1 groups with errors (def: remove) - * -l hostid flag =group problems as errors (def: -l 12) - * -m merge, keep group not on host2 (def: sync) - * -n name name given to ctlinnd newgroup commands (def: actsync) - * -o fmt type of output: (def: -o c) - * a output groups in active format - * a1 like 'a', but output ignored non-err host1 grps - * ak like 'a', keep host2 hi/low values on new groups - * aK like 'a', use host2 hi/low values always - * c output in ctlinnd change commands - * x no output, safely exec ctlinnd commands - * xi no output, safely exec commands interactively - * -p % min % host1 lines unchanged allowed (def: -p 96) - * -q hostid silence errors from a host (see -b) (def: -q 0) - * -s size ignore names longer than size (0=no lim) (def: -s 0) - * -t hostid ignore bad top level groups from:(see -b) (def: -t 2) - * -T no new hierarchies (def: allow) - * -v verbose_lvl verbosity level (def: -v 0) - * 0 no debug or status reports - * 1 summary if work done - * 2 summary & actions (if exec output) only if done - * 3 summary & actions (if exec output) - * 4 debug output plus all -v 3 messages - * -z sec sleep sec seconds per exec if -o x (def: -z 4) - * host1 host to be changed (def: local server) - * host2 reference host used in merge - */ -/* - * By: Landon Curt Noll chongo@toad.com (chongo was here /\../\) - * - * Copyright (c) Landon Curt Noll, 1996. - * All rights reserved. - * - * Permission to use and modify is hereby granted so long as this - * notice remains. Use at your own risk. No warranty is implied. - */ - -#include "config.h" -#include "clibrary.h" -#include "portable/wait.h" -#include -#include -#include -#include -#include -#include -#include - -#include "inn/innconf.h" -#include "inn/messages.h" -#include "inn/qio.h" -#include "libinn.h" -#include "paths.h" - -static const char usage[] = "\ -Usage: actsync [-A][-b hostid][-d hostid][-i ignore_file][-I hostid][-k]\n\ - [-l hostid][-m][-n name][-o fmt][-p min_%_unchg][-q hostid]\n\ - [-s size][-t hostid][-T][-v verbose_lvl][-z sec]\n\ - [host1] host2\n\ -\n\ - -A use authentication to server\n\ - -b hostid ignore *.bork.bork.bork groups from: (def: -b 0)\n\ - 0 from neither host\n\ - 1 from host1\n\ - 2 from host2\n\ - 12 from host1 and host2\n\ - 21 from host1 and host2\n\ - -d hostid ignore grps with all numeric components (def: -d 0)\n\ - -g max ignore group >max levels (0=don't) (def: -g 0)\n\ - -i file file with groups to ignore (def: no file)\n\ - -I hostid ignore_file applies only to hostid (def: -I 12)\n\ - -k keep host1 groups with errors (def: remove)\n\ - -l hostid flag =group problems as errors (def: -l 12)\n\ - -m merge, keep group not on host2 (def: sync)\n\ - -n name name given to ctlinnd newgroup cmds (def: actsync)\n\ - -o fmt type of output: (def: -o c)\n\ - a output groups in active format\n\ - a1 like 'a', but output ignored non-err host1 grps\n\ - ak like 'a', keep host2 hi/low values on new groups\n\ - aK like 'a', use host2 hi/low values always\n\ - c output in ctlinnd change commands\n\ - x no output, safely exec ctlinnd commands\n\ - xi no output, safely exec commands interactively\n\ - -p % min % host1 lines unchanged allowed (def: -p 96)\n\ - -q hostid silence errors from a host (see -b) (def: -q 0)\n\ - -s size ignore names > than size (0=no lim) (def: -s 0)\n\ - -t hostid ignore bad top level grps from: (see -b)(def: -t 2)\n\ - -T no new hierarchies (def: allow)\n\ - -v level verbosity level (def: -v 0)\n\ - 0 no debug or status reports\n\ - 1 summary if work done\n\ - 2 summary & actions (if exec output) only if done\n\ - 3 summary & actions (if exec output)\n\ - 4 debug output plus all -v 3 messages\n\ - -z sec sleep sec seconds per exec if -o x (def: -z 4)\n\ -\n\ - host1 host to be changed (def: local server)\n\ - host2 reference host used in merge\n"; - - -/* - * pat - internal ignore/check pattern - * - * A pattern, derived from an ignore file, will determine if a group - * is will be checked if it is on both hosts or ignored altogether. - * - * The type related to the 4th field of an active file. Types may - * currently be one of [ymjnx=]. If '=' is one of the types, an - * optional equivalence pattern may be given in the 'epat' element. - * - * For example, to ignore "foo.bar.*", if it is junked or equated to - * a group of the form "alt.*.foo.bar.*": - * - * x.pat = "foo.bar.*"; - * x.type = "j="; - * x.epat = "alt.*.foo.bar.*"; - * x.ignore = 1; - * - * To further check "foo.bar.mod" if it is moderated: - * - * x.pat = "foo.bar.mod"; - * x.type = "m"; - * x.epat = NULL; - * x.ignore = 0; - * - * The 'i' value means ignore, 'c' value means 'compare'. The last pattern - * that matches a group determines the fate of the group. By default all - * groups are included. - */ -struct pat { - char *pat; /* newsgroup pattern */ - int type_match; /* 1 => match only if group type matches */ - int y_type; /* 1 => match if a 'y' type group */ - int m_type; /* 1 => match if a 'm' type group */ - int n_type; /* 1 => match if a 'n' type group */ - int j_type; /* 1 => match if a 'j' type group */ - int x_type; /* 1 => match if a 'x' type group */ - int eq_type; /* 1 => match if a 'eq' type group */ - char *epat; /* =pattern to match, if non-NULL and = is in type */ - int ignore; /* 0 => check matching group, 1 => ignore it */ -}; - -/* internal representation of an active line */ -struct grp { - int ignore; /* ignore reason, 0 => not ignore (see below) */ - int hostid; /* HOSTID this group is from */ - int linenum; /* >0 => active line number, <=0 => not a line */ - int output; /* 1 => output to produce the merged active file */ - int remove; /* 1 => remove this group */ - char *name; /* newsgroup name */ - char *hi; /* high article string */ - char *low; /* low article string */ - char *type; /* newsgroup type string */ - char *outhi; /* output high article string */ - char *outlow; /* output low article string */ - char *outtype; /* output newsgroup type string */ -}; - -/* structure used in the process of looking for =group type problems */ -struct eqgrp { - int skip; /* 1 => skip this entry */ - struct grp *g; /* =group that is being examined */ - char *eq; /* current equivalence name */ -}; - -/* - * These ignore reasons are listed in order severity; from mild to severe. - */ -#define NOT_IGNORED 0x0000 /* newsgroup has not been ignored */ -#define CHECK_IGNORE 0x0001 /* ignore file ignores this entry */ -#define CHECK_TYPE 0x0002 /* group type is ignored */ -#define CHECK_BORK 0x0004 /* group is a *.bork.bork.bork group */ -#define CHECK_HIER 0x0008 /* -T && new group's hierarchy does not exist */ -#define ERROR_LONGLOOP 0x0010 /* =name refers to long =grp chain or cycle */ -#define ERROR_EQLOOP 0x0020 /* =name refers to itself in some way */ -#define ERROR_NONEQ 0x0040 /* =name does not refer to a valid group */ -#define ERROR_DUP 0x0080 /* newsgroup is a duplicate of another */ -#define ERROR_EQNAME 0x0100 /* =name is a bad group name */ -#define ERROR_BADTYPE 0x0200 /* newsgroup type is invalid */ -#define ERROR_BADNAME 0x0400 /* newsgroup name is invalid */ -#define ERROR_FORMAT 0x0800 /* entry line is malformed */ - -#define IS_IGNORE(ign) ((ign) & (CHECK_IGNORE|CHECK_TYPE|CHECK_BORK|CHECK_HIER)) -#define IS_ERROR(ign) ((ign) & ~(CHECK_IGNORE|CHECK_TYPE|CHECK_BORK|CHECK_HIER)) - -#define NOHOST 0 /* neither host1 nor host2 */ -#define HOSTID1 1 /* entry from the first host */ -#define HOSTID2 2 /* entry from the second host */ - -#define CHUNK 5000 /* number of elements to alloc at a time */ - -#define TYPES "ymjnx=" /* group types (1st char of 4th active fld) */ -#define TYPECNT (sizeof(TYPES)-1) - -#define DEF_HI "0000000000" /* default hi string value for new groups */ -#define DEF_LOW "0000000001" /* default low string value for new groups */ -#define WATER_LEN 10 /* string length of hi/low water mark */ - -#define DEF_NAME "actsync" /* default name to use for ctlinnd newgroup */ - -#define MIN_UNCHG (double)96.0 /* min % of host1 lines unchanged allowed */ - -#define DEV_NULL "/dev/null" /* path to the bit bucket */ -#define CTLINND_NAME "ctlinnd" /* basename of ctlinnd command */ -#define CTLINND_TIME_OUT "-t30" /* seconds to wait before timeout */ - -#define READ_SIDE 0 /* read side of a pipe */ -#define WRITE_SIDE 1 /* write side of a pipe */ - -#define EQ_LOOP 16 /* give up if =eq loop/chain is this long */ -#define NOT_REACHED 127 /* exit value if unable to get active files */ - -#define NEWGRP_EMPTY 0 /* no new group dir was found */ -#define NEWGRP_NOCHG 1 /* new group dir found but no hi/low change */ -#define NEWGRP_CHG 2 /* new group dir found but no hi/low change */ - -/* -b macros */ -#define BORK_CHECK(hostid) \ - ((hostid == HOSTID1 && bork_host1_flag) || \ - (hostid == HOSTID2 && bork_host2_flag)) - -/* -d macros */ -#define NUM_CHECK(hostid) \ - ((hostid == HOSTID1 && num_host1_flag) || \ - (hostid == HOSTID2 && num_host2_flag)) - -/* -t macros */ -#define TOP_CHECK(hostid) \ - ((hostid == HOSTID1 && t_host1_flag) || \ - (hostid == HOSTID2 && t_host2_flag)) - -/* -o output types */ -#define OUTPUT_ACTIVE 1 /* output in active file format */ -#define OUTPUT_CTLINND 2 /* output in ctlinnd change commands */ -#define OUTPUT_EXEC 3 /* no output, safely exec commands */ -#define OUTPUT_IEXEC 4 /* no output, exec commands interactively */ - -/* -q macros */ -#define QUIET(hostid) \ - ((hostid == HOSTID1 && quiet_host1) || (hostid == HOSTID2 && quiet_host2)) - -/* -v verbosity level */ -#define VER_MIN 0 /* minimum -v level */ -#define VER_NONE 0 /* no -v output */ -#define VER_SUMM_IF_WORK 1 /* output summary if actions were performed */ -#define VER_REPT_IF_WORK 2 /* output summary & actions only if performed */ -#define VER_REPORT 3 /* output summary & actions performed */ -#define VER_FULL 4 /* output all summary, actins and debug */ -#define VER_MAX 4 /* maximum -v level */ -#define D_IF_SUMM (v_flag >= VER_SUMM_IF_WORK) /* true => give summary always */ -#define D_REPORT (v_flag >= VER_REPT_IF_WORK) /* true => give reports */ -#define D_BUG (v_flag == VER_FULL) /* true => debug processing */ -#define D_SUMMARY (v_flag >= VER_REPORT) /* true => give summary always */ - -/* flag and arg related defaults */ -int bork_host1_flag = 0; /* 1 => -b 1 or -b 12 or -b 21 given */ -int bork_host2_flag = 0; /* 1 => -b 2 or -b 12 or -b 21 given */ -int num_host1_flag = 0; /* 1 => -d 1 or -d 12 or -d 21 given */ -int num_host2_flag = 0; /* 1 => -d 2 or -d 12 or -d 21 given */ -char *ign_file = NULL; /* default ignore file */ -int ign_host1_flag = 1; /* 1 => -i ign_file applies to host1 */ -int ign_host2_flag = 1; /* 1 => -i ign_file applies to host2 */ -int g_flag = 0; /* ignore grps deeper than > g_flag, 0=>dont */ -int k_flag = 0; /* 1 => -k given */ -int l_host1_flag = HOSTID1; /* HOSTID1 => host1 =group error detection */ -int l_host2_flag = HOSTID2; /* HOSTID2 => host2 =group error detection */ -int m_flag = 0; /* 1 => merge active files, don't sync */ -const char *new_name = DEF_NAME; /* ctlinnd newgroup name */ -int o_flag = OUTPUT_CTLINND; /* default output type */ -double p_flag = MIN_UNCHG; /* min % host1 lines allowed to be unchanged */ -int host1_errs = 0; /* errors found in host1 active file */ -int host2_errs = 0; /* errors found in host2 active file */ -int quiet_host1 = 0; /* 1 => -q 1 or -q 12 or -q 21 given */ -int quiet_host2 = 0; /* 1 => -q 2 or -q 12 or -q 21 given */ -int s_flag = 0; /* max group size (length), 0 => do not check */ -int t_host1_flag = 0; /* 1 => -t 1 or -t 12 or -t 21 given */ -int t_host2_flag = 1; /* 1 => -t 2 or -d 12 or -t 21 given */ -int no_new_hier = 0; /* 1 => -T; no new hierarchies */ -int host2_hilow_newgrp = 0; /* 1 => use host2 hi/low on new groups */ -int host2_hilow_all = 0; /* 1 => use host2 hi/low on all groups */ -int host1_ign_print = 0; /* 1 => print host1 ignored groups too */ -int v_flag = 0; /* default verbosity level */ -int z_flag = 4; /* sleep z_flag sec per exec if -o x */ -int A_flag = 0; - -/* forward declarations */ -static struct grp *get_active(); /* get an active file from a remote host */ -static int bad_grpname(); /* test if string is a valid group name */ -static struct pat *get_ignore(); /* read in an ignore file */ -static void ignore(); /* ignore newsgroups given an ignore list */ -static int merge_cmp(); /* qsort compare for active file merge */ -static void merge_grps(); /* merge groups from active files */ -static int active_cmp(); /* qsort compare for active file output */ -static void output_grps(); /* output the merged groups */ -static void process_args(); /* process command line arguments */ -static void error_mark(); /* mark for removal, error grps from host */ -static int eq_merge_cmp(); /* qsort compare for =type grp processing */ -static int mark_eq_probs(); /* mark =type problems from a host */ -static int exec_cmd(); /* exec a ctlinnd command */ -static int new_top_hier(); /* see if we have a new top level */ - -int -main(argc, argv) - int argc; /* arg count */ - char *argv[]; /* the args */ -{ - struct grp *grp; /* struct grp array for host1 & host2 */ - struct pat *ignor; /* ignore list from ignore file */ - int grplen; /* length of host1/host2 group array */ - int iglen; /* length of ignore list */ - char *host1; /* host to change */ - char *host2; /* comparison host */ - - /* First thing, set up our identity. */ - message_program_name = "actsync"; - - /* Read in default info from inn.conf. */ - if (!innconf_read(NULL)) - exit(1); - process_args(argc, argv, &host1, &host2); - - /* obtain the active files */ - grp = get_active(host1, HOSTID1, &grplen, NULL, &host1_errs); - grp = get_active(host2, HOSTID2, &grplen, grp, &host2_errs); - - /* ignore groups from both active files, if -i */ - if (ign_file != NULL) { - - /* read in the ignore file */ - ignor = get_ignore(ign_file, &iglen); - - /* ignore groups */ - ignore(grp, grplen, ignor, iglen); - } - - /* compare groups from both hosts */ - merge_grps(grp, grplen, host1, host2); - - /* mark for removal, error groups from host1 if -e */ - if (! k_flag) { - - /* mark error groups for removal */ - error_mark(grp, grplen, HOSTID1); - } - - /* output result of merge */ - output_grps(grp, grplen); - - /* all done */ - exit(0); -} - -/* - * process_args - process the command line arguments - * - * given: - * argc arg count - * argv the args - * host1 name of first host (may be 2nd if -R) - * host2 name of second host2 *may be 1st if -R) - */ -static void -process_args(argc, argv, host1, host2) - int argc; /* arg count */ - char *argv[]; /* the arg array */ - char **host1; /* where to place name of host1 */ - char **host2; /* where to place name of host2 */ -{ - char *def_serv = NULL; /* name of default server */ - int i; - - /* parse args */ - while ((i = getopt(argc,argv,"Ab:d:g:i:I:kl:mn:o:p:q:s:t:Tv:z:")) != EOF) { - switch (i) { - case 'A': - A_flag = 1; - break; - case 'b': /* -b {0|1|2|12|21} */ - switch (atoi(optarg)) { - case 0: - bork_host1_flag = 0; - bork_host2_flag = 0; - break; - case 1: - bork_host1_flag = 1; - break; - case 2: - bork_host2_flag = 1; - break; - case 12: - case 21: - bork_host1_flag = 1; - bork_host2_flag = 1; - break; - default: - warn("-b option must be 0, 1, 2, 12, or 21"); - die("%s", usage); - } - break; - case 'd': /* -d {0|1|2|12|21} */ - switch (atoi(optarg)) { - case 0: - num_host1_flag = 0; - num_host2_flag = 0; - break; - case 1: - num_host1_flag = 1; - break; - case 2: - num_host2_flag = 1; - break; - case 12: - case 21: - num_host1_flag = 1; - num_host2_flag = 1; - break; - default: - warn("-d option must be 0, 1, 2, 12, or 21"); - die("%s", usage); - } - break; - case 'g': /* -g max */ - g_flag = atoi(optarg); - break; - case 'i': /* -i ignore_file */ - ign_file = optarg; - break; - case 'I': /* -I {0|1|2|12|21} */ - switch (atoi(optarg)) { - case 0: - ign_host1_flag = 0; - ign_host2_flag = 0; - break; - case 1: - ign_host1_flag = 1; - ign_host2_flag = 0; - break; - case 2: - ign_host1_flag = 0; - ign_host2_flag = 1; - break; - case 12: - case 21: - ign_host1_flag = 1; - ign_host2_flag = 1; - break; - default: - warn("-I option must be 0, 1, 2, 12, or 21"); - die("%s", usage); - } - break; - case 'k': /* -k */ - k_flag = 1; - break; - case 'l': /* -l {0|1|2|12|21} */ - switch (atoi(optarg)) { - case 0: - l_host1_flag = NOHOST; - l_host2_flag = NOHOST; - break; - case 1: - l_host1_flag = HOSTID1; - l_host2_flag = NOHOST; - break; - case 2: - l_host1_flag = NOHOST; - l_host2_flag = HOSTID2; - break; - case 12: - case 21: - l_host1_flag = HOSTID1; - l_host2_flag = HOSTID2; - break; - default: - warn("-l option must be 0, 1, 2, 12, or 21"); - die("%s", usage); - } - break; - case 'm': /* -m */ - m_flag = 1; - break; - case 'n': /* -n name */ - new_name = optarg; - break; - case 'o': /* -o out_type */ - switch (optarg[0]) { - case 'a': - o_flag = OUTPUT_ACTIVE; - switch (optarg[1]) { - case '1': - switch(optarg[2]) { - case 'K': /* -o a1K */ - host1_ign_print = 1; - host2_hilow_all = 1; - host2_hilow_newgrp = 1; - break; - case 'k': /* -o a1k */ - host1_ign_print = 1; - host2_hilow_newgrp = 1; - break; - default: /* -o a1 */ - host1_ign_print = 1; - break; - } - break; - case 'K': - switch(optarg[2]) { - case '1': /* -o aK1 */ - host1_ign_print = 1; - host2_hilow_all = 1; - host2_hilow_newgrp = 1; - break; - default: /* -o aK */ - host2_hilow_all = 1; - host2_hilow_newgrp = 1; - break; - }; - break; - case 'k': - switch(optarg[2]) { - case '1': /* -o ak1 */ - host1_ign_print = 1; - host2_hilow_newgrp = 1; - break; - default: /* -o ak */ - host2_hilow_newgrp = 1; - break; - }; - break; - case '\0': /* -o a */ - break; - default: - warn("-o type must be a, a1, ak, aK, ak1, or aK1"); - die("%s", usage); - } - break; - case 'c': - o_flag = OUTPUT_CTLINND; - break; - case 'x': - if (optarg[1] == 'i') { - o_flag = OUTPUT_IEXEC; - } else { - o_flag = OUTPUT_EXEC; - } - break; - default: - warn("-o type must be a, a1, ak, aK, ak1, aK1, c, x, or xi"); - die("%s", usage); - } - break; - case 'p': /* -p %_min_host1_change */ - /* parse % into [0,100] */ - p_flag = atof(optarg); - if (p_flag > (double)100.0) { - p_flag = (double)100.0; - } else if (p_flag < (double)0.0) { - p_flag = (double)0.0; - } - break; - case 'q': /* -q {0|1|2|12|21} */ - switch (atoi(optarg)) { - case 0: - quiet_host1 = 0; - quiet_host2 = 0; - break; - case 1: - quiet_host1 = 1; - break; - case 2: - quiet_host2 = 1; - break; - case 12: - case 21: - quiet_host1 = 1; - quiet_host2 = 1; - break; - default: - warn("-q option must be 0, 1, 2, 12, or 21"); - die("%s", usage); - } - break; - case 's': /* -s size */ - s_flag = atoi(optarg); - break; - case 't': /* -t {0|1|2|12|21} */ - switch (atoi(optarg)) { - case 0: - t_host1_flag = NOHOST; - t_host2_flag = NOHOST; - break; - case 1: - t_host1_flag = HOSTID1; - t_host2_flag = NOHOST; - break; - case 2: - t_host1_flag = NOHOST; - t_host2_flag = HOSTID2; - break; - case 12: - case 21: - t_host1_flag = HOSTID1; - t_host2_flag = HOSTID2; - break; - default: - warn("-t option must be 0, 1, 2, 12, or 21"); - die("%s", usage); - } - break; - case 'T': /* -T */ - no_new_hier = 1; - break; - case 'v': /* -v verbose_lvl */ - v_flag = atoi(optarg); - if (v_flag < VER_MIN || v_flag > VER_MAX) { - warn("-v level must be >= %d and <= %d", VER_MIN, VER_MAX); - die("%s", usage); - } - break; - case 'z': /* -z sec */ - z_flag = atoi(optarg); - break; - default: - warn("unknown flag"); - die("%s", usage); - } - } - - /* process the remaining args */ - argc -= optind; - argv += optind; - *host1 = NULL; - switch (argc) { - case 1: - /* assume host1 is the local server */ - *host2 = argv[0]; - break; - case 2: - *host1 = argv[0]; - *host2 = argv[1]; - break; - default: - warn("expected 1 or 2 host args, found %d", argc); - die("%s", usage); - } - - /* determine default host name if needed */ - if (*host1 == NULL || strcmp(*host1, "-") == 0) { - def_serv = innconf->server; - *host1 = def_serv; - } - if (*host2 == NULL || strcmp(*host2, "-") == 0) { - def_serv = innconf->server; - *host2 = def_serv; - } - if (*host1 == NULL || *host2 == NULL) - die("unable to determine default server name"); - if (D_BUG && def_serv != NULL) - warn("STATUS: using default server: %s", def_serv); - - /* processing done */ - return; -} - -/* - * get_active - get an active file from a host - * - * given: - * host host to contact or file to read, NULL => local server - * hostid HOST_ID of host - * len pointer to length of grp return array - * grp existing host array to add, or NULL - * errs count of lines that were found to have some error - * - * returns; - * Pointer to an array of grp structures describing each active entry. - * Does not return on fatal error. - * - * If host starts with a '/' or '.', then it is assumed to be a local file. - * In that case, the local file is opened and read. - */ -static struct grp * -get_active(host, hostid, len, grp, errs) - char *host; /* the host to contact */ - int hostid; /* HOST_ID of host */ - int *len; /* length of returned grp array in elements */ - struct grp* grp; /* existing group array or NULL */ - int *errs; /* line error count */ -{ - FILE *active; /* stream for fetched active data */ - FILE *FromServer; /* stream from server */ - FILE *ToServer; /* stream to server */ - QIOSTATE *qp; /* QIO active state */ - char buff[8192+1]; /* QIO buffer */ - char *line; /* the line just read */ - struct grp *ret; /* array of groups to return */ - struct grp *cur; /* current grp entry being formed */ - int max; /* max length of ret */ - int cnt; /* number of entries read */ - int ucnt; /* number of entries to be used */ - int namelen; /* length of newsgroup name */ - int is_file; /* 1 => host is actually a filename */ - int num_check; /* true => check for all numeric components */ - char *rhost; - int rport; - char *p; - int i; - - /* firewall */ - if (len == NULL) - die("internal error #1: len is NULL"); - if (errs == NULL) - die("internal error #2: errs in NULL"); - if (D_BUG) - warn("STATUS: obtaining active file from %s", host); - - /* setup return array if needed */ - if (grp == NULL) { - ret = xmalloc(CHUNK * sizeof(struct grp)); - max = CHUNK; - *len = 0; - - /* or prep to use the existing array */ - } else { - ret = grp; - max = ((*len + CHUNK-1)/CHUNK)*CHUNK; - } - - /* check for host being a filename */ - if (host != NULL && (host[0] == '/' || host[0] == '.')) { - - /* note that host is actually a file */ - is_file = 1; - - /* setup to read the local file quickly */ - if ((qp = QIOopen(host)) == NULL) - sysdie("cannot open active file"); - - /* case: host is a hostname or NULL (default server) */ - } else { - - /* note that host is actually a hostname or NULL */ - is_file = 0; - - /* prepare remote host variables */ - if ((p = strchr(host, ':')) != NULL) { - rport = atoi(p + 1); - *p = '\0'; - rhost = xstrdup(host); - *p = ':'; - } else { - rhost = xstrdup(host); - rport = NNTP_PORT; - } - - /* open a connection to the server */ - buff[0] = '\0'; - if (NNTPconnect(rhost, rport, &FromServer, &ToServer, buff) < 0) - die("cannot connect to server: %s", - buff[0] ? buff : strerror(errno)); - - if (A_flag && NNTPsendpassword(rhost, FromServer, ToServer) < 0) - die("cannot authenticate to server"); - - free(rhost); - - /* get the active data from the server */ - active = CAlistopen(FromServer, ToServer, NULL); - if (active == NULL) - sysdie("cannot retrieve data"); - - /* setup to read the retrieved data quickly */ - if ((qp = QIOfdopen((int)fileno(active))) == NULL) - sysdie("cannot read temp file"); - } - - /* scan server's output, processing appropriate lines */ - num_check = NUM_CHECK(hostid); - for (cnt=0, ucnt=0; (line = QIOread(qp)) != NULL; ++(*len), ++cnt) { - - /* expand return array if needed */ - if (*len >= max) { - max += CHUNK; - ret = xrealloc(ret, sizeof(struct grp) * max); - } - - /* setup the next return element */ - cur = &ret[*len]; - cur->ignore = NOT_IGNORED; - cur->hostid = hostid; - cur->linenum = cnt+1; - cur->output = 0; - cur->remove = 0; - cur->name = NULL; - cur->hi = NULL; - cur->low = NULL; - cur->type = NULL; - cur->outhi = NULL; - cur->outlow = NULL; - cur->outtype = NULL; - - /* obtain a copy of the current line */ - cur->name = xstrdup(line); - - /* get the group name */ - if ((p = strchr(cur->name, ' ')) == NULL) { - if (!QUIET(hostid)) - warn("line %d from %s is malformed, skipping line", cnt + 1, - host); - - /* don't form an entry for this group */ - --(*len); - continue; - } - *p = '\0'; - namelen = p - cur->name; - - /* find the other 3 fields, ignore if not found */ - cur->hi = p+1; - if ((p = strchr(p + 1, ' ')) == NULL) { - if (!QUIET(hostid)) - warn("skipping malformed line %d (field 2) from %s", cnt + 1, - host); - - /* don't form an entry for this group */ - --(*len); - continue; - } - *p = '\0'; - cur->low = p+1; - if ((p = strchr(p + 1, ' ')) == NULL) { - if (!QUIET(hostid)) - warn("skipping malformed line %d (field 3) from %s", cnt + 1, - host); - - /* don't form an entry for this group */ - --(*len); - continue; - } - *p = '\0'; - cur->type = p+1; - if ((p = strchr(p + 1, ' ')) != NULL) { - if (!QUIET(hostid)) - warn("skipping line %d from %s, it has more than 4 fields", - cnt + 1, host); - - /* don't form an entry for this group */ - --(*len); - continue; - } - - /* check for bad group name */ - if (bad_grpname(cur->name, num_check)) { - if (!QUIET(hostid)) - warn("line %d <%s> from %s has a bad newsgroup name", - cnt + 1, cur->name, host); - cur->ignore |= ERROR_BADNAME; - continue; - } - - /* check for long name if requested */ - if (s_flag > 0 && strlen(cur->name) > (size_t)s_flag) { - if (!QUIET(hostid)) - warn("line %d <%s> from %s has a name that is too long", - cnt + 1, cur->name, host); - cur->ignore |= ERROR_BADNAME; - continue; - } - - /* look for only a bad top level element if the proper -t was given */ - if (TOP_CHECK(hostid)) { - - /* look for a '.' in the name */ - if (strcmp(cur->name, "junk") != 0 && - strcmp(cur->name, "control") != 0 && - strcmp(cur->name, "to") != 0 && - strcmp(cur->name, "test") != 0 && - strcmp(cur->name, "general") != 0 && - strchr(cur->name, '.') == NULL) { - if (!QUIET(hostid)) - warn("line %d <%s> from %s is an invalid top level name", - cnt + 1, cur->name, host); - cur->ignore |= ERROR_BADNAME; - continue; - } - } - - /* look for *.bork.bork.bork groups if the proper -b was given */ - if (BORK_CHECK(cur->hostid)) { - int elmlen; /* length of element */ - char *q; /* beyond end of element */ - - /* scan the name backwards */ - q = &(cur->name[namelen]); - for (p = &(cur->name[namelen-1]); p >= cur->name; --p) { - /* if '.', see if this is a bork element */ - if (*p == '.') { - /* see if the bork element is short enough */ - elmlen = q-p; - if (3*elmlen <= q-cur->name) { - /* look for a triple match */ - if (strncmp(p,p-elmlen,elmlen) == 0 && - strncmp(p,p-(elmlen*2),elmlen) == 0) { - /* found a *.bork.bork.bork group */ - cur->ignore |= CHECK_BORK; - break; - } - } - /* note the end of a new element */ - q = p; - } - } - } - - /* - * check for bad chars in the hi water mark - */ - for (p=cur->hi, i=0; *p && isascii(*p) && isdigit((int)*p); ++p, ++i) { - } - if (*p) { - if (!QUIET(hostid)) - warn("line %d <%s> from %s has non-digits in hi water", - cnt + 1, cur->name, cur->hi); - cur->ignore |= ERROR_FORMAT; - continue; - } - - /* - * check for excessive hi water length - */ - if (i > WATER_LEN) { - if (!QUIET(hostid)) - warn("line %d <%s> from %s hi water len: %d < %d", - cnt + 1, cur->name, cur->hi, i, WATER_LEN); - cur->ignore |= ERROR_FORMAT; - continue; - } - - /* - * if the hi water length is too small, malloc and resize - */ - if (i != WATER_LEN) { - p = xmalloc(WATER_LEN + 1); - memcpy(p, cur->hi, ((i > WATER_LEN) ? WATER_LEN : i)+1); - } - - /* - * check for bad chars in the low water mark - */ - for (p=cur->low, i=0; *p && isascii(*p) && isdigit((int)*p); ++p, ++i) { - } - if (*p) { - if (!QUIET(hostid)) - warn("line %d <%s> from %s has non-digits in low water", - cnt + 1, cur->name, cur->low); - cur->ignore |= ERROR_FORMAT; - continue; - } - - /* - * check for excessive low water length - */ - if (i > WATER_LEN) { - if (!QUIET(hostid)) - warn("line %d <%s> from %s low water len: %d < %d", - cnt + 1, cur->name, cur->hi, i, WATER_LEN); - cur->ignore |= ERROR_FORMAT; - continue; - } - - /* - * if the low water length is too small, malloc and resize - */ - if (i != WATER_LEN) { - p = xmalloc(WATER_LEN + 1); - memcpy(p, cur->low, ((i > WATER_LEN) ? WATER_LEN : i)+1); - } - - /* check for a bad group type */ - switch (cur->type[0]) { - case 'y': - /* of COURSE: collabra has incompatible flags. but it */ - /* looks like they can be fixed easily enough. */ - if (cur->type[1] == 'g') { - cur->type[1] = '\0'; - } - case 'm': - case 'j': - case 'n': - case 'x': - if (cur->type[1] != '\0') { - if (!QUIET(hostid)) - warn("line %d <%s> from %s has a bad newsgroup type", - cnt + 1, cur->name, host); - cur->ignore |= ERROR_BADTYPE; - } - break; - case '=': - if (cur->type[1] == '\0') { - if (!QUIET(hostid)) - warn("line %d <%s> from %s has an empty =group name", - cnt + 1, cur->name, host); - cur->ignore |= ERROR_BADTYPE; - } - break; - default: - if (!QUIET(hostid)) - warn("line %d <%s> from %s has an unknown newsgroup type", - cnt + 1, cur->name, host); - cur->ignore |= ERROR_BADTYPE; - break; - } - if (cur->ignore & ERROR_BADTYPE) { - continue; - } - - /* if an = type, check for bad = name */ - if (cur->type[0] == '=' && bad_grpname(&(cur->type[1]), num_check)) { - if (!QUIET(hostid)) - warn("line %d <%s> from %s is equivalenced to a bad name:" - " <%s>", cnt+1, cur->name, host, - (cur->type) ? cur->type : "NULL"); - cur->ignore |= ERROR_EQNAME; - continue; - } - - /* if an = type, check for long = name if requested */ - if (cur->type[0] == '=' && s_flag > 0 && - strlen(&(cur->type[1])) > (size_t)s_flag) { - if (!QUIET(hostid)) - warn("line %d <%s> from %s is equivalenced to a long name:" - " <%s>", cnt+1, cur->name, host, - (cur->type) ? cur->type : "NULL"); - cur->ignore |= ERROR_EQNAME; - continue; - } - - /* count this entry which will be used */ - ++ucnt; - } - if (D_BUG) - warn("STATUS: read %d groups, will merge %d groups from %s", - cnt, ucnt, host); - - /* count the errors */ - *errs = cnt - ucnt; - if (D_BUG) - warn("STATUS: found %d line errors from %s", *errs, host); - - /* determine why we stopped */ - if (QIOerror(qp)) - sysdie("cannot read temp file for %s at line %d", host, cnt); - else if (QIOtoolong(qp)) - sysdie("line %d from host %s is too long", cnt, host); - - /* all done */ - if (is_file) { - QIOclose(qp); - } else { - CAclose(); - fprintf(ToServer, "quit\r\n"); - fclose(ToServer); - fgets(buff, sizeof buff, FromServer); - fclose(FromServer); - } - return ret; -} - -/* - * bad_grpname - test if the string is a valid group name - * - * Newsgroup names must consist of only alphanumeric chars and - * characters from the following regular expression: - * - * [.+-_] - * - * One cannot have two '.'s in a row. The first character must be - * alphanumeric. The character following a '.' must be alphanumeric. - * The name cannot end in a '.' character. - * - * If we are checking for all numeric compnents, (see num_chk) then - * a component cannot be all numeric. I.e,. there must be a non-numeric - * character in the name, there must be a non-numeric character between - * the start and the first '.', there must be a non-numeric character - * between two '.'s anmd there must be a non-numeric character between - * the last '.' and the end. - * - * given: - * name newsgroup name to check - * num_chk true => all numeric newsgroups components are invalid - * false => do not check for numeric newsgroups - * - * returns: - * 0 group is ok - * 1 group is bad - */ -static int -bad_grpname(name, num_chk) - char *name; /* newsgroup name to check */ - int num_chk; /* true => check for numeric newsgroup */ -{ - char *p; - int non_num; /* true => found a non-numeric, non-. character */ - int level; /* group levels (.'s) */ - - /* firewall */ - if (name == NULL) { - return 1; - } - - /* must start with a alpha numeric ascii character */ - if (!isascii(name[0])) { - return 1; - } - /* set non_num as needed */ - if (isalpha((int)name[0])) { - non_num = true; - } else if ((int)isdigit((int)name[0])) { - non_num = false; - } else { - return 1; - } - - /* scan each char */ - level = 0; - for (p=name+1; *p; ++p) { - - /* name must contain ASCII chars */ - if (!isascii(*p)) { - return 1; - } - - /* alpha chars are ok */ - if (isalpha((int)*p)) { - non_num = true; - continue; - } - - /* numeric chars are ok */ - if (isdigit((int)*p)) { - continue; - } - - /* +, - and _ are ok */ - if (*p == '+' || *p == '-' || *p == '_') { - non_num = true; - continue; - } - - /* check for the '.' case */ - if (*p == '.') { - /* - * look for groups that are too deep, if requested by -g - */ - if (g_flag > 0 && ++level > g_flag) { - /* we are too deep */ - return 1; - } - - /* - * A '.' is ok as long as the next character is alphanumeric. - * This imples that '.' cannot before a previous '.' and - * that it cannot be at the end. - * - * If we are checking for all numeric compnents, then - * '.' is ok if we saw a non-numeric char before the - * last '.', or before the beginning if no previous '.' - * has been seen. - */ - if ((!num_chk || non_num) && isascii(*(p+1)) && isalnum((int)*(p+1))) { - ++p; /* '.' is ok, and so is the next char */ - if (isdigit((int)*p)) { /* reset non_num as needed */ - non_num = false; - } else { - non_num = true; - } - continue; - } - } - - /* this character must be invalid */ - return 1; - } - if (num_chk && !non_num) { - /* last component is all numeric */ - return 1; - } - - /* the name must be ok */ - return 0; -} - -/* - * get_ignore - get the ignore list from an ignore file - * - * given: - * filename name of the ignore file to read - * *len pointer to length of ignore return array - * - * returns: - * returns a malloced ignore pattern array, changes len - * - * An ignore file is of the form: - * - * # this is a comment which is ignored - * # comments begin at the first # character - * # comments may follow text on the same line - * - * # blank lines are ignored too - * - * # lines are [ic] pattern [ type] ... - * i foo.* # ignore foo.* groups, - * c foo.bar m # but check foo.bar if moderated - * c foo.keep.* # and check foo.keep.* - * i foo.keep.* j =alt.* # except when foo.keep.* is junked - * # or equivalenced to an alt.* group - * - * The 'i' value means ignore, 'c' value means 'compare'. The last pattern - * that matches a group determines the fate of the group. By default all - * groups are included. - * - * NOTE: Only one '=name' is allowed per line. - * "=" is considered to be equivalent to "=*". - */ -static struct pat * -get_ignore(filename, len) - char *filename; /* name of the ignore file to read */ - int *len; /* length of return array */ -{ - QIOSTATE *qp; /* QIO ignore file state */ - char *line; /* the line just read */ - struct pat *ret; /* array of ignore patterns to return */ - struct pat *cur; /* current pattern entry being formed */ - int max; /* max length (in elements) of ret */ - int linenum; /* current line number */ - char *p; - int i; - - /* firewall */ - if (filename == NULL) - die("internal error #3: filename is NULL"); - if (len == NULL) - die("internal error #4: len is NULL"); - if (D_BUG) - warn("STATUS: reading ignore file %s", filename); - - /* setup return array */ - ret = xmalloc(CHUNK * sizeof(struct grp)); - max = CHUNK; - - /* setup to read the ignore file data quickly */ - if ((qp = QIOopen(filename)) == NULL) - sysdie("cannot read ignore file %s", filename); - - /* scan server's output, displaying appropriate lines */ - *len = 0; - for (linenum = 1; (line = QIOread(qp)) != NULL; ++linenum) { - - /* expand return array if needed */ - if (*len >= max) { - max += CHUNK; - ret = xrealloc(ret, sizeof(struct pat) * max); - } - - /* remove any trailing comments */ - p = strchr(line, '#'); - if (p != NULL) { - *p = '\0'; - } - - /* remove any trailing spaces and tabs */ - for (p = &line[strlen(line)-1]; - p >= line && (*p == ' ' || *p == '\t'); - --p) { - *p = '\0'; - } - - /* ignore line if the remainder of the line is empty */ - if (line[0] == '\0') { - continue; - } - - /* ensure that the line starts with an i or c token */ - if ((line[0] != 'i' && line[0] != 'c') || - (line[1] != ' ' && line[1] != '\t')) - die("first token is not i or c in line %d of %s", linenum, - filename); - - /* ensure that the second newsgroup pattern token follows */ - p = strtok(line+2, " \t"); - if (p == NULL) - die("did not find 2nd field in line %d of %s", linenum, - filename); - - /* setup the next return element */ - cur = &ret[*len]; - cur->pat = NULL; - cur->type_match = 0; - cur->y_type = 0; - cur->m_type = 0; - cur->n_type = 0; - cur->j_type = 0; - cur->x_type = 0; - cur->eq_type = 0; - cur->epat = NULL; - cur->ignore = (line[0] == 'i'); - - /* obtain a copy of the newsgroup pattern token */ - cur->pat = xstrdup(p); - - /* process any other type tokens */ - for (p=strtok(NULL, " \t"), i=3; - p != NULL; - p=strtok(NULL, " \t"), ++i) { - - /* ensure that this next token is a valid type */ - switch (p[0]) { - case 'y': - case 'm': - case 'j': - case 'n': - case 'x': - if (p[1] != '\0') { - warn("field %d on line %d of %s not a valid type", - i, linenum, filename); - die("valid types are a char from [ymnjx=] or =name"); - } - break; - case '=': - break; - default: - warn("field %d on line %d of %s is not a valid type", - i, linenum, filename); - die("valid types are a char from [ymnjx=] or =name"); - } - - /* note that we have a type specific pattern */ - cur->type_match = 1; - - /* ensure that type is not a duplicate */ - if ((p[0] == 'y' && cur->y_type) || - (p[0] == 'm' && cur->m_type) || - (p[0] == 'n' && cur->n_type) || - (p[0] == 'j' && cur->j_type) || - (p[0] == 'x' && cur->x_type) || - (p[0] == '=' && cur->eq_type)) { - warn("only one %c type allowed per line", p[0]); - die("field %d on line %d of %s is a duplicate type", - i, linenum, filename); - } - - /* note what we have seen */ - switch (p[0]) { - case 'y': - cur->y_type = 1; - break; - case 'm': - cur->m_type = 1; - break; - case 'j': - cur->j_type = 1; - break; - case 'n': - cur->n_type = 1; - break; - case 'x': - cur->x_type = 1; - break; - case '=': - cur->eq_type = 1; - if (p[0] == '=' && p[1] != '\0') - cur->epat = xstrdup(p + 1); - break; - } - - /* object if too many fields */ - if (i-3 > TYPECNT) - die("too many fields on line %d of %s", linenum, filename); - } - - /* count another pat element */ - ++(*len); - } - - /* return the pattern array */ - return ret; -} - -/* - * ignore - ignore newsgroups given an ignore list - * - * given: - * grp array of groups - * grplen length of grp array in elements - * igcl array of ignore - * iglen length of igcl array in elements - */ -static void -ignore(grp, grplen, igcl, iglen) - struct grp *grp; /* array of groups */ - int grplen; /* length of grp array in elements */ - struct pat *igcl; /* array of ignore patterns */ - int iglen; /* length of igcl array in elements */ -{ - struct grp *gp; /* current group element being examined */ - struct pat *pp; /* current pattern element being examined */ - int g; /* current group index number */ - int p; /* current pattern index number */ - int ign; /* 1 => ignore this group, 0 => check it */ - int icnt; /* groups ignored */ - int ccnt; /* groups to be checked */ - - /* firewall */ - if (grp == NULL) - die("internal error #5: grp is NULL"); - if (igcl == NULL) - die("internal error $6: igcl is NULL"); - if (D_BUG) - warn("STATUS: determining which groups to ignore"); - - /* if nothing to do, return quickly */ - if (grplen <= 0 || iglen <= 0) { - return; - } - - /* examine each group */ - icnt = 0; - ccnt = 0; - for (g=0; g < grplen; ++g) { - - /* check the group to examine */ - gp = &grp[g]; - if (gp->ignore) { - /* already ignored no need to examine */ - continue; - } - - /* check group against all patterns */ - ign = 0; - for (p=0, pp=igcl; p < iglen; ++p, ++pp) { - - /* if pattern has a specific type, check it first */ - if (pp->type_match) { - - /* specific type required, check for match */ - switch (gp->type[0]) { - case 'y': - if (! pp->y_type) continue; /* pattern does not apply */ - break; - case 'm': - if (! pp->m_type) continue; /* pattern does not apply */ - break; - case 'n': - if (! pp->n_type) continue; /* pattern does not apply */ - break; - case 'j': - if (! pp->j_type) continue; /* pattern does not apply */ - break; - case 'x': - if (! pp->x_type) continue; /* pattern does not apply */ - break; - case '=': - if (! pp->eq_type) continue; /* pattern does not apply */ - if (pp->epat != NULL && !uwildmat(&gp->type[1], pp->epat)) { - /* equiv pattern doesn't match, patt does not apply */ - continue; - } - break; - } - } - - /* perform a match on group name */ - if (uwildmat(gp->name, pp->pat)) { - /* this pattern fully matches, use the ignore value */ - ign = pp->ignore; - } - } - - /* if this group is to be ignored, note it */ - if (ign) { - switch (gp->hostid) { - case HOSTID1: - if (ign_host1_flag) { - gp->ignore |= CHECK_IGNORE; - ++icnt; - } - break; - case HOSTID2: - if (ign_host2_flag) { - gp->ignore |= CHECK_IGNORE; - ++icnt; - } - break; - default: - die("newsgroup %s bad hostid: %d", gp->name, gp->hostid); - } - } else { - ++ccnt; - } - } - if (D_BUG) - warn("STATUS: examined %d groups: %d ignored, %d to be checked", - grplen, icnt, ccnt); -} - -/* - * merge_cmp - qsort compare function for later group merge - * - * given: - * a group a to compare - * b group b to compare - * - * returns: - * >0 a > b - * 0 a == b elements match (fatal error if a and b are different) - * <0 a < b - * - * To speed up group comparison, we compare by the following items listed - * in order of sorting: - * - * group name - * hostid (host1 ahead of host2) - * linenum (active file line number) - */ -static int -merge_cmp(arg_a, arg_b) - const void *arg_a; /* first qsort compare arg */ - const void *arg_b; /* first qsort compare arg */ -{ - const struct grp *a = arg_a; /* group a to compare */ - const struct grp *b = arg_b; /* group b to compare */ - int i; - - /* firewall */ - if (a == b) { - /* we guess this could happen */ - return(0); - } - - /* compare group names */ - i = strcmp(a->name, b->name); - if (i != 0) { - return i; - } - - /* compare hostid's */ - if (a->hostid != b->hostid) { - if (a->hostid > b->hostid) { - return 1; - } else { - return -1; - } - } - - /* compare active line numbers */ - if (a->linenum != b->linenum) { - if (a->linenum > b->linenum) { - return 1; - } else { - return -1; - } - } - - /* two different elements match, this should not happen! */ - die("two internal grp elements match!"); - /*NOTREACHED*/ -} - -/* - * merge_grps - compare groups from both hosts - * - * given: - * grp array of groups - * grplen length of grp array in elements - * host1 name of host with HOSTID1 - * host2 name of host with HOSTID2 - * - * This routine will select which groups to output form a merged active file. - */ -static void -merge_grps(grp, grplen, host1, host2) - struct grp *grp; /* array of groups */ - int grplen; /* length of grp array in elements */ - char *host1; /* name of host with HOSTID1 */ - char *host2; /* name of host with HOSTID2 */ -{ - int cur; /* current group index being examined */ - int nxt; /* next group index being examined */ - int outcnt; /* groups to output */ - int rmcnt; /* groups to remove */ - int h1_probs; /* =type problem groups from host1 */ - int h2_probs; /* =type problem groups from host2 */ - - /* firewall */ - if (grp == NULL) - die("internal error #7: grp is NULL"); - - /* sort groups for the merge */ - if (D_BUG) - warn("STATUS: sorting groups"); - qsort((char *)grp, grplen, sizeof(grp[0]), merge_cmp); - - /* mark =type problem groups from host2, if needed */ - h2_probs = mark_eq_probs(grp, grplen, l_host2_flag, host1, host2); - - /* - * We will walk thru the sorted group array, looking for pairs - * among the groups that we have not already ignored. - * - * If a host has duplicate groups, then the duplicates will - * be next to each other. - * - * If both hosts have the name group, they will be next to each other. - */ - if (D_BUG) - warn("STATUS: merging groups"); - outcnt = 0; - rmcnt = 0; - for (cur=0; cur < grplen; cur=nxt) { - - /* determine the next group index */ - nxt = cur+1; - - /* skip if this group is ignored */ - if (grp[cur].ignore) { - continue; - } - /* assert: cur is not ignored */ - - /* check for duplicate groups from the same host */ - while (nxt < grplen) { - - /* mark the later as a duplicate */ - if (grp[cur].hostid == grp[nxt].hostid && - strcmp(grp[cur].name, grp[nxt].name) == 0) { - grp[nxt].ignore |= ERROR_DUP; - if (!QUIET(grp[cur].hostid)) - warn("lines %d and %d from %s refer to the same group", - grp[cur].linenum, grp[nxt].linenum, - ((grp[cur].hostid == HOSTID1) ? host1 : host2)); - ++nxt; - } else { - break; - } - } - /* assert: cur is not ignored */ - /* assert: cur & nxt are not the same group from the same host */ - - /* if nxt is ignored, look for the next non-ignored group */ - while (nxt < grplen && grp[nxt].ignore) { - ++nxt; - } - /* assert: cur is not ignored */ - /* assert: nxt is not ignored or is beyond end */ - /* assert: cur & nxt are not the same group from the same host */ - - /* case: cur and nxt are the same group */ - if (nxt < grplen && strcmp(grp[cur].name, grp[nxt].name) == 0) { - - /* assert: cur is HOSTID1 */ - if (grp[cur].hostid != HOSTID1) - die("internal error #8: grp[%d].hostid: %d != %d", - cur, grp[cur].hostid, HOSTID1); - - /* - * Both hosts have the same group. Make host1 group type - * match host2. (it may already) - */ - grp[cur].output = 1; - grp[cur].outhi = (host2_hilow_all ? grp[nxt].hi : grp[cur].hi); - grp[cur].outlow = (host2_hilow_all ? grp[nxt].low : grp[cur].low); - grp[cur].outtype = grp[nxt].type; - ++outcnt; - - /* do not process nxt, skip to the one beyond */ - ++nxt; - - /* case: cur and nxt are different groups */ - } else { - - /* - * if cur is host2, then host1 doesn't have it, so output it - */ - if (grp[cur].hostid == HOSTID2) { - grp[cur].output = 1; - grp[cur].outhi = (host2_hilow_newgrp ? grp[cur].hi : DEF_HI); - grp[cur].outlow = (host2_hilow_newgrp ? grp[cur].low : DEF_LOW); - grp[cur].outtype = grp[cur].type; - ++outcnt; - - /* - * If cur is host1, then host2 doesn't have it. - * Mark for removal if -m was not given. - */ - } else { - grp[cur].output = 1; - grp[cur].outhi = grp[cur].hi; - grp[cur].outlow = grp[cur].low; - grp[cur].outtype = grp[cur].type; - if (! m_flag) { - grp[cur].remove = 1; - ++rmcnt; - } - } - - /* if no more groups to examine, we are done */ - if (nxt >= grplen) { - break; - } - } - } - - /* mark =type problem groups from host1, if needed */ - h1_probs = mark_eq_probs(grp, grplen, l_host1_flag, host1, host2); - - /* all done */ - if (D_BUG) { - warn("STATUS: sort-merge passed thru %d groups", outcnt); - warn("STATUS: sort-merge marked %d groups for removal", rmcnt); - warn("STATUS: marked %d =type error groups from host1", h1_probs); - warn("STATUS: marked %d =type error groups from host2", h2_probs); - } - return; -} - -/* - * active_cmp - qsort compare function for active file style output - * - * given: - * a group a to compare - * b group b to compare - * - * returns: - * >0 a > b - * 0 a == b elements match (fatal error if a and b are different) - * <0 a < b - * - * This sort will sort groups so that the lines that will we output - * host1 lines followed by host2 lines. Thus, we will sort by - * the following keys: - * - * hostid (host1 ahead of host2) - * linenum (active file line number) - */ -static int -active_cmp(arg_a, arg_b) - const void *arg_a; /* first qsort compare arg */ - const void *arg_b; /* first qsort compare arg */ -{ - const struct grp *a = arg_a; /* group a to compare */ - const struct grp *b = arg_b; /* group b to compare */ - - /* firewall */ - if (a == b) { - /* we guess this could happen */ - return(0); - } - - /* compare hostid's */ - if (a->hostid != b->hostid) { - if (a->hostid > b->hostid) { - return 1; - } else { - return -1; - } - } - - /* compare active line numbers */ - if (a->linenum != b->linenum) { - if (a->linenum > b->linenum) { - return 1; - } else { - return -1; - } - } - - /* two different elements match, this should not happen! */ - die("two internal grp elements match!"); - /*NOTREACHED*/ -} - -/* - * output_grps - output the result of the merge - * - * given: - * grp array of groups - * grplen length of grp array in elements - */ -static void -output_grps(grp, grplen) - struct grp *grp; /* array of groups */ - int grplen; /* length of grp array in elements */ -{ - int add; /* number of groups added */ - int change; /* number of groups changed */ - int remove; /* number of groups removed */ - int no_new_dir; /* number of new groups with missing/empty dirs */ - int new_dir; /* number of new groupsm, non-empty dir no water chg */ - int water_change; /* number of new groups where hi&low water changed */ - int work; /* adds + changes + removals */ - int same; /* the number of groups the same */ - int ignore; /* host1 newsgroups to ignore */ - int not_done; /* exec errors and execs not performed */ - int rm_cycle; /* 1 => removals only, 0 => adds & changes only */ - int sleep_msg; /* 1 => -o x sleep message was given */ - int top_ignore; /* number of groups ignored because of no top level */ - int restore; /* host1 groups restored due to -o a1 */ - double host1_same; /* % of host1 that is the same */ - int i; - - /* firewall */ - if (grp == NULL) - die("internal error #9: grp is NULL"); - - /* - * If -a1 was given, mark for output any host1 newsgroup that was - * simply ignored due to the -i ign_file. - */ - if (host1_ign_print) { - restore = 0; - for (i=0; i < grplen; ++i) { - if (grp[i].hostid == HOSTID1 && - (grp[i].ignore == CHECK_IGNORE || - grp[i].ignore == CHECK_TYPE || - grp[i].ignore == (CHECK_IGNORE|CHECK_TYPE))) { - /* force group to output and not be ignored */ - grp[i].ignore = 0; - grp[i].output = 1; - grp[i].remove = 0; - grp[i].outhi = grp[i].hi; - grp[i].outlow = grp[i].low; - grp[i].outtype = grp[i].type; - ++restore; - } - } - if (D_BUG) - warn("STATUS: restored %d host1 groups", restore); - } - - /* - * If -T, ignore new top level groups from host2 - */ - if (no_new_hier) { - top_ignore = 0; - for (i=0; i < grplen; ++i) { - /* look at new newsgroups */ - if (grp[i].hostid == HOSTID2 && - grp[i].output != 0 && - new_top_hier(grp[i].name)) { - /* no top level ignore this new group */ - grp[i].ignore |= CHECK_HIER; - grp[i].output = 0; - if (D_BUG) - warn("ignore new newsgroup: %s, new hierarchy", - grp[i].name); - ++top_ignore; - } - } - if (D_SUMMARY) - warn("STATUS: ignored %d new newsgroups due to new hierarchy", - top_ignore); - } - - /* sort by active file order if active style output (-a) */ - if (o_flag == OUTPUT_ACTIVE) { - if (D_BUG) - warn("STATUS: sorting groups in output order"); - qsort((char *)grp, grplen, sizeof(grp[0]), active_cmp); - } - - /* - * Determine the % of lines from host1 active file that remain unchanged - * ignoring any low/high water mark changes. - * - * Determine the number of old groups that will remain the same - * the number of new groups that will be added. - */ - add = 0; - change = 0; - remove = 0; - same = 0; - ignore = 0; - no_new_dir = 0; - new_dir = 0; - water_change = 0; - for (i=0; i < grplen; ++i) { - /* skip non-output ... */ - if (grp[i].output == 0) { - if (grp[i].hostid == HOSTID1) { - ++ignore; - } - continue; - - /* case: group needs removal */ - } else if (grp[i].remove) { - ++remove; - - /* case: group is from host2, so we need a newgroup */ - } else if (grp[i].hostid == HOSTID2) { - ++add; - - /* case: group is from host1, but the type changed */ - } else if (grp[i].type != grp[i].outtype && - strcmp(grp[i].type,grp[i].outtype) != 0) { - ++change; - - /* case: group did not change */ - } else { - ++same; - } - } - work = add+change+remove; - if (same+work+host1_errs <= 0) { - /* no lines, no work, no errors == nothing changed == 100% the same */ - host1_same = (double)100.0; - } else { - /* calculate % unchanged */ - host1_same = (double)100.0 * - ((double)same / (double)(same+work+host1_errs)); - } - if (D_BUG) { - warn("STATUS: same=%d add=%d, change=%d, remove=%d", - same, add, change, remove); - warn("STATUS: ignore=%d, work=%d, err=%d", - ignore, work, host1_errs); - warn("STATUS: same+work+err=%d, host1_same=%.2f%%", - same+work+host1_errs, host1_same); - } - - /* - * Bail out if we too few lines in host1 active file (ignoring - * low/high water mark changes) remaining unchanged. - * - * We define change as: - * - * line errors from host1 active file - * newsgroups to be added to host1 - * newsgroups to be removed from host1 - * newsgroups to be change in host1 - */ - if (host1_same < p_flag) { - warn("HALT: lines unchanged: %.2f%% < min change limit: %.2f%%", - host1_same, p_flag); - warn(" No output or commands executed. Determine if the degree"); - warn(" of changes is okay and re-execute with a lower -p value"); - die(" or with the problem fixed."); - } - - /* - * look at all groups - * - * If we are not producing active file output, we must do removals - * before we do any adds and changes. - * - * We recalculate the work stats in finer detail as well as noting how - * many actions were successful. - */ - add = 0; - change = 0; - remove = 0; - same = 0; - ignore = 0; - work = 0; - not_done = 0; - sleep_msg = 0; - rm_cycle = ((o_flag == OUTPUT_ACTIVE) ? 0 : 1); - do { - for (i=0; i < grplen; ++i) { - - /* if -o Ax, output ignored non-error groups too */ - - /* - * skip non-output ... - * - * but if '-a' and active output mode, then don't skip ignored, - * non-error, non-removed groups from host1 - */ - if (grp[i].output == 0) { - if (grp[i].hostid == HOSTID1) { - ++ignore; - } - continue; - } - - /* case: output active lines */ - if (o_flag == OUTPUT_ACTIVE) { - - /* case: group needs removal */ - if (grp[i].remove) { - ++remove; - ++work; - - /* case: group will be kept */ - } else { - - /* output in active file format */ - printf("%s %s %s %s\n", - grp[i].name, grp[i].outhi, grp[i].outlow, - grp[i].outtype); - - /* if -v level is high enough, do group accounting */ - if (D_IF_SUMM) { - - /* case: group is from host2, so we need a newgroup */ - if (grp[i].hostid == HOSTID2) { - ++add; - ++work; - - /* case: group is from host1, but the type changed */ - } else if (grp[i].type != grp[i].outtype && - strcmp(grp[i].type,grp[i].outtype) != 0) { - ++change; - ++work; - - /* case: group did not change */ - } else { - ++same; - } - } - } - - /* case: output ctlinnd commands */ - } else if (o_flag == OUTPUT_CTLINND) { - - /* case: group needs removal */ - if (grp[i].remove) { - - /* output rmgroup */ - if (rm_cycle) { - printf("ctlinnd rmgroup %s\n", grp[i].name); - ++remove; - ++work; - } - - /* case: group is from host2, so we need a newgroup */ - } else if (grp[i].hostid == HOSTID2) { - - /* output newgroup */ - if (! rm_cycle) { - printf("ctlinnd newgroup %s %s %s\n", - grp[i].name, grp[i].outtype, new_name); - ++add; - ++work; - } - - /* case: group is from host1, but the type changed */ - } else if (grp[i].type != grp[i].outtype && - strcmp(grp[i].type,grp[i].outtype) != 0) { - - /* output changegroup */ - if (! rm_cycle) { - printf("ctlinnd changegroup %s %s\n", - grp[i].name, grp[i].outtype); - ++change; - ++work; - } - - /* case: group did not change */ - } else { - if (! rm_cycle) { - ++same; - } - } - - /* case: exec ctlinnd commands */ - } else if (o_flag == OUTPUT_EXEC || o_flag == OUTPUT_IEXEC) { - - /* warn about sleeping if needed and first time */ - if (o_flag == OUTPUT_EXEC && z_flag > 0 && sleep_msg == 0) { - if (D_SUMMARY) - warn("will sleep %d seconds before each fork/exec", - z_flag); - sleep_msg = 1; - } - - /* case: group needs removal */ - if (grp[i].remove) { - - /* exec rmgroup */ - if (rm_cycle) { - if (D_REPORT && o_flag == OUTPUT_EXEC) - warn("rmgroup %s", grp[i].name); - if (! exec_cmd(o_flag, "rmgroup", - grp[i].name, NULL, NULL)) { - ++not_done; - } else { - ++remove; - ++work; - } - } - - /* case: group is from host2, so we need a newgroup */ - } else if (grp[i].hostid == HOSTID2) { - - /* exec newgroup */ - if (!rm_cycle) { - if (D_REPORT && o_flag == OUTPUT_EXEC) - warn("newgroup %s %s %s", - grp[i].name, grp[i].outtype, new_name); - if (! exec_cmd(o_flag, "newgroup", grp[i].name, - grp[i].outtype, new_name)) { - ++not_done; - } else { - ++add; - ++work; - } - } - - /* case: group is from host1, but the type changed */ - } else if (grp[i].type != grp[i].outtype && - strcmp(grp[i].type,grp[i].outtype) != 0) { - - /* exec changegroup */ - if (!rm_cycle) { - if (D_REPORT && o_flag == OUTPUT_EXEC) - warn("changegroup %s %s", - grp[i].name, grp[i].outtype); - if (! exec_cmd(o_flag, "changegroup", grp[i].name, - grp[i].outtype, NULL)) { - ++not_done; - } else { - ++change; - ++work; - } - } - - /* case: group did not change */ - } else { - if (! rm_cycle) { - ++same; - } - } - } - } - } while (--rm_cycle >= 0); - - /* final accounting, if -v */ - if (D_SUMMARY || (D_IF_SUMM && (work > 0 || not_done > 0))) { - warn("STATUS: %d group(s)", add+remove+change+same); - warn("STATUS: %d group(s)%s added", add, - ((o_flag == OUTPUT_EXEC || o_flag == OUTPUT_IEXEC) ? - "" : " to be")); - warn("STATUS: %d group(s)%s removed", remove, - ((o_flag == OUTPUT_EXEC || o_flag == OUTPUT_IEXEC) ? - "" : " to be")); - warn("STATUS: %d group(s)%s changed", change, - ((o_flag == OUTPUT_EXEC || o_flag == OUTPUT_IEXEC) ? - "" : " to be")); - warn("STATUS: %d group(s) %s the same", same, - ((o_flag == OUTPUT_EXEC || o_flag == OUTPUT_IEXEC) ? - "remain" : "are")); - warn("STATUS: %.2f%% of lines unchanged", host1_same); - warn("STATUS: %d group(s) ignored", ignore); - if (o_flag == OUTPUT_EXEC || o_flag == OUTPUT_IEXEC) - warn("STATUS: %d exec(s) not performed", not_done); - } -} - -/* - * error_mark - mark for removal, error groups from a given host - * - * given: - * grp array of groups - * grplen length of grp array in elements - * hostid host to mark error groups for removal - */ -static void -error_mark(grp, grplen, hostid) - struct grp *grp; /* array of groups */ - int grplen; /* length of grp array in elements */ - int hostid; /* host to mark error groups for removal */ -{ - int i; - int errcnt; - - /* firewall */ - if (grp == NULL) - die("internal error #11: grp is NULL"); - - /* loop thru groups, looking for error groups from a given host */ - errcnt = 0; - for (i=0; i < grplen; ++i) { - - /* skip if not from hostid */ - if (grp[i].hostid != hostid) { - continue; - } - - /* mark for removal if an error group not already removed */ - if (IS_ERROR(grp[i].ignore)) { - - /* mark for removal */ - if (grp[i].output != 1 || grp[i].remove != 1) { - grp[i].output = 1; - grp[i].remove = 1; - } - ++errcnt; - } - } - - /* all done */ - if (D_SUMMARY || (D_IF_SUMM && errcnt > 0)) - warn("STATUS: marked %d error groups for removal", errcnt); - return; -} - -/* - * eq_merge_cmp - qsort compare function for =type group processing - * - * given: - * a =group a to compare - * b =group b to compare - * - * returns: - * >0 a > b - * 0 a == b elements match (fatal error if a and b are different) - * <0 a < b - * - * To speed up group comparison, we compare by the following items listed - * in order of sorting: - * - * skip (non-skipped groups after skipped ones) - * group equiv name - * group name - * hostid (host1 ahead of host2) - * linenum (active file line number) - */ -static int -eq_merge_cmp(arg_a, arg_b) - const void *arg_a; /* first qsort compare arg */ - const void *arg_b; /* first qsort compare arg */ -{ - const struct eqgrp *a = arg_a; /* group a to compare */ - const struct eqgrp *b = arg_b; /* group b to compare */ - int i; - - /* firewall */ - if (a == b) { - /* we guess this could happen */ - return(0); - } - - /* compare skip values */ - if (a->skip != b->skip) { - if (a->skip > b->skip) { - /* a is skipped, b is not */ - return 1; - } else { - /* b is skipped, a is not */ - return -1; - } - } - - /* compare the names the groups are equivalenced to */ - i = strcmp(a->eq, b->eq); - if (i != 0) { - return i; - } - - /* compare the group names themselves */ - i = strcmp(a->g->name, b->g->name); - if (i != 0) { - return i; - } - - /* compare hostid's */ - if (a->g->hostid != b->g->hostid) { - if (a->g->hostid > b->g->hostid) { - return 1; - } else { - return -1; - } - } - - /* compare active line numbers */ - if (a->g->linenum != b->g->linenum) { - if (a->g->linenum > b->g->linenum) { - return 1; - } else { - return -1; - } - } - - /* two different elements match, this should not happen! */ - die("two internal eqgrp elements match!"); -} - -/* - * mark_eq_probs - mark =type groups from a given host that have problems - * - * given: - * grp sorted array of groups - * grplen length of grp array in elements - * hostid host to mark error groups for removal, or NOHOST - * host1 name of host with HOSTID1 - * host2 name of host with HOSTID2 - * - * This function assumes that the grp array has been sorted by name. - */ -static int -mark_eq_probs(grp, grplen, hostid, host1, host2) - struct grp *grp; /* array of groups */ - int grplen; /* length of grp array in elements */ - int hostid; /* host to mark error groups for removal */ - char *host1; /* name of host with HOSTID1 */ - char *host2; /* name of host with HOSTID2 */ -{ - struct eqgrp *eqgrp; /* =type pointer array */ - int eq_cnt; /* number of =type groups from host */ - int new_eq_cnt; /* number of =type groups remaining */ - int missing; /* =type groups equiv to missing groups */ - int cycled; /* =type groups equiv to themselves */ - int chained; /* =type groups in long chain or loop */ - int cmp; /* strcmp of two names */ - int step; /* equiv loop step */ - int i; - int j; - - /* firewall */ - if (grp == NULL) - die("internal error #12: grp is NULL"); - if (hostid == NOHOST) { - /* nothing to detect, nothing else to do */ - return 0; - } - - /* count the =type groups from hostid that are not in error */ - eq_cnt = 0; - for (i=0; i < grplen; ++i) { - if (grp[i].hostid == hostid && - ! IS_ERROR(grp[i].ignore) && - grp[i].type != NULL && - grp[i].type[0] == '=') { - ++eq_cnt; - } - } - if (D_BUG && hostid != NOHOST) - warn("STATUS: host%d has %d =type groups", hostid, eq_cnt); - - /* if no groups, then there is nothing to do */ - if (eq_cnt == 0) { - return 0; - } - - /* setup the =group record array */ - eqgrp = xmalloc(eq_cnt * sizeof(eqgrp[0])); - for (i=0, j=0; i < grplen && j < eq_cnt; ++i) { - if (grp[i].hostid == hostid && - ! IS_ERROR(grp[i].ignore) && - grp[i].type != NULL && - grp[i].type[0] == '=') { - - /* initialize record */ - eqgrp[j].skip = 0; - eqgrp[j].g = &grp[i]; - eqgrp[j].eq = &(grp[i].type[1]); - ++j; - } - } - - /* - * try to resolve =type groups in at least EQ_LOOP equiv links - */ - new_eq_cnt = eq_cnt; - missing = 0; - cycled = 0; - for (step=0; step < EQ_LOOP && new_eq_cnt >= 0; ++step) { - - /* sort the =group record array */ - qsort((char *)eqgrp, eq_cnt, sizeof(eqgrp[0]), eq_merge_cmp); - - /* look for the groups to which =type group point at */ - eq_cnt = new_eq_cnt; - for (i=0, j=0; i < grplen && j < eq_cnt; ++i) { - - /* we will skip any group in error or from the wrong host */ - if (grp[i].hostid != hostid || IS_ERROR(grp[i].ignore)) { - continue; - } - - /* we will skip any skipped eqgrp's */ - if (eqgrp[j].skip) { - /* try the same group against the next eqgrp */ - --i; - ++j; - continue; - } - - /* compare the =name of the eqgrp with the name of the grp */ - cmp = strcmp(grp[i].name, eqgrp[j].eq); - - /* case: this group is pointed at by an eqgrp */ - if (cmp == 0) { - - /* see if we have looped around to the original group name */ - if (strcmp(grp[i].name, eqgrp[j].g->name) == 0) { - - /* note the detected loop */ - if (! QUIET(hostid)) - warn("%s from %s line %d =loops around to itself", - eqgrp[j].g->name, - ((eqgrp[j].g->hostid == HOSTID1) ? host1 : host2), - eqgrp[j].g->linenum); - eqgrp[j].g->ignore |= ERROR_EQLOOP; - - /* the =group is bad, so we don't need to bother with it */ - eqgrp[j].skip = 1; - --new_eq_cnt; - ++cycled; - --i; - ++j; - continue; - } - - /* if =group refers to a valid group, we are done with it */ - if (grp[i].type != NULL && grp[i].type[0] != '=') { - eqgrp[j].skip = 1; - --new_eq_cnt; - /* otherwise note the equiv name */ - } else { - eqgrp[j].eq = &(grp[i].type[1]); - } - --i; - ++j; - - /* case: we missed the =name */ - } else if (cmp > 0) { - - /* mark the eqgrp in error */ - eqgrp[j].g->ignore |= ERROR_NONEQ; - if (! QUIET(hostid)) - warn("%s from %s line %d not equiv to a valid group", - eqgrp[j].g->name, - ((eqgrp[j].g->hostid == HOSTID1) ? host1 : host2), - eqgrp[j].g->linenum); - - /* =group is bad, so we don't need to bother with it anymore */ - eqgrp[j].skip = 1; - --new_eq_cnt; - ++missing; - ++j; - } - } - - /* any remaining non-skipped eqgrps are bad */ - while (j < eq_cnt) { - - /* mark the eqgrp in error */ - eqgrp[j].g->ignore |= ERROR_NONEQ; - if (! QUIET(hostid)) - warn("%s from %s line %d isn't equiv to a valid group", - eqgrp[j].g->name, - ((hostid == HOSTID1) ? host1 : host2), - eqgrp[j].g->linenum); - - /* the =group is bad, so we don't need to bother with it anymore */ - eqgrp[j].skip = 1; - --new_eq_cnt; - ++missing; - ++j; - } - } - - /* note groups that are in a long chain or loop */ - chained = new_eq_cnt; - qsort((char *)eqgrp, eq_cnt, sizeof(eqgrp[0]), eq_merge_cmp); - for (j=0; j < new_eq_cnt; ++j) { - - /* skip if already skipped */ - if (eqgrp[j].skip == 1) { - continue; - } - - /* mark as a long loop group */ - eqgrp[j].g->ignore |= ERROR_LONGLOOP; - if (! QUIET(hostid)) - warn("%s from %s line %d in a long equiv chain or loop > %d", - eqgrp[j].g->name, - ((hostid == HOSTID1) ? host1 : host2), - eqgrp[j].g->linenum, EQ_LOOP); - } - - /* all done */ - if (D_BUG) { - warn("%d =type groups from %s are not equiv to a valid group", - missing, ((hostid == HOSTID1) ? host1 : host2)); - warn("%d =type groups from %s are equiv to themselves", - cycled, ((hostid == HOSTID1) ? host1 : host2)); - warn("%d =type groups from %s are in a long chain or loop > %d", - chained, ((hostid == HOSTID1) ? host1 : host2), EQ_LOOP); - } - free(eqgrp); - return missing+cycled+chained; -} - -/* - * exec_cmd - exec a ctlinnd command in forked process - * - * given: - * mode OUTPUT_EXEC or OUTPUT_IEXEC (interactive mode) - * cmd "changegroup", "newgroup", "rmgroup" - * grp name of group - * type type of group or NULL - * who newgroup creator or NULL - * - * returns: - * 1 exec was performed - * 0 exec was not performed - */ -static int -exec_cmd(mode, cmd, grp, type, who) - int mode; /* OUTPUT_EXEC or OUTPUT_IEXEC (interactive mode) */ - char *cmd; /* changegroup, newgroup or rmgroup */ - char *grp; /* name of group to change, add, remove */ - char *type; /* type of group or NULL */ - char *who; /* newgroup creator or NULL */ -{ - FILE *ch_stream = NULL; /* stream from a child process */ - char buf[BUFSIZ+1]; /* interactive buffer */ - int pid; /* pid of child process */ - int io[2]; /* pair of pipe descriptors */ - int status; /* wait status */ - int exitval; /* exit status of the child */ - char *p; - - /* firewall */ - if (cmd == NULL || grp == NULL) - die("internal error #13, cmd or grp is NULL"); - - /* if interactive, ask the question */ - if (mode == OUTPUT_IEXEC) { - - /* ask the question */ - fflush(stdin); - fflush(stdout); - fflush(stderr); - if (type == NULL) { - printf("%s %s [yn]? ", cmd, grp); - } else if (who == NULL) { - printf("%s %s %s [yn]? ", cmd, grp, type); - } else { - printf("%s %s %s %s [yn]? ", cmd, grp, type, who); - } - fflush(stdout); - buf[0] = '\0'; - buf[BUFSIZ] = '\0'; - p = fgets(buf, BUFSIZ, stdin); - if (p == NULL) { - /* EOF/ERROR on interactive input, silently stop processing */ - exit(43); - } - - /* if non-empty line doesn't start with 'y' or 'Y', skip command */ - if (buf[0] != 'y' && buf[0] != 'Y' && buf[0] != '\n') { - /* indicate nothing was done */ - return 0; - } - } - - /* build a pipe for output from child interactive mode */ - if (mode == OUTPUT_IEXEC) { - if (pipe(io) < 0) - sysdie("pipe create failed"); - - /* setup a fake pipe to /dev/null for non-interactive mode */ - } else { - io[READ_SIDE] = open(DEV_NULL, 0); - if (io[READ_SIDE] < 0) - sysdie("unable to open %s for reading", DEV_NULL); - io[WRITE_SIDE] = open(DEV_NULL, 1); - if (io[WRITE_SIDE] < 0) - sysdie("unable to open %s for writing", DEV_NULL); - } - - /* pause if in non-interactive mode so as to not busy-out the server */ - if (mode == OUTPUT_EXEC && z_flag > 0) { - if (D_BUG) - warn("sleeping %d seconds before fork/exec", z_flag); - /* be sure they know what we are stalling */ - fflush(stderr); - sleep(z_flag); - } - - /* fork the child process */ - fflush(stdout); - fflush(stderr); - pid = fork(); - if (pid == -1) - sysdie("fork failed"); - - /* case: child process */ - if (pid == 0) { - - /* - * prep file descriptors - */ - fclose(stdin); - close(io[READ_SIDE]); - if (dup2(io[WRITE_SIDE], 1) < 0) - sysdie("child: dup of write I/O pipe to stdout failed"); - if (dup2(io[WRITE_SIDE], 2) < 0) - sysdie("child: dup of write I/O pipe to stderr failed"); - - /* exec the ctlinnd command */ - p = concatpath(innconf->pathbin, _PATH_CTLINND); - if (type == NULL) { - execl(p, - CTLINND_NAME, CTLINND_TIME_OUT, cmd, grp, (char *) 0); - } else if (who == NULL) { - execl(p, - CTLINND_NAME, CTLINND_TIME_OUT, cmd, grp, type, (char *) 0); - } else { - execl(p, - CTLINND_NAME, CTLINND_TIME_OUT, cmd, grp, type, who, (char *) 0); - } - - /* child exec failed */ - sysdie("child process exec failed"); - - /* case: parent process */ - } else { - - /* prep file descriptors */ - if (mode != OUTPUT_IEXEC) { - close(io[READ_SIDE]); - } - close(io[WRITE_SIDE]); - - /* print a line from the child, if interactive */ - if (mode == OUTPUT_IEXEC) { - - /* read what the child says */ - buf[0] = '\0'; - buf[BUFSIZ] = '\0'; - ch_stream = fdopen(io[READ_SIDE], "r"); - if (ch_stream == NULL) - sysdie("fdopen of pipe failed"); - p = fgets(buf, BUFSIZ, ch_stream); - - /* print what the child said, if anything */ - if (p != NULL) { - if (buf[strlen(buf)-1] == '\n') - buf[strlen(buf)-1] = '\0'; - warn(" %s", buf); - } - } - - /* look for abnormal child termination/status */ - errno = 0; - while (wait(&status) < 0) { - if (errno == EINTR) { - /* just an interrupt, try to wait again */ - errno = 0; - } else { - sysdie("wait returned -1"); - } - } - if (mode == OUTPUT_IEXEC) { - /* close the pipe now that we are done with reading it */ - fclose(ch_stream); - } - if (WIFSTOPPED(status)) { - warn(" %s %s %s%s%s%s%s stopped", - CTLINND_NAME, cmd, grp, - (type ? "" : " "), (type ? type : ""), - (who ? "" : " "), (who ? who : "")); - /* assume no work was done */ - return 0; - } - if (WIFSIGNALED(status)) { - warn(" %s %s %s%s%s%s%s killed by signal %d", - CTLINND_NAME, cmd, grp, - (type ? "" : " "), (type ? type : ""), - (who ? "" : " "), (who ? who : ""), WTERMSIG(status)); - /* assume no work was done */ - return 0; - } - if (!WIFEXITED(status)) { - warn(" %s %s %s%s%s%s%s returned unknown wait status: 0x%x", - CTLINND_NAME, cmd, grp, - (type ? "" : " "), (type ? type : ""), - (who ? "" : " "), (who ? who : ""), status); - /* assume no work was done */ - return 0; - } - exitval = WEXITSTATUS(status); - if (exitval != 0) { - warn(" %s %s %s%s%s%s%s exited with status: %d", - CTLINND_NAME, cmd, grp, - (type ? "" : " "), (type ? type : ""), - (who ? "" : " "), (who ? who : ""), exitval); - /* assume no work was done */ - return 0; - } - } - - /* all done */ - return 1; -} - -/* - * new_top_hier - determine if the newsgroup represents a new hierarchy - * - * Determine of the newsgroup name is a new hierarchy. - * - * given: - * name name of newsgroup to check - * - * returns: - * false hierarchy already exists - * true hierarchy does not exist, name represents a new hierarchy - * - * NOTE: This function assumes that we are at the top of the news spool. - */ -static int -new_top_hier(name) - char *name; -{ - struct stat statbuf; /* stat of the hierarchy */ - int result; /* return result */ - char *dot; - - /* - * temp change name to just the top level - */ - dot = strchr(name, '.'); - if (dot != NULL) { - *dot = '\0'; - } - - /* - * determine if we can find this top level hierarchy directory - */ - result = !(stat(name, &statbuf) >= 0 && S_ISDIR(statbuf.st_mode)); - /* restore name */ - if (dot != NULL) { - *dot = '.'; - } - - /* - * return the result - */ - return result; -} diff --git a/backends/actsyncd.in b/backends/actsyncd.in deleted file mode 100644 index a88f25d..0000000 --- a/backends/actsyncd.in +++ /dev/null @@ -1,256 +0,0 @@ -#! /bin/sh -# fixscript will replace this line with code to load innshellvars - -# @(#) $Id: actsyncd.in 6490 2003-10-18 05:49:04Z rra $ -# @(#) Under RCS control in /usr/local/news/src/inn/local/RCS/actsyncd.sh,v -# -# actsyncd - actsync daemon -# -# usage: -# actsyncd [-x] config_file [debug_level [debug_outfmt]] -# -# -x xexec instead of reload -# config_file name of file used to determine how to run actsync -# debug_level force no action and use -v debug_level -# debug_outfmt change -o a1 output to -o debug_outfmt for debug - -# By: Landon Curt Noll chongo@toad.com (chongo was here /\../\) -# -# Copyright (c) Landon Curt Noll, 1993. -# All rights reserved. -# -# Permission to use and modify is hereby granted so long as this -# notice remains. Use at your own risk. No warranty is implied. - -# preset vars -# - -# Our lock file -LOCK="${LOCKS}/LOCK.actsyncd" -# where actsync is located -ACTSYNC="${PATHBIN}/actsync" -# exit value of actsync if unable to get an active file -NOSYNC=127 - -# parse args -# -if [ $# -gt 1 ]; then - case $1 in - -x|-r) shift ;; # no longer relevant - esac -fi -case $# in - 1) cfg="$1"; DEBUG=; DEBUG_FMT=; ;; - 2) cfg="$1"; DEBUG="$2"; DEBUG_FMT=; ;; - 3) cfg="$1"; DEBUG="$2"; DEBUG_FMT="$3"; ;; - *) echo "usage: $0 [-x] config_file [debug_level [debug_outfmt]]" 1>&2; - exit 1 ;; -esac -if [ ! -s "$cfg" ]; then - echo "$0: config_file not found or empty: $ign" 1>&2 - exit 2 -fi - -# parse config_file -# -host="`sed -n -e 's/^host=[ ]*//p' $cfg | tail -1`" -if [ -z "$host" ]; then - echo "$0: no host specified in $cfg" 1>&2 - exit 3 -fi -flags="`sed -n -e 's/^flags=[ ]*//p' $cfg | tail -1`" -if [ -z "$flags" ]; then - echo "$0: no flags specified in $cfg" 1>&2 - exit 4 -fi -ign="`sed -n -e 's/^ignore_file=[ ]*//p' $cfg | tail -1`" -if [ -z "$ign" ]; then - echo "$0: no ignore file specified in $cfg" 1>&2 - exit 5 -fi -ftp="`sed -n -e 's/^ftppath=[ ]*//p' $cfg | tail -1`" -spool="`sed -n -e 's/^spool=[ ]*//p' $cfg | tail -1`" -if [ -z "$spool" ]; then - spool=$SPOOL - #echo "$0: no spool directory specified in $cfg" 1>&2 - #exit 6 -fi -if [ ! -f "$ign" ]; then - ign="${PATHETC}/$ign" -fi -if [ ! -s "$ign" ]; then - echo "$0: ignore_file not found or empty: $ign" 1>&2 - exit 7 -fi - -# force -o c mode (overrides any -o argument in the command line) -# -if [ -z "$DEBUG" ]; then - - # standard actsyncd output mode - flags="$flags -o c" - -# DEBUG processing, if debug_level was given -# -else - - if [ ! -z "$ftp" ]; then - echo "$0: cannot use DEBUG mode with ftp (yet)" >&2 - exit 88; - fi - - # force -v level as needed - flags="$flags -v $DEBUG" - - # force -o level but reject -o x modes - if [ ! -z "$DEBUG_FMT" ]; then - case "$DEBUG_FMT" in - x*) echo "$0: do not use any of the -o x debug_outfmt modes!" 1>&2; - exit 8 ;; - *) flags="$flags -o $DEBUG_FMT" ;; - esac - fi - - # execute actsync directly - echo "DEBUG: will execute $ACTSYNC -i $ign $flags $host" 1>&2 - eval "$ACTSYNC -i $ign $flags $host" - status="$?" - echo "DEBUG: exit status $status" 1>&2 - exit "$status" -fi - -# Lock out others -# -shlock -p $$ -f "${LOCK}" || { - echo "$0: Locked by `cat '${LOCK}'`" 1>&2 - exit 9 -} - -# setup -# -origdir=`pwd` -workdir="${TMPDIR}/actsyncd" -ctlinndcmds="cc_commands" -out="sync.msg" -cleanup="$SED -e 's/^/ /' < $out; cd ${origdir}; rm -rf '$workdir' '$LOCK'" -trap "eval $cleanup; exit 123" 1 2 3 15 - -set -e -rm -rf "$workdir" -mkdir "$workdir" -cd "$workdir" -set +e - -rm -f "$out" -touch "$out" -chmod 0644 "$out" - -# try to sync -# -# Try to sync off of the host. If unable to connect/sync then retry -# up to 9 more times waiting 6 minutes between each try. -# -echo "=-= `date` for $host" >>$out 2>&1 -for loop in 1 2 3 4 5 6 7 8 9 10; do - - # get the active file to compare against - status=0 - case $host in - /*) cp $host active; status=$? ;; - .*) cp $origdir/$host active; status=$? ;; - *) - if [ -z "$ftp" ]; then - port=`expr "$host" : '.*:\(.*\)'` - if [ -n "$port" ]; then - port="-p $port" - host=`expr "$host" : '\(.*\):.*'` - fi - echo "getlist -h $host $port" >>$out - if getlist -h $host $port > active 2>>$out; then - : - else - status=$NOSYNC - fi - else - echo "$GETFTP ftp://$host/$ftp" >>$out - $GETFTP ftp://$host/$ftp >>$out 2>&1 - status=$? - if [ "$status" -ne 0 ]; then - status=$NOSYNC - else - case "$ftp" in - *.gz) - echo "$GZIP -d active" >>$out - if $GZIP -d active >>$out 2>&1; then - : - else - status=1 - fi - ;; - *.Z) - echo "$UNCOMPRESS active" >>$out - if $UNCOMPRESS active >>$out 2>&1; then - : - else - status=1 - fi - ;; - esac - fi - fi - ;; - esac - - if [ "$status" -ne "$NOSYNC" ]; then - - # detect bad status - # - if [ "$status" -ne 0 ]; then - echo "FATAL: `date` for $host exit $status" >>$out - eval $cleanup - exit "$status" - fi - - echo "$ACTSYNC -i $ign $flags ./active" >>$out - eval "$ACTSYNC -i $ign $flags ./active >$ctlinndcmds 2>>$out" - - if [ $? -ne 0 ]; then - echo "FATAL: `date` for $host actsync balked" >>$out - eval $cleanup - exit $? - fi - - if [ ! -s $ctlinndcmds ]; then - echo "No changes need to be made" >>$out - else - echo "=-= `date` for $host, updating active" >>$out - echo "mod-active $ctlinndcmds" >>$out - mod-active $ctlinndcmds >>$out 2>&1 - - if [ $? -ne 0 ]; then - echo "FATAL: `date` for $host mod-active FAILED" >>$out - eval $cleanup - exit 1 - fi - fi - - # normal exit - all done - # - echo "=-= `date` for $host, end" >>$out - eval $cleanup - exit 0 - fi - - # failed to get the remote active file - echo "=-= `date` for $host failed to connect/sync, retrying" >>$out - - # wait 6 minutes - # - sleep 360 -done - -# give up -# -echo "FATAL: `date` for $host failed to connect/sync 10 times" >>$out 2>&1 -eval $cleanup -exit 1 diff --git a/backends/archive.c b/backends/archive.c deleted file mode 100644 index 73a7970..0000000 --- a/backends/archive.c +++ /dev/null @@ -1,653 +0,0 @@ -/* $Id: archive.c 6138 2003-01-19 04:13:51Z rra $ -** -** Read batchfiles on standard input and archive them. -*/ - -#include "config.h" -#include "clibrary.h" -#include -#include -#include -#include - -#ifdef TM_IN_SYS_TIME -# include -#endif - -#include "inn/innconf.h" -#include "inn/messages.h" -#include "inn/wire.h" -#include "libinn.h" -#include "paths.h" -#include "storage.h" - - -static char *Archive = NULL; -static char *ERRLOG = NULL; - -/* -** Return a YYYYMM string that represents the current year/month -*/ -static char * -DateString(void) -{ - static char ds[10]; - time_t now; - struct tm *x; - - time(&now); - x = localtime(&now); - snprintf(ds, sizeof(ds), "%d%d", x->tm_year + 1900, x->tm_mon + 1); - - return ds; -} - - -/* -** Try to make one directory. Return false on error. -*/ -static bool -MakeDir(char *Name) -{ - struct stat Sb; - - if (mkdir(Name, GROUPDIR_MODE) >= 0) - return true; - - /* See if it failed because it already exists. */ - return stat(Name, &Sb) >= 0 && S_ISDIR(Sb.st_mode); -} - - -/* -** Given an entry, comp/foo/bar/1123, create the directory and all -** parent directories needed. Return false on error. -*/ -static bool -MakeArchiveDirectory(char *Name) -{ - char *p; - char *save; - bool made; - - if ((save = strrchr(Name, '/')) != NULL) - *save = '\0'; - - /* Optimize common case -- parent almost always exists. */ - if (MakeDir(Name)) { - if (save) - *save = '/'; - return true; - } - - /* Try to make each of comp and comp/foo in turn. */ - for (p = Name; *p; p++) - if (*p == '/' && p != Name) { - *p = '\0'; - made = MakeDir(Name); - *p = '/'; - if (!made) { - if (save) - *save = '/'; - return false; - } - } - - made = MakeDir(Name); - if (save) - *save = '/'; - return made; -} - - -/* -** Copy a file. Return false if error. -*/ -static bool -Copy(char *src, char *dest) -{ - FILE *in; - FILE *out; - size_t i; - char *p; - char buff[BUFSIZ]; - - /* Open the output file. */ - if ((out = fopen(dest, "w")) == NULL) { - /* Failed; make any missing directories and try again. */ - if ((p = strrchr(dest, '/')) != NULL) { - if (!MakeArchiveDirectory(dest)) { - syswarn("cannot mkdir for %s", dest); - return false; - } - out = fopen(dest, "w"); - } - if (p == NULL || out == NULL) { - syswarn("cannot open %s for writing", dest); - return false; - } - } - - /* Opening the input file is easier. */ - if ((in = fopen(src, "r")) == NULL) { - syswarn("cannot open %s for reading", src); - fclose(out); - unlink(dest); - return false; - } - - /* Write the data. */ - while ((i = fread(buff, 1, sizeof buff, in)) != 0) - if (fwrite(buff, 1, i, out) != i) { - syswarn("cannot write to %s", dest); - fclose(in); - fclose(out); - unlink(dest); - return false; - } - fclose(in); - - /* Flush and close the output. */ - if (ferror(out) || fflush(out) == EOF) { - syswarn("cannot flush %s", dest); - unlink(dest); - fclose(out); - return false; - } - if (fclose(out) == EOF) { - syswarn("cannot close %s", dest); - unlink(dest); - return false; - } - - return true; -} - - -/* -** Copy an article from memory into a file. -*/ -static bool -CopyArt(ARTHANDLE *art, char *dest, bool Concat) -{ - FILE *out; - const char *p; - char *q, *article; - size_t i; - const char *mode = "w"; - - if (Concat) mode = "a"; - - /* Open the output file. */ - if ((out = fopen(dest, mode)) == NULL) { - /* Failed; make any missing directories and try again. */ - if ((p = strrchr(dest, '/')) != NULL) { - if (!MakeArchiveDirectory(dest)) { - syswarn("cannot mkdir for %s", dest); - return false; - } - out = fopen(dest, mode); - } - if (p == NULL || out == NULL) { - syswarn("cannot open %s for writing", dest); - return false; - } - } - - /* Copy the data. */ - article = xmalloc(art->len); - for (i=0, q=article, p=art->data; pdata+art->len;) { - if (&p[1] < art->data + art->len && p[0] == '\r' && p[1] == '\n') { - p += 2; - *q++ = '\n'; - i++; - if (&p[1] < art->data + art->len && p[0] == '.' && p[1] == '.') { - p += 2; - *q++ = '.'; - i++; - } - if (&p[2] < art->data + art->len && p[0] == '.' && p[1] == '\r' && p[2] == '\n') { - break; - } - } else { - *q++ = *p++; - i++; - } - } - *q++ = '\0'; - - /* Write the data. */ - if (Concat) { - /* Write a separator... */ - fprintf(out, "-----------\n"); - } - if (fwrite(article, i, 1, out) != 1) { - syswarn("cannot write to %s", dest); - fclose(out); - if (!Concat) unlink(dest); - free(article); - return false; - } - free(article); - - /* Flush and close the output. */ - if (ferror(out) || fflush(out) == EOF) { - syswarn("cannot flush %s", dest); - if (!Concat) unlink(dest); - fclose(out); - return false; - } - if (fclose(out) == EOF) { - syswarn("cannot close %s", dest); - if (!Concat) unlink(dest); - return false; - } - - return true; -} - - -/* -** Write an index entry. Ignore I/O errors; our caller checks for them. -*/ -static void -WriteArtIndex(ARTHANDLE *art, char *ShortName) -{ - const char *p; - int i; - char Subject[BUFSIZ]; - char MessageID[BUFSIZ]; - - Subject[0] = '\0'; /* default to null string */ - p = wire_findheader(art->data, art->len, "Subject"); - if (p != NULL) { - for (i=0; *p != '\r' && *p != '\n' && *p != '\0'; i++) { - Subject[i] = *p++; - } - Subject[i] = '\0'; - } - - MessageID[0] = '\0'; /* default to null string */ - p = wire_findheader(art->data, art->len, "Message-ID"); - if (p != NULL) { - for (i=0; *p != '\r' && *p != '\n' && *p != '\0'; i++) { - MessageID[i] = *p++; - } - MessageID[i] = '\0'; - } - - printf("%s %s %s\n", - ShortName, - MessageID[0] ? MessageID : "", - Subject[0] ? Subject : ""); -} - - -/* -** Crack an Xref line apart into separate strings, each of the form "ng:artnum". -** Return in "lenp" the number of newsgroups found. -** -** This routine blatantly stolen from tradspool.c -*/ -static char ** -CrackXref(const char *xref, unsigned int *lenp) { - char *p; - char **xrefs; - char *q; - unsigned int len, xrefsize; - - len = 0; - xrefsize = 5; - xrefs = xmalloc(xrefsize * sizeof(char *)); - - /* skip pathhost */ - if ((p = strchr(xref, ' ')) == NULL) { - warn("cannot find pathhost in Xref header"); - return NULL; - } - /* skip next spaces */ - for (p++; *p == ' ' ; p++) ; - while (true) { - /* check for EOL */ - /* shouldn't ever hit null w/o hitting a \r\n first, but best to be paranoid */ - if (*p == '\n' || *p == '\r' || *p == 0) { - /* hit EOL, return. */ - *lenp = len; - return xrefs; - } - /* skip to next space or EOL */ - for (q=p; *q && *q != ' ' && *q != '\n' && *q != '\r' ; ++q) ; - - xrefs[len] = xstrndup(p, q - p); - - if (++len == xrefsize) { - /* grow xrefs if needed. */ - xrefsize *= 2; - xrefs = xrealloc(xrefs, xrefsize * sizeof(char *)); - } - - p = q; - /* skip spaces */ - for ( ; *p == ' ' ; p++) ; - } -} - - -/* -** Crack an groups pattern parameter apart into separate strings -** Return in "lenp" the number of patterns found. -*/ -static char ** -CrackGroups(char *group, unsigned int *lenp) { - char *p; - char **groups; - char *q; - unsigned int len, grpsize; - - len = 0; - grpsize = 5; - groups = xmalloc(grpsize * sizeof(char *)); - - /* skip leading spaces */ - for (p=group; *p == ' ' ; p++) ; - while (true) { - /* check for EOL */ - /* shouldn't ever hit null w/o hitting a \r\n first, but best to be paranoid */ - if (*p == '\n' || *p == '\r' || *p == 0) { - /* hit EOL, return. */ - *lenp = len; - return groups; - } - /* skip to next comma, space, or EOL */ - for (q=p; *q && *q != ',' && *q != ' ' && *q != '\n' && *q != '\r' ; ++q) ; - - groups[len] = xstrndup(p, q - p); - - if (++len == grpsize) { - /* grow groups if needed. */ - grpsize *= 2; - groups = xrealloc(groups, grpsize * sizeof(char *)); - } - - p = q; - /* skip commas and spaces */ - for ( ; *p == ' ' || *p == ',' ; p++) ; - } -} - - -int -main(int ac, char *av[]) -{ - char *Name; - char *p; - FILE *F; - int i; - bool Flat; - bool Redirect; - bool Concat; - char *Index; - char buff[BUFSIZ]; - char *spool; - char dest[BUFSIZ]; - char **groups, *q, *ng; - char **xrefs; - const char *xrefhdr; - ARTHANDLE *art; - TOKEN token; - unsigned int numgroups, numxrefs; - int j; - char *base = NULL; - bool doit; - - /* First thing, set up our identity. */ - message_program_name = "archive"; - - /* Set defaults. */ - if (!innconf_read(NULL)) - exit(1); - Concat = false; - Flat = false; - Index = NULL; - Redirect = true; - umask(NEWSUMASK); - ERRLOG = concatpath(innconf->pathlog, _PATH_ERRLOG); - Archive = innconf->patharchive; - groups = NULL; - numgroups = 0; - - /* Parse JCL. */ - while ((i = getopt(ac, av, "a:cfi:p:r")) != EOF) - switch (i) { - default: - die("usage error"); - break; - case 'a': - Archive = optarg; - break; - case 'c': - Flat = true; - Concat = true; - break; - case 'f': - Flat = true; - break; - case 'i': - Index = optarg; - break; - case 'p': - groups = CrackGroups(optarg, &numgroups); - break; - case 'r': - Redirect = false; - break; - } - - /* Parse arguments -- at most one, the batchfile. */ - ac -= optind; - av += optind; - if (ac > 2) - die("usage error"); - - /* Do file redirections. */ - if (Redirect) - freopen(ERRLOG, "a", stderr); - if (ac == 1 && freopen(av[0], "r", stdin) == NULL) - sysdie("cannot open %s for input", av[0]); - if (Index && freopen(Index, "a", stdout) == NULL) - sysdie("cannot open %s for output", Index); - - /* Go to where the action is. */ - if (chdir(innconf->patharticles) < 0) - sysdie("cannot chdir to %s", innconf->patharticles); - - /* Set up the destination. */ - strcpy(dest, Archive); - Name = dest + strlen(dest); - *Name++ = '/'; - - if (!SMinit()) - die("cannot initialize storage manager: %s", SMerrorstr); - - /* Read input. */ - while (fgets(buff, sizeof buff, stdin) != NULL) { - if ((p = strchr(buff, '\n')) == NULL) { - warn("skipping %.40s: too long", buff); - continue; - } - *p = '\0'; - if (buff[0] == '\0' || buff[0] == '#') - continue; - - /* Check to see if this is a token... */ - if (IsToken(buff)) { - /* Get a copy of the article. */ - token = TextToToken(buff); - if ((art = SMretrieve(token, RETR_ALL)) == NULL) { - warn("cannot retrieve %s", buff); - continue; - } - - /* Determine groups from the Xref header */ - xrefhdr = wire_findheader(art->data, art->len, "Xref"); - if (xrefhdr == NULL) { - warn("cannot find Xref header"); - SMfreearticle(art); - continue; - } - - if ((xrefs = CrackXref(xrefhdr, &numxrefs)) == NULL || numxrefs == 0) { - warn("bogus Xref header"); - SMfreearticle(art); - continue; - } - - /* Process each newsgroup... */ - if (base) { - free(base); - base = NULL; - } - for (i=0; (unsigned)i 0) { - *p = '\0'; - ng = xrefs[i]; - doit = false; - for (j=0; (unsigned)jpathoutgoing, "archive"); - else if (*p == '/') - spool = concat(p, ".bch", (char *) 0); - else - spool = concat(innconf->pathoutgoing, "/", p, ".bch", (char *) 0); - if ((F = xfopena(spool)) == NULL) - sysdie("cannot spool to %s", spool); - - /* Write the rest of stdin to the spool file. */ - i = 0; - if (fprintf(F, "%s\n", buff) == EOF) { - syswarn("cannot start spool"); - i = 1; - } - while (fgets(buff, sizeof buff, stdin) != NULL) - if (fputs(buff, F) == EOF) { - syswarn("cannot write to spool"); - i = 1; - break; - } - if (fclose(F) == EOF) { - syswarn("cannot close spool"); - i = 1; - } - - /* If we had a named input file, try to rename the spool. */ - if (p != NULL && rename(spool, av[0]) < 0) { - syswarn("cannot rename spool"); - i = 1; - } - - exit(i); - /* NOTREACHED */ -} diff --git a/backends/batcher.c b/backends/batcher.c deleted file mode 100644 index 0595778..0000000 --- a/backends/batcher.c +++ /dev/null @@ -1,428 +0,0 @@ -/* $Id: batcher.c 6762 2004-05-17 04:24:53Z rra $ -** -** Read batchfiles on standard input and spew out batches. -*/ - -#include "config.h" -#include "clibrary.h" -#include -#include -#include -#include -#include -#include - -#include "inn/innconf.h" -#include "inn/messages.h" -#include "inn/timer.h" -#include "libinn.h" -#include "paths.h" -#include "storage.h" - - -/* -** Global variables. -*/ -static bool BATCHopen; -static bool STATprint; -static double STATbegin; -static double STATend; -static char *Host; -static char *InitialString; -static char *Input; -static char *Processor; -static int ArtsInBatch; -static int ArtsWritten; -static int BATCHcount; -static int MaxBatches; -static int BATCHstatus; -static long BytesInBatch = 60 * 1024; -static long BytesWritten; -static long MaxArts; -static long MaxBytes; -static sig_atomic_t GotInterrupt; -static const char *Separator = "#! rnews %ld"; -static char *ERRLOG; - -/* -** Start a batch process. -*/ -static FILE * -BATCHstart(void) -{ - FILE *F; - char buff[SMBUF]; - - if (Processor && *Processor) { - snprintf(buff, sizeof(buff), Processor, Host); - F = popen(buff, "w"); - if (F == NULL) - return NULL; - } - else - F = stdout; - BATCHopen = true; - BATCHcount++; - return F; -} - - -/* -** Close a batch, return exit status. -*/ -static int -BATCHclose(FILE *F) -{ - BATCHopen = false; - if (F == stdout) - return fflush(stdout) == EOF ? 1 : 0; - return pclose(F); -} - - -/* -** Update the batch file and exit. -*/ -static void -RequeueAndExit(off_t Cookie, char *line, long BytesInArt) -{ - static char LINE1[] = "batcher %s times user %.3f system %.3f elapsed %.3f"; - static char LINE2[] ="batcher %s stats batches %d articles %d bytes %ld"; - char *spool; - char buff[BIG_BUFFER]; - int i; - FILE *F; - double usertime; - double systime; - - /* Do statistics. */ - STATend = TMRnow_double(); - if (GetResourceUsage(&usertime, &systime) < 0) { - usertime = 0; - systime = 0; - } - - if (STATprint) { - printf(LINE1, Host, usertime, systime, STATend - STATbegin); - printf("\n"); - printf(LINE2, Host, BATCHcount, ArtsWritten, BytesWritten); - printf("\n"); - } - - syslog(L_NOTICE, LINE1, Host, usertime, systime, STATend - STATbegin); - syslog(L_NOTICE, LINE2, Host, BATCHcount, ArtsWritten, BytesWritten); - - /* Last batch exit okay? */ - if (BATCHstatus == 0) { - if (feof(stdin) && Cookie != -1) { - /* Yes, and we're all done -- remove input and exit. */ - fclose(stdin); - if (Input) - unlink(Input); - exit(0); - } - } - - /* Make an appropriate spool file. */ - if (Input == NULL) - spool = concatpath(innconf->pathoutgoing, Host); - else - spool = concat(Input, ".bch", (char *) 0); - if ((F = xfopena(spool)) == NULL) - sysdie("%s cannot open %s", Host, spool); - - /* If we can back up to where the batch started, do so. */ - i = 0; - if (Cookie != -1 && fseeko(stdin, Cookie, SEEK_SET) == -1) { - syswarn("%s cannot seek", Host); - i = 1; - } - - /* Write the line we had; if the fseeko worked, this will be an - * extra line, but that's okay. */ - if (line && fprintf(F, "%s %ld\n", line, BytesInArt) == EOF) { - syswarn("%s cannot write spool", Host); - i = 1; - } - - /* Write rest of stdin to spool. */ - while (fgets(buff, sizeof buff, stdin) != NULL) - if (fputs(buff, F) == EOF) { - syswarn("%s cannot write spool", Host); - i = 1; - break; - } - if (fclose(F) == EOF) { - syswarn("%s cannot close spool", Host); - i = 1; - } - - /* If we had a named input file, try to rename the spool. */ - if (Input != NULL && rename(spool, Input) < 0) { - syswarn("%s cannot rename spool", Host); - i = 1; - } - - exit(i); - /* NOTREACHED */ -} - - -/* -** Mark that we got interrupted. -*/ -static RETSIGTYPE -CATCHinterrupt(int s) -{ - GotInterrupt = true; - - /* Let two interrupts kill us. */ - xsignal(s, SIG_DFL); -} - - -int -main(int ac, char *av[]) -{ - bool Redirect; - FILE *F; - const char *AltSpool; - char *p; - char *data; - char line[BIG_BUFFER]; - char buff[BIG_BUFFER]; - int BytesInArt; - long BytesInCB; - off_t Cookie; - size_t datasize; - int i; - int ArtsInCB; - int length; - TOKEN token; - ARTHANDLE *art; - char *artdata; - - /* Set defaults. */ - openlog("batcher", L_OPENLOG_FLAGS | LOG_PID, LOG_INN_PROG); - message_program_name = "batcher"; - if (!innconf_read(NULL)) - exit(1); - AltSpool = NULL; - Redirect = true; - umask(NEWSUMASK); - ERRLOG = concatpath(innconf->pathlog, _PATH_ERRLOG); - - /* Parse JCL. */ - while ((i = getopt(ac, av, "a:A:b:B:i:N:p:rs:S:v")) != EOF) - switch (i) { - default: - die("usage error"); - break; - case 'a': - ArtsInBatch = atoi(optarg); - break; - case 'A': - MaxArts = atol(optarg); - break; - case 'b': - BytesInBatch = atol(optarg); - break; - case 'B': - MaxBytes = atol(optarg); - break; - case 'i': - InitialString = optarg; - break; - case 'N': - MaxBatches = atoi(optarg); - break; - case 'p': - Processor = optarg; - break; - case 'r': - Redirect = false; - break; - case 's': - Separator = optarg; - break; - case 'S': - AltSpool = optarg; - break; - case 'v': - STATprint = true; - break; - } - if (MaxArts && ArtsInBatch == 0) - ArtsInBatch = MaxArts; - if (MaxBytes && BytesInBatch == 0) - BytesInBatch = MaxBytes; - - /* Parse arguments. */ - ac -= optind; - av += optind; - if (ac != 1 && ac != 2) - die("usage error"); - Host = av[0]; - if ((Input = av[1]) != NULL) { - if (Input[0] != '/') - Input = concatpath(innconf->pathoutgoing, av[1]); - if (freopen(Input, "r", stdin) == NULL) - sysdie("%s cannot open %s", Host, Input); - } - - if (Redirect) - freopen(ERRLOG, "a", stderr); - - /* Go to where the articles are. */ - if (chdir(innconf->patharticles) < 0) - sysdie("%s cannot chdir to %s", Host, innconf->patharticles); - - /* Set initial counters, etc. */ - datasize = 8 * 1024; - data = xmalloc(datasize); - BytesInCB = 0; - ArtsInCB = 0; - Cookie = -1; - GotInterrupt = false; - xsignal(SIGHUP, CATCHinterrupt); - xsignal(SIGINT, CATCHinterrupt); - xsignal(SIGTERM, CATCHinterrupt); - /* xsignal(SIGPIPE, CATCHinterrupt); */ - STATbegin = TMRnow_double(); - - SMinit(); - F = NULL; - while (fgets(line, sizeof line, stdin) != NULL) { - /* Record line length in case we do an ftello. Not portable to - * systems with non-Unix file formats. */ - length = strlen(line); - Cookie = ftello(stdin) - length; - - /* Get lines like "name size" */ - if ((p = strchr(line, '\n')) == NULL) { - warn("%s skipping %.40s: too long", Host, line); - continue; - } - *p = '\0'; - if (line[0] == '\0' || line[0] == '#') - continue; - if ((p = strchr(line, ' ')) != NULL) { - *p++ = '\0'; - /* Try to be forgiving of bad input. */ - BytesInArt = CTYPE(isdigit, (int)*p) ? atol(p) : -1; - } - else - BytesInArt = -1; - - /* Strip of leading spool pathname. */ - if (line[0] == '/' - && line[strlen(innconf->patharticles)] == '/' - && strncmp(line, innconf->patharticles, strlen(innconf->patharticles)) == 0) - p = line + strlen(innconf->patharticles) + 1; - else - p = line; - - /* Open the file. */ - if (IsToken(p)) { - token = TextToToken(p); - if ((art = SMretrieve(token, RETR_ALL)) == NULL) { - if ((SMerrno != SMERR_NOENT) && (SMerrno != SMERR_UNINIT)) - warn("%s skipping %.40s: %s", Host, p, SMerrorstr); - continue; - } - BytesInArt = -1; - artdata = FromWireFmt(art->data, art->len, (size_t *)&BytesInArt); - SMfreearticle(art); - } else { - warn("%s skipping %.40s: not token", Host, p); - continue; - } - - /* Have an open article, do we need to open a batch? This code - * is here (rather then up before the while loop) so that we - * can avoid sending an empty batch. The goto makes the code - * a bit more clear. */ - if (F == NULL) { - if (GotInterrupt) { - RequeueAndExit(Cookie, (char *)NULL, 0L); - } - if ((F = BATCHstart()) == NULL) { - syswarn("%s cannot start batch %d", Host, BATCHcount); - break; - } - if (InitialString && *InitialString) { - fprintf(F, "%s\n", InitialString); - BytesInCB += strlen(InitialString) + 1; - BytesWritten += strlen(InitialString) + 1; - } - goto SendIt; - } - - /* We're writing a batch, see if adding the current article - * would exceed the limits. */ - if ((ArtsInBatch > 0 && ArtsInCB + 1 >= ArtsInBatch) - || (BytesInBatch > 0 && BytesInCB + BytesInArt >= BytesInBatch)) { - if ((BATCHstatus = BATCHclose(F)) != 0) { - if (BATCHstatus == -1) - syswarn("%s cannot close batch %d", Host, BATCHcount); - else - syswarn("%s batch %d exit status %d", Host, BATCHcount, - BATCHstatus); - break; - } - ArtsInCB = 0; - BytesInCB = 0; - - /* See if we can start a new batch. */ - if ((MaxBatches > 0 && BATCHcount >= MaxBatches) - || (MaxBytes > 0 && BytesWritten + BytesInArt >= MaxBytes) - || (MaxArts > 0 && ArtsWritten + 1 >= MaxArts)) { - break; - } - - if (GotInterrupt) { - RequeueAndExit(Cookie, (char *)NULL, 0L); - } - - if ((F = BATCHstart()) == NULL) { - syswarn("%s cannot start batch %d", Host, BATCHcount); - break; - } - } - - SendIt: - /* Now we can start to send the article! */ - if (Separator && *Separator) { - snprintf(buff, sizeof(buff), Separator, BytesInArt); - BytesInCB += strlen(buff) + 1; - BytesWritten += strlen(buff) + 1; - if (fprintf(F, "%s\n", buff) == EOF || ferror(F)) { - syswarn("%s cannot write separator", Host); - break; - } - } - - /* Write the article. In case of interrupts, retry the read but not - the fwrite because we can't check that reliably and portably. */ - if ((fwrite(artdata, 1, BytesInArt, F) != BytesInArt) || ferror(F)) - break; - - /* Update the counts. */ - BytesInCB += BytesInArt; - BytesWritten += BytesInArt; - ArtsInCB++; - ArtsWritten++; - - if (GotInterrupt) { - Cookie = -1; - BATCHstatus = BATCHclose(F); - RequeueAndExit(Cookie, line, BytesInArt); - } - } - - if (BATCHopen) - BATCHstatus = BATCHclose(F); - RequeueAndExit(Cookie, NULL, 0); - - return 0; -} diff --git a/backends/buffchan.c b/backends/buffchan.c deleted file mode 100644 index 34c9e5b..0000000 --- a/backends/buffchan.c +++ /dev/null @@ -1,483 +0,0 @@ -/* $Id: buffchan.c 6163 2003-01-19 22:56:34Z rra $ -** -** Buffered file exploder for innd. -*/ - -#include "config.h" -#include "clibrary.h" -#include -#include -#include -#include - -#include "inn/innconf.h" -#include "inn/messages.h" -#include "inn/qio.h" -#include "libinn.h" -#include "paths.h" -#include "map.h" - -/* -** Hash functions for hashing sitenames. -*/ -#define SITE_HASH(Name, p, j) \ - for (p = Name, j = 0; *p; ) j = (j << 5) + j + *p++ -#define SITE_SIZE 128 -#define SITE_BUCKET(j) &SITEtable[j & (SITE_SIZE - 1)] - - -/* -** Entry for a single active site. -*/ -typedef struct _SITE { - bool Dropped; - const char *Name; - int CloseLines; - int FlushLines; - time_t LastFlushed; - time_t LastClosed; - int CloseSeconds; - int FlushSeconds; - FILE *F; - const char *Filename; - char *Buffer; -} SITE; - - -/* -** Site hashtable bucket. -*/ -typedef struct _SITEHASH { - int Size; - int Used; - SITE *Sites; -} SITEHASH; - - -/* Global variables. */ -static char *Format; -static const char *Map; -static int BufferMode; -static int CloseEvery; -static int FlushEvery; -static int CloseSeconds; -static int FlushSeconds; -static sig_atomic_t GotInterrupt; -static SITEHASH SITEtable[SITE_SIZE]; -static TIMEINFO Now; - - -/* -** Set up the site information. Basically creating empty buckets. -*/ -static void -SITEsetup(void) -{ - SITEHASH *shp; - - for (shp = SITEtable; shp < ARRAY_END(SITEtable); shp++) { - shp->Size = 3; - shp->Sites = xmalloc(shp->Size * sizeof(SITE)); - shp->Used = 0; - } -} - - -/* -** Close a site -*/ -static void -SITEclose(SITE *sp) -{ - FILE *F; - - if ((F = sp->F) != NULL) { - if (fflush(F) == EOF || ferror(F) - || fchmod((int)fileno(F), 0664) < 0 - || fclose(F) == EOF) - syswarn("%s cannot close %s", sp->Name, sp->Filename); - sp->F = NULL; - } -} - -/* -** Close all open sites. -*/ -static void -SITEcloseall(void) -{ - SITEHASH *shp; - SITE *sp; - int i; - - for (shp = SITEtable; shp < ARRAY_END(SITEtable); shp++) - for (sp = shp->Sites, i = shp->Used; --i >= 0; sp++) - SITEclose(sp); -} - - -/* -** Open the file for a site. -*/ -static void SITEopen(SITE *sp) -{ - int e; - - if ((sp->F = xfopena(sp->Filename)) == NULL - && ((e = errno) != EACCES || chmod(sp->Filename, 0644) < 0 - || (sp->F = xfopena(sp->Filename)) == NULL)) { - syswarn("%s cannot fopen %s", sp->Name, sp->Filename); - if ((sp->F = fopen("/dev/null", "w")) == NULL) - /* This really should not happen. */ - sysdie("%s cannot fopen /dev/null", sp->Name); - } - else if (fchmod((int)fileno(sp->F), 0444) < 0) - syswarn("%s cannot fchmod %s", sp->Name, sp->Filename); - - if (BufferMode != '\0') - setbuf(sp->F, sp->Buffer); - - /* Reset all counters. */ - sp->FlushLines = 0; - sp->CloseLines = 0; - sp->LastFlushed = Now.time; - sp->LastClosed = Now.time; - sp->Dropped = false; -} - - -/* -** Find a site, possibly create if not found. -*/ -static SITE * -SITEfind(char *Name, bool CanCreate) -{ - char *p; - int i; - unsigned int j; - SITE *sp; - SITEHASH *shp; - char c; - char buff[BUFSIZ]; - - /* Look for site in the hash table. */ - SITE_HASH(Name, p, j); - shp = SITE_BUCKET(j); - for (c = *Name, sp = shp->Sites, i = shp->Used; --i >= 0; sp++) - if (c == sp->Name[0] && strcasecmp(Name, sp->Name) == 0) - return sp; - if (!CanCreate) - return NULL; - - /* Adding a new site -- grow hash bucket if we need to. */ - if (shp->Used == shp->Size - 1) { - shp->Size *= 2; - shp->Sites = xrealloc(shp->Sites, shp->Size * sizeof(SITE)); - } - sp = &shp->Sites[shp->Used++]; - - /* Fill in the structure for the new site. */ - sp->Name = xstrdup(Name); - snprintf(buff, sizeof(buff), Format, Map ? MAPname(Name) : sp->Name); - sp->Filename = xstrdup(buff); - if (BufferMode == 'u') - sp->Buffer = NULL; - else if (BufferMode == 'b') - sp->Buffer = xmalloc(BUFSIZ); - SITEopen(sp); - - return sp; -} - - -/* -** Flush a site -- close and re-open the file. -*/ -static void -SITEflush(SITE *sp) -{ - FILE *F; - - if ((F = sp->F) != NULL) { - if (fflush(F) == EOF || ferror(F) - || fchmod((int)fileno(F), 0664) < 0 - || fclose(F) == EOF) - syswarn("%s cannot close %s", sp->Name, sp->Filename); - sp->F = NULL; - } - if (!sp->Dropped) - SITEopen(sp); -} - - -/* -** Flush all open sites. -*/ -static void -SITEflushall(void) -{ - SITEHASH *shp; - SITE *sp; - int i; - - for (shp = SITEtable; shp < ARRAY_END(SITEtable); shp++) - for (sp = shp->Sites, i = shp->Used; --i >= 0; sp++) - SITEflush(sp); -} - - -/* -** Write data to a site. -*/ -static void -SITEwrite(char *name, char *text, size_t len) -{ - SITE *sp; - - sp = SITEfind(name, true); - if (sp->F == NULL) - SITEopen(sp); - - if (fwrite(text, 1, len, sp->F) != len) - syswarn("%s cannot write", sp->Name); - - /* Bump line count; see if time to close or flush. */ - if (CloseEvery && ++(sp->CloseLines) >= CloseEvery) { - SITEflush(sp); - return; - } - if (CloseSeconds && sp->LastClosed + CloseSeconds < Now.time) { - SITEflush(sp); - return; - } - if (FlushEvery && ++(sp->FlushLines) >= FlushEvery) { - if (fflush(sp->F) == EOF || ferror(sp->F)) - syswarn("%s cannot flush %s", sp->Name, sp->Filename); - sp->LastFlushed = Now.time; - sp->FlushLines = 0; - } - else if (FlushSeconds && sp->LastFlushed + FlushSeconds < Now.time) { - if (fflush(sp->F) == EOF || ferror(sp->F)) - syswarn("%s cannot flush %s", sp->Name, sp->Filename); - sp->LastFlushed = Now.time; - sp->FlushLines = 0; - } -} - - -/* -** Handle a command message. -*/ -static void -Process(char *p) -{ - SITE *sp; - - if (*p == 'b' && strncmp(p, "begin", 5) == 0) - /* No-op. */ - return; - - if (*p == 'f' && strncmp(p, "flush", 5) == 0) { - for (p += 5; ISWHITE(*p); p++) - continue; - if (*p == '\0') - SITEflushall(); - else if ((sp = SITEfind(p, false)) != NULL) - SITEflush(sp); - /*else - fprintf(stderr, "buffchan flush %s unknown site\n", p);*/ - return; - } - - if (*p == 'd' && strncmp(p, "drop", 4) == 0) { - for (p += 4; ISWHITE(*p); p++) - continue; - if (*p == '\0') - SITEcloseall(); - else if ((sp = SITEfind(p, false)) == NULL) - warn("drop %s unknown site", p); - else { - SITEclose(sp); - sp->Dropped = true; - } - return; - } - - if (*p == 'r' && strncmp(p, "readmap", 7) == 0) { - MAPread(Map); - return; - } - - /* Other command messages -- ignored. */ - warn("unknown message %s", p); -} - - -/* -** Mark that we got a signal; let two signals kill us. -*/ -static RETSIGTYPE -CATCHinterrupt(int s) -{ - GotInterrupt = true; - xsignal(s, SIG_DFL); -} - - -int -main(int ac, char *av[]) -{ - QIOSTATE *qp; - int i; - int Fields; - char *p; - char *next; - char *line; - char *Directory; - bool Redirect; - FILE *F; - char *ERRLOG; - - /* First thing, set up our identity. */ - message_program_name = "buffchan"; - - /* Set defaults. */ - if (!innconf_read(NULL)) - exit(1); - ERRLOG = concatpath(innconf->pathlog, _PATH_ERRLOG); - Directory = NULL; - Fields = 1; - Format = NULL; - Redirect = true; - GotInterrupt = false; - umask(NEWSUMASK); - - xsignal(SIGHUP, CATCHinterrupt); - xsignal(SIGINT, CATCHinterrupt); - xsignal(SIGQUIT, CATCHinterrupt); - xsignal(SIGPIPE, CATCHinterrupt); - xsignal(SIGTERM, CATCHinterrupt); - xsignal(SIGALRM, CATCHinterrupt); - - /* Parse JCL. */ - while ((i = getopt(ac, av, "bc:C:d:f:l:L:m:p:rs:u")) != EOF) - switch (i) { - default: - die("usage error"); - break; - case 'b': - case 'u': - BufferMode = i; - break; - case 'c': - CloseEvery = atoi(optarg); - break; - case 'C': - CloseSeconds = atoi(optarg); - break; - case 'd': - Directory = optarg; - if (Format == NULL) - Format =xstrdup("%s"); - break; - case 'f': - Fields = atoi(optarg); - break; - case 'l': - FlushEvery = atoi(optarg); - break; - case 'L': - FlushSeconds = atoi(optarg); - break; - case 'm': - Map = optarg; - MAPread(Map); - break; - case 'p': - if ((F = fopen(optarg, "w")) == NULL) - sysdie("cannot fopen %s", optarg); - fprintf(F, "%ld\n", (long)getpid()); - if (ferror(F) || fclose(F) == EOF) - sysdie("cannot fclose %s", optarg); - break; - case 'r': - Redirect = false; - break; - case 's': - Format = optarg; - break; - } - ac -= optind; - av += optind; - if (ac) - die("usage error"); - - /* Do some basic set-ups. */ - if (Redirect) - freopen(ERRLOG, "a", stderr); - if (Format == NULL) { - Format = concatpath(innconf->pathoutgoing, "%s"); - } - if (Directory && chdir(Directory) < 0) - sysdie("cannot chdir to %s", Directory); - SITEsetup(); - - /* Read input. */ - for (qp = QIOfdopen((int)fileno(stdin)); !GotInterrupt ; ) { - if ((line = QIOread(qp)) == NULL) { - if (QIOerror(qp)) { - syswarn("cannot read"); - break; - } - if (QIOtoolong(qp)) { - warn("long line"); - QIOread(qp); - continue; - } - - /* Normal EOF. */ - break; - } - - /* Command? */ - if (*line == EXP_CONTROL && *++line != EXP_CONTROL) { - Process(line); - continue; - } - - /* Skip the right number of leading fields. */ - for (i = Fields, p = line; *p; p++) - if (*p == ' ' && --i <= 0) - break; - if (*p == '\0') - /* Nothing to write. Probably shouldn't happen. */ - continue; - - /* Add a newline, get the length of all leading fields. */ - *p++ = '\n'; - i = p - line; - - if (GetTimeInfo(&Now) < 0) { - syswarn("cannot get time"); - break; - } - - /* Rest of the line is space-separated list of filenames. */ - for (; *p; p = next) { - /* Skip whitespace, get next word. */ - while (*p == ' ') - p++; - for (next = p; *next && *next != ' '; next++) - continue; - if (*next) - *next++ = '\0'; - - SITEwrite(p, line, i); - } - - } - - SITEcloseall(); - exit(0); - /* NOTREACHED */ -} diff --git a/backends/crosspost.c b/backends/crosspost.c deleted file mode 100644 index bef4fb2..0000000 --- a/backends/crosspost.c +++ /dev/null @@ -1,338 +0,0 @@ -/* $Id: crosspost.c 6135 2003-01-19 01:15:40Z rra $ -** -** Parse input to add links for cross posted articles. Input format is one -** line per article. Dots '.' are changed to '/'. Commas ',' or blanks -** ' ' separate entries. Typically this is via a channel feed from innd -** though an edit of the history file can also be used for recovery -** purposes. Sample newsfeeds entry: -** -** # Create the links for cross posted articles -** crosspost:*:Tc,Ap,WR:/usr/local/newsbin/crosspost -** -** WARNING: This no longer works with the current INN; don't use it -** currently. It still exists in the source tree in case someone will -** want to clean it up and make it useable again. -*/ - -#include "config.h" -#include "clibrary.h" -#include -#include -#include -#include - -#include "inn/qio.h" -#include "libinn.h" -#include "paths.h" - - -static char *Dir; - -static int debug = false; -static int syncfiles = true; - -static unsigned long STATTime = 0; -static unsigned long STATMissing = 0; /* Source file missing */ -static unsigned long STATTooLong = 0; /* Name Too Long (src or dest) */ -static unsigned long STATLink = 0; /* Link done */ -static unsigned long STATLError = 0; /* Link problem */ -static unsigned long STATSymlink = 0; /* Symlink done */ -static unsigned long STATSLError = 0; /* Symlink problem */ -static unsigned long STATMkdir = 0; /* Mkdir done */ -static unsigned long STATMdError = 0; /* Mkdir problem */ -static unsigned long STATOError = 0; /* Other errors */ - -#define MAXXPOST 256 -#define STATREFRESH 10800 /* 3 hours */ - -/* -** Write some statistics and reset all counters. -*/ -void -ProcessStats() -{ - time_t Time; - - Time = time (NULL); - syslog(L_NOTICE, - "seconds %lu links %lu %lu symlinks %lu %lu mkdirs %lu %lu missing %lu toolong %lu other %lu", - Time - STATTime, STATLink, STATLError, STATSymlink, STATSLError, - STATMkdir, STATMdError, STATMissing, STATTooLong, STATOError); - - STATMissing = STATTooLong = STATLink = STATLError = 0; - STATSymlink = STATSLError = STATMkdir = STATMdError = STATOError = 0; - STATTime = Time; -} - -/* -** Try to make one directory. Return false on error. -*/ -static bool -MakeDir(Name) - char *Name; -{ - struct stat Sb; - - if (mkdir(Name, GROUPDIR_MODE) >= 0) { - STATMkdir++; - return true; - } - - /* See if it failed because it already exists. */ - return stat(Name, &Sb) >= 0 && S_ISDIR(Sb.st_mode); -} - - -/* -** Make spool directory. Return false on error. -*/ -static bool -MakeSpoolDir(Name) - char *Name; -{ - char *p; - bool made; - - /* Optimize common case -- parent almost always exists. */ - if (MakeDir(Name)) - return true; - - /* Try to make each of comp and comp/foo in turn. */ - for (p = Name; *p; p++) - if (*p == '/') { - *p = '\0'; - made = MakeDir(Name); - *p = '/'; - if (!made) { - STATMdError++; - return false; - } - } - - return MakeDir(Name); -} - - -/* -** Process the input. Data can come from innd: -** news/group/name/ [space news/group/]... -** or -** news.group.name/,[news.group.name/]... -*/ -static void -ProcessIncoming(qp) - QIOSTATE *qp; -{ - char *p; - int i; - int nxp; - int fd; - int lnval ; - char *names[MAXXPOST]; - - - for ( ; ; ) { - - if (time(NULL) - STATTime > STATREFRESH) - ProcessStats(); - - /* Read the first line of data. */ - if ((p = QIOread(qp)) == NULL) { - if (QIOtoolong(qp)) { - fprintf(stderr, "crosspost line too long\n"); - STATTooLong++; - continue; - } - break; - } - - for (i = 0; *p && (i < MAXXPOST); i++) { /* parse input into array */ - names[i] = p; - for ( ; *p; p++) { - if (*p == '.') *p++ = '/'; /* dot to slash translation */ - else if ((*p == ',') /* name separators */ - || (*p == ' ') - || (*p == '\t') - || (*p == '\n')) { - *p++ = '\0'; - break; - } - } - } - nxp = i; - if (debug) { - for (i = 0; i < nxp; i++) - fprintf(stderr, "crosspost: debug %d %s\n", - i, names[i]); - } - - if(syncfiles) fd = open(names[0], O_RDWR); - - for (i = 1; i < nxp; i++) { - lnval = link(names[0], names[i]) ; - if (lnval == 0) STATLink++; - if (lnval < 0 && errno != EXDEV) { /* first try to link */ - int j; - char path[SPOOLNAMEBUFF+2]; - - for (j = 0; (path[j] = names[i][j]) != '\0' ; j++) ; - for (j--; (j > 0) && (path[j] != '/'); j--) ; - if (path[j] == '/') { - path[j] = '\0'; - /* try making parent dir */ - if (MakeSpoolDir(path) == false) { - fprintf(stderr, "crosspost cant mkdir %s\n", - path); - } - else { - /* 2nd try to link */ - lnval = link(names[0], names[i]) ; - if (lnval == 0) STATLink++; - if (lnval < 0 && errno == EXDEV) { -#if !defined(HAVE_SYMLINK) - fprintf(stderr, "crosspost cant link %s %s", - names[0], names[i]); - perror(" "); -#else - /* Try to make a symbolic link - ** to the full pathname. - */ - for (j = 0, p = Dir; (j < SPOOLNAMEBUFF) && *p; ) - path[j++] = *p++; /* copy spool dir */ - if (j < SPOOLNAMEBUFF) path[j++] = '/'; - for (p = names[0]; (j < SPOOLNAMEBUFF) && *p; ) - path[j++] = *p++; /* append path */ - path[j++] = '\0'; - if (symlink(path, names[i]) < 0) { - fprintf(stderr, - "crosspost cant symlink %s %s", - path, names[i]); - perror(" "); - STATSLError++; - } - else - STATSymlink++; -#endif /* !defined(HAVE_SYMLINK) */ - } else if (lnval < 0) { - if (lnval == ENOENT) - STATMissing++; - else { - fprintf(stderr, "crosspost cant link %s %s", - names[0], names[i]); - perror(" "); - STATLError++; - } - } - } - } else { - fprintf(stderr, "crosspost bad path %s\n", - names[i]); - STATOError++; - } - } else if (lnval < 0) { - int j; - char path[SPOOLNAMEBUFF+2]; - -#if !defined(HAVE_SYMLINK) - fprintf(stderr, "crosspost cant link %s %s", - names[0], names[i]); - perror(" "); -#else - /* Try to make a symbolic link - ** to the full pathname. - */ - for (j = 0, p = Dir; (j < SPOOLNAMEBUFF) && *p; ) - path[j++] = *p++; /* copy spool dir */ - if (j < SPOOLNAMEBUFF) path[j++] = '/'; - for (p = names[0]; (j < SPOOLNAMEBUFF) && *p; ) - path[j++] = *p++; /* append path */ - path[j++] = '\0'; - if (symlink(path, names[i]) < 0) { - fprintf(stderr, - "crosspost cant symlink %s %s", - path, names[i]); - perror(" "); - STATSLError++; - } - else - STATSymlink++; -#endif /* !defined(HAVE_SYMLINK) */ - } - } - - if (syncfiles && (fd >= 0)) { - fsync(fd); - close(fd); - } - } - - if (QIOerror(qp)) - fprintf(stderr, "crosspost cant read %s\n", strerror(errno)); - QIOclose(qp); -} - - -static void -Usage(void) -{ - fprintf(stderr, "usage: crosspost [-D dir] [files...]\n"); - exit(1); -} - - -int -main(ac, av) - int ac; - char *av[]; -{ - int i; - QIOSTATE *qp; - - /* Set defaults. */ - if (ReadInnConf() < 0) exit(1); - Dir = innconf->patharticles; - umask(NEWSUMASK); - - /* Parse JCL. */ - while ((i = getopt(ac, av, "D:ds")) != EOF) - switch (i) { - default: - Usage(); - /* NOTREACHED */ - case 'D': - Dir = optarg; /* specify spool path */ - break; - case 'd': - debug = true; - break; - case 's': - syncfiles = false; /* do not fsync articles */ - break; - } - ac -= optind; - av += optind; - - if (chdir(Dir) < 0) { - fprintf(stderr, "crosspost cant chdir %s %s\n", - Dir, strerror(errno)); - exit(1); - } - openlog("crosspost", L_OPENLOG_FLAGS | LOG_PID, LOG_INN_PROG); - STATTime = time (NULL); - if (ac == 0) - ProcessIncoming(QIOfdopen(STDIN_FILENO)); - else { - for ( ; *av; av++) - if (strcmp(*av, "-") == 0) - ProcessIncoming(QIOfdopen(STDIN_FILENO)); - else if ((qp = QIOopen(*av)) == NULL) - fprintf(stderr, "crosspost cant open %s %s\n", - *av, strerror(errno)); - else - ProcessIncoming(qp); - } - - ProcessStats(); - exit(0); - /* NOTREACHED */ -} diff --git a/backends/cvtbatch.c b/backends/cvtbatch.c deleted file mode 100644 index ba57ef8..0000000 --- a/backends/cvtbatch.c +++ /dev/null @@ -1,128 +0,0 @@ -/* $Id: cvtbatch.c 6135 2003-01-19 01:15:40Z rra $ -** -** Read file list on standard input and spew out batchfiles. -*/ - -#include "config.h" -#include "clibrary.h" - -#include "inn/innconf.h" -#include "inn/messages.h" -#include "inn/qio.h" -#include "inn/wire.h" -#include "libinn.h" -#include "paths.h" -#include "storage.h" - - -int -main(int ac, char *av[]) { - int i; - QIOSTATE *qp; - char *line; - const char *text; - char *format; - char *p, *q; - const char *r; - bool Dirty; - TOKEN token; - ARTHANDLE *art; - int len; - - /* First thing, set up our identity. */ - message_program_name = "cvtbatch"; - if (!innconf_read(NULL)) - exit(1); - - /* Parse JCL. */ - format = xstrdup("nm"); - while ((i = getopt(ac, av, "w:")) != EOF) - switch (i) { - default: - die("usage error"); - break; - case 'w': - for (p = format = optarg; *p; p++) { - switch (*p) { - case FEED_BYTESIZE: - case FEED_FULLNAME: - case FEED_MESSAGEID: - case FEED_NAME: - continue; - } - warn("ignoring %c in -w flag", *p); - } - } - ac -= optind; - av += optind; - if (ac) - die("usage error"); - - if (!SMinit()) - die("cannot initialize storage manager: %s", SMerrorstr); - - /* Loop over all input. */ - qp = QIOfdopen((int)fileno(stdin)); - while ((line = QIOread(qp)) != NULL) { - for (p = line; *p; p++) - if (ISWHITE(*p)) { - *p = '\0'; - break; - } - - if (!IsToken(line)) - continue; - token = TextToToken(line); - if ((art = SMretrieve(token, RETR_HEAD)) == NULL) - continue; - text = wire_findheader(art->data, art->len, "Message-ID"); - if (text == NULL) { - SMfreearticle(art); - continue; - } - len = art->len; - for (r = text; r < art->data + art->len; r++) { - if (*r == '\r' || *r == '\n') - break; - } - if (r == art->data + art->len) { - SMfreearticle(art); - continue; - } - q = xmalloc(r - text + 1); - memcpy(q, text, r - text); - SMfreearticle(art); - q[r - text] = '\0'; - - /* Write the desired info. */ - for (Dirty = false, p = format; *p; p++) { - switch (*p) { - default: - continue; - case FEED_BYTESIZE: - if (Dirty) - putchar(' '); - printf("%d", len); - break; - case FEED_FULLNAME: - case FEED_NAME: - if (Dirty) - putchar(' '); - printf("%s", line); - break; - case FEED_MESSAGEID: - if (Dirty) - putchar(' '); - printf("%s", q); - break; - } - Dirty = true; - } - free(q); - if (Dirty) - putchar('\n'); - } - - exit(0); - /* NOTREACHED */ -} diff --git a/backends/filechan.c b/backends/filechan.c deleted file mode 100644 index 93e81a8..0000000 --- a/backends/filechan.c +++ /dev/null @@ -1,132 +0,0 @@ -/* $Id: filechan.c 6135 2003-01-19 01:15:40Z rra $ -** -** An InterNetNews channel process that splits a funnel entry into -** separate files. Originally from Robert Elz . -*/ - -#include "config.h" -#include "clibrary.h" -#include -#include -#include - -#include "inn/innconf.h" -#include "inn/messages.h" -#include "libinn.h" -#include "paths.h" - -#include "map.h" - -int -main(int ac, char *av[]) -{ - char buff[2048]; - char *p; - char *next; - int i; - int fd; - int Fields; - const char *Directory; - bool Map; - FILE *F; - struct stat Sb; - uid_t uid; - gid_t gid; - uid_t myuid; - - /* First thing, set up our identity. */ - message_program_name = "filechan"; - - /* Set defaults. */ - if (!innconf_read(NULL)) - exit(1); - Fields = 1; - Directory = innconf->pathoutgoing; - Map = false; - myuid = geteuid(); - umask(NEWSUMASK); - - /* Parse JCL. */ - while ((i = getopt(ac, av, "d:f:m:p:")) != EOF) - switch (i) { - default: - die("usage error"); - break; - case 'd': - Directory = optarg; - break; - case 'f': - Fields = atoi(optarg); - break; - case 'm': - Map = true; - MAPread(optarg); - break; - case 'p': - if ((F = fopen(optarg, "w")) == NULL) - sysdie("cannot fopen %s", optarg); - fprintf(F, "%ld\n", (long)getpid()); - if (ferror(F) || fclose(F) == EOF) - sysdie("cannot fclose %s", optarg); - break; - } - - /* Move, and get owner of current directory. */ - if (chdir(Directory) < 0) - sysdie("cannot chdir to %s", Directory); - if (stat(".", &Sb) < 0) - sysdie("cannot stat %s", Directory); - uid = Sb.st_uid; - gid = Sb.st_gid; - - /* Read input. */ - while (fgets(buff, sizeof buff, stdin) != NULL) { - if ((p = strchr(buff, '\n')) != NULL) - *p = '\0'; - - /* Skip the right number of leading fields. */ - for (i = Fields, p = buff; *p; p++) - if (*p == ' ' && --i <= 0) - break; - if (*p == '\0') - /* Nothing to write. Probably shouldn't happen. */ - continue; - - /* Add a newline, get the length of all leading fields. */ - *p++ = '\n'; - i = p - buff; - - /* Rest of the line is space-separated list of filenames. */ - for (; *p; p = next) { - /* Skip whitespace, get next word. */ - while (*p == ' ') - p++; - for (next = p; *next && *next != ' '; next++) - continue; - if (*next) - *next++ = '\0'; - - if (Map) - p = MAPname(p); - fd = open(p, O_CREAT | O_WRONLY | O_APPEND, BATCHFILE_MODE); - if (fd >= 0) { - /* Try to lock it and set the ownership right. */ - inn_lock_file(fd, INN_LOCK_WRITE, true); - if (myuid == 0 && uid != 0) - chown(p, uid, gid); - - /* Just in case, seek to the end. */ - lseek(fd, 0, SEEK_END); - - errno = 0; - if (write(fd, buff, i) != i) - sysdie("write failed"); - - close(fd); - } - } - } - - exit(0); - /* NOTREACHED */ -} diff --git a/backends/inndf.c b/backends/inndf.c deleted file mode 100644 index 6a85c86..0000000 --- a/backends/inndf.c +++ /dev/null @@ -1,335 +0,0 @@ -/* $Id: inndf.c 6677 2004-03-03 18:36:07Z hkehoe $ -** -** Reports free kilobytes (not disk blocks) or free inodes. -** -** Written by Ian Dickinson -** Wed Jul 26 10:11:38 BST 1995 (My birthday - 27 today!) -** -** inndf is a replacement for 'df | awk' in innwatch.ctl and for reporting -** free space in other INN scripts. It doesn't sync, it forks less, and -** it's generally less complicated. -** -** Usage: inndf [-i] [ ...] -** inndf -n -** inndf -o -** -** Compile with -lserver (ie. /usr/lib/libserver.a) if you run Sun's Online -** DiskSuite under SunOS 4.x. The wrapper functions there make the system -** call transparent; they copy the f_spare values to the correct spots, so -** f_blocks, f_bfree, f_bavail can exceed 2GB. -** -** Compile with -DHAVE_STATVFS for these systems: -** System V Release 4.x -** Solaris 2.x -** HP-UX 10.x -** OSF1 -** -** Compile with -DHAVE_STATFS for these systems: -** SunOS 4.x/Solaris 1.x -** HP-UX 9.x -** Linux -** NeXTstep 3.x -** -** (Or even better, let autoconf take care of it.) -** -** Thanks to these folks for bug fixes and porting information: -** Mahesh Ramachandran -** Chuck Swiger -** Sang-yong Suh -** Swa Frantzen -** Brad Dickey -** Taso N. Devetzis -** Wei-Yeh Lee -** Jeff Garzik -*/ - -#include "config.h" -#include "clibrary.h" - -#include "inn/innconf.h" -#include "inn/messages.h" -#include "inn/qio.h" -#include "libinn.h" -#include "ov.h" -#include "paths.h" - -/* The portability mess. Hide everything in macros so that the actual code - is relatively clean. SysV uses statvfs, BSD uses statfs, and ULTRIX is - just weird (and isn't worth checking for in configure). - - df_declare declares a variable of the appropriate type to pass to df_stat - along with a path; df_stat will return true on success, false on failure. - df_avail gives the number of free blocks, the size of those blocks given - in df_bsize (which handles SysV's weird fragment vs. preferred block size - thing). df_inodes returns the free inodes. */ -#if HAVE_STATVFS -# include -# define df_stat(p, s) (statvfs((p), (s)) == 0) -# define df_declare(s) struct statvfs s -# define df_total(s) ((s).f_blocks) -# define df_avail(s) ((s).f_bavail) -# define df_scale(s) ((s).f_frsize == 0 ? (s).f_bsize : (s).f_frsize) -# define df_files(s) ((s).f_files) -# define df_favail(s) ((s).f_favail) -#elif HAVE_STATFS -# if HAVE_SYS_VFS_H -# include -# endif -# if HAVE_SYS_PARAM_H -# include -# endif -# if HAVE_SYS_MOUNT_H -# include -# endif -# ifdef __ultrix__ -# define df_stat(p, s) (statfs((p), (s)) >= 1) -# define df_declare(s) struct fs_data s -# define df_total(s) ((s).fd_btot) -# define df_avail(s) ((s).fd_bfreen) -# define df_scale(s) 1024 -# define df_files(s) ((s).fd_gtot) -# define df_favail(s) ((s).fd_gfree) -# else -# define df_stat(p, s) (statfs((p), (s)) == 0) -# define df_declare(s) struct statfs s -# define df_total(s) ((s).f_blocks) -# define df_avail(s) ((s).f_bavail) -# define df_scale(s) ((s).f_bsize) -# define df_files(s) ((s).f_files) -# define df_favail(s) ((s).f_ffree) -# endif -#else -# error "Platform not supported. Neither statvfs nor statfs available." -#endif - -static const char usage[] = "\ -Usage: inndf [-i] [-f filename] [-F] [ ...]\n\ - inndf -n\n\ - inndf -o\n\ -\n\ -The first form gives the free space in kilobytes (or the count of free\n\ -inodes if -i is given) in the file systems given by the arguments. If\n\ --f is given, the corresponding file should be a list of directories to\n\ -check in addition to the arguments. -F uses /filesystems as the\n\ -file and is otherwise the same.\n\ -\n\ -The second form gives the total count of overview records stored. The\n\ -third form gives the percentage space allocated to overview that's been\n\ -used (if the overview method used supports this query)."; - -/* -** Given a path, a flag saying whether to look at inodes instead of free -** disk space, and a flag saying whether to format in columns, print out -** the amount of free space or inodes on that file system. Returns the -** percentage free, which may be printed out by the caller. -*/ -static void -printspace(const char *path, bool inode, bool fancy) -{ - df_declare(info); - unsigned long amount; - double percent; - - if (df_stat(path, &info)) { - if (inode) { - amount = df_favail(info); - - /* This value is compared using the shell by innwatch, and some - shells can't cope with anything larger than the maximum value - of a signed long. ReiserFS returns 2^32 - 1, however, since it - has no concept of inodes. So cap the returned value at the max - value of a signed long. */ - if (amount > (1UL << 31) - 1) - amount = (1UL << 31) - 1; - - /* 2.6 kernels show 0 available and used inodes, instead. */ - if (amount == 0 && df_files(info) == 0) - amount = (1UL << 31) - 1; - } else { - /* Do the multiplication in floating point to try to retain - accuracy if the free space in bytes would overflow an - unsigned long. This should be safe until file systems larger - than 4TB (which may not be much longer -- we should use long - long instead if we have it). - - Be very careful about the order of casts here; it's too - easy to cast back into an unsigned long a value that - overflows, and one then gets silently wrong results. */ - amount = (unsigned long) - (((double) df_avail(info) * df_scale(info)) / 1024.0); - } - } else { - /* On error, free space is zero. */ - amount = 0; - } - printf(fancy ? "%10lu" : "%lu", amount); - if (fancy) { - printf(inode ? " inodes available " : " Kbytes available "); - if (inode) - percent = 100 * ((double) df_favail(info) / df_files(info)); - else - percent = 100 * ((double) df_avail(info) / df_total(info)); - if (percent < 9.95) - printf(" (%3.1f%%)", percent); - else if (percent < 99.95) - printf(" (%4.1f%%)", percent); - else - printf("(%5.1f%%)", percent); - } -} - -static void -printspace_formatted(const char *path, bool inode) -{ - printf("%-40s ", path); - printspace(path, inode, true); - printf("\n"); -} - -static char * -readline(QIOSTATE *qp) -{ - char *line, *p; - - for (line = QIOread(qp); line != NULL; line = QIOread(qp)) { - p = strchr(line, '#'); - if (p != NULL) - *p = '\0'; - for (; *line == ' ' || *line == '\t'; line++) - ; - if (*line != '\0') { - for (p = line; *p != '\0' && *p != ' ' && *p != '\t'; p++) - ; - *p = '\0'; - return line; - } - } - return NULL; -} - -int -main(int argc, char *argv[]) -{ - int option, i, count; - unsigned long total; - QIOSTATE *qp; - char *active, *group, *line, *p; - char *file = NULL; - bool inode = false; - bool overview = false; - bool ovcount = false; - bool use_filesystems = false; - - while ((option = getopt(argc, argv, "hinof:F")) != EOF) { - switch (option) { - default: - die(usage); - case 'h': - printf("%s\n", usage); - exit(0); - case 'i': - inode = true; - break; - case 'n': - ovcount = true; - break; - case 'o': - overview = true; - break; - case 'f': - if (file != NULL) - die("inndf: Only one of -f or -F may be given"); - file = xstrdup(optarg); - break; - case 'F': - if (file != NULL) - die("inndf: Only one of -f or -F may be given"); - if (!innconf_read(NULL)) - exit(1); - file = concatpath(innconf->pathetc, INN_PATH_FILESYSTEMS); - use_filesystems = true; - break; - } - } - argc -= optind; - argv += optind; - - if (argc == 0 && !overview && !ovcount && file == NULL) - die(usage); - - /* Set the program name now rather than earlier so that it doesn't get - prepended to usage messages. */ - message_program_name = "inndf"; - - /* If directories were specified, get statistics about them. If only - one was given, just print out the number without the path or any - explanatory text; this mode is used by e.g. innwatch. Otherwise, - format things nicely. */ - if (argc == 1 && !overview && !ovcount && file == NULL) { - printspace(argv[0], inode, false); - printf("\n"); - } else { - for (i = 0; i < argc; i++) - printspace_formatted(argv[i], inode); - if (file != NULL) { - qp = QIOopen(file); - if (qp == NULL) { - if (!use_filesystems) - sysdie("can't open %s", file); - } else { - line = readline(qp); - while (line != NULL) { - printspace_formatted(line, inode); - line = readline(qp); - } - QIOclose(qp); - } - free(file); - } - } - - /* If we're going to be getting information from overview, do the icky - initialization stuff. */ - if (overview || ovcount) { - if (!use_filesystems) - if (!innconf_read(NULL)) - exit(1); - if (!OVopen(OV_READ)) - die("OVopen failed"); - } - - /* For the count, we have to troll through the active file and query the - overview backend for each group. */ - if (ovcount) { - active = concatpath(innconf->pathdb, _PATH_ACTIVE); - qp = QIOopen(active); - if (qp == NULL) - sysdie("can't open %s", active); - - total = 0; - group = QIOread(qp); - while (group != NULL) { - p = strchr(group, ' '); - if (p != NULL) - *p = '\0'; - if (OVgroupstats(group, NULL, NULL, &count, NULL)) - total += count; - group = QIOread(qp); - } - QIOclose(qp); - printf("%lu overview records stored\n", total); - } - - /* Percentage used is simpler, but only some overview methods understand - that query. */ - if (overview) { - if (OVctl(OVSPACE, &count)) { - if (count == -1) - printf("Space used is meaningless for the %s method\n", - innconf->ovmethod); - else - printf("%d%% overview space used\n", count); - } - } - exit(0); -} diff --git a/backends/innxbatch.c b/backends/innxbatch.c deleted file mode 100644 index 9ebfe9c..0000000 --- a/backends/innxbatch.c +++ /dev/null @@ -1,550 +0,0 @@ -/* $Id: innxbatch.c 6351 2003-05-19 02:00:06Z rra $ -** -** Transmit batches to remote site, using the XBATCH command -** Modelled after innxmit.c and nntpbatch.c -** -** Invocation: -** innxbatch [options] ... -#ifdef FROMSTDIN -** innxbatch -i -#endif FROMSTDIN -** will connect to serverhost's nntp port, and transfer the named files, -** with an xbatch command for every file. Files that have been sent -** successfully are unlink()ed. In case of any error, innxbatch terminates -** and leaves any remaining files untouched, for later transmission. -** Options: -** -D increase debug level -** -v report statistics to stdout -#ifdef FROMSTDIN -** -i read batch file names from stdin instead from command line. -** For each successfully transmitted batch, an OK is printed on -** stdout, to indicate that another file name is expected. -#endif -** -t Timeout for connection attempt -** -T Timeout for batch transfers. -** We do not use any file locking. At worst, a batch could be transmitted -** twice in parallel by two independant invocations of innxbatch. -** To prevent this, innxbatch should be invoked by a shell script that uses -** shlock(1) to achieve mutual exclusion. -*/ - -#include "config.h" -#include "clibrary.h" -#include "portable/socket.h" -#include "portable/time.h" -#include -#include -#include -#include -#include -#include -#include - -/* Needed on AIX 4.1 to get fd_set and friends. */ -#ifdef HAVE_SYS_SELECT_H -# include -#endif - -#include "inn/innconf.h" -#include "inn/messages.h" -#include "inn/timer.h" -#include "libinn.h" -#include "nntp.h" - -/* -** Syslog formats - collected together so they remain consistent -*/ -static char STAT1[] = - "%s stats offered %lu accepted %lu refused %lu rejected %lu"; -static char STAT2[] = "%s times user %.3f system %.3f elapsed %.3f"; -static char CANT_CONNECT[] = "%s connect failed %s"; -static char CANT_AUTHENTICATE[] = "%s authenticate failed %s"; -static char XBATCH_FAIL[] = "%s xbatch failed %s"; -static char UNKNOWN_REPLY[] = "Unknown reply after sending batch -- %s"; -static char CANNOT_UNLINK[] = "cannot unlink %s: %m"; -/* -** Global variables. -*/ -static bool Debug = 0; -static bool STATprint; -static char *REMhost; -static double STATbegin; -static double STATend; -static char *XBATCHname; -static int FromServer; -static int ToServer; -static sig_atomic_t GotAlarm; -static sig_atomic_t GotInterrupt; -static sig_atomic_t JMPyes; -static jmp_buf JMPwhere; -static unsigned long STATaccepted; -static unsigned long STAToffered; -static unsigned long STATrefused; -static unsigned long STATrejected; - -/* -** Send a line to the server. \r\n will be appended -*/ -static bool -REMwrite(int fd, char *p) -{ - int i; - int err; - char *dest; - static char buff[NNTP_STRLEN]; - - for (dest = buff, i = 0; p[i]; ) *dest++ = p[i++]; - *dest++ = '\r'; - *dest++ = '\n'; - *dest++ = '\0'; - - for (dest = buff, i+=2; i; dest += err, i -= err) { - err = write(fd, dest, i); - if (err < 0) { - syswarn("cannot write %s to %s", dest, REMhost); - return false; - } - } - if (Debug) - fprintf(stderr, "> %s\n", p); - - return true; -} - -/* -** Print transfer statistics, clean up, and exit. -*/ -static void -ExitWithStats(int x) -{ - static char QUIT[] = "quit"; - double usertime; - double systime; - - REMwrite(ToServer, QUIT); - - STATend = TMRnow_double(); - if (GetResourceUsage(&usertime, &systime) < 0) { - usertime = 0; - systime = 0; - } - - if (STATprint) { - printf(STAT1, - REMhost, STAToffered, STATaccepted, STATrefused, STATrejected); - printf("\n"); - printf(STAT2, REMhost, usertime, systime, STATend - STATbegin); - printf("\n"); - } - - syslog(L_NOTICE, STAT1, - REMhost, STAToffered, STATaccepted, STATrefused, STATrejected); - syslog(L_NOTICE, STAT2, REMhost, usertime, systime, STATend - STATbegin); - - exit(x); - /* NOTREACHED */ -} - - -/* -** Clean up the NNTP escapes from a line. -*/ -static char * -REMclean(char *buff) -{ - char *p; - - if ((p = strchr(buff, '\r')) != NULL) - *p = '\0'; - if ((p = strchr(buff, '\n')) != NULL) - *p = '\0'; - - /* The dot-escape is only in text, not command responses. */ - return buff; -} - - -/* -** Read a line of input, with timeout. We expect only answer lines, so -** we ignore \r\n-->\n mapping and the dot escape. -** Return true if okay, *or we got interrupted.* -*/ -static bool -REMread(char *start, int size) -{ - char *p, *h; - struct timeval t; - fd_set rmask; - int i; - - for (p = start; size; ) { - FD_ZERO(&rmask); - FD_SET(FromServer, &rmask); - t.tv_sec = 10 * 60; - t.tv_usec = 0; - i = select(FromServer + 1, &rmask, NULL, NULL, &t); - if (GotInterrupt) return true; - if (i < 0) { - if (errno == EINTR) continue; - else return false; - } - if (i == 0 || !FD_ISSET(FromServer, &rmask)) return false; - i = read(FromServer, p, size-1); - if (GotInterrupt) return true; - if (i <= 0) return false; - h = p; - p += i; - size -= i; - for ( ; h < p; h++) { - if (h > start && '\n' == *h && '\r' == h[-1]) { - *h = h[-1] = '\0'; - size = 0; - } - } - } - - if (Debug) - fprintf(stderr, "< %s\n", start); - - return true; -} - - -/* -** Handle the interrupt. -*/ -static void -Interrupted(void) -{ - warn("interrupted"); - ExitWithStats(1); -} - - -/* -** Send a whole xbatch to the server. Uses the global variables -** REMbuffer & friends -*/ -static bool -REMsendxbatch(int fd, char *buf, int size) -{ - char *p; - int i; - int err; - - for (i = size, p = buf; i; p += err, i -= err) { - err = write(fd, p, i); - if (err < 0) { - syswarn("cannot write xbatch to %s", REMhost); - return false; - } - } - if (GotInterrupt) Interrupted(); - if (Debug) - fprintf(stderr, "> [%d bytes of xbatch]\n", size); - - /* What did the remote site say? */ - if (!REMread(buf, size)) { - syswarn("no reply after sending xbatch"); - return false; - } - if (GotInterrupt) Interrupted(); - - /* Parse the reply. */ - switch (atoi(buf)) { - default: - warn("unknown reply after sending batch -- %s", buf); - syslog(L_ERROR, UNKNOWN_REPLY, buf); - return false; - /* NOTREACHED */ - break; - case NNTP_RESENDIT_VAL: - case NNTP_GOODBYE_VAL: - syslog(L_NOTICE, XBATCH_FAIL, REMhost, buf); - STATrejected++; - return false; - /* NOTREACHED */ - break; - case NNTP_OK_XBATCHED_VAL: - STATaccepted++; - if (Debug) fprintf(stderr, "will unlink(%s)\n", XBATCHname); - if (unlink(XBATCHname)) { - /* probably another incarantion was faster, so avoid further duplicate - * work - */ - syswarn("cannot unlink %s", XBATCHname); - syslog(L_NOTICE, CANNOT_UNLINK, XBATCHname); - return false; - } - break; - } - - /* Article sent */ - return true; -} - -/* -** Mark that we got interrupted. -*/ -static RETSIGTYPE -CATCHinterrupt(int s) -{ - GotInterrupt = true; - - /* Let two interrupts kill us. */ - xsignal(s, SIG_DFL); -} - - -/* -** Mark that the alarm went off. -*/ -/* ARGSUSED0 */ -static RETSIGTYPE -CATCHalarm(int s UNUSED) -{ - GotAlarm = true; - if (JMPyes) - longjmp(JMPwhere, 1); -} - - -/* -** Print a usage message and exit. -*/ -static void -Usage(void) -{ - warn("Usage: innxbatch [-Dv] [-t#] [-T#] host file ..."); -#ifdef FROMSTDIN - warn(" innxbatch [-Dv] [-t#] [-T#] -i host"); -#endif - exit(1); -} - - -int -main(int ac, char *av[]) -{ - int i; - char *p; - FILE *From; - FILE *To; - char buff[NNTP_STRLEN]; - RETSIGTYPE (*old)(int) = NULL; - unsigned int ConnectTimeout; - unsigned int TotalTimeout; - struct stat statbuf; - int fd; - int err; - char *XBATCHbuffer = NULL; - int XBATCHbuffersize = 0; - int XBATCHsize; - - openlog("innxbatch", L_OPENLOG_FLAGS | LOG_PID, LOG_INN_PROG); - message_program_name = "innxbatch"; - - /* Set defaults. */ - if (!innconf_read(NULL)) - exit(1); - ConnectTimeout = 0; - TotalTimeout = 0; - umask(NEWSUMASK); - - /* Parse JCL. */ - while ((i = getopt(ac, av, "Dit:T:v")) != EOF) - switch (i) { - default: - Usage(); - /* NOTREACHED */ - break; - case 'D': - Debug++; - break; -#ifdef FROMSTDIN - case 'i': - FromStdin = true; - break; -#endif - case 't': - ConnectTimeout = atoi(optarg); - break; - case 'T': - TotalTimeout = atoi(optarg); - break; - case 'v': - STATprint = true; - break; - } - ac -= optind; - av += optind; - - /* Parse arguments; host and filename. */ - if (ac < 2) - Usage(); - REMhost = av[0]; - ac--; - av++; - - /* Open a connection to the remote server. */ - if (ConnectTimeout) { - GotAlarm = false; - old = xsignal(SIGALRM, CATCHalarm); - JMPyes = true; - if (setjmp(JMPwhere)) - die("cannot connect to %s: timed out", REMhost); - alarm(ConnectTimeout); - } - if (NNTPconnect(REMhost, NNTP_PORT, &From, &To, buff) < 0 || GotAlarm) { - i = errno; - warn("cannot connect to %s: %s", REMhost, - buff[0] ? REMclean(buff): strerror(errno)); - if (GotAlarm) - syslog(L_NOTICE, CANT_CONNECT, REMhost, "timeout"); - else - syslog(L_NOTICE, CANT_CONNECT, REMhost, - buff[0] ? REMclean(buff) : strerror(i)); - exit(1); - } - - if (Debug) - fprintf(stderr, "< %s\n", REMclean(buff)); - if (NNTPsendpassword(REMhost, From, To) < 0 || GotAlarm) { - i = errno; - syswarn("cannot authenticate with %s", REMhost); - syslog(L_ERROR, CANT_AUTHENTICATE, - REMhost, GotAlarm ? "timeout" : strerror(i)); - /* Don't send quit; we want the remote to print a message. */ - exit(1); - } - if (ConnectTimeout) { - alarm(0); - xsignal(SIGALRM, old); - JMPyes = false; - } - - /* We no longer need standard I/O. */ - FromServer = fileno(From); - ToServer = fileno(To); - -#if defined(SOL_SOCKET) && defined(SO_SNDBUF) && defined(SO_RCVBUF) - i = 24 * 1024; - if (setsockopt(ToServer, SOL_SOCKET, SO_SNDBUF, (char *)&i, sizeof i) < 0) - perror("cant setsockopt(SNDBUF)"); - if (setsockopt(FromServer, SOL_SOCKET, SO_RCVBUF, (char *)&i, sizeof i) < 0) - perror("cant setsockopt(RCVBUF)"); -#endif /* defined(SOL_SOCKET) && defined(SO_SNDBUF) && defined(SO_RCVBUF) */ - - GotInterrupt = false; - GotAlarm = false; - - /* Set up signal handlers. */ - xsignal(SIGHUP, CATCHinterrupt); - xsignal(SIGINT, CATCHinterrupt); - xsignal(SIGTERM, CATCHinterrupt); - xsignal(SIGPIPE, SIG_IGN); - if (TotalTimeout) { - xsignal(SIGALRM, CATCHalarm); - alarm(TotalTimeout); - } - - /* Start timing. */ - STATbegin = TMRnow_double(); - - /* main loop over all specified files */ - for (XBATCHname = *av; ac && (XBATCHname = *av); av++, ac--) { - - if (Debug) fprintf(stderr, "will work on %s\n", XBATCHname); - - if (GotAlarm) { - warn("timed out"); - ExitWithStats(1); - } - if (GotInterrupt) Interrupted(); - - if ((fd = open(XBATCHname, O_RDONLY, 0)) < 0) { - syswarn("cannot open %s, skipping", XBATCHname); - continue; - } - - if (fstat(fd, &statbuf)) { - syswarn("cannot stat %s, skipping", XBATCHname); - close(i); - continue; - } - - XBATCHsize = statbuf.st_size; - if (XBATCHsize == 0) { - warn("batch file %s is zero length, skipping", XBATCHname); - close(i); - unlink(XBATCHname); - continue; - } else if (XBATCHsize > XBATCHbuffersize) { - XBATCHbuffersize = XBATCHsize; - if (XBATCHbuffer) free(XBATCHbuffer); - XBATCHbuffer = xmalloc(XBATCHsize); - } - - err = 0; /* stupid compiler */ - for (i = XBATCHsize, p = XBATCHbuffer; i; i -= err, p+= err) { - err = read(fd, p, i); - if (err < 0) { - syswarn("error reading %s, skipping", XBATCHname); - break; - } else if (0 == err) { - syswarn("unexpected EOF reading %s, truncated", XBATCHname); - XBATCHsize = p - XBATCHbuffer; - break; - } - } - close(fd); - if (err < 0) - continue; - - if (GotInterrupt) Interrupted(); - - /* Offer the xbatch. */ - snprintf(buff, sizeof(buff), "xbatch %d", XBATCHsize); - if (!REMwrite(ToServer, buff)) { - syswarn("cannot offer xbatch to %s", REMhost); - ExitWithStats(1); - } - STAToffered++; - if (GotInterrupt) Interrupted(); - - /* Does he want it? */ - if (!REMread(buff, (int)sizeof buff)) { - syswarn("no reply to XBATCH %d from %s", XBATCHsize, REMhost); - ExitWithStats(1); - } - if (GotInterrupt) Interrupted(); - - /* Parse the reply. */ - switch (atoi(buff)) { - default: - warn("unknown reply to %s -- %s", XBATCHname, buff); - ExitWithStats(1); - /* NOTREACHED */ - break; - case NNTP_RESENDIT_VAL: - case NNTP_GOODBYE_VAL: - /* Most likely out of space -- no point in continuing. */ - syslog(L_NOTICE, XBATCH_FAIL, REMhost, buff); - ExitWithStats(1); - /* NOTREACHED */ - case NNTP_CONT_XBATCH_VAL: - if (!REMsendxbatch(ToServer, XBATCHbuffer, XBATCHsize)) - ExitWithStats(1); - /* NOTREACHED */ - break; - case NNTP_SYNTAX_VAL: - case NNTP_BAD_COMMAND_VAL: - warn("server %s seems not to understand XBATCH: %s", REMhost, buff); - syslog(L_FATAL, XBATCH_FAIL, REMhost, buff); - break; - } - } - ExitWithStats(0); - /* NOTREACHED */ - return 0; -} diff --git a/backends/innxmit.c b/backends/innxmit.c deleted file mode 100644 index 475ce63..0000000 --- a/backends/innxmit.c +++ /dev/null @@ -1,1457 +0,0 @@ -/* $Id: innxmit.c 6716 2004-05-16 20:26:56Z rra $ -** -** Transmit articles to remote site. -** Modified for NNTP streaming: 1996-01-03 Jerry Aguirre -*/ - -#include "config.h" -#include "clibrary.h" -#include "portable/socket.h" -#include "portable/time.h" -#include -#include -#include -#include -#include -#include -#include -#include - -/* Needed on AIX 4.1 to get fd_set and friends. */ -#ifdef HAVE_SYS_SELECT_H -# include -#endif - -#include "inn/history.h" -#include "inn/innconf.h" -#include "inn/messages.h" -#include "inn/qio.h" -#include "inn/timer.h" -#include "inn/wire.h" -#include "libinn.h" -#include "nntp.h" -#include "paths.h" -#include "storage.h" - -#define OUTPUT_BUFFER_SIZE (16 * 1024) - -/* Streaming extensions to NNTP. This extension removes the lock-step -** limitation of conventional NNTP. Article transfer is several times -** faster. Negotiated and falls back to old mode if receiver refuses. -*/ - -/* max number of articles that can be streamed ahead */ -#define STNBUF 32 - -/* Send "takethis" without "check" if this many articles were -** accepted in a row. -*/ -#define STNC 16 - -/* typical number of articles to stream */ -/* must be able to fopen this many articles */ -#define STNBUFL (STNBUF/2) - -/* number of retries before requeueing to disk */ -#define STNRETRY 5 - -struct stbufs { /* for each article we are procesing */ - char *st_fname; /* file name */ - char *st_id; /* message ID */ - int st_retry; /* retry count */ - int st_age; /* age count */ - ARTHANDLE *art; /* arthandle to read article contents */ - int st_hash; /* hash value to speed searches */ - long st_size; /* article size */ -}; -static struct stbufs stbuf[STNBUF]; /* we keep track of this many articles */ -static int stnq; /* current number of active entries in stbuf */ -static long stnofail; /* Count of consecutive successful sends */ - -static int TryStream = true; /* Should attempt stream negotation? */ -static int CanStream = false; /* Result of stream negotation */ -static int DoCheck = true; /* Should check before takethis? */ -static char modestream[] = "mode stream"; -static char modeheadfeed[] = "mode headfeed"; -static long retries = 0; -static int logRejects = false ; /* syslog the 437 responses. */ - - - -/* -** Syslog formats - collected together so they remain consistent -*/ -static char STAT1[] = - "%s stats offered %lu accepted %lu refused %lu rejected %lu missing %lu accsize %.0f rejsize %.0f"; -static char STAT2[] = "%s times user %.3f system %.3f elapsed %.3f"; -static char GOT_BADCOMMAND[] = "%s rejected %s %s"; -static char REJECTED[] = "%s rejected %s (%s) %s"; -static char REJ_STREAM[] = "%s rejected (%s) %s"; -static char CANT_CONNECT[] = "%s connect failed %s"; -static char CANT_AUTHENTICATE[] = "%s authenticate failed %s"; -static char IHAVE_FAIL[] = "%s ihave failed %s"; - -static char CANT_FINDIT[] = "%s can't find %s"; -static char CANT_PARSEIT[] = "%s can't parse ID %s"; -static char UNEXPECTED[] = "%s unexpected response code %s"; - -/* -** Global variables. -*/ -static bool AlwaysRewrite; -static bool Debug; -static bool DoRequeue = true; -static bool Purging; -static bool STATprint; -static bool HeadersFeed; -static char *BATCHname; -static char *BATCHtemp; -static char *REMhost; -static double STATbegin; -static double STATend; -static FILE *BATCHfp; -static int FromServer; -static int ToServer; -static struct history *History; -static QIOSTATE *BATCHqp; -static sig_atomic_t GotAlarm; -static sig_atomic_t GotInterrupt; -static sig_atomic_t JMPyes; -static jmp_buf JMPwhere; -static char *REMbuffer; -static char *REMbuffptr; -static char *REMbuffend; -static unsigned long STATaccepted; -static unsigned long STAToffered; -static unsigned long STATrefused; -static unsigned long STATrejected; -static unsigned long STATmissing; -static double STATacceptedsize; -static double STATrejectedsize; - - -/* Prototypes. */ -static ARTHANDLE *article_open(const char *path, const char *id); -static void article_free(ARTHANDLE *); - - -/* -** Return true if the history file has the article expired. -*/ -static bool -Expired(char *MessageID) { - return !HISlookup(History, MessageID, NULL, NULL, NULL, NULL); -} - - -/* -** Flush and reset the site's output buffer. Return false on error. -*/ -static bool -REMflush(void) -{ - int i; - - if (REMbuffptr == REMbuffer) return true; /* nothing buffered */ - i = xwrite(ToServer, REMbuffer, (int)(REMbuffptr - REMbuffer)); - REMbuffptr = REMbuffer; - return i < 0 ? false : true; -} - -/* -** Return index to entry matching this message ID. Else return -1. -** The hash is to speed up the search. -** the protocol. -*/ -static int -stindex(char *MessageID, int hash) { - int i; - - for (i = 0; i < STNBUF; i++) { /* linear search for ID */ - if ((stbuf[i].st_id) && (stbuf[i].st_id[0]) - && (stbuf[i].st_hash == hash)) { - int n; - - if (strcasecmp(MessageID, stbuf[i].st_id)) continue; - - /* left of '@' is case sensitive */ - for (n = 0; (MessageID[n] != '@') && (MessageID[n] != '\0'); n++) ; - if (strncmp(MessageID, stbuf[i].st_id, n)) continue; - else break; /* found a match */ - } - } - if (i >= STNBUF) i = -1; /* no match found ? */ - return (i); -} - -/* stidhash(): calculate a hash value for message IDs to speed comparisons */ -static int -stidhash(char *MessageID) { - char *p; - int hash; - - hash = 0; - for (p = MessageID + 1; *p && (*p != '>'); p++) { - hash <<= 1; - if (isascii((int)*p) && isupper((int)*p)) { - hash += tolower(*p); - } else { - hash += *p; - } - } - return hash; -} - -/* stalloc(): save path, ID, and qp into one of the streaming mode entries */ -static int -stalloc(char *Article, char *MessageID, ARTHANDLE *art, int hash) { - int i; - - for (i = 0; i < STNBUF; i++) { - if ((!stbuf[i].st_fname) || (stbuf[i].st_fname[0] == '\0')) break; - } - if (i >= STNBUF) { /* stnq says not full but can not find unused */ - syslog(L_ERROR, "stalloc: Internal error"); - return (-1); - } - if ((int)strlen(Article) >= SPOOLNAMEBUFF) { - syslog(L_ERROR, "stalloc: filename longer than %d", SPOOLNAMEBUFF); - return (-1); - } - /* allocate buffers on first use. - ** If filename ever is longer than SPOOLNAMEBUFF then code will abort. - ** If ID is ever longer than NNTP_STRLEN then other code would break. - */ - if (!stbuf[i].st_fname) - stbuf[i].st_fname = xmalloc(SPOOLNAMEBUFF); - if (!stbuf[i].st_id) - stbuf[i].st_id = xmalloc(NNTP_STRLEN); - strlcpy(stbuf[i].st_fname, Article, SPOOLNAMEBUFF); - strlcpy(stbuf[i].st_id, MessageID, NNTP_STRLEN); - stbuf[i].art = art; - stbuf[i].st_hash = hash; - stbuf[i].st_retry = 0; - stbuf[i].st_age = 0; - stnq++; - return i; -} - -/* strel(): release for reuse one of the streaming mode entries */ -static void -strel(int i) { - if (stbuf[i].art) { - article_free(stbuf[i].art); - stbuf[i].art = NULL; - } - if (stbuf[i].st_id) stbuf[i].st_id[0] = '\0'; - if (stbuf[i].st_fname) stbuf[i].st_fname[0] = '\0'; - stnq--; -} - -/* -** Send a line to the server, adding the dot escape and \r\n. -*/ -static bool -REMwrite(char *p, int i, bool escdot) { - int size; - - /* Buffer too full? */ - if (REMbuffend - REMbuffptr < i + 3) { - if (!REMflush()) - return false; - if (REMbuffend - REMbuffer < i + 3) { - /* Line too long -- grow buffer. */ - size = i * 2; - REMbuffer = xrealloc(REMbuffer, size); - REMbuffend = &REMbuffer[size]; - } - } - - /* Dot escape, text of the line, line terminator. */ - if (escdot && (*p == '.')) - *REMbuffptr++ = '.'; - memcpy(REMbuffptr, p, i); - REMbuffptr += i; - *REMbuffptr++ = '\r'; - *REMbuffptr++ = '\n'; - - return true; -} - - -/* -** Print transfer statistics, clean up, and exit. -*/ -static void -ExitWithStats(int x) -{ - static char QUIT[] = "quit"; - double usertime; - double systime; - - if (!Purging) { - REMwrite(QUIT, strlen(QUIT), false); - REMflush(); - } - STATend = TMRnow_double(); - if (GetResourceUsage(&usertime, &systime) < 0) { - usertime = 0; - systime = 0; - } - - if (STATprint) { - printf(STAT1, REMhost, STAToffered, STATaccepted, STATrefused, - STATrejected, STATmissing, STATacceptedsize, STATrejectedsize); - printf("\n"); - printf(STAT2, REMhost, usertime, systime, STATend - STATbegin); - printf("\n"); - } - - syslog(L_NOTICE, STAT1, REMhost, STAToffered, STATaccepted, STATrefused, - STATrejected, STATmissing, STATacceptedsize, STATrejectedsize); - syslog(L_NOTICE, STAT2, REMhost, usertime, systime, STATend - STATbegin); - if (retries) - syslog(L_NOTICE, "%s %lu Streaming retries", REMhost, retries); - - if (BATCHfp != NULL && unlink(BATCHtemp) < 0 && errno != ENOENT) - syswarn("cannot remove %s", BATCHtemp); - sleep(1); - SMshutdown(); - HISclose(History); - exit(x); - /* NOTREACHED */ -} - - -/* -** Close the batchfile and the temporary file, and rename the temporary -** to be the batchfile. -*/ -static void -CloseAndRename(void) -{ - /* Close the files, rename the temporary. */ - if (BATCHqp) { - QIOclose(BATCHqp); - BATCHqp = NULL; - } - if (ferror(BATCHfp) - || fflush(BATCHfp) == EOF - || fclose(BATCHfp) == EOF) { - unlink(BATCHtemp); - syswarn("cannot close %s", BATCHtemp); - ExitWithStats(1); - } - if (rename(BATCHtemp, BATCHname) < 0) { - syswarn("cannot rename %s", BATCHtemp); - ExitWithStats(1); - } -} - - -/* -** Requeue an article, opening the temp file if we have to. If we get -** a file write error, exit so that the original input is left alone. -*/ -static void -Requeue(const char *Article, const char *MessageID) -{ - int fd; - - /* Temp file already open? */ - if (BATCHfp == NULL) { - fd = mkstemp(BATCHtemp); - if (fd < 0) { - syswarn("cannot create a temporary file"); - ExitWithStats(1); - } - BATCHfp = fdopen(fd, "w"); - if (BATCHfp == NULL) { - syswarn("cannot open %s", BATCHtemp); - ExitWithStats(1); - } - } - - /* Called only to get the file open? */ - if (Article == NULL) - return; - - if (MessageID != NULL) - fprintf(BATCHfp, "%s %s\n", Article, MessageID); - else - fprintf(BATCHfp, "%s\n", Article); - if (fflush(BATCHfp) == EOF || ferror(BATCHfp)) { - syswarn("cannot requeue %s", Article); - ExitWithStats(1); - } -} - - -/* -** Requeue an article then copy the rest of the batch file out. -*/ -static void -RequeueRestAndExit(char *Article, char *MessageID) { - char *p; - - if (!AlwaysRewrite - && STATaccepted == 0 && STATrejected == 0 && STATrefused == 0 - && STATmissing == 0) { - warn("nothing sent -- leaving batchfile alone"); - ExitWithStats(1); - } - - warn("rewriting batch file and exiting"); - if (CanStream) { /* streaming mode has a buffer of articles */ - int i; - - for (i = 0; i < STNBUF; i++) { /* requeue unacknowledged articles */ - if ((stbuf[i].st_fname) && (stbuf[i].st_fname[0] != '\0')) { - if (Debug) - fprintf(stderr, "stbuf[%d]= %s, %s\n", - i, stbuf[i].st_fname, stbuf[i].st_id); - Requeue(stbuf[i].st_fname, stbuf[i].st_id); - if (Article == stbuf[i].st_fname) Article = NULL; - strel(i); /* release entry */ - } - } - } - Requeue(Article, MessageID); - - for ( ; BATCHqp; ) { - if ((p = QIOread(BATCHqp)) == NULL) { - if (QIOtoolong(BATCHqp)) { - warn("skipping long line in %s", BATCHname); - QIOread(BATCHqp); - continue; - } - if (QIOerror(BATCHqp)) { - syswarn("cannot read %s", BATCHname); - ExitWithStats(1); - } - - /* Normal EOF. */ - break; - } - - if (fprintf(BATCHfp, "%s\n", p) == EOF - || ferror(BATCHfp)) { - syswarn("cannot requeue %s", p); - ExitWithStats(1); - } - } - - CloseAndRename(); - ExitWithStats(1); -} - - -/* -** Clean up the NNTP escapes from a line. -*/ -static char * -REMclean(char *buff) { - char *p; - - if ((p = strchr(buff, '\r')) != NULL) - *p = '\0'; - if ((p = strchr(buff, '\n')) != NULL) - *p = '\0'; - - /* The dot-escape is only in text, not command responses. */ - return buff; -} - - -/* -** Read a line of input, with timeout. Also handle \r\n-->\n mapping -** and the dot escape. Return true if okay, *or we got interrupted.* -*/ -static bool -REMread(char *start, int size) { - static int count; - static char buffer[BUFSIZ]; - static char *bp; - char *p; - char *q; - char *end; - struct timeval t; - fd_set rmask; - int i; - char c; - - if (!REMflush()) - return false; - - for (p = start, end = &start[size - 1]; ; ) { - if (count == 0) { - /* Fill the buffer. */ - Again: - FD_ZERO(&rmask); - FD_SET(FromServer, &rmask); - t.tv_sec = 10 * 60; - t.tv_usec = 0; - i = select(FromServer + 1, &rmask, NULL, NULL, &t); - if (GotInterrupt) - return true; - if (i < 0) { - if (errno == EINTR) - goto Again; - return false; - } - if (i == 0 || !FD_ISSET(FromServer, &rmask)) - return false; - count = read(FromServer, buffer, sizeof buffer); - if (GotInterrupt) - return true; - if (count <= 0) - return false; - bp = buffer; - } - - /* Process next character. */ - count--; - c = *bp++; - if (c == '\n') - break; - if (p < end) - *p++ = c; - } - - /* We know we got \n; if previous char was \r, turn it into \n. */ - if (p > start && p < end && p[-1] == '\r') - p[-1] = '\n'; - *p = '\0'; - - /* Handle the dot escape. */ - if (*p == '.') { - if (p[1] == '\n' && p[2] == '\0') - /* EOF. */ - return false; - for (q = &start[1]; (*p++ = *q++) != '\0'; ) - continue; - } - return true; -} - - -/* -** Handle the interrupt. -*/ -static void -Interrupted(char *Article, char *MessageID) { - warn("interrupted"); - RequeueRestAndExit(Article, MessageID); -} - - -/* -** Returns the length of the headers. -*/ -static int -HeadersLen(ARTHANDLE *art, int *iscmsg) { - const char *p; - char lastchar = -1; - - /* from nnrpd/article.c ARTsendmmap() */ - for (p = art->data; p < (art->data + art->len); p++) { - if (*p == '\r') - continue; - if (*p == '\n') { - if (lastchar == '\n') { - if (*(p-1) == '\r') - p--; - break; - } - if (*(p + 1) == 'C' && strncasecmp(p + 1, "Control: ", 9) == 0) - *iscmsg = 1; - } - lastchar = *p; - } - return (p - art->data); -} - - -/* -** Send a whole article to the server. -*/ -static bool -REMsendarticle(char *Article, char *MessageID, ARTHANDLE *art) { - char buff[NNTP_STRLEN]; - - if (!REMflush()) - return false; - if (HeadersFeed) { - struct iovec vec[3]; - char buf[20]; - int iscmsg = 0; - int len = HeadersLen(art, &iscmsg); - - vec[0].iov_base = (char *) art->data; - vec[0].iov_len = len; - /* Add 14 bytes, which maybe will be the length of the Bytes header */ - snprintf(buf, sizeof(buf), "Bytes: %lu\r\n", - (unsigned long) art->len + 14); - vec[1].iov_base = buf; - vec[1].iov_len = strlen(buf); - if (iscmsg) { - vec[2].iov_base = (char *) art->data + len; - vec[2].iov_len = art->len - len; - } else { - vec[2].iov_base = (char *) "\r\n.\r\n"; - vec[2].iov_len = 5; - } - if (xwritev(ToServer, vec, 3) < 0) - return false; - } else - if (xwrite(ToServer, art->data, art->len) < 0) - return false; - if (GotInterrupt) - Interrupted(Article, MessageID); - if (Debug) { - fprintf(stderr, "> [ article %lu ]\n", (unsigned long) art->len); - fprintf(stderr, "> .\n"); - } - - if (CanStream) return true; /* streaming mode does not wait for ACK */ - - /* What did the remote site say? */ - if (!REMread(buff, (int)sizeof buff)) { - syswarn("no reply after sending %s", Article); - return false; - } - if (GotInterrupt) - Interrupted(Article, MessageID); - if (Debug) - fprintf(stderr, "< %s", buff); - - /* Parse the reply. */ - switch (atoi(buff)) { - default: - warn("unknown reply after %s -- %s", Article, buff); - if (DoRequeue) - Requeue(Article, MessageID); - break; - case NNTP_BAD_COMMAND_VAL: - case NNTP_SYNTAX_VAL: - case NNTP_ACCESS_VAL: - /* The receiving server is likely confused...no point in continuing */ - syslog(L_FATAL, GOT_BADCOMMAND, REMhost, MessageID, REMclean(buff)); - RequeueRestAndExit(Article, MessageID); - /* NOTREACHED */ - case NNTP_RESENDIT_VAL: - case NNTP_GOODBYE_VAL: - Requeue(Article, MessageID); - break; - case NNTP_TOOKIT_VAL: - STATaccepted++; - STATacceptedsize += (double)art->len; - break; - case NNTP_REJECTIT_VAL: - if (logRejects) - syslog(L_NOTICE, REJECTED, REMhost, - MessageID, Article, REMclean(buff)); - STATrejected++; - STATrejectedsize += (double)art->len; - break; - } - - /* Article sent, or we requeued it. */ - return true; -} - - -/* -** Get the Message-ID header from an open article. -*/ -static char * -GetMessageID(ARTHANDLE *art) { - static char *buff; - static int buffsize = 0; - const char *p, *q; - - p = wire_findheader(art->data, art->len, "Message-ID"); - if (p == NULL) - return NULL; - for (q = p; q < art->data + art->len; q++) { - if (*q == '\r' || *q == '\n') - break; - } - if (q == art->data + art->len) - return NULL; - if (buffsize < q - p) { - if (buffsize == 0) - buff = xmalloc(q - p + 1); - else - buff = xrealloc(buff, q - p + 1); - buffsize = q - p; - } - memcpy(buff, p, q - p); - buff[q - p] = '\0'; - return buff; -} - - -/* -** Mark that we got interrupted. -*/ -static RETSIGTYPE -CATCHinterrupt(int s) { - GotInterrupt = true; - - /* Let two interrupts kill us. */ - xsignal(s, SIG_DFL); -} - - -/* -** Mark that the alarm went off. -*/ -static RETSIGTYPE -CATCHalarm(int s UNUSED) -{ - GotAlarm = true; - if (JMPyes) - longjmp(JMPwhere, 1); -} - -/* check articles in streaming NNTP mode -** return true on failure. -*/ -static bool -check(int i) { - char buff[NNTP_STRLEN]; - - /* send "check " to the other system */ - snprintf(buff, sizeof(buff), "check %s", stbuf[i].st_id); - if (!REMwrite(buff, (int)strlen(buff), false)) { - syswarn("cannot check article"); - return true; - } - STAToffered++; - if (Debug) { - if (stbuf[i].st_retry) - fprintf(stderr, "> %s (retry %d)\n", buff, stbuf[i].st_retry); - else - fprintf(stderr, "> %s\n", buff); - } - if (GotInterrupt) - Interrupted(stbuf[i].st_fname, stbuf[i].st_id); - - /* That all. Response is checked later by strlisten() */ - return false; -} - -/* Send article in "takethis streaming NNTP mode. -** return true on failure. -*/ -static bool -takethis(int i) { - char buff[NNTP_STRLEN]; - - if (!stbuf[i].art) { - warn("internal error: null article for %s in takethis", - stbuf[i].st_fname); - return true; - } - /* send "takethis " to the other system */ - snprintf(buff, sizeof(buff), "takethis %s", stbuf[i].st_id); - if (!REMwrite(buff, (int)strlen(buff), false)) { - syswarn("cannot send takethis"); - return true; - } - if (Debug) - fprintf(stderr, "> %s\n", buff); - if (GotInterrupt) - Interrupted((char *)0, (char *)0); - if (!REMsendarticle(stbuf[i].st_fname, stbuf[i].st_id, stbuf[i].art)) - return true; - stbuf[i].st_size = stbuf[i].art->len; - article_free(stbuf[i].art); /* should not need file again */ - stbuf[i].art = 0; /* so close to free descriptor */ - stbuf[i].st_age = 0; - /* That all. Response is checked later by strlisten() */ - return false; -} - - -/* listen for responses. Process acknowledgments to remove items from -** the queue. Also sends the articles on request. Returns true on error. -** return true on failure. -*/ -static bool -strlisten(void) -{ - int resp; - int i; - char *id, *p; - char buff[NNTP_STRLEN]; - int hash; - - while(true) { - if (!REMread(buff, (int)sizeof buff)) { - syswarn("no reply to check"); - return true; - } - if (GotInterrupt) - Interrupted((char *)0, (char *)0); - if (Debug) - fprintf(stderr, "< %s", buff); - - /* Parse the reply. */ - resp = atoi(buff); - /* Skip the 1XX informational messages */ - if ((resp >= 100) && (resp < 200)) continue; - switch (resp) { /* first time is to verify it */ - case NNTP_ERR_GOTID_VAL: - case NNTP_OK_SENDID_VAL: - case NNTP_OK_RECID_VAL: - case NNTP_ERR_FAILID_VAL: - case NNTP_RESENDID_VAL: - if ((id = strchr(buff, '<')) != NULL) { - p = strchr(id, '>'); - if (p) *(p+1) = '\0'; - hash = stidhash(id); - i = stindex(id, hash); /* find table entry */ - if (i < 0) { /* should not happen */ - syslog(L_NOTICE, CANT_FINDIT, REMhost, REMclean(buff)); - return (true); /* can't find it! */ - } - } else { - syslog(L_NOTICE, CANT_PARSEIT, REMhost, REMclean(buff)); - return (true); - } - break; - case NNTP_GOODBYE_VAL: - /* Most likely out of space -- no point in continuing. */ - syslog(L_NOTICE, IHAVE_FAIL, REMhost, REMclean(buff)); - return true; - /* NOTREACHED */ - default: - syslog(L_NOTICE, UNEXPECTED, REMhost, REMclean(buff)); - if (Debug) - fprintf(stderr, "Unknown reply \"%s\"", - buff); - return (true); - } - switch (resp) { /* now we take some action */ - case NNTP_RESENDID_VAL: /* remote wants it later */ - /* try again now because time has passed */ - if (stbuf[i].st_retry < STNRETRY) { - if (check(i)) return true; - stbuf[i].st_retry++; - stbuf[i].st_age = 0; - } else { /* requeue to disk for later */ - Requeue(stbuf[i].st_fname, stbuf[i].st_id); - strel(i); /* release entry */ - } - break; - case NNTP_ERR_GOTID_VAL: /* remote doesn't want it */ - strel(i); /* release entry */ - STATrefused++; - stnofail = 0; - break; - - case NNTP_OK_SENDID_VAL: /* remote wants article */ - if (takethis(i)) return true; - stnofail++; - break; - - case NNTP_OK_RECID_VAL: /* remote received it OK */ - STATacceptedsize += (double) stbuf[i].st_size; - strel(i); /* release entry */ - STATaccepted++; - break; - - case NNTP_ERR_FAILID_VAL: - STATrejectedsize += (double) stbuf[i].st_size; - if (logRejects) - syslog(L_NOTICE, REJ_STREAM, REMhost, - stbuf[i].st_fname, REMclean(buff)); -/* XXXXX Caution THERE BE DRAGONS, I don't think this logs properly - The message ID is returned in the peer response... so this is redundant - stbuf[i].st_id, stbuf[i].st_fname, REMclean(buff)); */ - strel(i); /* release entry */ - STATrejected++; - stnofail = 0; - break; - } - break; - } - return (false); -} - -/* -** Print a usage message and exit. -*/ -static void -Usage(void) -{ - die("Usage: innxmit [-acdHlprs] [-t#] [-T#] host file"); -} - - -/* -** Open an article. If the argument is a token, retrieve the article via -** the storage API. Otherwise, open the file and fake up an ARTHANDLE for -** it. Only fill in those fields that we'll need. Articles not retrieved -** via the storage API will have a type of TOKEN_EMPTY. -*/ -static ARTHANDLE * -article_open(const char *path, const char *id) -{ - TOKEN token; - ARTHANDLE *article; - int fd, length; - struct stat st; - char *p; - - if (IsToken(path)) { - token = TextToToken(path); - article = SMretrieve(token, RETR_ALL); - if (article == NULL) { - if (SMerrno == SMERR_NOENT || SMerrno == SMERR_UNINIT) - STATmissing++; - else { - warn("requeue %s: %s", path, SMerrorstr); - Requeue(path, id); - } - } - return article; - } else { - char *data; - fd = open(path, O_RDONLY); - if (fd < 0) - return NULL; - if (fstat(fd, &st) < 0) { - syswarn("requeue %s", path); - Requeue(path, id); - return NULL; - } - article = xmalloc(sizeof(ARTHANDLE)); - article->type = TOKEN_EMPTY; - article->len = st.st_size; - data = xmalloc(article->len); - if (xread(fd, data, article->len) < 0) { - syswarn("requeue %s", path); - free(data); - free(article); - close(fd); - Requeue(path, id); - return NULL; - } - close(fd); - p = memchr(data, '\n', article->len); - if (p == NULL || p == data) { - warn("requeue %s: cannot find headers", path); - free(data); - free(article); - Requeue(path, id); - return NULL; - } - if (p[-1] != '\r') { - p = ToWireFmt(data, article->len, (size_t *)&length); - free(data); - data = p; - article->len = length; - } - article->data = data; - return article; - } -} - - -/* -** Free an article, using the type field to determine whether to free it -** via the storage API. -*/ -static void -article_free(ARTHANDLE *article) -{ - if (article->type == TOKEN_EMPTY) { - free((char *)article->data); - free(article); - } else - SMfreearticle(article); -} - - -int main(int ac, char *av[]) { - static char SKIPPING[] = "Skipping \"%s\" --%s?\n"; - int i; - char *p; - ARTHANDLE *art; - FILE *From; - FILE *To; - char buff[8192+128]; - char *Article; - char *MessageID; - RETSIGTYPE (*old)(int) = NULL; - unsigned int ConnectTimeout; - unsigned int TotalTimeout; - int port = NNTP_PORT; - bool val; - char *path; - - openlog("innxmit", L_OPENLOG_FLAGS | LOG_PID, LOG_INN_PROG); - message_program_name = "innxmit"; - - /* Set defaults. */ - if (!innconf_read(NULL)) - exit(1); - - ConnectTimeout = 0; - TotalTimeout = 0; - - umask(NEWSUMASK); - - /* Parse JCL. */ - while ((i = getopt(ac, av, "lacdHprst:T:vP:")) != EOF) - switch (i) { - default: - Usage(); - /* NOTREACHED */ - case 'P': - port = atoi(optarg); - break; - case 'a': - AlwaysRewrite = true; - break; - case 'c': - DoCheck = false; - break; - case 'd': - Debug = true; - break; - case 'H': - HeadersFeed = true; - break; - case 'l': - logRejects = true ; - break ; - case 'p': - AlwaysRewrite = true; - Purging = true; - break; - case 'r': - DoRequeue = false; - break; - case 's': - TryStream = false; - break; - case 't': - ConnectTimeout = atoi(optarg); - break; - case 'T': - TotalTimeout = atoi(optarg); - break; - case 'v': - STATprint = true; - break; - } - ac -= optind; - av += optind; - - /* Parse arguments; host and filename. */ - if (ac != 2) - Usage(); - REMhost = av[0]; - BATCHname = av[1]; - - if (chdir(innconf->patharticles) < 0) - sysdie("cannot cd to %s", innconf->patharticles); - - val = true; - if (!SMsetup(SM_PREOPEN,(void *)&val)) - die("cannot set up the storage manager"); - if (!SMinit()) - die("cannot initialize the storage manager: %s", SMerrorstr); - - /* Open the batch file and lock others out. */ - if (BATCHname[0] != '/') { - BATCHname = concatpath(innconf->pathoutgoing, av[1]); - } - if (((i = open(BATCHname, O_RDWR)) < 0) || ((BATCHqp = QIOfdopen(i)) == NULL)) { - syswarn("cannot open %s", BATCHname); - SMshutdown(); - exit(1); - } - if (!inn_lock_file(QIOfileno(BATCHqp), INN_LOCK_WRITE, true)) { -#if defined(EWOULDBLOCK) - if (errno == EWOULDBLOCK) { - SMshutdown(); - exit(0); - } -#endif /* defined(EWOULDBLOCK) */ - syswarn("cannot lock %s", BATCHname); - SMshutdown(); - exit(1); - } - - /* Get a temporary name in the same directory as the batch file. */ - p = strrchr(BATCHname, '/'); - *p = '\0'; - BATCHtemp = concatpath(BATCHname, "bchXXXXXX"); - *p = '/'; - - /* Set up buffer used by REMwrite. */ - REMbuffer = xmalloc(OUTPUT_BUFFER_SIZE); - REMbuffend = &REMbuffer[OUTPUT_BUFFER_SIZE]; - REMbuffptr = REMbuffer; - - /* Start timing. */ - STATbegin = TMRnow_double(); - - if (!Purging) { - /* Open a connection to the remote server. */ - if (ConnectTimeout) { - GotAlarm = false; - old = xsignal(SIGALRM, CATCHalarm); - if (setjmp(JMPwhere)) { - warn("cannot connect to %s: timed out", REMhost); - SMshutdown(); - exit(1); - } - JMPyes = true; - alarm(ConnectTimeout); - } - if (NNTPconnect(REMhost, port, &From, &To, buff) < 0 || GotAlarm) { - i = errno; - warn("cannot connect to %s: %s", REMhost, - buff[0] ? REMclean(buff) : strerror(errno)); - if (GotAlarm) - syslog(L_NOTICE, CANT_CONNECT, REMhost, "timeout"); - else - syslog(L_NOTICE, CANT_CONNECT, REMhost, - buff[0] ? REMclean(buff) : strerror(i)); - SMshutdown(); - exit(1); - } - if (Debug) - fprintf(stderr, "< %s\n", REMclean(buff)); - if (NNTPsendpassword(REMhost, From, To) < 0 || GotAlarm) { - i = errno; - syswarn("cannot authenticate with %s", REMhost); - syslog(L_ERROR, CANT_AUTHENTICATE, - REMhost, GotAlarm ? "timeout" : strerror(i)); - /* Don't send quit; we want the remote to print a message. */ - SMshutdown(); - exit(1); - } - if (ConnectTimeout) { - alarm(0); - xsignal(SIGALRM, old); - JMPyes = false; - } - - /* We no longer need standard I/O. */ - FromServer = fileno(From); - ToServer = fileno(To); - - if (TryStream) { - if (!REMwrite(modestream, (int)strlen(modestream), false)) { - syswarn("cannot negotiate %s", modestream); - } - if (Debug) - fprintf(stderr, ">%s\n", modestream); - /* Does he understand mode stream? */ - if (!REMread(buff, (int)sizeof buff)) { - syswarn("no reply to %s", modestream); - } else { - if (Debug) - fprintf(stderr, "< %s", buff); - - /* Parse the reply. */ - switch (atoi(buff)) { - default: - warn("unknown reply to %s -- %s", modestream, buff); - CanStream = false; - break; - case NNTP_OK_STREAM_VAL: /* YES! */ - CanStream = true; - break; - case NNTP_AUTH_NEEDED_VAL: /* authentication refusal */ - case NNTP_BAD_COMMAND_VAL: /* normal refusal */ - CanStream = false; - break; - } - } - if (CanStream) { - for (i = 0; i < STNBUF; i++) { /* reset buffers */ - stbuf[i].st_fname = 0; - stbuf[i].st_id = 0; - stbuf[i].art = 0; - } - stnq = 0; - } - } - if (HeadersFeed) { - if (!REMwrite(modeheadfeed, strlen(modeheadfeed), false)) - syswarn("cannot negotiate %s", modeheadfeed); - if (Debug) - fprintf(stderr, ">%s\n", modeheadfeed); - if (!REMread(buff, sizeof buff)) { - syswarn("no reply to %s", modeheadfeed); - } else { - if (Debug) - fprintf(stderr, "< %s", buff); - - /* Parse the reply. */ - switch (atoi(buff)) { - case 250: /* YES! */ - break; - case NNTP_BAD_COMMAND_VAL: /* normal refusal */ - die("%s not allowed -- %s", modeheadfeed, buff); - default: - die("unknown reply to %s -- %s", modeheadfeed, buff); - } - } - } - } - - /* Set up signal handlers. */ - xsignal(SIGHUP, CATCHinterrupt); - xsignal(SIGINT, CATCHinterrupt); - xsignal(SIGTERM, CATCHinterrupt); - xsignal(SIGPIPE, SIG_IGN); - if (TotalTimeout) { - xsignal(SIGALRM, CATCHalarm); - alarm(TotalTimeout); - } - - path = concatpath(innconf->pathdb, _PATH_HISTORY); - History = HISopen(path, innconf->hismethod, HIS_RDONLY); - free(path); - - /* Main processing loop. */ - GotInterrupt = false; - GotAlarm = false; - for (Article = NULL, MessageID = NULL; ; ) { - if (GotAlarm) { - warn("timed out"); - /* Don't resend the current article. */ - RequeueRestAndExit((char *)NULL, (char *)NULL); - } - if (GotInterrupt) - Interrupted(Article, MessageID); - - if ((Article = QIOread(BATCHqp)) == NULL) { - if (QIOtoolong(BATCHqp)) { - warn("skipping long line in %s", BATCHname); - QIOread(BATCHqp); - continue; - } - if (QIOerror(BATCHqp)) { - syswarn("cannot read %s", BATCHname); - ExitWithStats(1); - } - - /* Normal EOF -- we're done. */ - QIOclose(BATCHqp); - BATCHqp = NULL; - break; - } - - /* Ignore blank lines. */ - if (*Article == '\0') - continue; - - /* Split the line into possibly two fields. */ - if (Article[0] == '/' - && Article[strlen(innconf->patharticles)] == '/' - && strncmp(Article, innconf->patharticles, strlen(innconf->patharticles)) == 0) - Article += strlen(innconf->patharticles) + 1; - if ((MessageID = strchr(Article, ' ')) != NULL) { - *MessageID++ = '\0'; - if (*MessageID != '<' - || (p = strrchr(MessageID, '>')) == NULL - || *++p != '\0') { - warn("ignoring line %s %s...", Article, MessageID); - continue; - } - } - - if (*Article == '\0') { - if (MessageID) - warn("empty file name for %s in %s", MessageID, BATCHname); - else - warn("empty file name, no message ID in %s", BATCHname); - /* We could do a history lookup. */ - continue; - } - - if (Purging && MessageID != NULL && !Expired(MessageID)) { - Requeue(Article, MessageID); - continue; - } - - /* Drop articles with a message ID longer than NNTP_MSGID_MAXLEN to - avoid overrunning buffers and throwing the server on the - receiving end a blow from behind. */ - if (MessageID != NULL && strlen(MessageID) > NNTP_MSGID_MAXLEN) { - warn("dropping article in %s: long message ID %s", BATCHname, - MessageID); - continue; - } - - art = article_open(Article, MessageID); - if (art == NULL) - continue; - - if (Purging) { - article_free(art); - Requeue(Article, MessageID); - continue; - } - - /* Get the Message-ID from the article if we need to. */ - if (MessageID == NULL) { - if ((MessageID = GetMessageID(art)) == NULL) { - warn(SKIPPING, Article, "no message ID"); - article_free(art); - continue; - } - } - if (GotInterrupt) - Interrupted(Article, MessageID); - - /* Offer the article. */ - if (CanStream) { - int lim; - int hash; - - hash = stidhash(MessageID); - if (stindex(MessageID, hash) >= 0) { /* skip duplicates in queue */ - if (Debug) - fprintf(stderr, "Skipping duplicate ID %s\n", - MessageID); - article_free(art); - continue; - } - /* This code tries to optimize by sending a burst of "check" - * commands before flushing the buffer. This should result - * in several being sent in one packet reducing the network - * overhead. - */ - if (DoCheck && (stnofail < STNC)) lim = STNBUF; - else lim = STNBUFL; - if (stnq >= lim) { /* need to empty a buffer */ - while (stnq >= STNBUFL) { /* or several */ - if (strlisten()) { - RequeueRestAndExit(Article, MessageID); - } - } - } - /* save new article in the buffer */ - i = stalloc(Article, MessageID, art, hash); - if (i < 0) { - article_free(art); - RequeueRestAndExit(Article, MessageID); - } - if (DoCheck && (stnofail < STNC)) { - if (check(i)) { - RequeueRestAndExit((char *)NULL, (char *)NULL); - } - } else { - STAToffered++ ; - if (takethis(i)) { - RequeueRestAndExit((char *)NULL, (char *)NULL); - } - } - /* check for need to resend any IDs */ - for (i = 0; i < STNBUF; i++) { - if ((stbuf[i].st_fname) && (stbuf[i].st_fname[0] != '\0')) { - if (stbuf[i].st_age++ > stnq) { - /* This should not happen but just in case ... */ - if (stbuf[i].st_retry < STNRETRY) { - if (check(i)) /* resend check */ - RequeueRestAndExit((char *)NULL, (char *)NULL); - retries++; - stbuf[i].st_retry++; - stbuf[i].st_age = 0; - } else { /* requeue to disk for later */ - Requeue(stbuf[i].st_fname, stbuf[i].st_id); - strel(i); /* release entry */ - } - } - } - } - continue; /* next article */ - } - snprintf(buff, sizeof(buff), "ihave %s", MessageID); - if (!REMwrite(buff, (int)strlen(buff), false)) { - syswarn("cannot offer article"); - article_free(art); - RequeueRestAndExit(Article, MessageID); - } - STAToffered++; - if (Debug) - fprintf(stderr, "> %s\n", buff); - if (GotInterrupt) - Interrupted(Article, MessageID); - - /* Does he want it? */ - if (!REMread(buff, (int)sizeof buff)) { - syswarn("no reply to ihave"); - article_free(art); - RequeueRestAndExit(Article, MessageID); - } - if (GotInterrupt) - Interrupted(Article, MessageID); - if (Debug) - fprintf(stderr, "< %s", buff); - - /* Parse the reply. */ - switch (atoi(buff)) { - default: - warn("unknown reply to %s -- %s", Article, buff); - if (DoRequeue) - Requeue(Article, MessageID); - break; - case NNTP_BAD_COMMAND_VAL: - case NNTP_SYNTAX_VAL: - case NNTP_ACCESS_VAL: - /* The receiving server is likely confused...no point in continuing */ - syslog(L_FATAL, GOT_BADCOMMAND, REMhost, MessageID, REMclean(buff)); - RequeueRestAndExit(Article, MessageID); - /* NOTREACHED */ - case NNTP_AUTH_NEEDED_VAL: - case NNTP_RESENDIT_VAL: - case NNTP_GOODBYE_VAL: - /* Most likely out of space -- no point in continuing. */ - syslog(L_NOTICE, IHAVE_FAIL, REMhost, REMclean(buff)); - RequeueRestAndExit(Article, MessageID); - /* NOTREACHED */ - case NNTP_SENDIT_VAL: - if (!REMsendarticle(Article, MessageID, art)) - RequeueRestAndExit(Article, MessageID); - break; - case NNTP_HAVEIT_VAL: - STATrefused++; - break; -#if defined(NNTP_SENDIT_LATER) - case NNTP_SENDIT_LATER_VAL: - Requeue(Article, MessageID); - break; -#endif /* defined(NNTP_SENDIT_LATER) */ - } - - article_free(art); - } - if (CanStream) { /* need to wait for rest of ACKs */ - while (stnq > 0) { - if (strlisten()) { - RequeueRestAndExit((char *)NULL, (char *)NULL); - } - } - } - - if (BATCHfp != NULL) - /* We requeued something, so close the temp file. */ - CloseAndRename(); - else if (unlink(BATCHname) < 0 && errno != ENOENT) - syswarn("cannot remove %s", BATCHtemp); - ExitWithStats(0); - /* NOTREACHED */ - return 0; -} diff --git a/backends/map.c b/backends/map.c deleted file mode 100644 index 5d5bcb9..0000000 --- a/backends/map.c +++ /dev/null @@ -1,99 +0,0 @@ -/* $Id: map.c 6135 2003-01-19 01:15:40Z rra $ -** -*/ - -#include "config.h" -#include "clibrary.h" -#include - -#include "libinn.h" -#include "paths.h" - -#include "map.h" - - -typedef struct _PAIR { - char First; - char *Key; - char *Value; -} PAIR; - -static PAIR *MAPdata; -static PAIR *MAPend; - - -/* -** Free the map. -*/ -void -MAPfree(void) -{ - PAIR *mp; - - for (mp = MAPdata; mp < MAPend; mp++) { - free(mp->Key); - free(mp->Value); - } - free(MAPdata); - MAPdata = NULL; -} - - -/* -** Read the map file. -*/ -void -MAPread(const char *name) -{ - FILE *F; - int i; - PAIR *mp; - char *p; - char buff[BUFSIZ]; - - if (MAPdata != NULL) - MAPfree(); - - /* Open file, count lines. */ - if ((F = fopen(name, "r")) == NULL) { - fprintf(stderr, "Can't open %s, %s\n", name, strerror(errno)); - exit(1); - } - for (i = 0; fgets(buff, sizeof buff, F) != NULL; i++) - continue; - mp = MAPdata = xmalloc((i + 1) * sizeof(PAIR)); - - /* Read each line; ignore blank and comment lines. */ - fseeko(F, 0, SEEK_SET); - while (fgets(buff, sizeof buff, F) != NULL) { - if ((p = strchr(buff, '\n')) != NULL) - *p = '\0'; - if (buff[0] == '\0' - || buff[0] == '#' - || (p = strchr(buff, ':')) == NULL) - continue; - *p++ = '\0'; - mp->First = buff[0]; - mp->Key = xstrdup(buff); - mp->Value = xstrdup(p); - mp++; - } - fclose(F); - MAPend = mp; -} - - -/* -** Look up a name in the map, return original value if not found. -*/ -char * -MAPname(char *p) -{ - PAIR *mp; - char c; - - for (c = *p, mp = MAPdata; mp < MAPend; mp++) - if (c == mp->First && strcmp(p, mp->Key) == 0) - return mp->Value; - return p; -} diff --git a/backends/map.h b/backends/map.h deleted file mode 100644 index c6fd6e7..0000000 --- a/backends/map.h +++ /dev/null @@ -1,7 +0,0 @@ -/* $Id: map.h 5292 2002-03-10 08:59:54Z vinocur $ -** -*/ - -void MAPfree(void); /* free the map */ -void MAPread(const char *name); /* read the map file */ -char *MAPname(char *p); /* lookup in the map */ diff --git a/backends/mod-active.in b/backends/mod-active.in deleted file mode 100644 index 4360e0b..0000000 --- a/backends/mod-active.in +++ /dev/null @@ -1,115 +0,0 @@ -#! /usr/bin/perl -# fixscript will replace this line with require innshellvars.pl - -# batch-active-update -# Author: David Lawrence - -# Reads a series of ctlinnd newgroup/rmgroup/changegroup commands, such as -# is output by checkgroups and actsync, and efficiently handles them all at -# once. Input can come from command line files or stdin, a la awk/sed. - -$oldact = $inn::active; # active file location -$oldact = $inn::active; # active file location (same; shut up, perl -w) -$newact = "$oldact.new$$"; # temporary name for new active file -$actime = "$oldact.times"; # active.times file -$pausemsg = 'batch active update, ok'; # message to be used for pausing? -$diff_flags = ''; # Flags for diff(1); default chosen if null. - -$0 =~ s#^.*/##; - -die "$0: must run as $inn::newsuser user" - unless $> == (getpwnam($inn::newsuser))[2]; - -$debug = -t STDOUT ? 1 : 0; - -$| = 1; # show output as it happens (for an rsh/ssh pipe) - -# Guess at best flags for a condensed diff listing. The -# checks for alternative operating systems is incomplete. -unless ($diff_flags) { - if (`diff -v 2>&1` =~ /GNU/) { - $diff_flags = '-U0'; - } elsif ($^O =~ /^(dec_osf|solaris)$/) { - $diff_flags = '-C0'; - } elsif ($^O eq 'nextstep') { - $diff_flags = '-c0'; - } else { - $diff_flags = '-c'; - } -} - -print "reading list of groups to update\n" if $debug; - -$eval = "while () {\n"; -$eval .= " \$group = (split)[0];\n"; - -while (<>) { - if (/^\s*\S*ctlinnd newgroup (\S+) (\S)/) { - $toadd{$1} = $2; - } elsif (/^\s*\S*ctlinnd rmgroup (\S+)/) { - $eval .= " next if \$group eq '$1';\n"; - } elsif (/^\s*\S*ctlinnd changegroup (\S+) (\S)/) { - $eval .= " s/ \\S+\$/ $2/ if \$group eq '$1';\n"; - } -} - -$eval .= " delete \$toadd{\$group};\n"; -$eval .= " if (!print(NEWACT \$_)) {\n"; -$eval .= " die \"\$0: writing \$newact failed (\$!), aborting\\n\";\n"; -$eval .= " }\n"; -$eval .= "}\n"; - -&ctlinnd("pause $pausemsg"); - -open(OLDACT, "< $oldact") || die "$0: open $oldact: $!\n"; -open(NEWACT, "> $newact") || die "$0: open $newact: $!\n"; - -print "rewriting active file\n" if $debug; -eval $eval; -for (sort keys %toadd) { - $add = "$_ 0000000000 0000000001 $toadd{$_}\n"; - if (!print( NEWACT $add)) { - &ctlinnd("go $pausemsg"); - die "$0: writing $newact failed ($!), aborting\n"; - } -} - -close(OLDACT) || warn "$0: close $oldact: $!\n"; -close(NEWACT) || warn "$0: close $newact: $!\n"; - -if (!rename("$oldact", "$oldact.old")) { - warn "$0: rename $oldact $oldact.old: $!\n"; -} - -if (!rename("$newact", "$oldact")) { - die "$0: rename $newact $oldact: $!\n"; -} - -&ctlinnd("reload active 'updated from checkgroups'"); -system("diff $diff_flags $oldact.old $oldact"); -&ctlinnd("go $pausemsg"); - -print "updating $actime\n" if $debug; -if (open(TIMES, ">> $actime")) { - $time = time; - for (sort keys %toadd) { - print TIMES "$_ $time checkgroups-update\n" || last; - } - close(TIMES) || warn "$0: close $actime: $!\n"; -} else { - warn "$0: $actime not updated: $!\n"; -} - -exit 0; - -sub -ctlinnd - -{ - local($command) = @_; - - print "ctlinnd $command\n" if $debug; - if (system("$inn::newsbin/ctlinnd -s $command")) { - die "$0: \"$command\" failed, aborting\n"; - } -} diff --git a/backends/news2mail.in b/backends/news2mail.in deleted file mode 100644 index 5f22231..0000000 --- a/backends/news2mail.in +++ /dev/null @@ -1,153 +0,0 @@ -#! /usr/bin/perl -# fixscript will replace this line with require innshellvars.pl - -# news to mail channel backend -# -# INN gives us -# @token@ addrs -# for each article that needs to be mailed. We invoke sm on the -# localhost to get the actual article and stuff -# it down sendmail's throat. -# -# This program expect to find a file that maps listname to listaddrs, -# @prefix@/etc/news2mail.cf -# which must contain address mapping pairs such as -# -# big-red-ants@ucsd.edu big-red-ants-digest@ucsd.edu -# -# where the first token is the name fed to us from INN, and which is -# also placed in the To: header of the outgoing mail. It's probably -# the subscriber's list submittal address so that replies go to the -# right place. The second token is the actual address sendmail ships -# the article to. -# -# In the INN newsfeeds file, you need to have a channel feed: -# n2m!:!*:Tc,Ac,Wn*:@prefix@/bin/news2mail -# and a site for each of the various mailing lists you're feeding, -# such as -# big-red-ants@ucsd.edu:rec.pets.redants.*:Tm:n2m! -# -# Error handling is nearly nonexistent. -# -# - Brian Kantor, UCSD Aug 1998 - -require 5.006; - -use FileHandle; -use Sys::Syslog; -use strict; - -my $cfFile = $inn::pathetc . "/news2mail.cf" ; -my $sendmail = $inn::mta ; -my $sm = $inn::pathbin . "/sm" ; -my %maddr = (); - -# -# the syslog calls are here but don't work on my system -# -openlog('news2mail', 'pid', 'mail'); - -syslog('info', 'begin'); - -# -# load the list names and their mail addresses from cf file -# #comments and blank lines are ignored -# -unless (open CF, "< $cfFile") { - syslog('notice', 'CF open failed %m'); - die "bad CF"; - } - -while ( ) { - next if /^#|^\s+$/; - my ( $ln, $ma ) = split /\s+/; - $maddr{ $ln } = $ma; - } -close CF; - -# -# for each incoming line from the INN channel -# -while ( ) { - chomp; - - syslog('info', $_); - - my ($token, $lnames) = split /\s+/, $_, 2; - my @addrs = split /\s+/, $lnames; - - my @good = grep { defined $maddr{$_} } @addrs; - my @bad = grep { !defined $maddr{$_} } @addrs; - - if (! @good) { - syslog('notice', "unknown listname $_"); - next; - } - - if (@bad) { - syslog('info', 'skipping unknown lists: ', join(' ', @bad)); - } - mailto($token, $lnames, @maddr{@good}); - } - -syslog ("info", "end") ; - -exit 0; - -sub mailto { - my($t, $l, @a) = @_ ; - - my $sendmail = $inn::mta ; - $sendmail =~ s!\s*%s!! ; - my @command = (split (' ', $sendmail), '-ee', '-fnews', '-odq', @a); -# @command[0] = '/usr/local/bin/debug'; - - syslog('info', join(' ', @command)); - - unless (open(SM, '|-', @command)) { - syslog('notice', join(' ', '|', @command), 'failed!'); - die "bad $sendmail"; - } - - my $smgr = "$sm -q $t |"; - - unless (open(SMGR, $smgr)) { - syslog('notice', "$smgr failed!"); - die "bad $smgr"; - } - - # header - while ( ) { - chomp; - - # empty line signals end of header - if ( /^$/ ) { - print SM "To: $l\n\n"; - last; - } - - # - # skip unnecessary headers - # - next if /^NNTP-Posting-Date:/i; - next if /^NNTP-Posting-Host:/i; - next if /^X-Trace:/i; - next if /^Xref:/i; - next if /^Path:/i; - - # - # convert Newsgroups header into X-Newsgroups - # - s/^Newsgroups:/X-Newsgroups:/i; - - print SM "$_\n"; - } - - # body - while ( ) { - print SM $_; - } - - close(SMGR); - close(SM); - } diff --git a/backends/ninpaths.c b/backends/ninpaths.c deleted file mode 100644 index 95f397d..0000000 --- a/backends/ninpaths.c +++ /dev/null @@ -1,519 +0,0 @@ -/* $Id: ninpaths.c 6362 2003-05-31 18:35:04Z rra $ -** -** New inpaths reporting program. -** -** Idea, data structures and part of code based on inpaths 2.5 -** by Brian Reid, Landon Curt Noll -** -** This version written by Olaf Titz, Feb. 1997. Public domain. -*/ - -#include "config.h" -#include "clibrary.h" -#include -#include - -#define VERSION "3.1.1" - -#define MAXFNAME 1024 /* max length of file name */ -#define MAXLINE 1024 /* max length of Path line */ -#define HASH_TBL 65536 /* hash table size (power of two) */ -#define MAXHOST 128 /* max length of host name */ -#define HOSTF "%127s" /* scanf format for host name */ -#define RECLINE 120 /* dump file line length softlimit */ - -/* structure used to tally the traffic between two hosts */ -struct trec { - struct trec *rlink; /* next in chain */ - struct nrec *linkid; /* pointer to... */ - long tally; /* count */ -}; - -/* structure to hold the information about a host */ -struct nrec { - struct nrec *link; /* next in chain */ - struct trec *rlink; /* start of trec chain */ - char *id; /* host name */ - long no; /* identificator for dump file */ - long sentto; /* tally of articles sent from here */ -}; - -struct nrec *hosthash[HASH_TBL]; - -time_t starttime; /* Start time */ -double atimes=0.0; /* Sum of articles times wrt. starttime */ -long total=0, /* Total articles processed */ - sites=0; /* Total sites known */ - -/* malloc and warn if out of mem */ -void * -wmalloc(size_t s) -{ - void *p=malloc(s); - if (!p) - fprintf(stderr, "warning: out of memory\n"); - return p; -} - -/* Hash function due to Glenn Fowler / Landon Curt Noll / Phong Vo */ -int -hash(const char *str) -{ - unsigned long val; - unsigned long c; - - for (val = 0; (c=(unsigned long)(*str)); ++str) { - val *= 16777619; /* magic */ - val ^= c; /* more magic */ - } - return (int)(val & (unsigned long)(HASH_TBL-1)); -} - -/* Look up a host in the hash table. Add if necessary. */ -struct nrec * -hhost(const char *n) -{ - struct nrec *h; - int i=hash(n); - - for (h=hosthash[i]; h; h=h->link) - if (!strcmp(n, h->id)) - return h; - /* not there - allocate */ - h=wmalloc(sizeof(struct nrec)); - if (!h) - return NULL; - h->id=strdup(n); - if (!h->id) { - free(h); return NULL; - } - h->link=hosthash[i]; - h->rlink=NULL; - h->no=h->sentto=0; - hosthash[i]=h; - sites++; - return h; -} - -/* Look up a tally record between hosts. Add if necessary. */ -struct trec * -tallyrec(struct nrec *r, struct nrec *h) -{ - struct trec *t; - for (t=r->rlink; t; t=t->rlink) - if (t->linkid==h) - return t; - t=wmalloc(sizeof(struct trec)); - if (!t) - return NULL; - t->rlink=r->rlink; - t->linkid=h; - t->tally=0; - r->rlink=t; - return t; -} - - -/* Dump file format: - "!!NINP" "\n" - followed by S-records, - "!!NLREC\n" - [3.0] - followed by max. ^2 L-records - [3.1] - followed by max. L-records - "!!NEND" "\n" - starttime, endtime, avgtime as UNIX date - the records are separated by space or \n - an S-record is "site count" - [3.0] - an L-record is "sitea!siteb!count" - [3.1] - an L-record is ":sitea" { "!siteb,count" }... - ",count" omitted if count==1 - where sitea and siteb are numbers of the S-records starting at 0 -*/ - -int -writedump(FILE *f) -{ - int i, j; - long n; - struct nrec *h; - struct trec *t; - - if (!total) { - return -1; - } - fprintf(f, "!!NINP " VERSION " %lu %lu %ld %ld %ld\n", - (unsigned long) starttime, (unsigned long) time(NULL), sites, - total, (long)(atimes/total)+starttime); - n=j=0; - /* write the S-records (hosts), numbering them in the process */ - for (i=0; ilink) { - h->no=n++; - j+=fprintf(f, "%s %ld", h->id, h->sentto); - if (j>RECLINE) { - j=0; - fprintf(f, "\n"); - } else { - fprintf(f, " "); - } - } - if (n!=sites) - fprintf(stderr, "internal error: sites=%ld, dumped=%ld\n", sites, n); - - fprintf(f, "\n!!NLREC\n"); - - n=j=0; - /* write the L-records (links) */ - for (i=0; ilink) - if ((t=h->rlink)) { - j+=fprintf(f, ":%ld", h->no); - for (; t; t=t->rlink) { - j+=fprintf(f, "!%ld", t->linkid->no); - if (t->tally>1) - j+=fprintf(f, ",%ld", t->tally); - n++; - } - if (j>RECLINE) { - j=0; - fprintf(f, "\n"); - } - } - fprintf(f, "\n!!NLEND %ld\n", n); - return 0; -} - -/* Write dump to a named file. Substitute %d in file name with system time. */ - -void -writedumpfile(const char *n) -{ - char buf[MAXFNAME]; - FILE *d; - - if (n[0]=='-' && n[1]=='\0') { - writedump(stdout); - return; - } - snprintf(buf, sizeof(buf), n, time(0)); - d=fopen(buf, "w"); - if (d) { - if (writedump(d)<0) - unlink(buf); - } else { - perror("writedumpfile: fopen"); - } -} - -/* Read a dump file. */ - -int -readdump(FILE *f) -{ - int a, b; - long i, m, l; - unsigned long st, et, at; - long sit, tot; - struct nrec **n; - struct trec *t; - char c[MAXHOST]; - char v[16]; - - #define formerr(i) {\ - fprintf(stderr, "dump file format error #%d\n", (i)); return -1; } - - if (fscanf(f, "!!NINP %15s %lu %lu %ld %ld %lu\n", - v, &st, &et, &sit, &tot, &at)!=6) - formerr(0); - - n=calloc(sit, sizeof(struct nrec *)); - if (!n) { - fprintf(stderr, "error: out of memory\n"); - return -1; - } - for (i=0; isentto+=l; - } - if ((fscanf(f, HOSTF "\n", c)!=1) || - strcmp(c, "!!NLREC")) - formerr(2); - m=0; - if (!strncmp(v, "3.0", 3)) { - /* Read 3.0-format L-records */ - while (fscanf(f, "%d!%d!%ld ", &a, &b, &l)==3) { - t=tallyrec(n[a], n[b]); - if (!t) - return -1; - t->tally+=l; - ++m; - } - } else if (!strncmp(v, "3.1", 3)) { - /* Read L-records */ - while (fscanf(f, " :%d", &a)==1) { - while ((i=fscanf(f, "!%d,%ld", &b, &l))>0) { - t=tallyrec(n[a], n[b]); - if (i<2) - l=1; - if (!t) - return -1; - t->tally+=l; - ++m; - } - } - } else { - fprintf(stderr, "version %s ", v); - formerr(9); - } - if ((fscanf(f, "!!NLEND %ld\n", &i)!=1) - || (i!=m)) - formerr(3); -#ifdef DEBUG - fprintf(stderr, " dumped start %s total=%ld atimes=%ld (%ld)\n", - ctime(&st), tot, at, at-st); -#endif - /* Adjust the time average and total count */ - if ((unsigned long) starttime > st) { - atimes+=(double)total*(starttime-st); - starttime=st; - } - atimes+=(double)tot*(at-starttime); - total+=tot; -#ifdef DEBUG - fprintf(stderr, " current start %s total=%ld atimes=%.0f (%.0f)\n\n", - ctime(&starttime), total, atimes, atimes/total); -#endif - free(n); - return 0; -} - -/* Read dump from a file. */ - -int -readdumpfile(const char *n) -{ - FILE *d; - int i; - - if (n[0]=='-' && n[1]=='\0') - return readdump(stdin); - - d=fopen(n, "r"); - if (d) { - /* fprintf(stderr, "Reading dump file %s\n", n); */ - i=readdump(d); - fclose(d); - return i; - } else { - perror("readdumpfile: fopen"); - return -1; - } -} - - -/* Process a Path line. */ - -int -pathline(char *c) -{ - char *c2; - struct nrec *h, *r; - struct trec *t; - - r=NULL; - while (*c) { - for (c2=c; *c2 && *c2!='!'; c2++); - if (c2-c>MAXHOST-1) - /* looks broken, dont bother with rest */ - return 0; - while (*c2=='!') - *c2++='\0'; /* skip "!!" too */ - h=hhost(c); - if (!h) - return -1; - ++h->sentto; - if (r && r!=h) { - t=tallyrec(r, h); - if (!t) - return -1; - ++t->tally; - } - c=c2; - r=h; - } - return 0; -} - -/* Take Path lines from file (stdin used here). */ - -void -procpaths(FILE *f) -{ - char buf[MAXLINE]; - char *c, *ce; - int v=1; /* current line is valid */ - - while (fgets(buf, sizeof(buf), f)) { - c=buf; - if (!strncmp(c, "Path: ", 6)) - c+=6; - /* find end of line. Some broken newsreaders preload Path with - a name containing spaces. Chop off those entries. */ - for (ce=c; *ce && !CTYPE(isspace, *ce); ++ce); - if (!*ce) { - /* bogus line */ - v=0; - } else if (v) { - /* valid line */ - for (; ce>c && *ce!='!'; --ce); /* ignore last element */ - *ce='\0'; - if (pathline(c)<0) /* process it */ - /* If an out of memory condition occurs while reading - Path lines, stop reading and write the dump so far. - INN will restart a fresh ninpaths. */ - return; - /* update average age and grand total */ - atimes+=(time(0)-starttime); - ++total; - } else { - /* next line is valid */ - v=1; - } - } -} - -/* Output a report suitable for mailing. From inpaths 2.5 */ - -void -report(const char *hostname, int verbose) -{ - double avgAge; - int i, columns, needHost; - long nhosts=0, nlinks=0; - struct nrec *list, *relay; - struct trec *rlist; - char hostString[MAXHOST]; - time_t t0=time(0); - - if (!total) { - fprintf(stderr, "report: no traffic\n"); - return; - } - /* mark own site to not report it */ - list=hhost(hostname); - if (list) - list->id[0]='\0'; - - avgAge=((double)t0 - (atimes/total + (double)starttime)) /86400.0; - printf("ZCZC begin inhosts %s %s %d %ld %3.1f\n", - VERSION,hostname,verbose,total,avgAge); - for (i=0; iid[0] != 0 && list->rlink != NULL) { - if (verbose > 0 || (100*list->sentto > total)) - printf("%ld\t%s\n",list->sentto, list->id); - } - list = list->link; - } - } - printf("ZCZC end inhosts %s\n",hostname); - - printf("ZCZC begin inpaths %s %s %d %ld %3.1f\n", - VERSION,hostname,verbose,total,avgAge); - for (i=0; i 1 || (100*list->sentto > total)) { - if (list->id[0] != 0 && list->rlink != NULL) { - columns = 3+strlen(list->id); - snprintf(hostString,sizeof(hostString),"%s H ",list->id); - needHost = 1; - rlist = list->rlink; - while (rlist != NULL) { - if ( - (100*rlist->tally > total) - || ((verbose > 1)&&(5000*rlist->tally>total)) - ) { - if (needHost) printf("%s",hostString); - needHost = 0; - relay = rlist->linkid; - if (relay->id[0] != 0) { - if (columns > 70) { - printf("\n%s",hostString); - columns = 3+strlen(list->id); - } - printf("%ld Z %s U ", rlist->tally, relay->id); - columns += 9+strlen(relay->id); - } - } - rlist = rlist->rlink; - ++nlinks; - } - if (!needHost) printf("\n"); - } - } - list = list->link; - ++nhosts; - } - } - printf("ZCZC end inpaths %s\n",hostname); -#ifdef DEBUG - fprintf(stderr, "Processed %ld hosts, %ld links.\n", nhosts, nlinks); -#endif -} - -extern char *optarg; - -int -main(int argc, char *argv[]) -{ - int i; - int pf=0, vf=2; - char *df=NULL, *rf=NULL; - - for (i=0; i -#include -#include - -/* Needed on AIX 4.1 to get fd_set and friends. */ -#ifdef HAVE_SYS_SELECT_H -# include -#endif - -#include "inn/history.h" -#include "inn/innconf.h" -#include "inn/messages.h" -#include "libinn.h" -#include "nntp.h" -#include "paths.h" - -/* -** All information about a site we are connected to. -*/ -typedef struct _SITE { - char *Name; - int Rfd; - int Wfd; - char Buffer[BUFSIZ]; - char *bp; - int Count; -} SITE; - - -/* -** Global variables. -*/ -static struct iovec SITEvec[2]; -static char SITEv1[] = "\r\n"; -static char READER[] = "mode reader"; -static unsigned long STATgot; -static unsigned long STAToffered; -static unsigned long STATsent; -static unsigned long STATrejected; -static struct history *History; - - - -/* -** Read a line of input, with timeout. -*/ -static bool -SITEread(SITE *sp, char *start) -{ - char *p; - char *end; - struct timeval t; - fd_set rmask; - int i; - char c; - - for (p = start, end = &start[NNTP_STRLEN - 1]; ; ) { - if (sp->Count == 0) { - /* Fill the buffer. */ - Again: - FD_ZERO(&rmask); - FD_SET(sp->Rfd, &rmask); - t.tv_sec = DEFAULT_TIMEOUT; - t.tv_usec = 0; - i = select(sp->Rfd + 1, &rmask, NULL, NULL, &t); - if (i < 0) { - if (errno == EINTR) - goto Again; - return false; - } - if (i == 0 - || !FD_ISSET(sp->Rfd, &rmask) - || (sp->Count = read(sp->Rfd, sp->Buffer, sizeof sp->Buffer)) < 0) - return false; - if (sp->Count == 0) - return false; - sp->bp = sp->Buffer; - } - - /* Process next character. */ - sp->Count--; - c = *sp->bp++; - if (c == '\n') - break; - if (p < end) - *p++ = c; - } - - /* If last two characters are \r\n, kill the \r as well as the \n. */ - if (p > start && p < end && p[-1] == '\r') - p--; - *p = '\0'; - return true; -} - - -/* -** Send a line to the server, adding \r\n. Don't need to do dot-escape -** since it's only for sending DATA to local site, and the data we got from -** the remote site already is escaped. -*/ -static bool -SITEwrite(SITE *sp, const char *p, int i) -{ - SITEvec[0].iov_base = (char *) p; - SITEvec[0].iov_len = i; - return xwritev(sp->Wfd, SITEvec, 2) >= 0; -} - - -static SITE * -SITEconnect(char *host) -{ - FILE *From; - FILE *To; - SITE *sp; - int i; - - /* Connect and identify ourselves. */ - if (host) - i = NNTPconnect(host, NNTP_PORT, &From, &To, (char *)NULL); - else { - host = innconf->server; - if (host == NULL) - die("no server specified and server not set in inn.conf"); - i = NNTPlocalopen(&From, &To, (char *)NULL); - } - if (i < 0) - sysdie("cannot connect to %s", host); - - if (NNTPsendpassword(host, From, To) < 0) - sysdie("cannot authenticate to %s", host); - - /* Build the structure. */ - sp = xmalloc(sizeof(SITE)); - sp->Name = host; - sp->Rfd = fileno(From); - sp->Wfd = fileno(To); - sp->bp = sp->Buffer; - sp->Count = 0; - return sp; -} - - -/* -** Send "quit" to a site, and get its reply. -*/ -static void -SITEquit(SITE *sp) -{ - char buff[NNTP_STRLEN]; - - SITEwrite(sp, "quit", 4); - SITEread(sp, buff); -} - - -static bool -HIShaveit(char *mesgid) -{ - return HIScheck(History, mesgid); -} - - -static void -Usage(const char *p) -{ - warn("%s", p); - fprintf(stderr, "Usage: nntpget" - " [ -d dist -n grps [-f file | -t time -u file]] host\n"); - exit(1); -} - - -int -main(int ac, char *av[]) -{ - char buff[NNTP_STRLEN]; - char mesgid[NNTP_STRLEN]; - char tbuff[SMBUF]; - char *msgidfile = NULL; - int msgidfd; - const char *Groups; - char *distributions; - char *Since; - char *path; - int i; - struct tm *gt; - struct stat Sb; - SITE *Remote; - SITE *Local = NULL; - FILE *F; - bool Offer; - bool Error; - bool Verbose = false; - char *Update; - char *p; - - /* First thing, set up our identity. */ - message_program_name = "nntpget"; - - /* Set defaults. */ - distributions = NULL; - Groups = NULL; - Since = NULL; - Offer = false; - Update = NULL; - if (!innconf_read(NULL)) - exit(1); - - umask(NEWSUMASK); - - /* Parse JCL. */ - while ((i = getopt(ac, av, "d:f:n:t:ovu:")) != EOF) - switch (i) { - default: - Usage("bad flag"); - /* NOTREACHED */ - case 'd': - distributions = optarg; - break; - case 'u': - Update = optarg; - /* FALLTHROUGH */ - case 'f': - if (Since) - Usage("only one of -f, -t, or -u may be given"); - if (stat(optarg, &Sb) < 0) - sysdie("cannot stat %s", optarg); - gt = gmtime(&Sb.st_mtime); - /* Y2K: NNTP Spec currently allows only two digit years. */ - snprintf(tbuff, sizeof(tbuff), "%02d%02d%02d %02d%02d%02d GMT", - gt->tm_year % 100, gt->tm_mon + 1, gt->tm_mday, - gt->tm_hour, gt->tm_min, gt->tm_sec); - Since = tbuff; - break; - case 'n': - Groups = optarg; - break; - case 'o': - /* Open the history file. */ - path = concatpath(innconf->pathdb, _PATH_HISTORY); - History = HISopen(path, innconf->hismethod, HIS_RDONLY); - if (!History) - sysdie("cannot open history"); - free(path); - Offer = true; - break; - case 't': - if (Since) - Usage("only one of -t or -f may be given"); - Since = optarg; - break; - case 'v': - Verbose = true; - break; - } - ac -= optind; - av += optind; - if (ac != 1) - Usage("no host given"); - - /* Set up the scatter/gather vectors used by SITEwrite. */ - SITEvec[1].iov_base = SITEv1; - SITEvec[1].iov_len = strlen(SITEv1); - - /* Connect to the remote server. */ - if ((Remote = SITEconnect(av[0])) == NULL) - sysdie("cannot connect to %s", av[0]); - if (!SITEwrite(Remote, READER, (int)strlen(READER)) - || !SITEread(Remote, buff)) - sysdie("cannot start reading"); - - if (Since == NULL) { - F = stdin; - if (distributions || Groups) - Usage("no -d or -n flags allowed when reading stdin"); - } - else { - /* Ask the server for a list of what's new. */ - if (Groups == NULL) - Groups = "*"; - if (distributions) - snprintf(buff, sizeof(buff), "NEWNEWS %s %s <%s>", - Groups, Since, distributions); - else - snprintf(buff, sizeof(buff), "NEWNEWS %s %s", Groups, Since); - if (!SITEwrite(Remote, buff, (int)strlen(buff)) - || !SITEread(Remote, buff)) - sysdie("cannot start list"); - if (buff[0] != NNTP_CLASS_OK) { - SITEquit(Remote); - die("protocol error from %s, got %s", Remote->Name, buff); - } - - /* Create a temporary file. */ - msgidfile = concatpath(innconf->pathtmp, "nntpgetXXXXXX"); - msgidfd = mkstemp(msgidfile); - if (msgidfd < 0) - sysdie("cannot create a temporary file"); - F = fopen(msgidfile, "w+"); - if (F == NULL) - sysdie("cannot open %s", msgidfile); - - /* Read and store the Message-ID list. */ - for ( ; ; ) { - if (!SITEread(Remote, buff)) { - syswarn("cannot read from %s", Remote->Name); - fclose(F); - SITEquit(Remote); - exit(1); - } - if (strcmp(buff, ".") == 0) - break; - if (Offer && HIShaveit(buff)) - continue; - if (fprintf(F, "%s\n", buff) == EOF || ferror(F)) { - syswarn("cannot write %s", msgidfile); - fclose(F); - SITEquit(Remote); - exit(1); - } - } - if (fflush(F) == EOF) { - syswarn("cannot flush %s", msgidfile); - fclose(F); - SITEquit(Remote); - exit(1); - } - fseeko(F, 0, SEEK_SET); - } - - if (Offer) { - /* Connect to the local server. */ - if ((Local = SITEconnect((char *)NULL)) == NULL) { - syswarn("cannot connect to local server"); - fclose(F); - exit(1); - } - } - - /* Loop through the list of Message-ID's. */ - while (fgets(mesgid, sizeof mesgid, F) != NULL) { - STATgot++; - if ((p = strchr(mesgid, '\n')) != NULL) - *p = '\0'; - - if (Offer) { - /* See if the local server wants it. */ - STAToffered++; - snprintf(buff, sizeof(buff), "ihave %s", mesgid); - if (!SITEwrite(Local, buff, (int)strlen(buff)) - || !SITEread(Local, buff)) { - syswarn("cannot offer %s", mesgid); - break; - } - if (atoi(buff) != NNTP_SENDIT_VAL) - continue; - } - - /* Try to get the article. */ - snprintf(buff, sizeof(buff), "article %s", mesgid); - if (!SITEwrite(Remote, buff, (int)strlen(buff)) - || !SITEread(Remote, buff)) { - syswarn("cannot get %s", mesgid); - printf("%s\n", mesgid); - break; - } - if (atoi(buff) != NNTP_ARTICLE_FOLLOWS_VAL) { - if (Offer) { - SITEwrite(Local, ".", 1); - if (!SITEread(Local, buff)) { - syswarn("no reply after %s", mesgid); - break; - } - } - continue; - } - - if (Verbose) - notice("%s...", mesgid); - - /* Read each line in the article and write it. */ - for (Error = false; ; ) { - if (!SITEread(Remote, buff)) { - syswarn("cannot read %s from %s", mesgid, Remote->Name); - Error = true; - break; - } - if (Offer) { - if (!SITEwrite(Local, buff, (int)strlen(buff))) { - syswarn("cannot send %s", mesgid); - Error = true; - break; - } - } - else - printf("%s\n", buff); - if (strcmp(buff, ".") == 0) - break; - } - if (Error) { - printf("%s\n", mesgid); - break; - } - STATsent++; - - /* How did the local server respond? */ - if (Offer) { - if (!SITEread(Local, buff)) { - syswarn("no reply after %s", mesgid); - printf("%s\n", mesgid); - break; - } - i = atoi(buff); - if (i == NNTP_TOOKIT_VAL) - continue; - if (i == NNTP_RESENDIT_VAL) { - printf("%s\n", mesgid); - break; - } - syswarn("%s to %s", buff, mesgid); - STATrejected++; - } - } - - /* Write rest of the list, close the input. */ - if (!feof(F)) - while (fgets(mesgid, sizeof mesgid, F) != NULL) { - if ((p = strchr(mesgid, '\n')) != NULL) - *p = '\0'; - printf("%s\n", mesgid); - STATgot++; - } - fclose(F); - - /* Remove our temp file. */ - if (msgidfile && unlink(msgidfile) < 0) - syswarn("cannot remove %s", msgidfile); - - /* All done. */ - SITEquit(Remote); - if (Offer) - SITEquit(Local); - - /* Update timestamp file? */ - if (Update) { - if ((F = fopen(Update, "w")) == NULL) - sysdie("cannot update %s", Update); - fprintf(F, "got %ld offered %ld sent %ld rejected %ld\n", - STATgot, STAToffered, STATsent, STATrejected); - if (ferror(F) || fclose(F) == EOF) - sysdie("cannot update %s", Update); - } - - exit(0); - /* NOTREACHED */ -} diff --git a/backends/nntpsend.in b/backends/nntpsend.in deleted file mode 100644 index eb68718..0000000 --- a/backends/nntpsend.in +++ /dev/null @@ -1,472 +0,0 @@ -#! /bin/sh -# fixscript will replace this line with code to load innshellvars - -## $Revision: 5047 $ -## Send news via NNTP by running several innxmit processes in the background. -## Usage: -## nntpsend [-n][-p][-r][-s size][-S][-t timeout][-T limit][host fqdn]... -## -a Always have innxmit rewrite the batchfile -## -d debug mode, run innxmits with debug as well -## -D same as -d except innxmits are not debugged -## -p Run innxmit with -p to prune batch files -## -r innxmit, don't requeue on unexpected error code -## -s size limit the =n file to size bytes -## -c disable message-ID checking in streaming mode -## -t timeout innxmit timeout to make connection (def: 180) -## -T limit innxmit connection transmit time limit (def: forever) -## -P portnum port number to use -## -l innxmit, log rejected articles -## -N innxmit, disable streaming mode -## -n do not lock for nntpsend, do not sleep between sets -## -w delay wait delay seconds just before innxmit -## host fqdn send to host and qualified domain (def: nntpsend.ctl) -## If no "host fqdn" pairs appear on the command line, then ${CTLFILE} -## file is read. - -PROGNAME=`basename $0` -LOCK=${LOCKS}/LOCK.${PROGNAME} -CTLFILE=${PATHETC}/${PROGNAME}.ctl -LOG=${MOST_LOGS}/${PROGNAME}.log - -## Set defaults. -A_FLAG= -D_FLAG= -NO_LOG_FLAG= -P_FLAG= -R_FLAG= -S_FLAG= -C_FLAG= -L_FLAG= -S2_FLAG= -TRUNC_SIZE= -T_FLAG= -TIMELIMIT= -PP_FLAG= -NOLOCK= -W_SECONDS= - -## Parse JCL. -MORETODO=true -while ${MORETODO} ; do - case X"$1" in - X-a) - A_FLAG="-a" - ;; - X-d) - D_FLAG="-d" - NO_LOG_FLAG="true" - ;; - X-D) - NO_LOG_FLAG="true" - ;; - X-l) - L_FLAG="-l" - ;; - X-p) - P_FLAG="-p" - ;; - X-r) - R_FLAG="-r" - ;; - X-S) - S_FLAG="-S" - ;; - X-N) - S2_FLAG="-s" - ;; - X-c) - C_FLAG="-c" - ;; - X-s) - if [ -z "$2" ] ; then - echo "${PROGNAME}: option requires an argument -- s" 1>&2 - exit 1 - fi - TRUNC_SIZE="$2" - shift - ;; - X-s*) - TRUNC_SIZE="`echo $1 | ${SED} -e 's/-s//'`" - ;; - X-t) - if [ -z "$2" ] ; then - echo "${PROGNAME}: option requires an argument -- t" 1>&2 - exit 1 - fi - T_FLAG="-t$2" - shift - ;; - X-t*) - T_FLAG="$1" - ;; - X-P) - if [ -z "$2" ] ; then - echo "${PROGNAME}: option requires an argument -- P" 1>&2 - exit 1 - fi - PP_FLAG="-P$2" - shift - ;; - X-P*) - PP_FLAG="$1" - ;; - X-T) - if [ -z "$2" ] ; then - echo "${PROGNAME}: option requires an argument -- T" 1>&2 - exit 1 - fi - TIMELIMIT="-T$2" - shift - ;; - X-T*) - TIMELIMIT="$1" - ;; - X-n) - NOLOCK=true - ;; - X-w) - if [ -z "$2" ] ; then - echo "${PROGNAME}: option requires an argument -- w" 1>&2 - exit 1 - fi - W_SECONDS="$2" - shift - ;; - X--) - shift - MORETODO=false - ;; - X-*) - echo "${PROGNAME}: illegal option -- $1" 1>&2 - exit 1 - ;; - *) - MORETODO=false - ;; - esac - ${MORETODO} && shift -done - -## grab the lock if not -n -NNTPLOCK=${LOCKS}/LOCK.nntpsend -if [ -z "${NOLOCK}" ]; then - shlock -p $$ -f ${NNTPLOCK} || { - # nothing to do - exit 0 - } -fi - -## Parse arguments; host/fqdn pairs. -INPUT=${TMPDIR}/nntpsend$$ -cp /dev/null ${INPUT} -while [ $# -gt 0 ]; do - if [ $# -lt 2 ]; then - echo "${PROGNAME}: Bad host/fqdn pair" 1>&2 - rm -f ${NNTPLOCK} - exit 1 - fi - echo "$1 $2" >>${INPUT} - shift - shift -done - -## If nothing specified on the command line, read the control file. -if [ ! -s ${INPUT} ] ; then - if [ ! -r ${CTLFILE} ]; then - echo "${PROGNAME}: cannot read ${CTLFILE}" - rm -f ${NNTPLOCK} - exit 1 - fi - ${SED} -e 's/#.*//' -e '/^$/d' -e 's/::\([^:]*\)$/:max:\1/' \ - -e 's/:/ /g' <${CTLFILE} >${INPUT} -fi - -## Go to where the action is. -if [ ! -d ${BATCH} ]; then - echo "${PROGNAME}: directory ${BATCH} not found" 1>&2 - rm -f ${NNTPLOCK} - exit 1 -fi -cd ${BATCH} - -## Set up log file. -umask 002 -if [ -z "${NO_LOG_FLAG}" ]; then - test ! -f ${LOG} && touch ${LOG} - chmod 0660 ${LOG} - exec >>${LOG} 2>&1 -fi -PARENTPID=$$ -echo "${PROGNAME}: [${PARENTPID}] start" - -## Set up environment. -export BATCH PROGNAME PARENTPID INNFLAGS - -## Loop over all sites. -cat ${INPUT} | while read SITE HOST SIZE_ARG FLAGS; do - ## Parse the input parameters. - if [ -z "${SITE}" -o -z "${HOST}" ] ; then - echo "Ignoring bad line: ${SITE} ${HOST} ${SIZE_ARG} ${FLAGS}" 1>&2 - continue - fi - - ## give up early if we cannot even lock it - ## - ## NOTE: This lock is not nntpsend's lock but rather the - ## lock that the parent shell of innxmit will use. - ## Later on the child will take the lock from us. - ## - LOCK="${LOCKS}/LOCK.${SITE}" - shlock -p $$ -f "${LOCK}" || continue - - ## Compute the specific parameters for this site. - test "${SIZE_ARG}" = "max" && SIZE_ARG= - if [ -n "${TRUNC_SIZE}" ]; then - SIZE_ARG="${TRUNC_SIZE}" - fi - ## Parse the SIZE_ARG for either MaxSize-TruncSize or TruncSize - case "${SIZE_ARG}" in - *-*) MAXSIZE="`echo ${SIZE_ARG} | ${SED} -e 's/-.*//'`"; - SIZE="`echo ${SIZE_ARG} | ${SED} -e 's/^.*-//'`" ;; - *) MAXSIZE="${SIZE_ARG}"; - SIZE="${SIZE_ARG}" ;; - esac - D_PARAM= - R_PARAM= - S_PARAM= - S2_PARAM= - C_PARAM= - PP_PARAM= - L_PARAM= - TIMEOUT_PARAM= - TIMELIMIT_PARAM= - if [ -z "${FLAGS}" ]; then - MORETODO=false - else - MORETODO=true - set -- ${FLAGS} - fi - while ${MORETODO} ; do - case "X$1" in - X-a) - ;; - X-d) - D_PARAM="-d" - ;; - X-c) - C_PARAM="-c" - ;; - X-p) - P_PARAM="-p" - ;; - X-r) - R_PARAM="-r" - ;; - X-S) - S_PARAM="-S" - ;; - X-s) - S2_PARAM="-s" - ;; - X-l) - L_PARAM="-l" - ;; - X-t) - if [ -z "$2" ] ; then - echo "${PROGNAME}: option requires an argument -- t" 1>&2 - rm -f "${NNTPLOCK}" "${LOCK}" - exit 1 - fi - TIMEOUT_PARAM="-t$2" - shift - ;; - X-t*) - TIMEOUT_PARAM="$1" - ;; - X-P) - if [ -z "$2" ] ; then - echo "${PROGNAME}: option requires an argument -- P" 1>&2 - rm -f "${NNTPLOCK}" "${LOCK}" - exit 1 - fi - PP_PARAM="-P$2" - shift - ;; - X-P*) - PP_PARAM="$1" - ;; - X-T) - if [ -z "$2" ] ; then - echo "${PROGNAME}: option requires an argument -- T" 1>&2 - rm -f "${NNTPLOCK}" "${LOCK}" - exit 1 - fi - TIMELIMIT_PARAM="-T$2" - shift - ;; - X-T*) - TIMELIMIT_PARAM="$1" - ;; - X-w) - if [ -z "$2" ] ; then - echo "${PROGNAME}: option requires an argument -- w" 1>&2 - rm -f "${NNTPLOCK}" "${LOCK}" - exit 1 - fi - W_SECONDS="$2" - shift - ;; - *) - MORETODO=false - ;; - esac - ${MORETODO} && shift - done - if [ -z "${SIZE}" -o -n "${A_FLAG}" ]; then - # rewrite batch file if we do not have a size limit - INNFLAGS="-a" - else - # we have a size limit, let shrinkfile rewrite the file - INNFLAGS= - fi - if [ -n "${D_FLAG}" ]; then - INNFLAGS="${INNFLAGS} ${D_FLAG}" - else - test -n "${D_PARAM}" && INNFLAGS="${INNFLAGS} ${D_PARAM}" - fi - if [ -n "${C_FLAG}" ]; then - INNFLAGS="${INNFLAGS} ${C_FLAG}" - else - test -n "${C_PARAM}" && INNFLAGS="${INNFLAGS} ${C_PARAM}" - fi - if [ -n "${P_FLAG}" ]; then - INNFLAGS="${INNFLAGS} ${P_FLAG}" - else - test -n "${P_PARAM}" && INNFLAGS="${INNFLAGS} ${P_PARAM}" - fi - if [ -n "${L_FLAG}" ]; then - INNFLAGS="${INNFLAGS} ${L_FLAG}" - else - test -n "${L_PARAM}" && INNFLAGS="${INNFLAGS} ${L_PARAM}" - fi - if [ -n "${R_FLAG}" ]; then - INNFLAGS="${INNFLAGS} ${R_FLAG}" - else - test -n "${R_PARAM}" && INNFLAGS="${INNFLAGS} ${R_PARAM}" - fi - if [ -n "${S_FLAG}" ]; then - INNFLAGS="${INNFLAGS} ${S_FLAG}" - else - test -n "${S_PARAM}" && INNFLAGS="${INNFLAGS} ${S_PARAM}" - fi - if [ -n "${S2_FLAG}" ]; then - INNFLAGS="${INNFLAGS} ${S2_FLAG}" - else - test -n "${S2_PARAM}" && INNFLAGS="${INNFLAGS} ${S2_PARAM}" - fi - if [ -n "${T_FLAG}" ]; then - INNFLAGS="${INNFLAGS} ${T_FLAG}" - else - test -n "${TIMEOUT_PARAM}" && INNFLAGS="${INNFLAGS} ${TIMEOUT_PARAM}" - fi - if [ -n "${PP_FLAG}" ]; then - INNFLAGS="${INNFLAGS} ${PP_FLAG}" - else - test -n "${PP_PARAM}" && INNFLAGS="${INNFLAGS} ${PP_PARAM}" - fi - if [ -n "${TIMELIMIT}" ]; then - INNFLAGS="${INNFLAGS} ${TIMELIMIT}" - else - test -n "${TIMELIMIT_PARAM}" \ - && INNFLAGS="${INNFLAGS} ${TIMELIMIT_PARAM}" - fi - - ## Flush the buffers for the site now, rather than in the child. - ## This helps pace the number of ctlinnd commands because the - ## nntpsend process does not proceed until the site flush has - ## been completed. - ## - # carry old unfinished work over to this task - BATCHFILE="${SITE}=n" - if [ -f "${SITE}.work" ] ; then - cat ${SITE}.work >>"${BATCHFILE}" - rm -f "${SITE}.work" - fi - # form BATCHFILE to hold the work for this site - if [ -f "${SITE}" ]; then - mv "${SITE}" "${SITE}.work" - if ctlinnd -s -t30 flush ${SITE} ; then - cat ${SITE}.work >>"${BATCHFILE}" - rm -f ${SITE}.work - else - # flush failed, continue if we have any batchfile to work on - echo "${PROGNAME}: bad flush for ${HOST} via ${SITE}" - if [ -f "${BATCHFILE}" ]; then - echo "${PROGNAME}: trying ${HOST} via ${SITE} anyway" - else - echo "${PROGNAME}: skipping ${HOST} via ${SITE}" - rm -f ${LOCK} - continue - fi - fi - else - # nothing to work on, so flush and move on - ctlinnd -s -t30 flush ${SITE} - echo "${PROGNAME}: file ${BATCH}/${SITE} for ${HOST} not found" - if [ -f "${BATCHFILE}" ]; then - echo "${PROGNAME}: trying ${HOST} via ${SITE} anyway" - else - echo "${PROGNAME}: skipping ${HOST} via ${SITE}" - rm -f ${LOCK} - continue - fi - fi - - ## Start sending this site in the background. - export MAXSIZE SITE HOST PROGNAME PARENTPID SIZE TMPDIR LOCK BATCHFILE W_SECONDS - sh -c ' - # grab the lock from the parent - # - # This is safe because only the parent will have locked - # the site. We break the lock and reclaim it. - rm -f ${LOCK} - trap "rm -f ${LOCK} ; exit 1" 1 2 3 15 - shlock -p $$ -f ${LOCK} || { - WHY="`cat ${LOCK}`" - echo "${PROGNAME}: [${PARENTPID}:$$] ${SITE} locked ${WHY} `date`" - exit - } - # process the site BATCHFILE - if [ -f "${BATCHFILE}" ]; then - test -n "${SIZE}" && shrinkfile -m${MAXSIZE} -s${SIZE} -v ${BATCHFILE} - if [ -s ${BATCHFILE} ] ; then - if [ -n "${W_SECONDS}" ] ; then - echo "${PROGNAME}: [${PARENTPID}:$$] sleeping ${W_SECONDS} seconds before ${SITE}" - sleep "${W_SECONDS}" - fi - echo "${PROGNAME}: [${PARENTPID}:$$] begin ${SITE} `date`" - echo "${PROGNAME}: [${PARENTPID}:$$] innxmit ${INNFLAGS} ${HOST} ..." - eval innxmit ${INNFLAGS} ${HOST} ${BATCH}/${BATCHFILE} - echo "${PROGNAME}: [${PARENTPID}:$$] end ${SITE} `date`" - else - rm -f ${BATCHFILE} - fi - else - echo "${PROGNAME}: file ${BATCH}/${BATCHFILE} for ${HOST} not found" - fi - rm -f ${LOCK} - ' & -done - -## release the nntpsend lock and clean up before we wait on child processes -if [ -z "${NOLOCK}" ]; then - rm -f ${NNTPLOCK} -fi -rm -f ${INPUT} - -## wait for child processes to finish -wait - -## all done -echo "${PROGNAME}: [${PARENTPID}] stop" -exit 0 diff --git a/backends/overchan.c b/backends/overchan.c deleted file mode 100644 index 30bb028..0000000 --- a/backends/overchan.c +++ /dev/null @@ -1,142 +0,0 @@ -/* $Id: overchan.c 6135 2003-01-19 01:15:40Z rra $ -** -** Parse input to add to news overview database. -*/ - -#include "config.h" -#include "clibrary.h" -#include "portable/time.h" -#include -#include -#include - -#include "inn/innconf.h" -#include "inn/messages.h" -#include "inn/qio.h" -#include "libinn.h" -#include "ov.h" -#include "paths.h" - -unsigned int NumArts; -unsigned int StartTime; -unsigned int TotOvTime; - -/* - * Timer function (lifted from innd/timer.c). - * This function is designed to report the number of milliseconds since - * the first invocation. I wanted better resolution than time(), and - * something easier to work with than gettimeofday()'s struct timeval's. - */ - -static unsigned gettime(void) -{ - static int init = 0; - static struct timeval start_tv; - struct timeval tv; - - if (! init) { - gettimeofday(&start_tv, NULL); - init++; - } - gettimeofday(&tv, NULL); - return((tv.tv_sec - start_tv.tv_sec) * 1000 + (tv.tv_usec - start_tv.tv_usec) / 1000); -} - -/* -** Process the input. Data comes from innd in the form: -** @token@ data -*/ - -#define TEXT_TOKEN_LEN (2*sizeof(TOKEN)+2) -static void ProcessIncoming(QIOSTATE *qp) -{ - char *Data; - char *p; - TOKEN token; - unsigned int starttime, endtime; - time_t Time, Expires; - - for ( ; ; ) { - /* Read the first line of data. */ - if ((Data = QIOread(qp)) == NULL) { - if (QIOtoolong(qp)) { - warn("line too long"); - continue; - } - break; - } - - if (Data[0] != '@' || strlen(Data) < TEXT_TOKEN_LEN+2 - || Data[TEXT_TOKEN_LEN-1] != '@' || Data[TEXT_TOKEN_LEN] != ' ') { - warn("malformed token %s", Data); - continue; - } - token = TextToToken(Data); - Data += TEXT_TOKEN_LEN+1; /* skip over token and space */ - for (p = Data; !ISWHITE(*p) ;p++) ; - *p++ = '\0'; - Time = (time_t)atol(Data); - for (Data = p; !ISWHITE(*p) ;p++) ; - *p++ = '\0'; - Expires = (time_t)atol(Data); - Data = p; - NumArts++; - starttime = gettime(); - if (OVadd(token, Data, strlen(Data), Time, Expires) == OVADDFAILED) - syswarn("cannot write overview %s", Data); - endtime = gettime(); - TotOvTime += endtime - starttime; - } - QIOclose(qp); -} - - -int main(int ac, char *av[]) -{ - QIOSTATE *qp; - unsigned int now; - - /* First thing, set up our identity. */ - message_program_name = "overchan"; - - /* Log warnings and fatal errors to syslog unless we were given command - line arguments, since we're probably running under innd. */ - if (ac == 0) { - openlog("overchan", L_OPENLOG_FLAGS | LOG_PID, LOG_INN_PROG); - message_handlers_warn(1, message_log_syslog_err); - message_handlers_die(1, message_log_syslog_err); - message_handlers_notice(1, message_log_syslog_notice); - } - - /* Set defaults. */ - if (!innconf_read(NULL)) - exit(1); - umask(NEWSUMASK); - if (innconf->enableoverview && !innconf->useoverchan) - warn("overchan is running while innd is creating overview data (you" - " can ignore this message if you are running makehistory -F)"); - - ac -= 1; - av += 1; - - if (!OVopen(OV_WRITE)) - die("cannot open overview"); - - StartTime = gettime(); - if (ac == 0) - ProcessIncoming(QIOfdopen(STDIN_FILENO)); - else { - for ( ; *av; av++) - if (strcmp(*av, "-") == 0) - ProcessIncoming(QIOfdopen(STDIN_FILENO)); - else if ((qp = QIOopen(*av)) == NULL) - syswarn("cannot open %s", *av); - else - ProcessIncoming(qp); - } - OVclose(); - now = gettime(); - notice("timings %u arts %u of %u ms", NumArts, TotOvTime, now - StartTime); - exit(0); - /* NOTREACHED */ -} diff --git a/backends/send-ihave.in b/backends/send-ihave.in deleted file mode 100644 index f1ba03c..0000000 --- a/backends/send-ihave.in +++ /dev/null @@ -1,95 +0,0 @@ -#! /bin/sh -# fixscript will replace this line with code to load innshellvars - -## $Revision: 2674 $ -## SH script to send IHAVE batches out. - -PROGNAME=`basename $0` -LOG=${MOST_LOGS}/${PROGNAME}.log - -## How many Message-ID's per message. -PERMESSAGE=1000 - -## Go to where the action is, start logging -cd $BATCH -umask 002 -DEBUG="" -if [ "X$1" = X-d ] ; then - DEBUG="-d" - shift -else - test ! -f ${LOG} && touch ${LOG} - chmod 0660 ${LOG} - exec >>${LOG} 2>&1 -fi - -echo "${PROGNAME}: [$$] begin `date`" - -## List of sitename:hostname pairs to send to -if [ -n "$1" ] ; then - LIST="$*" -else - echo "${PROGNAME}: [$$] no sites specified" >&2 - exit 1 -fi - -## Do the work... -for SITE in ${LIST}; do - case $SITE in - *:*) - HOST=`expr $SITE : '.*:\(.*\)'` - SITE=`expr $SITE : '\(.*\):.*'` - ;; - *) - HOST=$SITE - ;; - esac - BATCHFILE=${SITE}.ihave.batch - LOCK=${LOCKS}/LOCK.${SITE}.ihave - trap 'rm -f ${LOCK} ; exit 1' 1 2 3 15 - shlock -p $$ -f ${LOCK} || { - echo "${PROGNAME}: [$$] ${SITE}.ihave locked by `cat ${LOCK}`" - continue - } - - ## See if any data is ready for host. - if [ -f ${SITE}.ihave.work ] ; then - cat ${SITE}.ihave.work >>${BATCHFILE} - rm -f ${SITE}.ihave.work - fi - if [ ! -f ${SITE}.ihave -o ! -s ${SITE}.ihave ] ; then - if [ ! -f ${BATCHFILE} -o ! -s ${BATCHFILE} ] ; then - rm -f ${LOCK} - continue - fi - fi - mv ${SITE}.ihave ${SITE}.ihave.work - ctlinnd -s -t30 flush ${SITE}.ihave || continue - cat ${SITE}.ihave.work >>${BATCHFILE} - rm -f ${SITE}.ihave.work - if [ ! -s ${BATCHFILE} ] ; then - echo "${PROGNAME}: [$$] no articles for ${SITE}.ihave" - rm -f ${BATCHFILE} - continue - fi - - echo "${PROGNAME}: [$$] begin ${SITE}.ihave" - - ## Write out the batchfile as a control message, in clumps. - export SITE PERMESSAGE BATCHFILE - while test -s ${BATCHFILE} ; do - ( - echo Newsgroups: to.${SITE} - echo Control: ihave `innconfval pathhost` - echo Subject: cmsg ihave `innconfval pathhost` - echo '' - ${SED} -e ${PERMESSAGE}q <${BATCHFILE} - ) | ${INEWS} -h - ${SED} -e "1,${PERMESSAGE}d" <${BATCHFILE} >${BATCHFILE}.tmp - mv ${BATCHFILE}.tmp ${BATCHFILE} - done - echo "${PROGNAME}: [$$] end ${SITE}.ihave" - rm -f ${LOCK} -done - -echo "${PROGNAME}: [$$] end `date`" diff --git a/backends/send-nntp.in b/backends/send-nntp.in deleted file mode 100644 index 018eb6d..0000000 --- a/backends/send-nntp.in +++ /dev/null @@ -1,88 +0,0 @@ -#! /bin/sh -# fixscript will replace this line with code to load innshellvars - -## $Revision: 4115 $ -## SH script to send NNTP news out. - -PROGNAME=`basename $0` -LOG=${MOST_LOGS}/${PROGNAME}.log - -## Go to where the action is, start logging -cd $BATCH -umask 002 -DEBUG="" -if [ "X$1" = X-d ] ; then - DEBUG="-d" - shift -else - test ! -f ${LOG} && touch ${LOG} - chmod 0660 ${LOG} - exec >>${LOG} 2>&1 -fi - -echo "${PROGNAME}: [$$] begin `date`" - -## List of sitename:hostname pairs to send to -if [ -n "$1" ] ; then - LIST="$*" -else - echo "${PROGNAME}: [$$] no sites specified" >&2 - exit 1 -fi - -## Do the work... -for SITE in ${LIST}; do - case $SITE in - *:*) - HOST=`expr $SITE : '.*:\(.*\)'` - SITE=`expr $SITE : '\(.*\):.*'` - ;; - *) - HOST=$SITE - ;; - esac - case $HOST in - *@*) - PORT=`expr $HOST : '\(.*\)@.*'` - HOST=`expr $HOST : '.*@\(.*\)'` - ;; - *) - PORT=119 - ;; - esac - BATCHFILE=${SITE}.nntp - LOCK=${LOCKS}/LOCK.${SITE} - trap 'rm -f ${LOCK} ; exit 1' 1 2 3 15 - shlock -p $$ -f ${LOCK} || { - echo "${PROGNAME}: [$$] ${SITE} locked by `cat ${LOCK}`" - continue - } - - ## See if any data is ready for host. - if [ -f ${SITE}.work ] ; then - cat ${SITE}.work >>${BATCHFILE} - rm -f ${SITE}.work - fi - if [ ! -f ${SITE} -o ! -s ${SITE} ] ; then - if [ ! -f ${BATCHFILE} -o ! -s ${BATCHFILE} ] ; then - rm -f ${LOCK} - continue - fi - fi - mv ${SITE} ${SITE}.work - ctlinnd -s -t30 flush ${SITE} || continue - cat ${SITE}.work >>${BATCHFILE} - rm -f ${SITE}.work - if [ ! -s ${BATCHFILE} ] ; then - echo "${PROGNAME}: [$$] no articles for ${SITE}" - rm -f ${BATCHFILE} - continue - fi - - echo "${PROGNAME}: [$$] begin ${SITE}" - time innxmit ${DEBUG} -P ${PORT} ${HOST} ${BATCH}/${BATCHFILE} - echo "${PROGNAME}: [$$] end ${SITE}" - rm -f ${LOCK} -done - -echo "${PROGNAME}: [$$] end `date`" diff --git a/backends/send-uucp.in b/backends/send-uucp.in deleted file mode 100644 index 8ba2937..0000000 --- a/backends/send-uucp.in +++ /dev/null @@ -1,382 +0,0 @@ -#!/usr/bin/perl -w -# fixscript will replace this line with code to load innshellvars - -############################################################################## -# send-uucp.pl create news batches from the outgoing files -# -# Author: Edvard Tuinder -# -# Copyright (C) 1994 Edvard Tuinder - ELM Consultancy B.V. -# Copyright (C) 1995-1997 Miquel van Smoorenburg - Cistron Internet Services -# -# Copyright (C) 2003 Marco d'Itri -# Nearly rewritten. Added syslog support, real errors checking and more. -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -############################################################################## - -use strict; -use Sys::Syslog; - -# for compatibility with earlier versions of INN -$inn::pathetc ||= '/etc/news'; -$inn::syslog_facility ||= 'news'; -$inn::uux ||= 'uux'; - -# some default values -my $MAXSIZE = 500000; -my $MAXJOBS = 200; - -my %UNBATCHER = ( - compress => 'cunbatch', - bzip2 => 'bunbatch', - gzip => 'gunbatch', -); - -my $UUX_FLAGS = '- -z -r -gd'; -my $BATCHER_FLAGS = ''; - -############################################################################## -my $config_file = $inn::pathetc . '/send-uucp.cf'; -my $lockfile = $inn::locks . '/LOCK.send-uucp'; - -openlog('send-uucp', 'pid', $inn::syslog_facility); - -my @sitelist; -if (@ARGV) { - foreach my $site (@ARGV) { - my @cfg = read_cf($config_file, $site); - if (not @cfg) { - logmsg("site $site not found in the configuration", 'err'); - next; - } - push @sitelist, @cfg; - } -} else { - @sitelist = read_cf($config_file, undef); -} - -if (not @sitelist) { - logmsg('nothing to do', 'debug'); - exit 0; -} - -chdir $inn::batch or logdie("Can't access $inn::batch: $!", 'crit'); - -shlock($lockfile); - -run_site($_) foreach @sitelist; -unlink $lockfile; -exit 0; - -# lint food -$inn::compress.$inn::locks.$inn::syslog_facility.$inn::have_uustat = 0 if 0; - -############################################################################## -sub read_cf { - my ($conf_file, $site_wanted) = @_; - - my $hour = (localtime time)[2]; - - my @sites; - open(CF, $conf_file) or logdie("cannot open $conf_file: $!", 'crit'); - while () { - chop; - s/\s*\#.*$//; - next if /^$/; - - my ($sitespec, $compress, $size, $time) = split(/\s+/); - next if not $sitespec; - - my ($site, $host, $funnel) = split(/:/, $sitespec); - $host = $site if not $host; - $funnel = $site if not $funnel; - - $compress =~ s/_/ /g if $compress; - - if ($site_wanted) { - if ($site eq $site_wanted) { - push @sites, [$site, $host, $funnel, $compress, $size]; - last; - } - next; - } - - if ($time) { - foreach my $time (split(/,/, $time)) { - next if $time != $hour; - push @sites, [$site, $host, $funnel, $compress, $size]; - } - } else { - push @sites, [$site, $host, $funnel, $compress, $size]; - } - } - close CF; - return @sites; -} - -############################################################################## -# count number of jobs in the UUCP queue for a given site -sub count_jobs { - my ($site) = @_; - - return 0 if not $inn::have_uustat; - open(JOBS, "uustat -s $site 2> /dev/null |") or logdie("cannot fork: $!"); - my $count = grep(/ Executing rnews /, ); - close JOBS; # ignore errors, uustat may fail - return $count; -} - -# select the rnews label appropriate for the compressor program used -sub unbatcher { - my ($compressor) = @_; - - $compressor =~ s%.*/%%; # Do not keep the complete path. - $compressor =~ s% .*%%; # Do not keep the optional parameters. - return $UNBATCHER{$compressor} || 'cunbatch'; -} - -############################################################################## -# batch articles for one site -sub run_site { - my ($cfg) = @_; - my ($site, $host, $funnel, $compress, $size) = @$cfg; - - logmsg("checking site $site", 'debug'); - my $maxjobs = ''; - if ($MAXJOBS) { - my $jobs = count_jobs($site); - if ($jobs >= $MAXJOBS) { - logmsg("too many jobs queued for $site"); - return; - } - $maxjobs = '-N ' . ($MAXJOBS - $jobs); - } - - $compress ||= $inn::compress; - $size ||= $MAXSIZE; - - # if exists a .work temp file left by a previous invocation, rename - # it to .work.tmp, we'll append it to the current batch file once it - # has been renamed and flushed. - if (-f "$site.work") { - rename("$site.work", "$site.work.tmp") - or logdie("cannot rename $site.work: $!", 'crit'); - } - - if (not -f $site and not -f "$site.work.tmp") { - logmsg("no batch file for site $site", 'err'); - return; - } - - rename($site, "$site.work") or logdie("cannot rename $site: $!", 'crit'); - logmsg("Flushing $funnel for site $site", 'debug'); - ctlinnd('-t120', 'flush', $funnel); - - # append the old .work temp file to the current batch file if needed - if (-f "$site.work.tmp") { - my $err = ''; - open(OUT, ">>$site.work") - or logdie("cannot open $site.work: $!", 'crit'); - open(IN, "$site.work.tmp") - or logdie("cannot open $site.work.tmp: $!", 'crit'); - print OUT while ; - close IN; - close OUT or logdie("cannot close $site.work: $!");; - unlink "$site.work.tmp" - or logmsg("cannot delete $site.work.tmp: $!", 'err'); - } - - if (not -s "$site.work") { - logmsg("no articles for $site", 'debug'); - unlink "$site.work" or logmsg("cannot delete $site.work: $!", 'err'); - } else { - if ($compress eq 'none') { - system "batcher -b $size $maxjobs $BATCHER_FLAGS " - . "-p\"$inn::uux $UUX_FLAGS %s!rnews\" $host $site.work"; - } else { - system "batcher -b $size $maxjobs $BATCHER_FLAGS " - . "-p\"{ echo '#! " . unbatcher($compress) - . "' ; exec $compress; } | " - . "$inn::uux $UUX_FLAGS %s!rnews\" $host $site.work"; - } - logmsg("batched articles for $site", 'debug'); - } -} - -############################################################################## -sub logmsg { - my ($msg, $lvl) = @_; - - syslog($lvl || 'notice', '%s', $msg); -} - -sub logdie { - my ($msg, $lvl) = @_; - - logmsg($msg, $lvl || 'err'); - unlink $lockfile; - exit 1; -} - -sub ctlinnd { - my ($cmd, @args) = @_; - - my $st = system("$inn::newsbin/ctlinnd", '-s', $cmd, @args); - logdie('Cannot run ctlinnd: ' . $!) if $st == -1; - logdie('ctlinnd returned status ' . ($st & 255)) if $st > 0; -} - -sub shlock { - my $lockfile = shift; - - my $locktry = 0; - while ($locktry < 60) { - if (system("$inn::newsbin/shlock", '-p', $$, '-f', $lockfile) == 0) { - return 1; - } - $locktry++; - sleep 2; - } - - my $lockreason; - if (open(LOCKFILE, $lockfile)) { - $lockreason = 'held by ' . ( || '?'); - close LOCKFILE; - } else { - $lockreason = $!; - } - logdie("Cannot get lock $lockfile: $lockreason"); - return undef; -} - -__END__ - -=head1 NAME - -send-uucp - Send Usenet articles via UUCP - -=head1 SYNOPSIS - -B [I ...] - -=head1 DESCRIPTION - -The B program processes batch files written by innd(8) to send -Usenet articles to UUCP sites. It reads a configuration file to control how -it behaves with various sites. Normally, it's run periodically out of cron -to put together batches and send them to remote UUCP sites. - -=head1 OPTIONS - -Any arguments provided to the program are interpreted as a list of sites -specfied in F for which batches should be generated. If no -arguments are supplied then batches will be generated for all sites listed -in that configuration file. - -=head1 CONFIGURATION - -The sites to which articles are to be sent must be configured in the -configuration file F. Each site is specified with a line of -the form: - - site[:host[:funnel]] [compressor [maxsize [batchtime]]] - -=over 4 - -=item I - -The news site name being configured. This must match a site name -from newsfeeds(5). - -=item I - -The UUCP host name to which batches should be sent for this site. -If omitted, the news site name will be used as the UUCP host name. - -=item I - -In the case of a site configured as a funnel, B needs to flush -the channel (or exploder) being used as the target of the funnel instead of -flushing the site. This is the way to tell B the name of the -channel or exploder to flush for this site. If not specified, default to -flushing the site. - -=item I - -The compression method to use for batches. This should be one of compress, -gzip or none. Arguments for the compression command may be specified by -using C<_> instead of spaces. For example, C. The default value is -C. - -=item I - -The maximum size of a single batch before compression. The default value is -500,000 bytes. - -=item I - -A comma separated list of hours during which batches should be generated for -a given site. When B runs, a site will only be processed if the -current hour matches one of the hours in I. The default is no -limitation on when to generate batches. - -=back - -Fields are seperated by spaces and only the site name needs to be specified, -with defaults being used for unspecified values. If the first character on -a line is a C<#> then the rest of the line is ignored. - -=head1 EXAMPLE - -Here is an example send-uucp.cf configuration file: - - zoetermeer gzip 1048576 5,18,22 - hoofddorp gzip 1048576 5,18,22 - pa3ebv gzip 1048576 5,18,22 - drinkel gzip 1048576 5,6,18,20,22,0,2 - manhole compress 1048576 5,18,22 - owl compress 1048576 - able - pern::MYFUNNEL! - -This defines eight UUCP sites. The first four use gzip compression and the -last three use compress. The first six use a batch size of 1MB, and the -last site (able) uses the default of 500,000 bytes. The zoetermeer, -hoofddorp, pa3ebv, and manhole sites will only have batches generated for -them during the hours of 05:00, 18:00, and 22:00, and the drinkel site will -only have batches generated during those hours and 20:00, 00:00, and 02:00. -There are no restrictions on when batches will be generated for owl or able. - -The pern site is configured as a funnel into C. B will -issue C instead of C. - -=head1 FILES - -=over 4 - -=item I/send-uucp.cf - -Configuration file specifying a list of sites to be processed. - -=back - -=head1 NOTES - -The usual flags used for a UUCP feed in the I file are C. - -=head1 SEE ALSO - -innd(8), newsfeeds(5), uucp(8) - -=head1 AUTHOR - -This program was originally written by Edvard Tuinder and then -maintained and extended by Miquel van Smoorenburg . -Marco d'Itri cleaned up the code for inclusion in INN. This -manual page was written by Mark Brown . - -=cut diff --git a/backends/sendinpaths.in b/backends/sendinpaths.in deleted file mode 100644 index aedf451..0000000 --- a/backends/sendinpaths.in +++ /dev/null @@ -1,44 +0,0 @@ -#!/bin/sh -# fixscript will replace this line with code to load innshellvars -# -# Submit path statistics based on ninpaths -# $Id: sendinpaths.in 5854 2002-11-25 17:53:06Z rra $ - -# Assuming the ninpaths dump files are in ${MOST_LOGS}/path/inpaths.%d - -cd ${MOST_LOGS}/path -ME=`${NEWSBIN}/innconfval pathhost` -report=30 -keep=14 -TMP="" -defaddr="pathsurvey@top1000.org top1000@anthologeek.net" - -# Renice to give other processes priority, since this isn't too important. -renice 20 -p $$ > /dev/null - -# Make report from (up to) $report days of dumps -LOGS=`find . -name 'inpaths.*' ! -size 0 -mtime -$report -print` -if [ -z "$LOGS" ] ; then - echo "No data has been collected this month!" - exit 1 -fi - -# for check dumps -for i in $LOGS -do - ninpaths -u $i -r $ME > /dev/null 2>&1 - if test $? -eq 0; then : - TMP="$TMP -u $i" - fi -done - -if [ "$1" = "-n" ] ; then - ninpaths $TMP -r $ME -else - ninpaths $TMP -r $ME |\ - $MAILCMD -s "inpaths $ME" ${1:-$defaddr} - # remove dumps older than $keep days - find . -name 'inpaths.*' -mtime +$keep -exec rm '{}' \; -fi - -exit 0 diff --git a/backends/sendxbatches.in b/backends/sendxbatches.in deleted file mode 100644 index ee8387b..0000000 --- a/backends/sendxbatches.in +++ /dev/null @@ -1,39 +0,0 @@ -#! /bin/sh -# fixscript will replace this line with code to load innshellvars - -# $Id: sendxbatches.in 2674 1999-11-15 06:28:29Z rra $ -# By petri@ibr.cs.tu-bs.de with mods by libove@jerry.alf.dec.com -# -# Script to send xbatches for a site, wrapped around innxbatch -# Invocation: sendxbatches ... -# -## TODO: - we should check the amount of queued batches for the site, -## to prevent disk overflow due to unreachable sites. - -if [ $# -lt 3 ] -then - echo "usage: $0 " - exit 1 -fi - -LOCK=${LOCKS}/LOCK.sendxbatches -shlock -p $$ -f ${LOCK} -if [ $? -ne 0 ] -then - echo Locked by `cat ${LOCK}` - exit 1 -fi - -trap 'rm -f ${LOCK} ; exit 1' 1 2 3 15 -site="$1" -host="$2" -shift; shift - -ctlinnd -s flush "$site" -if [ $? -ne 0 ] -then - echo "ctlinnd flush $site failed." - exit 1 -fi -sleep 5 -$NEWSBIN/innxbatch -D -v "$host" $* diff --git a/backends/shlock.c b/backends/shlock.c deleted file mode 100644 index bb4c503..0000000 --- a/backends/shlock.c +++ /dev/null @@ -1,204 +0,0 @@ -/* $Id: shlock.c 6124 2003-01-14 06:03:29Z rra $ -** -** Produce reliable locks for shell scripts, by Peter Honeyman as told -** to Rich $alz. -*/ - -#include "config.h" -#include "clibrary.h" -#include -#include -#include -#include - -#include "inn/messages.h" - - -static bool BinaryLock; - - -/* -** See if the process named in an existing lock still exists by -** sending it a null signal. -*/ -static bool -ValidLock(char *name, bool JustChecking) -{ - int fd; - int i; - pid_t pid; - char buff[BUFSIZ]; - - /* Open the file. */ - if ((fd = open(name, O_RDONLY)) < 0) { - if (JustChecking) - return false; - syswarn("cannot open %s", name); - return true; - } - - /* Read the PID that is written there. */ - if (BinaryLock) { - if (read(fd, (char *)&pid, sizeof pid) != sizeof pid) { - close(fd); - return false; - } - } - else { - if ((i = read(fd, buff, sizeof buff - 1)) <= 0) { - close(fd); - return false; - } - buff[i] = '\0'; - pid = (pid_t) atol(buff); - } - close(fd); - if (pid <= 0) - return false; - - /* Send the signal. */ - if (kill(pid, 0) < 0 && errno == ESRCH) - return false; - - /* Either the kill worked, or we're optimistic about the error code. */ - return true; -} - - -/* -** Unlink a file, print a message on error, and exit. -*/ -static void -UnlinkAndExit(char *name, int x) -{ - if (unlink(name) < 0) - syswarn("cannot unlink %s", name); - exit(x); -} - - -/* -** Print a usage message and exit. -*/ -static void -Usage(void) -{ - fprintf(stderr, "Usage: shlock [-u|-b] -f file -p pid\n"); - exit(1); -} - - -int -main(int ac, char *av[]) -{ - int i; - char *p; - int fd; - char tmp[BUFSIZ]; - char buff[BUFSIZ]; - char *name; - pid_t pid; - bool ok; - bool JustChecking; - - /* Establish our identity. */ - message_program_name = "shlock"; - - /* Set defaults. */ - pid = 0; - name = NULL; - JustChecking = false; - umask(NEWSUMASK); - - /* Parse JCL. */ - while ((i = getopt(ac, av, "bcup:f:")) != EOF) - switch (i) { - default: - Usage(); - /* NOTREACHED */ - case 'b': - case 'u': - BinaryLock = true; - break; - case 'c': - JustChecking = true; - break; - case 'p': - pid = (pid_t) atol(optarg); - break; - case 'f': - name = optarg; - break; - } - ac -= optind; - av += optind; - if (ac || pid == 0 || name == NULL) - Usage(); - - /* Create the temp file in the same directory as the destination. */ - if ((p = strrchr(name, '/')) != NULL) { - *p = '\0'; - snprintf(tmp, sizeof(tmp), "%s/shlock%ld", name, (long)getpid()); - *p = '/'; - } - else - snprintf(tmp, sizeof(tmp), "shlock%ld", (long)getpid()); - - /* Loop until we can open the file. */ - while ((fd = open(tmp, O_RDWR | O_CREAT | O_EXCL, 0644)) < 0) - switch (errno) { - default: - /* Unknown error -- give up. */ - sysdie("cannot open %s", tmp); - case EEXIST: - /* If we can remove the old temporary, retry the open. */ - if (unlink(tmp) < 0) - sysdie("cannot unlink %s", tmp); - break; - } - - /* Write the process ID. */ - if (BinaryLock) - ok = write(fd, &pid, sizeof pid) == sizeof pid; - else { - snprintf(buff, sizeof(buff), "%ld\n", (long) pid); - i = strlen(buff); - ok = write(fd, buff, i) == i; - } - if (!ok) { - syswarn("cannot write PID to %s", tmp); - close(fd); - UnlinkAndExit(tmp, 1); - } - - close(fd); - - /* Handle the "-c" flag. */ - if (JustChecking) { - if (ValidLock(name, true)) - UnlinkAndExit(tmp, 1); - UnlinkAndExit(tmp, 0); - } - - /* Try to link the temporary to the lockfile. */ - while (link(tmp, name) < 0) - switch (errno) { - default: - /* Unknown error -- give up. */ - syswarn("cannot link %s to %s", tmp, name); - UnlinkAndExit(tmp, 1); - /* NOTREACHED */ - case EEXIST: - /* File exists; if lock is valid, give up. */ - if (ValidLock(name, false)) - UnlinkAndExit(tmp, 1); - if (unlink(name) < 0) { - syswarn("cannot unlink %s", name); - UnlinkAndExit(tmp, 1); - } - } - - UnlinkAndExit(tmp, 0); - /* NOTREACHED */ - return 1; -} diff --git a/backends/shrinkfile.c b/backends/shrinkfile.c deleted file mode 100644 index 7702ff2..0000000 --- a/backends/shrinkfile.c +++ /dev/null @@ -1,390 +0,0 @@ -/* $Id: shrinkfile.c 6135 2003-01-19 01:15:40Z rra $ -** -** Shrink files on line boundaries. -** -** Written by Landon Curt Noll , and placed in the -** public domain. Rewritten for INN by Rich Salz. -** -** Usage: -** shrinkfile [-n] [-s size [-m maxsize]] [-v] file... -** -n No writes, exit 0 if any file is too large, 1 otherwise -** -s size Truncation size (0 default); suffix may be k, m, -** or g to scale. Must not be larger than 2^31 - 1. -** -m maxsize Maximum size allowed before truncation. If maxsize -** <= size, then it is reset to size. Default == size. -** -v Print status line. -** -** Files will be shrunk an end of line boundary. In no case will the -** file be longer than size bytes if it was longer than maxsize bytes. -** If the first line is longer than the absolute value of size, the file -** will be truncated to zero length. -** -** The -n flag may be used to determine of any file is too large. No -** files will be altered in this mode. -*/ - -#include "config.h" -#include "clibrary.h" -#include -#include -#include -#include - -#include "inn/innconf.h" -#include "inn/messages.h" -#include "libinn.h" - -#define MAX_SIZE 0x7fffffffUL - - -/* -** Open a safe unique temporary file that will go away when closed. -*/ -static FILE * -OpenTemp(void) -{ - FILE *F; - char *filename; - int fd; - - filename = concatpath(innconf->pathtmp, "shrinkXXXXXX"); - fd = mkstemp(filename); - if (fd < 0) - sysdie("cannot create temporary file"); - F = fdopen(fd, "w+"); - if (F == NULL) - sysdie("cannot fdopen %s", filename); - unlink(filename); - free(filename); - return F; -} - - -/* -** Does file end with \n? Assume it does on I/O error, to avoid doing I/O. -*/ -static int -EndsWithNewline(FILE *F) -{ - int c; - - if (fseeko(F, 1, SEEK_END) < 0) { - syswarn("cannot seek to end of file"); - return true; - } - - /* return the actual character or EOF */ - if ((c = fgetc(F)) == EOF) { - if (ferror(F)) - syswarn("cannot read last byte"); - return true; - } - return c == '\n'; -} - - -/* -** Add a newline to location of a file. -*/ -static bool -AppendNewline(char *name) -{ - FILE *F; - - if ((F = xfopena(name)) == NULL) { - syswarn("cannot add newline"); - return false; - } - - if (fputc('\n', F) == EOF - || fflush(F) == EOF - || ferror(F) - || fclose(F) == EOF) { - syswarn("cannot add newline"); - return false; - } - - return true; -} - -/* -** Just check if it is too big -*/ -static bool -TooBig(FILE *F, off_t maxsize) -{ - struct stat Sb; - - /* Get the file's size. */ - if (fstat((int)fileno(F), &Sb) < 0) { - syswarn("cannot fstat"); - return false; - } - - /* return true if too large */ - return (maxsize > Sb.st_size ? false : true); -} - -/* -** This routine does all the work. -*/ -static bool -Process(FILE *F, char *name, off_t size, off_t maxsize, bool *Changedp) -{ - off_t len; - FILE *tmp; - struct stat Sb; - char buff[BUFSIZ + 1]; - int c; - size_t i; - bool err; - - /* Get the file's size. */ - if (fstat((int)fileno(F), &Sb) < 0) { - syswarn("cannot fstat"); - return false; - } - len = Sb.st_size; - - /* Process a zero size request. */ - if (size == 0 && len > maxsize) { - if (len > 0) { - fclose(F); - if ((F = fopen(name, "w")) == NULL) { - syswarn("cannot overwrite"); - return false; - } - fclose(F); - *Changedp = true; - } - return true; - } - - /* See if already small enough. */ - if (len <= maxsize) { - /* Newline already present? */ - if (EndsWithNewline(F)) { - fclose(F); - return true; - } - - /* No newline, add it if it fits. */ - if (len < size - 1) { - fclose(F); - *Changedp = true; - return AppendNewline(name); - } - } - else if (!EndsWithNewline(F)) { - if (!AppendNewline(name)) { - fclose(F); - return false; - } - } - - /* We now have a file that ends with a newline that is bigger than - * we want. Starting from {size} bytes from end, move forward - * until we get a newline. */ - if (fseeko(F, -size, SEEK_END) < 0) { - syswarn("cannot fseeko"); - fclose(F); - return false; - } - - while ((c = getc(F)) != '\n') - if (c == EOF) { - syswarn("cannot read"); - fclose(F); - return false; - } - - /* Copy rest of file to temp. */ - tmp = OpenTemp(); - err = false; - while ((i = fread(buff, 1, sizeof buff, F)) > 0) - if (fwrite(buff, 1, i, tmp) != i) { - err = true; - break; - } - if (err) { - syswarn("cannot copy to temporary file"); - fclose(F); - fclose(tmp); - return false; - } - - /* Now copy temp back to original file. */ - fclose(F); - if ((F = fopen(name, "w")) == NULL) { - syswarn("cannot overwrite file"); - fclose(tmp); - return false; - } - fseeko(tmp, 0, SEEK_SET); - - while ((i = fread(buff, 1, sizeof buff, tmp)) > 0) - if (fwrite(buff, 1, i, F) != i) { - err = true; - break; - } - if (err) { - syswarn("cannot overwrite file"); - fclose(F); - fclose(tmp); - return false; - } - - fclose(F); - fclose(tmp); - *Changedp = true; - return true; -} - - -/* -** Convert size argument to numeric value. Return -1 on error. -*/ -static off_t -ParseSize(char *p) -{ - off_t scale; - unsigned long str_num; - char *q; - - /* Skip leading spaces */ - while (ISWHITE(*p)) - p++; - if (*p == '\0') - return -1; - - /* determine the scaling factor */ - q = &p[strlen(p) - 1]; - switch (*q) { - default: - return -1; - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - scale = 1; - break; - case 'k': case 'K': - scale = 1024; - *q = '\0'; - break; - case 'm': case 'M': - scale = 1024 * 1024; - *q = '\0'; - break; - case 'g': case 'G': - scale = 1024 * 1024 * 1024; - *q = '\0'; - break; - } - - /* Convert string to number. */ - if (sscanf(p, "%lud", &str_num) != 1) - return -1; - if (str_num > MAX_SIZE / scale) - die("size is too big"); - - return scale * str_num; -} - - -/* -** Print usage message and exit. -*/ -static void -Usage(void) -{ - fprintf(stderr, - "Usage: shrinkfile [-n] [ -m maxsize ] [-s size] [-v] file..."); - exit(1); -} - - -int -main(int ac, char *av[]) -{ - bool Changed; - bool Verbose; - bool no_op; - FILE *F; - char *p; - int i; - off_t size = 0; - off_t maxsize = 0; - - /* First thing, set up our identity. */ - message_program_name = "shrinkfile"; - - /* Set defaults. */ - Verbose = false; - no_op = false; - umask(NEWSUMASK); - - if (!innconf_read(NULL)) - exit(1); - - /* Parse JCL. */ - while ((i = getopt(ac, av, "m:s:vn")) != EOF) - switch (i) { - default: - Usage(); - /* NOTREACHED */ - case 'n': - no_op = true; - break; - case 'm': - if ((maxsize = ParseSize(optarg)) < 0) - Usage(); - break; - case 's': - if ((size = ParseSize(optarg)) < 0) - Usage(); - break; - case 'v': - Verbose = true; - break; - } - if (maxsize < size) { - maxsize = size; - } - ac -= optind; - av += optind; - if (ac == 0) - Usage(); - - while ((p = *av++) != NULL) { - if ((F = fopen(p, "r")) == NULL) { - syswarn("cannot open %s", p); - continue; - } - - /* -n (no_op) or normal processing */ - if (no_op) { - - /* check if too big and exit zero if it is */ - if (TooBig(F, maxsize)) { - if (Verbose) - notice("%s is too large", p); - exit(0); - /* NOTREACHED */ - } - - /* no -n, do some real work */ - } else { - Changed = false; - if (!Process(F, p, size, maxsize, &Changed)) - syswarn("cannot shrink %s", p); - else if (Verbose && Changed) - notice("shrunk %s", p); - } - } - if (no_op && Verbose) { - notice("did not find a file that was too large"); - } - - /* if -n, then exit non-zero to indicate no file too big */ - exit(no_op ? 1 : 0); - /* NOTREACHED */ -} diff --git a/contrib/Makefile b/contrib/Makefile deleted file mode 100644 index f09ab09..0000000 --- a/contrib/Makefile +++ /dev/null @@ -1,56 +0,0 @@ -## $Id: Makefile 6299 2003-04-20 19:04:14Z vinocur $ -## -## There are no installation rules or other top-level rules for this -## directory as it's not properly part of INN. Installation should be -## done by the user by hand for those files that they're interested in. - -include ../Makefile.global - -top = .. -CFLAGS = $(GCFLAGS) - -ALL = archivegz backlogstat backupfeed cleannewsgroups delayer \ - findreadgroups makeexpctl makestorconf mlockfile newsresp \ - pullart reset-cnfs respool showtoken stathist thdexpire \ - tunefeed - -all: $(ALL) - -warnings: - $(MAKE) COPT='$(WARNINGS)' all - -clean clobber distclean: - rm -f *.o $(ALL) - rm -rf .libs - -$(FIXSCRIPT): - @echo Run configure before running make. See INSTALL for details. - @exit 1 - - -## Compilation rules. - -LINK = $(LIBLD) $(LDFLAGS) -o $@ -FIX = $(FIXSCRIPT) - -STORELIBS = $(LIBSTORAGE) $(LIBINN) $(EXTSTORAGELIBS) $(LIBS) - -expirectl: expirectl.o ; $(LINK) expirectl.o -mlockfile: mlockfile.o ; $(LINK) mlockfile.o -newsresp: newsresp.o ; $(LINK) newsresp.o $(LIBS) -pullart: pullart.o ; $(LINK) pullart.o $(LIBINN) -reset-cnfs: reset-cnfs.o ; $(LINK) reset-cnfs.o -respool: respool.o ; $(LINK) respool.o $(STORELIBS) - -archivegz: archivegz.in $(FIX) ; $(FIX) -i archivegz.in -backlogstat: backlogstat.in $(FIX) ; $(FIX) backlogstat.in -backupfeed: backupfeed.in $(FIX) ; $(FIX) -i backupfeed.in -cleannewsgroups: cleannewsgroups.in $(FIX) ; $(FIX) cleannewsgroups.in -delayer: delayer.in $(FIX) ; $(FIX) -i delayer.in -findreadgroups: findreadgroups.in $(FIX) ; $(FIX) findreadgroups.in -makeexpctl: makeexpctl.in $(FIX) ; $(FIX) makeexpctl.in -makestorconf: makestorconf.in $(FIX) ; $(FIX) makestorconf.in -showtoken: showtoken.in $(FIX) ; $(FIX) -i showtoken.in -stathist: stathist.in $(FIX) ; $(FIX) -i stathist.in -thdexpire: thdexpire.in $(FIX) ; $(FIX) thdexpire.in -tunefeed: tunefeed.in $(FIX) ; $(FIX) -i tunefeed.in diff --git a/contrib/README b/contrib/README deleted file mode 100644 index e7e8866..0000000 --- a/contrib/README +++ /dev/null @@ -1,150 +0,0 @@ -This directory contains unsupported contributions to INN. Most of these -programs are of interest to a limited set of sites, require some manual -modifications to make work, and/or are separately maintained independent -of INN. Programs in here may or may not have been tested on the latest -version of INN, so keep that in mind when trying them out. The INN -developers may not be able to answer bug reports for these utilities; it's -best to send them to the original author. - -Volunteers who would like to take particularly useful applications in this -directory and make them suitable for inclusion in INN proper are heartily -encouraged, but discuss this on inn-workers@isc.org. Sometimes there's a -reason why this hasn't already been done or something specific that's -needed before they can be included. - -Type "make " to build any of the following programs and then copy -the binary to somewhere on your PATH to use it. For details on what each -program does, see below, as well as the comments at the beginning of each -file (if any). - -In addition to these files, also see the contrib section of the INN FTP -site at for more software designed -to work with INN. - - ------------------------- - -archivegz - - A compressing version of archive, writing out .gz files instead of - plain text files. May not work with the storage API without some - changes to use sm. - -backlogstat - - Prints informations about the current state of innfeed's backlog, if - any. - -backupfeed - - Another version of suck or pullnews that downloads posts from a remote - news server and offers them to the local news server. - -cleannewsgroups - - Performs various cleanups on the newsgroups file. - -count_overview.pl - - Counts the groups in a bunch of Xref records. - -delayer - - Sits in a data stream and delays it by some constant period of time. - Mostly useful for delaying innfeed feeds to allow cancels a chance to - remove articles before innfeed sends them to your peers. See the - beginning of the file for an example of how to use it. - -expirectl - - Automatically builds expire.ctl based on current available disk space - and a template, adjusting the expiration times of groups based on a - weight and the available space. Uses a template expire.ctl.ctl file; - see the end of expirectl.c for a sample. - -findreadgroups - - Scans the news log files and generates a file giving readership counts - by newsgroup. Used by makeexpctl and makestorconf. - -fixhist - - Performs various cleanups and sanity checks on the history database. - -innconfcheck - - Merges your inn.conf settings with the inn.conf man page to make it - easier to be sure that your settings match what you want. Edit this - script to add the correct paths to the man page; see the comments at - the beginning of this script. - -makeexpctl - - Generates an expire.ctl based on what newsgroups are actually read. - Uses data generated by findreadgroups. This script will require - editing before being usable for your server. - -makestorconf - - Generates a storage.conf file putting frequently read newsgroups into - timecaf rather than CNFS. Uses data gefnerated by findreadgroups. - This script will require editing before being usable for your server. - -mkbuf - - Creates a CNFS cycbuff; see the comments at the beginning of - this script. - -mlockfile - - Locks files given on the command line into memory using mlock (only - tested on Solaris). Useful primarily for locking the history files - (history.hash and history.index) into memory on a system with - sufficient memory to speed history lookups in innd. This seems to - help some systems quite a lot and others not at all. - -newsresp - - Opens an NNTP channel to a server and takes a peek at various response - times. Can check the round-trip time and the history lookup time. - See the comments at the beginning of the source for more details. - -pullart - - Attempts to pull news articles out of CNFS cycbuffs. Useful for - emergency recoveries. - -reset-cnfs - - Clears a CNFS cycbuff; see the comments at the beginning of - this script. - -respool - - Takes a list of tokens on stdin and respools them, by retrieving the - article, storing it again, and then calling SMcancel on the previous - instance of the article. Note that after running this program, you'd - need to rebuild the history and overview, since it doesn't update - either. - -showtoken - - Decodes storage API tokens. - -stathist - - Parses and summarizes the log files created by the history profiling - code. - -thdexpire - - A dynamic expire daemon for timehash and timecaf spools. It should - be started along with innd and periodically looks if news spool space - is getting tight, and then frees space by removing articles until - enough is free. It is an adjunct to (not a replacement for) INN's - expire program. - -tunefeed - - Given two active files, attempts to produce a good set of wildmat - patterns for newsfeeds to minimize the number of rejects. For full - documentation, run "perldoc tunefeed". diff --git a/contrib/archivegz.in b/contrib/archivegz.in deleted file mode 100644 index e4f06b7..0000000 --- a/contrib/archivegz.in +++ /dev/null @@ -1,334 +0,0 @@ -#!/usr/bin/perl -# Copyright 1999 Stephen M. Benoit, Service Providers of America. -# See notice at end of this file. -# -# Filename: archivegz.pl -# Author: Stephen M. Benoit (benoits@servicepro.com) -# Created: Wed Apr 14 13:56:01 1999 -# Version: $Id: archivegz.in 4329 2001-01-14 13:47:52Z rra $ -# -$RCSID='$Id: archivegz.in 4329 2001-01-14 13:47:52Z rra $ '; - -# Specify command line options, and decode the command line. - -require 'newgetopt.pl'; -require 'newusage.pl'; -@opts = - ( - "help|usage;;print this message", - "version;;print version", - "a=s;;directory to archive in instead of the default", - "f;;directory names will be flattened out", - "i=s;;append one line to the index file for each article (Destination name, Message ID, Subject)", - "m;; Files are copied by making a link. Not applicable, ignored", - "r;;Suppress stderr redirection to /var/log/news/errlog", - "n=s;;the news spool (source) directory (default=/var/spool/news/)", - "t=i;;timeout that separates batches (default 10 seconds)", - ";;input", - # Examples. - # - # "OPT;;Option without an argument", - # "OPT!;;Negatable option without an argument", - # "VAR=T;;Option with mandatory argumet T = s(tring),i(nteger), or f(loat). - # "VAR:T;;Option with optional argument. - # "OPT|AAA|BBB";;AAA and BBB are aliases for OPT", - # "VAR=T@";;Push option argument onto array @opt_VAR" - ); -$ignorecase = 0; -$badopt = !&NGetOpt(&NMkOpts(@opts)); -# $badarg = (@ARGV != 0); -if ($badarg || $badopt || $opt_help) - { - &NUsage($0,0,'',@opts); - exit ($badopt||$badarg); - } -if ($opt_version) {print STDERR "$RCSID\n"; exit 0} - -# -------------------------------------------------------------------- - -# --- constants and defaults --- -$NEWS_ROOT = "/var/spool/news/"; -$NEWS_ERR = "/var/log/news/errlog"; -$NEWS_ARCHIVE = $NEWS_ROOT . "news.archive/"; -$timeout = 10; -if ($opt_t) - { $timeout = $opt_t;} -if ($timeout<1) {$timeout=1;} - -# -------------------------------------------------------------------- - -sub regexp_escape - { - local($data)=@_; - - $data =~ s+\\+\\\\+gi; # replace \ with \\ - $data =~ s+\/+\\\/+gi; # replace / with \/ - - $data =~ s/([\+\*\?\[\]\(\)\{\}\.\|])/\\$1/gi; # replace +*?[](){}.| - - return $data; - } - -sub fhbits { - local(@fhlist) = split(' ',$_[0]); - local($bits); - for (@fhlist) { - vec($bits,fileno($_),1) = 1; - } - $bits; -} - -sub timed_getline - { - my ($fileh,$timeout)=@_; - my $filehandle = (ref($fileh) - ? (ref($fileh) eq 'GLOB' - || UNIVERSAL::isa($fileh, 'GLOB') - || UNIVERSAL::isa($fileh, 'IO::Handle')) - : (ref(\$fileh) eq 'GLOB')); - local(*FILEH) = *$fileh{FILEHANDLE}; - - local($rin,$win,$ein); - local($rout,$wout,$eout); - $rin = $win = $ein = ''; - $rin = fhbits('FILEH'); - $ein = $rin | $win; - local($nfound); - local($offset)=0; - local($accum)=''; - local($done)=0; - local($result); - - $nfound = select($rout=$rin, $wout=$win, $eout=$ein, $timeout); - - if ($nfound>0) - { - - # use sysread() to get characters up to end-of-line (incl.) - while (!$done) - { - $result = sysread(FILEH, $accum, 1, $offset); - if ($result<=0) - { - $done=1; - return undef; - } - - if (substr($accum,$offset,1) eq "\n") - { - $done=1; - } - else - { - $offset+=$result; - } - } - } - return $accum; - } - -# -------------------------------------------------------------------- - -# --- source spool directory --- -if ($opt_n) - { - if ($opt_n !~ /^\//) # absolute path? - { $opt_n = $NEWS_ROOT . $opt_n; } - if ($opt_n !~ /\/$/) # must end with / - { $opt_n .= '/'; } - $NEWS_ROOT = $opt_n; - } - -# --- archive directory --- -if ($opt_a) - { - if ($opt_a !~ /^\//) # absolute path? - { $opt_a = $NEWS_ROOT . $opt_a; } - if ($opt_a !~ /\/$/) # must end with / - { $opt_a .= '/'; } - $NEWS_ARCHIVE = $opt_a; - } - -# --- redirect stderr --- -if (!$opt_r) - { - open(SAVEERR, ">&STDERR"); - open(STDERR, ">>$NEWS_ERR") || die "Can't redirect stderr"; - } - -# --- get input file opened --- -if ($infilename=shift(@ARGV)) - { - if ($infilename !~ /^\//) # absolute filename? - { - $infilename = $NEWS_ROOT . $infilename; - } - - } -else - { - $infilename="-"; - } -open(INFILE,"<$infilename"); - -$done=0; -while (!$done) - { - %sourcefile=(); - %destfile=(); - %destname=(); - - - # --- loop over each line in infile --- - # comments start with '#', ignore blank lines, each line is a filename - while ($srcfile = &timed_getline(INFILE,$timeout)) - { - if ($srcfile =~ /\#/) {$srcfile = $`;} - if ($srcfile =~ /^\s*/) {$srcfile = $';} - if ($srcfile =~ /\s*$/) {$srcfile = $`;} - if ($srcfile) # if a filename survived all that... - { - if ($srcfile !~ /^\//) # absolute filename? - { - $srcfile = $NEWS_ROOT . $srcfile; - } - # $srcfile is now a valid, absolute filename - # split filename into news directory, newsgroup and article number - $artnum=-1; - $remaining=$srcfile; - if ($remaining =~ /\/(\d*)$/) # remove / and article number - { $artnum = $1; $remaining=$`;} - $regex = ®exp_escape($NEWS_ROOT); - if ($remaining =~ /^$regex/) # split off news dir - { $newsdir = $&; $grpdir = $';} - else - { $newsdir = ''; $grpdir = $remaining; } # ... otherwise, grp = dir - $newsgrp = $grpdir; - $newsgrp =~ s/\//\./g; # replace slash (/) with dot (.) - if ($opt_f) - { - $grpdir = "$newsgrp.gz"; - } - else - { $grpdir .= "/archive.gz"; } - $destfile = $NEWS_ARCHIVE . $grpdir; - - # print STDERR "$srcfile --> $newsgrp --> $destfile\n"; - if ($sourcefile{$newsgrp}) {$sourcefile{$newsgrp} .= " ";} - $sourcefile{$newsgrp} .= $srcfile; - $destfile{$newsgrp} = $destfile; - $destname{$newsgrp} = $grpdir; - } - } - - # --- is there anything to do at this time? --- - if (%destfile) - { - - # --- open INDEX --- - if ($opt_i) - { - # make sure directory exists - if ($opt_i =~ /\/[^\/]*$/) - { - $dirbase=$`; - system("mkdir -p $dirbase"); - } - open(INDEX,">>$opt_i"); - } - - # --- make sure that archive file can be written (make parent dirs) --- - if ($destfile{$group} =~ /\/[^\/]*$/) - { - $dirbase=$`; - system("mkdir -p $dirbase"); - } - - # --- process each article --- - foreach $group (keys(%destfile)) - { - # --- gzip the concatenated document, appending archive file --- - open(GZIP, "|gzip -c >> $destfile{$group}") || die "Can't open gzip"; - - # --- concatenate the articles, keeping header info if needed --- - @accum_headers=(); - foreach $srcfile (split(/\s+/, $sourcefile{$group})) - { - # print STDERR "reading $srcfile...\n"; - $this_doc=''; - open(DOC, "<$srcfile"); - while ($line=) - { - $this_doc .= $line; - } - close(DOC); - print GZIP $this_doc; - if ($opt_i) - { - # --- get header information and store it in index - $subject=''; $mesageid=''; $destname=''; - if ($this_doc =~ /Subject:\s*(.*)/) - { $subject = $1; } - if ($subject =~ /^\s*/) {$subject = $';} - if ($subject =~ /\s*$/) {$subject = $`;} - if ($this_doc =~ /Message-ID:\s*(.*)/) - {$messageid = $1; } - if ($messageid =~ /^\s*/) {$messageid = $';} - if ($messageid =~ /\s*$/) {$messageid = $`;} - - print INDEX "$destname{$group} $messageid $subject\n"; - } - } - - close(GZIP); - } - - # --- close index file --- - if ($opt_i) - { - close(INDEX); - } - } - - if (!defined($srcfile)) # file was closed - { - $done=1; - last; # "break" - } - - } - -# --- restore stderr --- -if (!$opt_r) - { - close(STDERR); - open(STDERR,">>&SAVEERR"); - } - -# --- close input file --- -close(INFILE); - - -__END__ -# Local Variables: -# mode: perl -# End: - -# Copyright 1999 Stephen M. Benoit, Service Providers of America (SPA). -# -# Permission to use, copy, modify, and distribute this software and its -# documentation for any purpose without fee is hereby granted without fee, -# provided that the above copyright notice appear in all copies and that both -# that copyright notice and this permission notice appear in supporting -# documentation, and that the name of SPA not be used in advertising or -# publicity pertaining to distribution of the software without specific, -# written prior permission. SPA makes no representations about the -# suitability of this software for any purpose. It is provided "as is" -# without express or implied warranty. -# -# SPA DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL -# SPA BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY -# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN -# AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/contrib/auth_pass.README b/contrib/auth_pass.README deleted file mode 100644 index 6919fb2..0000000 --- a/contrib/auth_pass.README +++ /dev/null @@ -1,75 +0,0 @@ -This directory contains sample authorization programs for use with the -'authinfo generic' command in nnrpd. - -The first program in here is from Doug Needham I have successfully -tested this program when connecting to nnrpd by hand, but I've not -taken the time to figure out how to get my newsreader to use -'authinfo generic'. There is no Makefile here and no serious -testing of it, so it's not integrated. If you have success using -it and care to share what you've done. Please drop me a note -(). Thanks. - - ---------------------------------------------------------------------------- - -Replied: Fri, 26 Jul 1996 19:29:17 +0200 -Replied: Douglas Wade Needham -Received: by gw.home.vix.com id UAA05867; Thu, 25 Jul 1996 20:45:27 -0700 (PDT) -Received: (from dneedham@localhost) by dneedham.inhouse.compuserve.com (8.7.4/8.6.9) id XAA21103; Thu, 25 Jul 1996 23:45:25 -0400 (EDT) -From: Douglas Wade Needham -Message-Id: <199607260345.XAA21103@dneedham.inhouse.compuserve.com> -Subject: A sample program for authinfo generic (for inn 1.5) -To: inn-workers@vix.com (INN Gurus/Workers) -Date: Thu, 25 Jul 1996 23:45:25 -0400 (EDT) -Cc: inn@isc.org, brister@vix.com (James A. Brister) -X-Mailer: ELM [version 2.4 PL25] -MIME-Version: 1.0 -Content-Type: multipart/mixed; boundary=%#%record%#% -Status: U - ---%#%record%#% -Content-Type: text/plain; charset=US-ASCII -Content-Transfer-Encoding: 7bit -Content-Length: 1894 - -Hi folks... - -Finally started to get some time to clear some things from my todo list...Here -is a sample program which can be used by "authinfo generic" to validate a user -against the password file on the news host. While not a great example, it does -demonstrate how you can write an authentication program. All I ask is that -credit be given. - -A couple of notes that I have found out about these programs for those of you -who may be interested in writing your own... - -1) These programs have stdin and stdout connected all the way back to the - reader, so they can carry on a dialog in whatever fashion they want to - with the user's news reader. This can include passing Kerberos tickets, - encrypted or hashed passwords, or doing a challenge-response type session - for authenticating the user rather than passing the password in clear-text - across the network. - -2) Regardless of the outcome, the authentication program must send NNRPD a - record such as is found in nnrp.access by writing it to stderr. - -3) Successful authentication is indicated by a zero exit status, and - unsuccessful authentication is indicated by a non-zero exit status. - -4) Need I say it (again)...these programs can be a security hole unless care is - taken to avoid SUID programs and those that transmit/recieve passwords in - the clear (especially those that use login passwords). We should give some - thought to doing a similiar program for Kerberos authentication (what sort - of instance should we use???) and other authentication methods such as - Compuserve's Distributed Authentication (guess I should do this one once the - standard is finialized with the IETF 8) ). - -Also, a question for the list as a whole... what readers easily support -authinfo generic (including running a program at the reader's end to do things -like challenge-response)??? - -Well...here it is...enjoy 8)... - -- doug - -#### See auth_pass.c ##### diff --git a/contrib/auth_pass.c b/contrib/auth_pass.c deleted file mode 100644 index 7ecf0a1..0000000 --- a/contrib/auth_pass.c +++ /dev/null @@ -1,163 +0,0 @@ -/* - * auth_pass.c ( $Revision: 6141 $ ) - * - * Abstract: - * - * This module is the complete source for a sample "authinfo generic" - * program. This program takes a user's login name and password - * (supplied either as arguments or as responses to prompts) and - * validates them against the contents of the password database. - * - * If the user properly authenticates themselves, a nnrp.auth style - * record indicating the user's authenticated login and permitting - * reading and posting to all groups is output on stderr (for reading by - * nnrpd) and the program exits with a 0 status. If the user fails to - * authenticate, then a record with the attempted login name and no - * access is output on stderr and a non-zero exit status is returned. - * - * Exit statuses: - * 0 Successfully authenticated. - * 1 getpeername() failed, returned a bad address family, or - * gethostbyaddr() failed. - * 2 Entry not found in password file. - * 3 No permission to read passwords, or password field is '*'. - * 4 Bad password match. - * - * Environment: - * Run by nnrpd with stdin/stdout connected to the reader and stderr - * connected back to nnrpd. This program will need to be run as suid - * root on systems where passwords are stored in a file readable only by - * root. - * - * Written 1996 July 6 by Douglas Wade Needham (dneedham@oucsace.cs.ohiou.edu). - * - */ - -#include "config.h" -#include "clibrary.h" -#include "portable/socket.h" -#include -#include - - -main(int argc, char** argv) -/*+ - * Abstract: - * Main routine of the program, implementing all prompting, validation, - * and status returns. - * - * Arguments: - * argc Argument count. - * argv Null terminated argument vector. - * - * Returns: - * Exits according to program status values. - * - * Variables: - * hp Pointer to host entry. - * length General integer variable - * password Password given by user. - * peername Hostname of the peer. - * pwd Pointer to entry from passwd file. - * sin Socket address structure. - * username User's login name. - */ -{ - struct hostent * hp; - int length; - char password[256]; - char peername[1024]; - struct passwd * pwd; - struct sockaddr_in sin; - char username[32]; - - /* - * Get the user name and password if needed. - */ - if (argc<2) { - fprintf(stdout, "Username: "); fflush(stdout); - fgets(username, sizeof(username), stdin); - } else { - strlcpy(username, argv[1], sizeof(username)); - } - if (argc<3) { - fprintf(stdout, "Password: "); fflush(stdout); - fgets(password, sizeof(password), stdin); - } else { - strlcpy(password, argv[2], sizeof(password)); - } - - /* - * Strip CR's and NL's from the end. - */ - length = strlen(username)-1; - while (username[length] == '\r' || username[length] == '\n') { - username[length--] = '\0'; - } - length = strlen(password)-1; - while (password[length] == '\r' || password[length] == '\n') { - password[length--] = '\0'; - } - - /* - * Get the hostname of the peer. - */ - length = sizeof(sin); - if (getpeername(0, (struct sockaddr *)&sin, &length) < 0) { - if (!isatty(0)) { - fprintf(stderr, "cant getpeername()::%s:+:!*\n", username); - exit(1); - } - strlcpy(peername, "stdin", sizeof(peername)); - } else if (sin.sin_family != AF_INET) { - fprintf(stderr, "Bad address family %ld::%s:+:!*\n", - (long)sin.sin_family, username); - exit(1); - } else if ((hp = gethostbyaddr((char *)&sin.sin_addr, sizeof(sin.sin_addr), AF_INET)) == NULL) { - strlcpy(peername, inet_ntoa(sin.sin_addr), sizeof(peername)); - } else { - strlcpy(peername, hp->h_name, sizeof(peername)); - } - - /* - * Get the user name in the passwd file. - */ - if ((pwd = getpwnam(username)) == NULL) { - - /* - * No entry in the passwd file. - */ - fprintf(stderr, "%s::%s:+:!*\n", peername, username); - exit(2); - } - - /* - * Make sure we managed to read in the password. - */ - if (strcmp(pwd->pw_passwd, "*")==0) { - - /* - * No permission to read passwords. - */ - fprintf(stderr, "%s::%s:+:!*\n", peername, username); - exit(3); - } - - /* - * Verify the password. - */ - if (strcmp(pwd->pw_passwd, crypt(password, pwd->pw_passwd))!=0) { - - /* - * Password was invalid. - */ - fprintf(stderr, "%s::%s:+:!*\n", peername, username); - exit(4); - } - - /* - * We managed to authenticate the user. - */ - fprintf(stderr, "%s:RP:%s:+:*\n", peername, username); - exit(0); -} diff --git a/contrib/backlogstat.in b/contrib/backlogstat.in deleted file mode 100644 index 70da166..0000000 --- a/contrib/backlogstat.in +++ /dev/null @@ -1,118 +0,0 @@ -#!/usr/bin/perl -# fixscript will replace this line with require innshellvars.pl - -# backlogstat - display backlog to sites -# based on bklog by bill davidsen - -# breaks if backlog-directory in innfeed.conf is not "innfeed" -my $dir = "$inn::pathspool/innfeed"; -my $Revision = '1.8'; - -use strict; -use warnings; - -use Getopt::Std; -use vars qw($opt_H $opt_h $opt_n $opt_t $opt_k $opt_S $opt_d); -$| = 1; - -# option processing -&getopts('HhntkS:d:') || &Usage; -&Usage if $opt_h; - -# open the directory; -$dir = $opt_d if $opt_d; -print "$opt_d\n"; -chdir($dir) or die "Can't cd to $dir"; -opendir(DIR, ".") or die "Can't open dir"; - -my %nodes; -while (my $name = readdir(DIR)) { - # must be a file, correct name, non-zero size - my $size; - next unless -f $name; - next unless ($size = -s $name); - next unless $name =~ m/.*\.(in|out)put/; - my $io = $1; - (my $nodename = $name) =~ s/\..*//; - - # check for only some sites wanted - next if ($opt_S && $nodename !~ /^${opt_S}.*/); - # here we do the counts if asked - if ($opt_n) { - # open the file and count lines - if (open(IN, "<$name")) { - if ($name =~ m/.*\.input/) { - my $offset = + 0; - seek(IN, $offset, 0); - } - $size = 0; - for ($size = 0; ; ++$size) {}; - close IN; - } - } else { - # get the offset on .input files - if ($name =~ m/.*\.input/ && open(IN, "<$name")) { - my $offset = + 0; - $size -= $offset; - close IN; - } - } - $nodes{$nodename} = () unless defined $nodes{$nodename}; - $nodes{$nodename}->{$io} = ( $opt_k ? $size / 1024 : $size ); -} -closedir DIR; - -# output the data for each node -if (my $numnodes = keys %nodes) { - if ($opt_H) { - if ($opt_n) { - print " <---------- posts ----------->\n"; - } else { - print " <---------- bytes ----------->\n"; - } - } - my $ofmt; - if ($opt_k) { - print " input(k) output(k) total(k) Feed Name\n" if $opt_H; - $ofmt = ( $opt_n ? "%10.2f" : "%10.1f" ); - } else { - print " input output total Feed Name\n" if $opt_H; - $ofmt = "%10d"; - } - for my $node (sort keys %nodes) { - my $hash = $nodes{$node}; - my $size_in = $hash->{in} || 0; - my $size_out = $hash->{out} || 0; - my $size_tot = $size_in + $size_out; - printf "${ofmt} ${ofmt} ${ofmt} %s\n", - $size_in, $size_out, $size_tot, $node; - } -} else { - print "NO backlog!\n"; -} - -exit 0; - -sub Usage -{ - print "\n" - . "bklog - print innfeed backlog info - v$Revision\n" - . "\n" - . "Format:\n" - . " bklog [ options ]\n" - . "\n" - . "Options:\n" - . " -H output a header at the top of the output\n" - . " -k scale all numbers in k (1024) units\n" - . " -n count number of arts, not bytes of backlog filesize\n" - . " Note: this may be SLOW for large files!\n" - . " -Sxx Display only site names starting with xx\n" - . " -d dir Use \"dir\" instead of \$pathspool/innfeed\n" - . "\n" - . " -h HELP - this is all, you got it!\n" - . "\n"; - - exit 1; -} - - diff --git a/contrib/backupfeed.in b/contrib/backupfeed.in deleted file mode 100644 index 815fd74..0000000 --- a/contrib/backupfeed.in +++ /dev/null @@ -1,249 +0,0 @@ -#! /usr/bin/perl -w -# -# Date: 26 Jun 1999 17:59:00 +0200 -# From: kaih=7Jbfpa7mw-B@khms.westfalen.de (Kai Henningsen) -# Newsgroups: news.software.nntp -# Message-ID: <7Jbfpa7mw-B@khms.westfalen.de> -# Subject: Re: Version of pullnews that support authentication? -# -# [...] -# I'm appending a script I wrote (called backupfeed.pl for some reason). Hmm -# ... oh, I hereby put that into the public domain. Use as you see fit. If -# it breaks, you get to keep all the parts. -# -# Needs the newer Net::NNTP versions for the MODE READER fix. -# -# This thing is both faster and uses far less memory than suck. And it -# inserts a predictable Path: entry (in case the host you pull from -# doesn't). -# -# It's in production use as a backup to regular feeds, so it specifically -# fetches only old articles unless you say -p 1 (default is -p 0.6666...). - -use strict; -use Net::NNTP; -use DB_File; -use Data::Dumper; -use Getopt::Std; -use vars qw($Group $Host $Pos $Rc %Rc $Starttime - $opt_S $opt_T $opt_d $opt_p $opt_s $opt_t); - -my ( @groups, $localhost, $remotehost, $accepted, $rejected, $lockf, - $history, $acc, $rej, $his, @parms, $from, $to, $art, %err ); - -$| = 1; - -$opt_S = 10; # sleep between groups -$opt_T = 10000; # max running time -$opt_d = 0; # debugging -$opt_p = 2/3; # how many articles to fetch -$opt_s = 0; # sleep between articles -$opt_t = 0; # timeout for NNTP connections -getopts("dt:p:s:S:T:"); - -die <> /var/log/news/backupfeed.$Host" or die "normal log: $!"; -autoflush LOG; - -open ERR, ">> /var/log/news/backupfeed.$Host.errors" or die "error log: $!"; -autoflush ERR; - -print LOG scalar(localtime), " $0 starting for $Host\n"; -print ERR scalar(localtime), " $0 starting for $Host\n"; - -open GUP, $GroupsWanted or die "Groups Wanted: $GroupsWanted: $!"; -@groups = ; -close GUP; - -$Starttime = time; - -$localhost = Net::NNTP->new("localhost", "Debug", $opt_d, "Timeout", $opt_t, "Reader", 0) or die "localhost: $!"; - -$remotehost = Net::NNTP->new($Host, "Debug", $opt_d, "Timeout", $opt_t) or die "remotehost: $!"; -$remotehost->reader; -&lifecheck($remotehost, $Host); -$remotehost->authinfo($userid, $password) if ($userid); -&lifecheck($remotehost, $Host); - -tie %Rc, "DB_File", "$Host.bfrc" or die "$Host.bfrc: $!"; - -$SIG{HUP} = 'IGNORE'; -$SIG{INT} = \&sig; -$SIG{TERM} = \&sig; - -my $restart = $Rc{'=restart='}; -$restart='' unless ($restart); - -my @before = grep $_ lt $restart, @groups; -my @after = grep $_ ge $restart, @groups; -@groups = ( @after, @before ); - -($acc, $rej, $his) = (0, 0, 0); -foreach $Group (@groups) { - chomp $Group; - (@parms = $remotehost->group($Group)) or next; - &lifecheck($remotehost, $Host); - next if ($#parms < 3); - $Rc{'=restart='} = $Group; - print LOG scalar(localtime), " \t<$Group>\n"; - $Rc{$Group} = 0 - if (!defined $Rc{$Group}); - $Rc{$Group} = 0 - if (!$Rc{$Group}); - $from = $parms[1]; - $to = $parms[2]; - $to = $from + ($to - $from) * $opt_p; - if ($to < $Rc{$Group}) { - print LOG scalar(localtime), " \t watermark high, reset\n"; - $Rc{$Group} = $from-1; - } - $Rc{$Group} = $from-1 - if ($from > $Rc{$Group}); -# print LOG scalar(localtime), " \t\t",$Rc{$Group}+1,"-$to\n"; - $remotehost->nntpstat($Rc{$Group}+1); -# print LOG scalar(localtime), " \t\t",$remotehost->message,"\n"; - &lifecheck($remotehost, $Host); - $art = $remotehost->nntpstat; - &lifecheck($remotehost, $Host); - $remotehost->message =~ /^(\d+)/; - $Pos = $1; - $accepted=0; - $rejected=0; - $history=0; - &offer($art) - if ($art); - while ($art = $remotehost->next) { - &lifecheck($remotehost, $Host); - $remotehost->message =~ /^(\d+)/; - $Pos = $1; - last - if ($Pos > $to); - &offer($art); - } - &lifecheck($remotehost, $Host); - print LOG scalar(localtime), " \taccepted=$accepted rejected=$rejected history=$history\n"; - $acc+=$accepted; - $rej+=$rejected; - $his+=$history; - $accepted=0; - $rejected=0; - $history=0; - (tied %Rc)->sync; - sleep $opt_S if $opt_S; -} - -untie %Rc; - -$localhost->quit; - -$remotehost->quit; - -&end0; - -sub offer -{ - system("echo $Host $Group $Pos > $Host.status"); - if ($localhost->ihave($_[0])) { - &lifecheck($localhost, 'localhost'); - my $article = $remotehost->article; - if (ref $article) { - #open ART1, "> art1"; - #print ART1 @$article; - #close ART1; - my $i = 0; - while ($i <= @$article && !($$article[$i] =~ /^Path:/i)) { - $i++; - } - $$article[$i] =~ s/^(Path:\s*)/$1NNTP-from-$Host!/i; - #open ART2, "> art2"; - #print ART2 @$article; - #close ART2; - #exit; - $localhost->datasend($article); - if ($localhost->dataend) { - $accepted++; - } - else { - $rejected++; - $err{" local " . $localhost->code . " " . $localhost->message} ++; - } - $Rc{$Group} = $Pos; - (tied %Rc)->sync; - } - else { - $err{" remote " . $remotehost->code . " " . $remotehost->message} ++; - } - sleep $opt_s if $opt_s; - } - else { - if ($localhost->status == 4) { - if ($localhost->code == 435) { - $err{" local " . $localhost->code . " " . $localhost->message} ++; - } - else { - $err{" local " . $localhost->code . " " . $localhost->message} ++; - print LOG scalar(localtime), " local ", $localhost->code, " ", $localhost->message, "\n"; - &end; - } - } - &lifecheck($localhost, 'localhost'); - $history++; - $Rc{$Group} = $Pos; - } -} - -sub lifecheck -{ - unless (defined $_[0]->code and $_[0]->code > 0) { - print LOG scalar(localtime), " Connection to $_[1] dropped\n"; - print ERR scalar(localtime), " Connection to $_[1] dropped\n"; - &end; - } - #print "time=",time," starttime=$Starttime\n"; - kill 'TERM', $$ if time-$Starttime > $opt_T; -} - -sub sig -{ - print LOG scalar(localtime), " Caught sig: ", Data::Dumper::Dumper(@_), "\n"; - print ERR scalar(localtime), " Caught sig: ", Data::Dumper::Dumper(@_), "\n"; - &end; -} - -sub end -{ - $acc+=$accepted; - $rej+=$rejected; - $his+=$history; - &end0; -} - -sub end0 -{ - print LOG scalar(localtime), " $0 $Host accepted=$acc rejected=$rej history=$his\n"; - foreach my $e (sort keys %err) { - print ERR $err{$e}, $e, "\n"; - } - print ERR scalar(localtime), " $0 $Host accepted=$acc rejected=$rej history=$his\n"; - close LOG; - close ERR; - unlink $lockf; - exit 0; -} diff --git a/contrib/cleannewsgroups.in b/contrib/cleannewsgroups.in deleted file mode 100644 index daa406b..0000000 --- a/contrib/cleannewsgroups.in +++ /dev/null @@ -1,45 +0,0 @@ -#! /usr/bin/perl -# fixscript will replace this line with require innshellvars.pl - -# This script cleans the newsgroups file: -# * Groups no longer in the active file are removed. -# * Duplicate entries are removed. The last of a set of duplicates -# is the one retained. That way, you could simply append the -# new/revised entries from a docheckgroups run and then this script -# will remove the old ones. -# * Groups with no description are removed. -# * Groups matching the $remove regexp are removed. - -$remove=''; -# $remove='^alt\.'; - -open ACT, $inn::active or die "Can't open $inn::active: $!\n"; -while() { - ($group) = split; - $act{$group} = 1 unless($remove ne "" && $group =~ /$remove/o); -} -close ACT; - -open NG, $inn::newsgroups or die "Can't open $inn::newsgroups: $!\n"; -while() { - chomp; - ($group, $desc) = split /\s+/,$_,2; - next unless(defined $act{$group}); - - next if(!defined $desc); - next if($desc =~ /^[?\s]*$/); - next if($desc =~ /^no desc(ription)?(\.)?$/i); - - $hist{$group} = $desc; -} -close NG; - -open NG, ">$inn::newsgroups.new" or die "Can't open $inn::newsgroups.new for write: $!\n"; -foreach $group (sort keys %act) { - if(defined $hist{$group}) { - print NG "$group\t$hist{$group}\n" or die "Can't write: $!\n"; - } -} -close NG or die "Can't close: $!\n"; - -rename "$inn::newsgroups.new", $inn::newsgroups or die "Can't rename $inn::newsgroups.new to $inn::newsgroups: $!\n"; diff --git a/contrib/count_overview.pl b/contrib/count_overview.pl deleted file mode 100755 index 910938e..0000000 --- a/contrib/count_overview.pl +++ /dev/null @@ -1,27 +0,0 @@ -#!/usr/local/bin/perl -# -# count_overview.pl: Count the groups in a bunch of xref records. - -while (<>) { - -chop; -@xreflist = split(/\t/); # split apart record - -$_ = $xreflist[$#xreflist]; # xref is last. - -@xreflist = reverse(split(/ /)); #break part xref line. - -pop @xreflist; # get rid xref header -pop @xreflist; - -while ($current = pop @xreflist) { - ($current) = split(/:/,$current); #get newsgroup name - $groups{$current}++; #tally -} - -} - -# display accumulated groups and counts. -foreach $current (sort keys %groups) { - printf "%-50s\t%5d\n", $current, $groups{$current}; -} diff --git a/contrib/delayer.in b/contrib/delayer.in deleted file mode 100644 index 4528d96..0000000 --- a/contrib/delayer.in +++ /dev/null @@ -1,71 +0,0 @@ -#!/usr/bin/perl -# -*- perl -*- -# -# delay lines for N seconds. -# -# primarily meant to be used with INN to generate a delayed feed with innfeed. -# -# put it into your newsfeeds file like -# -# innfeed-delayed!\ -# :!*\ -# :Tc,Wnm*,S16384:/usr/local/news/bin/delayer 60 \ -# /usr/local/news/bin/startinnfeed -c innfeed-delayed.conf -# -# -# -# done by christian mock sometime in july 1998, -# and put into the public domain. -# -$delay = shift || die "usage: $0 delay prog-n-args\n"; - -$timeout = $delay; -$eof = 0; - -open(OUT, "|" . join(" ", @ARGV)) || die "open |prog-n-args: $!\n"; - -#select(OUT); -#$| = 1; -#select(STDOUT); - -$rin = ''; -vec($rin,fileno(STDIN),1) = 1; - -while(!$eof || $#queue >= 0) { - if(!$eof) { - ($nfound,$timeleft) = - select($rout=$rin, undef, undef, $timeout); - } else { - sleep($timeout); - } - $now = time(); $exp = $now + $delay; - - if(!$eof && vec($rout,fileno(STDIN),1)) { - $line = ; - if(!defined $line) { # exit NOW! - foreach(@queue) { - s/^[^:]+://g; - print OUT; - } - close(OUT); - sleep(1); - exit; - } - push(@queue, "$exp:$line"); - } - - if($#queue < 0) { - undef $timeout; - next; - } - - ($first, $line) = split(/:/, $queue[0], 2); - while($#queue >= 0 && $first <= $now) { - print OUT $line; - shift(@queue); - ($first, $line) = split(/:/, $queue[0], 2); - } - $timeout = $first - $now; - -} - diff --git a/contrib/expirectl.c b/contrib/expirectl.c deleted file mode 100644 index 2224ad7..0000000 --- a/contrib/expirectl.c +++ /dev/null @@ -1,306 +0,0 @@ -/* - * EXPIRECTL.C - * - * expirectl - * - * This program uses expire.ctl.ctl as input; please see the end of this - * file for an example of such a file. - */ - -/* - * Date: Mon, 21 Nov 1994 12:29:52 -0801 - * From: Matthew Dillon - * Message-Id: <199411212030.MAA21835@apollo.west.oic.com> - * To: rsalz@uunet.uu.net - * Subject: Re: INN is great, bug fix for BSDI - * - * [...] - * Oh, while I'm at it, I also wrote a cute program that builds the - * expire.ctl file dynamically based on available space. Feel free - * to include this in the dist (or not) as you please. - * - * Basically, the expirectl programs determines the amount of disk blocks - * and inodes free in the spool and creates a new expire.ctl file based - * on an expire.ctl.ctl template. The template specifies expiration times - * as a fraction of nominal. expirectl adjusts the nominal expiration - * up or down based on available disk space. - * - * The idea is to make expiration as hands off as possible. I tested - * it on a smaller spool and it appeared to work fine. Currently it - * only works for single-partition news spools tho. The above spool - * will not really exercise the program for another 14 days or so :-). - */ - - -#include -#include -#include -#include -#include -#include - -#define EXPIRE_CTL_DIR "/home/news" -#define NEWS_SPOOL "/home/news/spool/news/." - -#define EXPIRE_DAYS EXPIRE_CTL_DIR "/expire.days" -#define EXPIRE_CTL EXPIRE_CTL_DIR "/expire.ctl" -#define EXPIRE_CTL_CTL EXPIRE_CTL_DIR "/expire.ctl.ctl" - -void -main(int ac, char **av) -{ - struct statfs sfs; - long minFree = 100 * 1024 * 1024; - long minIFree = 20 * 1024; - long expireDays = 2; - time_t expireIncTime = time(NULL) - 24 * 60 * 60; - int modified = 0; - int verbose = 0; - - /* - * options - */ - - { - int i; - - for (i = 1; i < ac; ++i) { - char *ptr = av[i]; - - if (*ptr == '-') { - ptr += 2; - switch(ptr[-1]) { - case 'v': - verbose = 1; - break; - case 'f': - modified = 1; - break; - case 'n': - modified = -1; - break; - case 'b': - minFree = strtol(((*ptr) ? ptr : av[++i]), &ptr, 0); - if (*ptr == 'k') - minFree *= 1024; - if (*ptr == 'm') - minFree *= 1024 * 1024; - break; - case 'i': - minIFree = strtol(((*ptr) ? ptr : av[++i]), NULL, 0); - if (*ptr == 'k') - minIFree *= 1024; - if (*ptr == 'm') - minIFree *= 1024 * 1024; - break; - default: - fprintf(stderr, "bad option: %s\n", ptr - 2); - exit(1); - } - } else { - fprintf(stderr, "bad option: %s\n", ptr); - exit(1); - } - } - } - - if (statfs("/home/news/spool/news/.", &sfs) != 0) { - fprintf(stderr, "expirectl: couldn't fsstat /home/news/spool/news/.\n"); - exit(1); - } - - /* - * Load /home/news/expire.days - */ - - { - FILE *fi; - char buf[256]; - - if ((fi = fopen(EXPIRE_DAYS, "r")) != NULL) { - while (fgets(buf, sizeof(buf), fi) != NULL) { - if (strncmp(buf, "time", 4) == 0) { - expireIncTime = strtol(buf + 4, NULL, 0); - } else if (strncmp(buf, "days", 4) == 0) { - expireDays = strtol(buf + 4, NULL, 0); - } - } - fclose(fi); - } else { - if (modified >= 0) - modified = 1; - printf("creating %s\n", EXPIRE_DAYS); - } - } - - /* - * print status - */ - - if (verbose) { - printf("spool: %4.2lfM / %3.2lfKinode free\n", - (double)sfs.f_fsize * (double)sfs.f_bavail / (1024.0 * 1024.0), - (double)sfs.f_ffree / 1024.0 - ); - printf("decrs: %4.2lfM / %3.2lfKinode\n", - (double)(minFree) / (double)(1024*1024), - (double)(minIFree) / (double)(1024) - ); - printf("incrs: %4.2lfM / %3.2lfKinode\n", - (double)(minFree * 2) / (double)(1024*1024), - (double)(minIFree * 2) / (double)(1024) - ); - } - - /* - * Check limits, update as appropriate - */ - - { - double bytes; - long inodes; - - bytes = (double)sfs.f_fsize * (double)sfs.f_bavail; - inodes = sfs.f_ffree; - - if (bytes < (double)minFree || inodes < minIFree) { - if (--expireDays <= 0) { - expireDays = 1; - expireIncTime = time(NULL) - 24 * 60 * 60; - } - if (modified >= 0) - modified = 1; - printf("decrement expiration to %d days\n", expireDays); - } else if (bytes >= (double)minFree * 2.0 && inodes >= minIFree * 2) { - long dt = (long)(time(NULL) - expireIncTime); - - if (dt >= 60 * 60 * 24 || dt < -60) { - ++expireDays; - expireIncTime = time(NULL); - if (modified >= 0) - modified = 1; - printf("increment expiration to %d days\n", expireDays); - } else { - printf("will increment expiration later\n"); - } - } else if (verbose) { - printf("expiration unchanged: %d\n", expireDays); - } - } - - /* - * Write EXPIRE_CTL file from EXPIRE_CTL_CTL template - */ - - if (modified > 0) { - FILE *fi; - FILE *fo; - - if ((fi = fopen(EXPIRE_CTL_CTL, "r")) != NULL) { - if ((fo = fopen(EXPIRE_CTL ".tmp", "w")) != NULL) { - char sbuf[2048]; - char dbuf[4096]; - - while (fgets(sbuf, sizeof(sbuf), fi) != NULL) { - char *base = sbuf; - char *sptr; - char *dptr = dbuf; - - while ((sptr = strchr(base, '[')) != NULL) { - double d; - int m = 0; - - bcopy(base, dptr, sptr - base); - dptr += sptr - base; - base = sptr; - - d = strtod(sptr + 1, &sptr); - if (*sptr == '/') - m = strtol(sptr + 1, &sptr, 0); - if (*sptr == ']') { - long v = (long)((double)expireDays * d + 0.5); - if (v < 1) - v = 1; - if (v < m) - v = m; - sprintf(dptr, "%d", v); - dptr += strlen(dptr); - ++sptr; - } - base = sptr; - } - strcpy(dptr, base); - fputs(dbuf, fo); - } - fclose(fo); - if (rename(EXPIRE_CTL ".tmp", EXPIRE_CTL) != 0) { - fprintf(stderr, "rename(%s,%s): %s\n", - EXPIRE_CTL ".tmp", - EXPIRE_CTL, - strerror(errno) - ); - } - } - fclose(fi); - } - } - - /* - * Write EXPIRE_DAYS file - */ - - if (modified > 0) { - FILE *fo; - - if ((fo = fopen(EXPIRE_DAYS, "w")) != NULL) { - fprintf(fo, "time 0x%08lx\n", expireIncTime); - fprintf(fo, "days %d\n", expireDays); - fclose(fo); - } else { - fprintf(stderr, "unable to create %s\n", EXPIRE_DAYS); - } - } - exit(0); -} - - -/* - -# Start of sample expire.ctl.ctl file. - -# EXPIRE.CTL.CTL (EXPIRE.CTL GENERATED FROM EXPIRE.CTL.CTL !!!) -# -# The expire.ctl file is generated by the expirectl program from the -# expire.ctl.ctl file. The expirectl program calculates the proper -# expiration based on the number of free inodes and free bytes available. -# -# This file is exactly expire.ctl but with the multiplier [N] replaced by -# a calculated value, where a multiplier of '1' nominally fills the whole -# disk. -# -# Any field [N] is substituted after being multiplied by the expiration -# time (in days). A integer minimum can also be specified with a slash, -# as in [N/minimum]. -# -# expirectl is normally run just after expire is run. Note that expirectl -# isn't very useful for the case where you are 'catching up' on news after -# a long period of downtime UNLESS you use the -p option to expire. - -/remember/:[1.2/20] - -## Keep for 1-10 days, allow Expires headers to work. -# -*:A:1:[1.0]:[6.0] -*.advocacy:A:1:[0.5]:[2.0] -alt.binaries.pictures.erotica:A:1:[0.8]:[2.0] - -# permanent, semi-permanent -# -best.intro:A:never:never:never -best.announce:A:5:60:120 -best.general:A:never:never:never -best.bugs:A:never:never:never - -# End of sample expire.ctl.ctl file. - -*/ diff --git a/contrib/findreadgroups.in b/contrib/findreadgroups.in deleted file mode 100644 index 4c5e8ff..0000000 --- a/contrib/findreadgroups.in +++ /dev/null @@ -1,38 +0,0 @@ -#!/usr/local/bin/perl -# fixscript will replace this line with require innshellvars.pl - -# Keep track of which groups are currently being read. Takes logfile input -# on stdin. -$readfile="$inn::newsetc/readgroups"; - -$curtime = time; -$oldtime = $curtime - 30 * 86400; # 30 days in the past - -if (open(RDF, $readfile)) { - while () { - chop; - @foo=split(/ /); # foo[0] should be group, foo[1] lastreadtime - if ($foo[1] < $oldtime) { - next; # skip entries that are too old. - } - $groups{$foo[0]} = $foo[1]; - } - close(RDF); -} - -# read input logs. -while (<>) { - next unless /nnrpd/; - next unless / group /; - chop; - @foo = split(/ +/); - # group name is in the 8th field. - $groups{$foo[7]} = $curtime; -} - -open(WRF, ">$readfile") || die "cannot open $readfile for write.\n"; -foreach $i (keys %groups) { - print WRF $i, " ", $groups{$i}, "\n"; -} - -exit(0); diff --git a/contrib/fixhist b/contrib/fixhist deleted file mode 100755 index 0541a00..0000000 --- a/contrib/fixhist +++ /dev/null @@ -1,89 +0,0 @@ -#!/usr/local/bin/perl -# -# history database sanity checker -# David Barr -# version 1.4 -# w/mods from: hucka@eecs.umich.edu -# Katsuhiro Kondou -# version 1.1 -# Throw away history entries with: -# malformed lines (too long, contain nulls or special characters) -# -# INN Usage: -# ctlinnd throttle 'fixing history' -# ./fixhist history.n -# makedbz -s `wc -l ) { - chop; - ($msgid,$dates,$arts,$xtra) = split('\t'); - if ($xtra) { - &tossit(); # too many fields - next; - } - if (!($dates) && (($arts) || ($xtra))) { - &tossit(); # if not date field, then the rest - next; # should be empty - } - if (length($msgid) >= $MAXKEYLEN) { - &tossit(); # message-id too long - next; - } - if ($msgid !~ /^<[^<> ]*>$/) { - if ($msgid =~ /^\[[0-9A-F]{32}\]$/) { - if ($arts ne "") { - if ($arts =~ /^\@[0-9A-F]{56}\@$/) { - $arts =~ s/^\@([0-9A-F]{36})([0-9A-F]{20})\@$/\@${1}\@/; - print "$msgid\t$dates\t$arts\n"; - next; - } - if ($arts !~ /^\@[0-9A-F]{36}\@$/) { - &tossit(); - next; - } - } - } else { - &tossit(); # malformed msg-ids - next; - } - } else { - if ($arts ne "" && ($arts !~ /[^\/]*\/[0-9]*/)) { - &tossit(); # malformed articles list - next; - } - } - if (/[\000-\010\012-\037\177-\237]/) { # non-control chars except tab - &tossit(); # illegal chars - next; - } - if ($dates) { - if ($dates =~ /[^\d~\-]/) { # rudimentary check - &tossit(); # full check would be too slow - next; - } - } - print "$_\n"; - $count++; - $0 = "history line $./$count" if $. % 50000 == 0; -} -print STDERR "Done. Now run:\nmakedbz -s $count -f history.n\n"; - -sub tossit { - print STDERR "$_\n"; -} diff --git a/contrib/innconfcheck b/contrib/innconfcheck deleted file mode 100755 index 83a19d0..0000000 --- a/contrib/innconfcheck +++ /dev/null @@ -1,125 +0,0 @@ -#!/bin/ksh - -### INNCONFcheck v1.1 - -### Revision history: -# v1.0 B. Galliart (designed to work with 2.3 inn.conf man page) -# v1.1 B. Galliart (optional support for using inn.conf POD src instead) - -### Description: -# This script is written to inner-mix the inn.conf settings with the -# documentation from the inn.conf man page. The concept was shamelessly -# ripped off of a CGI application provided at Mib Software's Usenet Rapid -# Knowledge Transfer (http://www.mibsoftware.com/userkt/inn2.0/). - -# The idea is that a news administrator usually must go through the -# task of reading the inn.conf man page in parallel with the inn.conf -# inn.conf to confirm that the settings are set as desired. Manually -# matching up the two files can become troublesome. This script should -# make the task easier and hopefully reduce the chance a misconfiguration -# is missed. - -### Known bugs: -# - Is very dependent on the format of the man page. It is know NOT to -# work with the inn.conf man pages written before INN 2.3 and may -# require minor rewriting to address future revisions of inn.conf -# Note: this known bug is addressed via the "EDITPOD" option below -# but is not enabled by default (details explained below). -# -# - SECURITY! While taken from the concept of a CGI script, it is not -# intended to be a CGI script itself. It is *assumed* that the -# inn.conf file is provided by a "trusted" source. - -### License: this script is provided under the same terms as the majority -# of INN 2.3.0 as stated in the file "inn-2.3.0/LICENSE" - -### Warrenty/Disclaimer: There is no warrenty provided. For details, please -# refer to the file "inn-2.3.0/LICENSE" from the INN 2.3 package - - ################ - -### The User Modifiable Parameters/Settings: - -# INNCONF should be set to the actual location of the inn.conf file -INNCONF=/usr/local/news/etc/inn.conf - -# INNCONFMAN should be set to the location of the inn.conf man page -INNCONFMAN=/usr/local/news/man/man5/inn.conf.5 - -# INNCONFPOD should be set to the location of the inn.conf POD source -# INNCONFPOD=/usr/local/src/inn-2.3.0/doc/pod/inn.conf.pod -INNCONFPOD=/usr/local/news/man/man5/inn.conf.pod - -# NROFF should be set to an approbate program for formating the man page -# this could be the vendor provided nroff, the FSF's groff (which could be -# used for producing PostScript output) or Earl Hood's man2html from -# http://www.oac.uci.edu/indiv/ehood/man2html.html - -# NROFF=man2html -NROFF="nroff -man" - -# Pager should be set to an approbate binary for making the output -# readable in the user's desired method. Possible settings include -# page, more, less, ghostview, lynx, mozilla, lpr, etc. If no pager -# application is desire then by setting it to "cat" will cause the output -# to continue on to stdout. -PAGER=less - -# By default the script uses the inn.conf man page before being processed -# by nroff to edit in the actual inn.conf settings. The problem with this -# approach is that if the format of the inn.conf man page ever changes -# assumptions about the format that this script makes will probably break. -# Presently, the base/orginal format of the inn.conf man page is in perl -# POD documentation. The formating of this file is less likely to change -# in the future and is a cleaner format for automated editing. However, -# their is some disadvantages to using this file. First disadvantage, -# the POD file is not installed by INN 2.3.0 by default (see INNCONFPOD -# enviromental variable for setting the script to find the file in the -# correct location). Second disadvantage, pod2man does not appear to -# support using stdin so the edited POD must be temporarily stored as a -# file. Finally, the last disadvantage, the script is slower due to the -# added processing time of pod2man. Weighing the advantages and -# disadvantages to both approaches are left to the user. If you wish to -# have innconfcheck edit the POD file then change the variable below to -# a setting of "1", otherwise leave it with the setting of "0" -EDITPOD=0 - - ################ - -### The Script: (non-developers should not need to go beyond this point) - -# All variable settings in inn.conf should not contain a comment -# character of "#" and should have a ":" in the line. These variable names -# should then be matched up with the man page "items" in the inn.conf file. -# In the INN 2.3 man page, these items appear in the following format: -# .Ip "\fIvariable name\fR" 4 -# Hence, if there exists an entry in the inn.conf of "verifycancels: false" -# then the awk script will produce: -# s#^.Ip "\fIvarifycancels\f$" 4#.Ip "\verifycancels: false\f$" 4# -# once piped to sed, this expression will replace the man page item to -# include the setting from the inn.conf file. The nroff and pager -# applications then polish the script off to provide a documented formated -# in a way that is easier to find incorrect setting withen. - -if [ $EDITPOD -eq 0 ] ; then - - grep -v "#" $INNCONF | grep ":" | \ - awk 'BEGIN { FS = ":" } { print "s#^.Ip \042\\\\fI"$1"\\\\fR\042 4#.Ip \042\\\\fI"$0"\\\\fR\042 4#" }' | \ - sed -f - $INNCONFMAN | $NROFF | $PAGER - -else - -# The next part is similar to above but provides working from the POD source -# instead of from the resulting nroff/man page. This section is discussed -# in more detail above with the "EDITPOD" setting. - - grep -v "#" $INNCONF | grep ":" | \ - awk 'BEGIN { FS = ":" } { print "s#=item I<"$1">#=item I<"$0">#" }' | \ - sed -f - $INNCONFPOD > /tmp/innconfcheck-$$ - pod2man /tmp/innconfcheck-$$ | $NROFF | $PAGER - rm -f /tmp/innconfcheck-$$ - -fi - -# That's all. -# EOF diff --git a/contrib/makeexpctl.in b/contrib/makeexpctl.in deleted file mode 100644 index 320ae1f..0000000 --- a/contrib/makeexpctl.in +++ /dev/null @@ -1,76 +0,0 @@ -#!/usr/local/bin/perl -# fixscript will replace this line with require innshellvars.pl - -# Create expire.ctl script based on recently read articles. Argument gives -# scale factor to use to adjust expires. - -$readfile="$inn::pathdb/readgroups"; - -$expirectl=$inn::expirectl; -if (open(RDF, $readfile)) { - while () { - chop; - @foo=split(/ /); # foo[0] should be group, foo[1] lastreadtime - if ($foo[1] < $oldtime) { - next; # skip entries that are too old. - } - $groups{$foo[0]} = $foo[1]; - } - close(RDF); -} - -$scale = $ARGV[0]; -if ($scale <= 0) { - die "invalid scale parameter\n"; -} - -rename($expirectl, "$expirectl.OLD") || die "rename $expirectl failed!\n"; -open(OUTFILE, ">$expirectl") || die "open $expirectl for write failed!\n"; - -print OUTFILE <<'EOF' ; -## expire.ctl - expire control file -## Format: -## /remember/: -## :::: -## First line gives history retention; other lines specify expiration -## for newsgroups. Must have a "*:A:..." line which is the default. -## wildmat-style patterns for the newsgroups -## Pick one of M U A -- modifies pattern to be only -## moderated, unmoderated, or all groups -## Mininum number of days to keep article -## Default number of days to keep the article -## Flush article after this many days -## , , and can be floating-point numbers or the -## word "never." Times are based on when received unless -p is used; -## see expire.8 - -# How long to remember old history entries for. -/remember/:2 -# -EOF - -# defaults for most groups. -printline("*", "A", 1); -printline("alt*,misc*,news*,rec*,sci*,soc*,talk*,vmsnet*","U",3); -printline("alt*,misc*,news*,rec*,sci*,soc*,talk*,vmsnet*","M",5); -printline("comp*,gnu*,info*,ok*,ecn*,uok*", "U", 5); -printline("comp*,gnu*,info*,ok*,ecn*,uok*", "M", 7); -# and now handle each group that's regularly read, -# assinging them 3* normal max expire -foreach $i (keys %groups) { - printline($i, "A", 21); -} -# and now put some overrides for groups which are too likely to fill spool if -# we let them go to autoexpire. -printline("*binaries*,*pictures*", "A", 0.5); -printline("control*","A",1); -printline("control.cancel","A",0.5); -printline("news.lists.filters,alt.nocem.misc","A",1); - -close(OUTFILE); -exit(1); - -sub printline { - local($grpstr, $mflag, $len) = @_; - print OUTFILE $grpstr,":",$mflag,":",$len*$scale,":",$len*$scale,":",$len*$scale,"\n"; -} diff --git a/contrib/makestorconf.in b/contrib/makestorconf.in deleted file mode 100644 index c92bc83..0000000 --- a/contrib/makestorconf.in +++ /dev/null @@ -1,56 +0,0 @@ -#!/usr/local/bin/perl -# fixscript will replace this line with require innshellvars.pl - -# Create storage.conf script based on recently read articles. - -$readfile="$inn::pathdb/readgroups"; - -$outfile="$inn::pathdb/storage.conf"; -outloop: -for ($level=9 ; $level >= 2; --$level) { - # clear groups hash. - foreach $i (keys %groups) { - delete $groups{$i}; - } - if (open(RDF, "sort $readfile|")) { - while () { - chop; - next if (/^group/); # bogus - @foo=split(/ /); # foo[0] should be group, foo[1] lastreadtime - @bar=split(/\./,$foo[0]); - if ( $level >= scalar @bar) { - $grf = join(".", @bar); - } else { - $grf=join(".", @bar[0..($level-1)]) . ".*"; - } - $groups{$grf} = 1; - } - close(RDF); - } - $grlist = join(",",keys(%groups)); - last outloop if (length($grlist) < 2048); -} - -open(OUT, ">$outfile") || die "cant open $outfile"; -#open(OUT, ">/dev/tty"); - -print OUT <<"EOF" ; -method cnfs { - newsgroups: control,control.* - class: 1 - options: MINI -} - -method timecaf { - newsgroups: $grlist - class: 1 -} - -method cnfs { - newsgroups: * - options: MONGO - class: 0 -} -EOF -close(OUT); -exit(0); diff --git a/contrib/mkbuf b/contrib/mkbuf deleted file mode 100755 index 53e326e..0000000 --- a/contrib/mkbuf +++ /dev/null @@ -1,29 +0,0 @@ -#!/usr/bin/perl - -sub usage { - print STDERR "Usage: $0 \n"; - exit 1; -} - -usage if(@ARGV != 2); - -$buf1k = "\0"x1024; -$buf1m = "$buf1k"x1024; - -$kb = $ARGV[0] * 1; -&usage if($kb == 0); - -if($ARGV[1] eq '-') { - open(FILE, "|cat") or die; -} else { - open(FILE, ">$ARGV[1]") or die; -} - -for($i = 0; $i+1024 <= $kb; $i+=1024) { - print FILE $buf1m or die; -} -if($i < $kb) { - print FILE "$buf1k"x($kb-$i) or die; -} - -close FILE; diff --git a/contrib/mlockfile.c b/contrib/mlockfile.c deleted file mode 100644 index 4bf274f..0000000 --- a/contrib/mlockfile.c +++ /dev/null @@ -1,182 +0,0 @@ -/* $Id: mlockfile.c 6014 2002-12-16 11:28:07Z alexk $ */ - -/* Locks the files given on the command line into memory using mlock. - This code has only been tested on Solaris and may not work on other - platforms. - - Contributed by Alex Kiernan . */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -struct mlock { - const char *path; - struct stat st; - void *base; - off_t offset; - size_t length; -}; - -char *progname; - -int flush = 0; -int interval = 60000; - -void -inn_lock_files(struct mlock *ml) -{ - for (; ml->path != NULL; ++ml) { - int fd; - - fd = open(ml->path, O_RDONLY); - if (fd == -1) { - fprintf(stderr, "%s: can't open `%s' - %s\n", - progname, ml->path, strerror(errno)); - } else { - struct stat st; - - /* check if size, inode or device of the path have - * changed, if so unlock the previous file & lock the new - * one */ - if (fstat(fd, &st) != 0) { - fprintf(stderr, "%s: can't stat `%s' - %s\n", - progname, ml->path, strerror(errno)); - } else if (ml->st.st_ino != st.st_ino || - ml->st.st_dev != st.st_dev || - ml->st.st_size != st.st_size) { - if (ml->base != MAP_FAILED) - munmap(ml->base, - ml->length ? ml->length : ml->st.st_size); - - /* free everything here, so in case of failure we try - * again next time */ - ml->st.st_ino = 0; - ml->st.st_dev = 0; - ml->st.st_size = 0; - - ml->base = mmap(NULL, - ml->length ? ml->length : st.st_size, - PROT_READ, - MAP_SHARED, fd, ml->offset); - - if (ml->base == MAP_FAILED) { - fprintf(stderr, "%s: can't mmap `%s' - %s\n", - progname, ml->path, strerror(errno)); - } else { - if (mlock(ml->base, - ml->length ? ml->length : st.st_size) != 0) { - fprintf(stderr, "%s: can't mlock `%s' - %s\n", - progname, ml->path, strerror(errno)); - } else { - ml->st = st; - } - } - } else if (flush) { - msync(ml->base, ml->length ? ml->length : st.st_size, MS_SYNC); - } - } - close (fd); - } -} - -static void -usage(void) -{ - fprintf(stderr, - "usage: %s [-f] [-i interval] file[@offset[:length]] ...\n", - progname); - fprintf(stderr, " -f\tflush locked bitmaps at interval\n"); - fprintf(stderr, " -i interval\n\tset interval between checks/flushes\n"); -} - -int -main(int argc, char *argv[]) -{ - struct mlock *ml; - int i; - - progname = *argv; - while ((i = getopt(argc, argv, "fi:")) != EOF) { - switch (i) { - case 'i': - interval = 1000 * atoi(optarg); - break; - - case 'f': - flush = 1; - break; - - default: - usage(); - return EX_USAGE; - } - } - argc -= optind; - argv += optind; - - /* construct list of pathnames which we're to operate on, zero out - * the "cookies" so we lock it in core first time through */ - ml = malloc((1 + argc) * sizeof ml); - for (i = 0; argc--; ++i, ++argv) { - char *at; - off_t offset = 0; - size_t length = 0; - - ml[i].path = *argv; - ml[i].st.st_ino = 0; - ml[i].st.st_dev = 0; - ml[i].st.st_size = 0; - ml[i].base = MAP_FAILED; - - /* if we have a filename of the form ...@offset:length, only - * map in that portion of the file */ - at = strchr(*argv, '@'); - if (at != NULL) { - char *end; - - *at++ = '\0'; - errno = 0; - offset = strtoull(at, &end, 0); - if (errno != 0) { - fprintf(stderr, "%s: can't parse offset `%s' - %s\n", - progname, at, strerror(errno)); - return EX_USAGE; - } - if (*end == ':') { - at = end + 1; - errno = 0; - length = strtoul(at, &end, 0); - if (errno != 0) { - fprintf(stderr, "%s: can't parse length `%s' - %s\n", - progname, at, strerror(errno)); - return EX_USAGE; - } - } - if (*end != '\0') { - fprintf(stderr, "%s: unrecognised separator `%c'\n", - progname, *end); - return EX_USAGE; - } - } - ml[i].offset = offset; - ml[i].length = length; - } - ml[i].path = NULL; - - /* loop over the list of paths, sleeping 60s between iterations */ - for (;;) { - inn_lock_files(ml); - poll(NULL, 0, interval); - } - return EX_OSERR; -} diff --git a/contrib/newsresp.c b/contrib/newsresp.c deleted file mode 100644 index b2931b7..0000000 --- a/contrib/newsresp.c +++ /dev/null @@ -1,297 +0,0 @@ -/* newsresp.c - EUnet - bilse */ - -/* - * From: Koen De Vleeschauwer - * Subject: Re: innfeed-users: innfeed: measuring server response time - * To: jeff.garzik@spinne.com (Jeff Garzik) - * Date: Tue, 13 May 1997 16:33:27 +0200 (MET DST) - * Cc: innfeed-users@vix.com - * - * > Is there an easy way to measure server response time, and print it out - * > on the innfeed status page? Cyclone's nntpTime measures login banner - * > response time and an article add and lookup operation. - * > - * > It seems to me that innfeed could do something very similar. It could - * > very easily sample gettimeofday() or Time.Now to determine a remote - * > server's average response time for lookups, lookup failures, article - * > send throughput, whatever. - * > - * > These statistics might be invaluable to developers creating advanced - * > connection and article delivery algorithms. If I knew, for example, - * > that a site's article send/save throughput was really fast, but history - * > lookups were really slow, my algorithm could reserve a channel or two - * > for TAKETHIS-only use. - * - * We use a stand-alone program which opens up an additional nntp channel - * from time to time and takes a peek at the various response times. - * It's also interesting to tune one's own box. - * I've included the source code; please consider this supplied 'as is'; - * bugs and features alike. SunOS, Solaris and Irix ought to be ok; - * eg. gcc -traditional -o newsresp ./newsresp.c -lnsl -lsocket on S0laris. - * If a host has an uncommonly long banner you may have to change a constant - * somewhere; forget. Please note one has to interpret the output; - * eg. whether one is measuring rtt or history lookup time. - * - * Basic usage is: - * news 1 % newsresp -n 5 news.eu.net - * --------------------------------- - * news.eu.net is 134.222.90.2 port 119 - * elap diff - * 0.0 0.0 Connecting ... - * 0.0 0.0 OK, waiting for prompt - * 0.0 0.0 <<< 200 EU.net InterNetNews server INN 1.5.1 17-Dec-1996 re [...] - * 0.0 0.0 >>> ihave <244796399@a> - * 0.0 0.0 <<< 335 - * 0.0 0.0 >>> . - * 0.0 0.0 <<< 437 Empty article - * 0.0 0.0 >>> ihave <244796398@a> - * 0.0 0.0 <<< 335 - * 0.0 0.0 >>> . - * 0.0 0.0 <<< 437 Empty article - * 0.0 0.0 >>> ihave <244796397@a> - * 0.0 0.0 <<< 335 - * 0.0 0.0 >>> . - * 0.0 0.0 <<< 437 Empty article - * 0.0 0.0 >>> ihave <244796396@a> - * 0.1 0.0 <<< 335 - * 0.1 0.0 >>> . - * 0.1 0.0 <<< 437 Empty article - * 0.1 0.0 >>> ihave <244796395@a> - * 0.1 0.0 <<< 335 - * 0.1 0.0 >>> . - * 0.1 0.0 <<< 437 Empty article - * 0.1 0.0 >>> quit - * 0.1 0.0 <<< 205 . - */ - -#include -#include -#include -#include -#include -#include -#include - -#define NNTPPORT 119 -struct sockaddr_in sock_in; -int sock; -char buf[1024]; - -main(argc,argv) -int argc; -char *argv[]; -{ - int errflg = 0, c; - extern char *optarg; - extern int optind; - struct hostent *host; - unsigned long temp; - unsigned numart = 1; - struct protoent *tcp_proto; - char **whoP; - - while ( (c = getopt(argc,argv,"n:")) != -1 ) - switch ( c ) { - case 'n': sscanf(optarg,"%u",&numart); break; - default : errflg++; - } - if ( numart == 0 || optind == argc ) - errflg++; - if ( errflg ) { - fprintf(stderr,"Usage: %s [-n articles] host ...\n",argv[0]); - exit(1); - } - - if ( (tcp_proto = getprotobyname("tcp")) == 0 ) - fatal("getprotobyname"); - for ( whoP = argv+optind; *whoP != 0; whoP++ ) { - if ( (sock = socket(PF_INET,SOCK_STREAM,tcp_proto->p_proto)) < 0 ) - fatal("socket"); - temp = inet_addr(*whoP); - if ( temp != (unsigned long) -1 ) { - sock_in.sin_addr.s_addr = temp; - sock_in.sin_family = AF_INET; - } - else { - host = gethostbyname(*whoP); - if ( host ) { - sock_in.sin_family = host->h_addrtype; - memcpy(&sock_in.sin_addr,host->h_addr,host->h_length); - } - else { - fprintf(stderr,"gethostbyname can't find %s\n",*whoP); - exit(1); - } - } - sock_in.sin_port = htons(NNTPPORT); - printf("---------------------------------\n%s is %s port %d\n", - *whoP,inet_ntoa(sock_in.sin_addr),ntohs(sock_in.sin_port)); - punt(numart); - close(sock); - } -} - -error(what) -char *what; -{ - ptime(); fflush(stdout); - perror(what); -} - -fatal(what) -char *what; -{ - error(what); - exit(2); -} - -ierror(how,what) -char *how, *what; -{ - printf("Expected %s, bailing out.\n",how); -} - -ifatal(how,what) -char *how, *what; -{ - ierror(how,what); - exit(1); -} - -unsigned do_time(start) -unsigned start; -{ - struct timeval now; - - gettimeofday(&now,(struct timezone *)0); - return ( now.tv_sec*1000 + now.tv_usec/1000 - start ); -} - - -unsigned start, elapsed, diff; - -ptime() -{ - diff = elapsed; - elapsed = do_time(start); - diff = elapsed - diff; - printf("%5.1f %5.1f ",((float)elapsed)/1000.0,((float)diff)/1000.0); -} - -massagebuff(bread,buf) -int bread; -char *buf; -{ - char *p; - - if ( bread > 55 ) - strcpy(buf+55," [...]\n"); - else - buf[bread] = '\0'; - for ( p = buf; *p != '\0'; ) - if ( *p != '\r' ) /* We like to do it RISC style. */ - p++; - else { - *p = ' '; - p++; - } -} - -punt(numart) -int numart; -{ - static char ihave[32], - dot[] = ".\r\n", - quit[] = "quit\r\n"; - struct timeval start_tv; - int bread; - - printf(" elap diff\n"); - diff = elapsed = 0; - gettimeofday(&start_tv,(struct timezone *)0); - start = start_tv.tv_sec*1000 + start_tv.tv_usec/1000; - - ptime(); - printf("Connecting ...\n"); - if ( connect(sock,(struct sockaddr*)&sock_in,sizeof(sock_in)) < 0 ) { - error("connect"); - return(-1); - } - ptime(); - printf("OK, waiting for prompt\n"); - - if ( (bread=read(sock,buf,sizeof(buf))) < 0 ) { - error("read socket"); - return(-1); - } - massagebuff(bread,buf); - ptime(); - printf("<<< %s",buf); - if ( strncmp(buf,"200",3) != 0 && strncmp(buf,"201",3) != 0 ) { - ierror("200 or 201",buf); - return(-1); - } - - do { - snprintf(ihave,sizeof(ihave),"ihave <%u@a>\r\n",start+numart); - ptime(); - printf(">>> %s",ihave); - if ( write(sock,ihave,strlen(ihave)) != strlen(ihave) ) { - error("write socket"); - return(-1); - } - - if ( (bread=read(sock,buf,sizeof(buf))) < 0 ) { - error("read socket"); - return(-1); - } - massagebuff(bread,buf); - ptime(); - printf("<<< %s",buf); - if ( strncmp(buf,"335",3) != 0 && strncmp(buf,"435",3) != 0 ) { - ierror("335 or 435 ",buf); - return(-1); - } - - if ( strncmp(buf,"335",3) == 0 ) { - ptime(); - printf(">>> %s",dot); - if ( write(sock,dot,sizeof(dot)-1) != sizeof(dot)-1 ) { - error("write socket"); - return(-1); - } - - if ( (bread=read(sock,buf,sizeof(buf))) < 0 ) { - error("read socket"); - return(-1); - } - massagebuff(bread,buf); - ptime(); - printf("<<< %s",buf); - if ( strncmp(buf,"437",3) != 0 && strncmp(buf,"235",3) != 0 ) { - ierror("437 or 235",buf); - return(-1); - } - } - } while ( --numart != 0 ); - - ptime(); - printf(">>> %s",quit); - if ( write(sock,quit,sizeof(quit)-1) != sizeof(quit)-1 ) { - error("write socket"); - return(-1); - } - - if ( (bread=read(sock,buf,sizeof(buf))) < 0 ) { - error("read socket"); - return(-1); - } - massagebuff(bread,buf); - ptime(); - printf("<<< %s",buf); - if ( strncmp(buf,"205",3) != 0 ) { - ierror("205",buf); - return(-1); - } - return(0); -} diff --git a/contrib/pullart.c b/contrib/pullart.c deleted file mode 100644 index 6b06099..0000000 --- a/contrib/pullart.c +++ /dev/null @@ -1,297 +0,0 @@ -/* -June 14, 1999 - -Recover text articles from cyclic buffers -Articles start with "\0Path:" -and end with "\r\n.\r\n" - -Tested with INND 2.2 under AIX 4.2 - -rifkin@uconn.edu -*/ -/* -(1) Pull 16 bytes at a time -(2) Last 7 bytes must be \000\000\000Path -(3) When found, print "\nPath"; -(4) print subsequent bytes until \r\n.\r\n found -*/ - -#include "config.h" -#include -#include -#include - -#define INFILE 1 -#define FILEPREFIX 2 -#define HEADER 3 -#define STRING 4 - -/* String buffer size */ -#define NBUFF 512 - -#define MAX_ART_SIZE 2200000 - - -#define WRITEMSG printf ("File %s line %i\n", __FILE__, __LINE__); \ - fflush(stdout); - -#define WRITEVAR(VAR_NAME,VAR_TYPE) \ - { \ - printf ("FILE %s LINE %i :", __FILE__, __LINE__); \ - printf ("%s = ", #VAR_NAME); \ - printf (#VAR_TYPE, (VAR_NAME) ); \ - printf ("\n"); \ - } - -#define WRITETXT(TEXT) \ - printf ("FILE %s LINE %i \"%s\"\n", __FILE__, __LINE__, TEXT); \ - fflush(stdout); - -#if 0 -#define WRITEMSG -#define WRITEVAR(X,Y) -#endif - - -int WriteArticle (char *, int, char *, char *, char *, int); - - -char ArtHead[7] = {0, 0, 0, 'P', 'a', 't', 'h'}; -char ArtTail[5] = {'\r', '\n', '.', '\r', '\n'}; -int LenTail = 5; - -int main (int argc, char *argv[]) - { - FILE *Infile; - int NumTailCharFound; - bool ReadingArticle = false; - char buffer[32]; - char *obuffer = NULL; - char *header = NULL; - char *string = NULL; - int osize = MAX_ART_SIZE; - int opos = 0; - int i; - int nchar; - int fileno = 0; - int artno = 0; - - /* Check number of args */ - if (argc<3) - { - printf ("Usage: pullart [
]\n"); - printf (" Read cycbuffer and print all articles whose\n"); - printf (" article header
contains .\n"); - printf (" Articles are written to files name .nnnnnn\n"); - printf (" where nnnnnn is numbered sequentially from 0.\n"); - printf (" If
and not specified, all articles\n"); - printf (" are written.\n"); - printf (" Examples:\n"); - printf (" pullart /news3/cycbuff.3 alt.rec Newsgroup: alt.rec\n"); - printf (" pullart /news3/cycbuff.3 all\n"); - printf (" pullart firstbuff article Subject bluejay\n"); - return 0; - } - - /* Allocate output buffer */ - obuffer = (char *) calloc (osize+1, sizeof(char)); - if (obuffer==NULL) - { - printf ("Cannot allocate obuffer[]\n"); - return 1; - } - - - /* Open input file */ - Infile = fopen (argv[INFILE], "rb"); - if (Infile==NULL) - { - printf ("Cannot open input file.\n"); - return 1; - } - - -if (argc>=4) header = argv[HEADER]; -if (argc>=5) string = argv[STRING]; -if (*header=='\0') header=NULL; -if (*string=='\0') string=NULL; - -/*test*/ -printf ("filename <%s>\n", argv[INFILE]); -printf ("fileprefix <%s>\n", argv[FILEPREFIX]); -printf ("header <%s>\n", header); -printf ("string <%s>\n", string); - - - /* Skip first 0x38000 16byte buffers */ - i = fseek (Infile, 0x38000L, SEEK_SET); - - /* Read following 16 byte buffers */ - ReadingArticle = false; - NumTailCharFound = 0; - nchar=0; - artno=0; - while ( 0!=fread(buffer, 16, 1, Infile) ) - { - - nchar+=16; - - /* Found start of article, start writing to obuffer */ - if (0==memcmp(buffer+9, ArtHead, 7)) - { - ReadingArticle = true; - memcpy (obuffer, "Path", 4); - opos = 4; - continue; - } - - /* Currnetly reading article */ - if (ReadingArticle) - { - for (i=0; i<16; i++) - { - - /* Article too big, drop it and move on */ - if (opos>=osize) - { - printf - ("article number %i bigger than buffer size %i.\n", - artno+1, osize); - artno++; - ReadingArticle=false; - break; - } - - /* Add current character to output buffer, but remove \r */ - if ('\r' != buffer[i]) - obuffer[opos++] = buffer[i]; - - /* Check for article ending sequence */ - if (buffer[i]==ArtTail[NumTailCharFound]) - { - NumTailCharFound++; - } - else - NumTailCharFound=0; - - /* End found, write article, reset for next */ - if (NumTailCharFound==LenTail) - { - ReadingArticle = false; - NumTailCharFound = 0; - - /* Add trailing \0 to buffer */ - obuffer[opos+1] = '\0'; - - fileno += WriteArticle - (obuffer, opos, argv[FILEPREFIX], - header, string, fileno); - artno++; - break; - } - } - - } - - } - - close (Infile); - - return 0; - } - - - -/* -Writes article stored in buff[] if it has a -"Newsgroups:" header line which contains *newsgroup -Write to a file named fileprefix.fileno -*/ -int -WriteArticle -(char *buff, int n, char *fileprefix, char *headerin, char *string, int fileno) - { - char *begptr; - char *endptr; - char *newsptr; - char savechar; - char header[NBUFF]; - char filename[NBUFF]; - FILE *outfile; - - - /* Prevent buffer overflow due to fileprefix too long */ - if (strlen(fileprefix)>384) - { - printf - ("program error: cannot have file prefix greater then 384 characters\n"); - exit(1); - } - - /* - Is header here? Search if header string requested, leave if not found - */ - if (headerin!=NULL) - { - /* Find \nHEADER */ - strlcpy(header, "\n", sizeof(header)); - strlcat(header, headerin, sizeof(header)); - - begptr = strstr (buff, header); - - /* return if Header name not found */ - if (begptr==NULL) - { - return 0; - } - - /* - Header found. What about string? - Search if string requested, leave if not found - */ - if (string!=NULL) - { - /* Find end of header line */ - begptr++; - endptr = strchr (begptr, '\n'); - - /* Something is wrong, end of header not found, do not write - * article - */ - if (endptr==NULL) - return 0; - - /* Temporarily make string end a null char */ - savechar = *endptr; - *endptr = '\0'; - newsptr = strstr (begptr, string); - - /* Requested newsgroup not found */ - if (newsptr==NULL) - return 0; - - /* Restore character at end of header string */ - *endptr = savechar; - } - /* No string specified */ - - } - /* No header specified */ - - /* Open file, write buffer, close file */ - snprintf (filename, sizeof(filename), "%s.%06i", fileprefix, fileno); - - outfile = fopen (filename, "wt"); - if (outfile==NULL) { - printf ("Cannot open file name %s\n", filename); - exit(1); - } - - while (n--) - fprintf (outfile, "%c", *buff++); - - close (outfile); - - /* Return number of files written */ - return 1; - } diff --git a/contrib/reset-cnfs.c b/contrib/reset-cnfs.c deleted file mode 100644 index 18bb334..0000000 --- a/contrib/reset-cnfs.c +++ /dev/null @@ -1,56 +0,0 @@ -/* Quick and Dirty Hack to reset a CNFS buffer without having to DD the - * Entire Thing from /dev/zero again. */ -#include -#include -#include -#include - -#include - -/* uncomment the below for LARGE_FILES support */ -/* #define LARGE_FILES */ - -int main(int argc, char *argv[]) -{ - int fd; - int i, j; - char buf[512]; -#ifdef LARGE_FILES - struct stat64 st; -#else - struct stat st; -#endif - int numwr; - - bzero(buf, sizeof(buf)); - for (i = 1; i < argc; i++) { -#ifdef LARGE_FILES - if ((fd = open(argv[i], O_LARGEFILE | O_RDWR, 0664)) < 0) -#else - if ((fd = open(argv[i], O_RDWR, 0664)) < 0) -#endif - fprintf(stderr, "Could not open file %s: %s\n", argv[i], strerror(errno)); - else { -#ifdef LARGE_FILES - if (fstat64(fd, &st) < 0) { -#else - if (fstat(fd, &st) < 0) { -#endif - fprintf(stderr, "Could not stat file %s: %s\n", argv[i], strerror(errno)); - } else { - /* each bit in the bitfield is 512 bytes of data. Each byte - * has 8 bits, so calculate as 512 * 8 bytes of data, plus - * fuzz. buf has 512 bytes in it, therefore containing data for - * (512 * 8) * 512 bytes of data. */ - numwr = (st.st_size / (512*8) / sizeof(buf)) + 50; - printf("File %s: %u %u\n", argv[i], st.st_size, numwr); - for (j = 0; j < numwr; j++) { - if (!(j % 100)) - printf("\t%d/%d\n", j, numwr); - write(fd, buf, sizeof(buf)); - } - } - close(fd); - } - } -} diff --git a/contrib/respool.c b/contrib/respool.c deleted file mode 100644 index 71ed2bd..0000000 --- a/contrib/respool.c +++ /dev/null @@ -1,95 +0,0 @@ -/* -** Refile articles into the storage manager under the current storage.conf -** rules, deleting articles from their old place in the spool. -** Written 10-09-99 by rmtodd@servalan.servalan.com -** -** Note that history and overview will have to be rebuilt for the moved -** articles to be visible after they're moved. -*/ - -/* include foo needed by libinn/storage manager */ -#include "config.h" -#include "clibrary.h" -#include - -#include "inn/innconf.h" -#include "inn/qio.h" -#include "libinn.h" -#include "paths.h" -#include "storage.h" - -char *ME; - -static void -ProcessLine(char *line) -{ - char *tokenptr; - int len; - ARTHANDLE *art; - ARTHANDLE newart; - TOKEN token, newtoken; - char *arttmp; - time_t arrived; - - tokenptr = line; - - /* zap newline at end of tokenptr, if present. */ - len = strlen(tokenptr); - if (tokenptr[len-1] == '\n') { - tokenptr[len-1] = '\0'; - } - - token = TextToToken(tokenptr); - if ((art = SMretrieve(token, RETR_ALL)) == NULL) return; - - len = art->len; - arrived = art->arrived; - arttmp = xmalloc(len); - memcpy(arttmp, art->data, len); - SMfreearticle(art); - if (!SMcancel(token)) { - fprintf(stderr, "%s: cant cancel %s:%s\n", ME, tokenptr, SMerrorstr); - return; - } - - newart.data = arttmp; - newart.len = len; - newart.arrived = (time_t) 0; /* set current time */ - newart.token = (TOKEN *)NULL; - - newtoken = SMstore(newart); - if (newtoken.type == TOKEN_EMPTY) { - fprintf(stderr, "%s: cant store article:%s\n", ME, SMerrorstr); - return; - } - free(arttmp); - printf("refiled %s ",TokenToText(token)); - printf("to %s\n", TokenToText(newtoken)); - return; -} - -int -main(int argc UNUSED, char *argv[]) -{ - bool one = true; - char buff[SMBUF]; - - ME = argv[0]; - - if (!innconf_read(NULL)) - exit(1); - - if (!SMsetup(SM_PREOPEN, &one) || !SMsetup(SM_RDWR, (void *)&one)) { - fprintf(stderr, "can't init storage manager"); - exit(1); - } - if (!SMinit()) { - fprintf(stderr, "Can't init storage manager: %s", SMerrorstr); - } - while (fgets(buff, SMBUF, stdin)) { - ProcessLine(buff); - } - printf("\nYou will now need to rebuild history and overview for the moved" - "\narticles to be visible again.\n"); - exit(0); -} diff --git a/contrib/sample.init.script b/contrib/sample.init.script deleted file mode 100644 index 104ca48..0000000 --- a/contrib/sample.init.script +++ /dev/null @@ -1,18 +0,0 @@ -#!/sbin/sh - -# This is a simple, bare-bones example of a SysV-style init.d script for INN. - -case $1 in - -start) - su news -c /usr/local/news/bin/rc.news - ;; - -stop) - su news -c '/usr/local/news/bin/rc.news stop' - ;; - -esac - -exit 0 - diff --git a/contrib/showtoken.in b/contrib/showtoken.in deleted file mode 100644 index 4f513ce..0000000 --- a/contrib/showtoken.in +++ /dev/null @@ -1,95 +0,0 @@ -#!/usr/bin/perl -w -# showtoken - decode SM tokens -# Olaf Titz, 1999. Marco d'Itri, 2000. Public domain. -# Takes tokens on stdin and write them along with a decoded form on stdout. - -use strict; - -my ($pathspool, %NG); - -my @types = ('trash', '', 'timehash', 'cnfs', 'timecaf', 'tradspool'); - -if ($ARGV[0]) { - $pathspool = $ARGV[0]; - if (open(MAP, "$pathspool/tradspool.map")) { - while () { - my ($ng, $gnum) = split; - $NG{$gnum} = $ng; - } - close MAP; - } -} - -$| = 1; -while () { - chomp; - next if not /^@.+@/; - print "$_ "; - splittoken($_); -} - -sub splittoken { - my $t = shift; - - $t =~ tr/@//d; - $t = pack('H*', $t); - my ($type, $class, $token, $index, $offset, $overlen, $cancelled) = - unpack('C C a16 CLnc', $t); - - if (not $types[$type]) { - print "type=$type unknown!\n"; - next; - } - print "type=$types[$type] class=$class "; - - if ($type == 0) { # trash - } elsif ($type == 2) { # timehash - my ($time, $seq) = unpack('Nn', $token); - my ($a, $b, $c, $d) = unpack('CCCC', $token); - printf 'time=%08lX seq=%04X file=time-%02x/%02x/%02x/%04x-%02x%02x', - $time, $seq, $class, $b, $c, $seq, $a, $d; - } elsif ($type == 3) { # cnfs - my ($buffn, $offset, $cnum) = unpack('A8NN', $token); - printf 'buffer=%s offset=%x cycnum=%x', $buffn, $offset * 512, $cnum; - } elsif ($type == 4) { # timecaf - my ($time, $seq) = unpack('Nn', $token); - my (undef, $b, $c, $d) = unpack('CCCC', $token); - printf 'time=%06lX seq=%04X caf=timecaf-%02x/%02x/%02x%02x.CF', - $time, $seq, $class, $c, $b, $d; - } elsif ($type == 5) { # tradspool - my ($gnum, $art) = unpack('NN', $token); - printf 'ng=%08X art=%d', $gnum, $art; - print "file=articles/$NG{$gnum}/$art" if $NG{$gnum}; - } else { - die "invalid type $type"; - } - print " over=$index offset=$offset overlen=$overlen cancelled=$cancelled" - if length $t > 36; - print "\n"; -} -__END__ -# Format of a token: -# 1 type -# 1 class -# 16 token -# 1 index -# 4 offset -# 2 overlen -# 2 cancelled -# The fields "index" and following are not available with OV3 (INN 2.3 up) -# -# the "token" field is: -# for type=0 (trash) ignored -# for type=2 (timehash) -# 4 time -# 2 seqnum -# for type=3 (cnfs) -# 8 cycbuffname -# 4 offset/512 -# 4 cycnum -# for type=4 (timecaf) -# 4 time -# 2 seqnum -# for type=5 (tradspool) -# 4 ngnum -# 4 artnum diff --git a/contrib/stathist.in b/contrib/stathist.in deleted file mode 100644 index c34c911..0000000 --- a/contrib/stathist.in +++ /dev/null @@ -1,79 +0,0 @@ -#!/usr/bin/perl -w - -# Parse log files created by innd history profiler -# 2001/01/29 - Fabien Tassin - -use strict; -use FileHandle; - -my $file = shift || "stathist.log"; -if ($file eq '-h' || $file eq '--help') { - print "Usage: stathist [logfile]\n"; - exit 0; -} - -sub parse { - my $file = shift; - - my $f = new FileHandle $file; - unless (defined $f) { - print STDERR "Can't open file: $!\n"; - return {}; - } - my $data = {}; - my $begin = 1; - my @stack = (); - while (defined (my $line = <$f>)) { - next if $begin && $line !~ / HIS(havearticle|write|setup) begin/; - $begin = 0; - chomp $line; - my @c = split /[\[\]\(\) ]+/, $line; - ($c[4] eq 'begin') && do { - push @stack, $c[3]; - my $d = $data; - for my $l (@stack) { - unless (defined $$d{$l}) { - $$d{$l}{'min'} = 1E10; - $$d{$l}{'total'} = $$d{$l}{'count'} = $$d{$l}{'max'} = 0; - } - $d = $$d{$l} - } - } || - ($c[4] eq 'end') && do { - my $d = $data; - for my $l (@stack) { - $d = $$d{$l}; - } - $$d{'count'}++; - $$d{'total'} += $c[5]; - $$d{'min'} = $c[5] if $$d{'min'} > $c[5]; - $$d{'max'} = $c[5] if $$d{'max'} < $c[5]; - pop @stack; - }; - } - $f->close; - $data; -} - -sub report { - my $data = shift; - my $inc = shift; - - unless (defined $inc) { - printf "%-16s %10s %14s %10s %10s %10s\n\n", "Function", "Invoked", - "Total(s)", "Min(ms)", "Avg(ms)", "Max(ms)"; - $inc = 0; - } - - for my $key (sort keys %$data) { - next unless $key =~ m/^HIS/; - printf "%-16s %10d %14.6f %10.3f %10.3f %10.3f\n", (' ' x $inc) . $key, - $$data{$key}{'count'}, $$data{$key}{'total'}, $$data{$key}{'min'} * 1000, - $$data{$key}{'total'} / $$data{$key}{'count'} * 1000, - $$data{$key}{'max'} * 1000; - &report($$data{$key}, $inc + 1) - } -} - -my $data = &parse($file); -&report($data); diff --git a/contrib/thdexpire.in b/contrib/thdexpire.in deleted file mode 100644 index 93b09bf..0000000 --- a/contrib/thdexpire.in +++ /dev/null @@ -1,647 +0,0 @@ -#!/usr/bin/perl -w -# fixscript will replace this line with require innshellvars.pl -$ID='$Id: thdexpire.in 4572 2001-02-24 22:31:05Z rra $$'; - -use POSIX ":fcntl_h"; -use SDBM_File; -use Getopt::Std; - -# With the -M switch this program installs its own man page. -#----------------------------------------------------------------------------- - -=head1 NAME - -thdexpire - dynamic expire daemon for timehash and timecaf storage - -=head1 SYNOPSIS - -B -[ B<-t> I ] -[ B<-f> I ] -[ B<-i> I ] -[ B<-m> I ] -[ B<-x> I ] -[ B<-N> ] -[ B<-v> I ] - -B - -=head1 DESCRIPTION - -This is a daemon, to be started along with B, which periodically -looks if news spool space is getting tight, and frees space by removing -articles until enough is free. It is an adjunct (not a replacement) to -INNs B program. - -=head2 Setting Up - -=over 4 - -=item 1. - -Configure your storage classes carefully. Let the default go in class -100 and choose the storage classes as relative (percent) retention -times. E.g. if you want to give C a fifth of the -default time, put them in class 20. Storage classes above 200 are -ignored by this program. 0 expires immediately. An example is given -in L<"EXAMPLES">. - -=item 2. - -Set up your F in a way that it puts only a maximum cap on -retention times. Run B from B as usual. However, -it should only expire articles which have an Expires line or are in -classes above 200. See L<"EXAMPLES">. - -=item 3. - -Ensure to start this daemon along with B. - -=item 4. - -To get information and statistics, run B (in parallel to -a running daemon). This will show you the current actual retention -times. - -=back - -=head2 How It Works - -B works directly on the spool. It assumes the layout -described in the timehash and timecaf sections of L as of -INN-2.x-CURRENT (Dec. 5, 1998). For every storage class associated -with timehash/timecaf, B keeps a I which is the -modification time of the oldest article/CAF file in this class. This -time is chosen so that the difference of the work time of class N to -now (i.e. the I for class N) will be N/100 of the -retention time of class 100. The work time of all classes is -continuously adjusted as time goes by. Articles and CAF files which -are older than the work time are deleted. - -=head1 OPTIONS - -=over 8 - -=item B<-t> I - -Check for free space every I minutes (default 30). - -=item B<-f> I - -Leave I kilobytes of free disk space on each spool -filesystem (default 50000). - -=item B<-i> I - -Leave I inodes free on each spool filesystem (default 5000). - -=item B<-m> I - -Set the minimum normal holding time for class 100 to I days -(default 7). - -=item B<-x> I - -Set the absolute minimum holding time for any article to I -seconds (default 86400, i.e. 1 day). - -=item B<-N> - -Do not delete any articles, just print what would be done. - -=item B<-v> I - -Set the verbosity level. Values from 1 to 3 are meaningful, where -higher levels are mostly for debugging. - -=item B<-r> - -Do not run as a daemon, instead print a report from the database (see -L) on the available storage classes, current expire times and -other stuff. - -=back - -=head1 EXAMPLES - -Here is an example F file: - - # Large postings in binary groups are expired fast: - # 20% retention time - method timehash { - newsgroups: *.binaries.*,*.binaer.*,*.dateien.*,alt.mag.* - size: 30000 - class: 20 - } - - # Local groups and *.answers groups don't expire at all with - # thdexpire. These are handled by Expires lines and a cutoff - # in expire.ctl. - method timehash { - newsgroups: *.answers,news.announce.*,local.* - class: 201 - } - - # Expires lines are honored if they dont exceed 90 days. - # Exempt those postings from thdexpire handling. - method timehash { - newsgroups: * - expires: 1d,90d - class: 202 - } - - # Default: should be class 100 because thdexpire bases its - # calculations thereupon. - method timecaf { - newsgroups: * - class: 100 - } - -And here is an F which fits: - - # Our local groups are held 6 months - local.*:A:7:180:180 - # Everything else is handled by thdexpire, or Expires lines - *:A:7:never:never - -Note that B does not actually use these files, they just -configure other parts of the news system in an appropriate way. - -=head1 FILES - -=over 4 - -=item Finn::pathdbE/thdexpstat.{dir,pag}> - -Holds state information like classes, expire times, oldest articles. -When this file is missing, it will be rebuilt the next time the daemon -is started, which basically means scanning the spool directories to -find the oldest articles. With the B<-r> option, the contents of this -file are printed. - -=item Finn::innddirE/thdexpire.pid> - -Contains the PID of the running daemon. - -=back - -=head1 SIGNALS - -I or I can be sent to the daemon at any time, causing -it to gracefully exit immediately. - -=head1 SEE ALSO - -L, L, L - -=head1 NOTES - -This version needs the B program supplied with newer releases of INN. - -The filenames for timecaf were wrong in older versions of the INN -documentation. This program uses the true filenames, as found by -reading the INN source. - -=head1 DIAGNOSTICS - -Any error messages are printed on standard error. Normal progress -messages, as specified by the B<-v> option, are printed on standard -output. - -=head1 BUGS - -Storage classes which are in I but not on disk (i.e. -which have never been filed into) when the daemon starts are ignored. - -The code is ugly and uses too many global variables. -Should probably rewrite it in C. - -=head1 RESTRICTIONS - -Directories which are left empty are not removed. - -The overview database is not affected by B, it has to be -cleaned up by the daily regular B run. This may need a -patch to B. - -=head1 AUTHOR - -Olaf Titz . Use and distribution of this work is -permitted under the same terms as the B package. - -=head1 HISTORY - -Inspired by the old B program for the traditional spool. - -June 1998: wrote the first version for timehash. - -November 1998: added code for timecaf, works on multiple spool -filesystems, PODed documentation. - -July 1999: bugfixes. - -=cut - -#----------------------------------------------------------------------------- - -chdir $inn::spool || die "chdir $inn::spool: $!"; -$opt_r=0; # make a report -$opt_t=30; # check interval in minutes -$opt_f=50000; # required space in kilobytes -$opt_i=5000; # required space in inodes -$opt_m=7; # minimum normal (class 100) time in days -$opt_x=86400; # absolute minimum hold time in seconds -$opt_N=0; # dont actually delete articles -$opt_v=0; # verbosity level -$opt_M=0; # install man page -getopts("rt:f:i:m:x:Nv:M"); - -$_=$inn::pathdb; $_=$inn::pathnews; # shut up warning -$sfile="$inn::pathdb/thdexpstat"; -$ID=~/ ([^,]+,v [^ ]+)/; $ID=$1; - -if ($opt_M) { - print "Installing thdexpire(8) man page\n"; - $0=~m:^(.*)/([^/]+)$:; - chdir $1 || die "chdir $1"; - exec "pod2man --section=8 --center='Contributed News Software'" . - " --release='$ID' $2 >$inn::pathnews/man/man8/thdexpire.8"; -} - -if ($opt_r) { - tie(%S, SDBM_File, $sfile, O_RDONLY, 0664) || die "open $sfile: $!"; - &report; - untie %S; - exit 0; -} - -(system "shlock", "-p", $$, "-f", "$inn::innddir/thdexpire.pid")>>8==0 - || die "Already running"; -tie(%S, SDBM_File, $sfile, O_RDWR|O_CREAT, 0664) || die "open $sfile: $!"; -$SIG{'TERM'}=$SIG{'INT'}='finish'; -$|=1; -printf "%s starting at %s\n", $ID, &wtime(time) if ($opt_v>0); - -undef @c; -$NOW=time; $ac=$cc=0; -opendir(CD, ".") || &err("opendir $inn::spool: $!"); -while ($cd=readdir(CD), defined($cd)) { - $cd=~/^time(caf)?-([0-9a-f][0-9a-f])$/i || next; - $c{hex($2)}=1 unless hex($2)>200; -} -closedir CD; -@classes=sort {$a<=>$b} keys %c; -foreach $c (@classes) { - &initclass($c); - $S{"work$;$c"}=$S{"oldest$;$c"}&0xFFFFFF00; -} - -$S{"classes"}=join(",", @classes); -$S{"inittime"}=time; -$S{"ID"}=$ID; -printf "Checked %d articles, %d CAFs in %d seconds\n", $ac, $cc, time-$NOW - if ($ac+$cc>0 && $opt_v>0); - -chdir $inn::spool || die "chdir $inn::spool: $!"; -while (1) { - $S{"lastrun"}=$NOW=time; - printf "%s\n", &wtime($NOW) if ($opt_v>0); - $nt=0; - foreach $c (@classes) { - $t=($NOW-$S{"work$;$c"})*100/$c; - $nt=$t if ($nt<$t); - } - printf "Normal time (class 100): %s\n", &xtime($NOW-$nt) - if ($opt_v>0); - if ($nt<$opt_m*24*60*60) { - printf " capped at minimum %d days\n", $opt_m - if ($opt_v>0); - $nt=$opt_m*24*60*60; - } - if ($nt>180*24*60*60) { - print " capped at maximum 180 days\n" - if ($opt_v>0); - $nt=180*24*60*60; - } - $S{"normaltime"}=$nt; - $decrement=$opt_t*60; - $pass=$need=0; - $x="/"; - undef %needk; undef %needi; - foreach $c (@classes) { - $Dart{$c}=$Dcaf{$c}=$Dkb{$c}=$Dino{$c}=0; - $y=sprintf("time-%02x", $c); - if (-d $y) { - @S=stat(_); - if ($#S>=0) { - $dev{$y}=$S[0]; - unless (defined($needk{$S[0]})) { - $x.=" $y"; - $needk{$S[0]}=$needi{$S[0]}=-1; - } - } - } - $y=sprintf("timecaf-%02x", $c); - if (-d $y) { - @S=stat(_); - if ($#S>=0) { - $dev{$y}=$S[0]; - unless (defined($needk{$S[0]})) { - $x.=" $y"; - $needk{$S[0]}=$needi{$S[0]}=-1; - } - } - } - } - if (open(D, "inndf $x |")) { - while () { - @S=split(/\s+/, $_); - $needk{$dev{$S[0]}}=$opt_f-$S[1] unless ($S[0] eq "/"); - } - close D; - } - if (open(D, "inndf -i $x |")) { - while () { - @S=split(/\s+/, $_); - $needi{$dev{$S[0]}}=$opt_i-$S[1] unless ($S[0] eq "/"); - } - close D; - } - foreach $c (keys %needk) { - printf "Device %d needs to free %d kilobytes, %d inodes\n", - $c, $needk{$c}<0?0:$needk{$c}, $needi{$c}<0?0:$needi{$c} - if ($opt_v>0 && ($needk{$c}>0 || $needi{$c}>0)); - if ($needk{$c}>0 || $needi{$c}>0) { - ++$need; - } - } - if ($opt_v>0 && $need<=0) { - print " (nothing to do)\n"; - $tt=0; - } else { - $error=0; - while (!$error && $need>0) { - if ($S{"normaltime"}-$decrement<$opt_m*24*60*60) { - print " Normal time hit minimum\n" if ($opt_v>0); - last; - } - $S{"normaltime"}-=$decrement; - printf " normal time (100) becomes %ld\n", $S{"normaltime"} - if ($opt_v>2); - ++$pass; - $Dart=$Dcaf=$Dkb=$Dino=$need=0; - foreach $c (keys %needk) { - if ($needk{$c}>0 || $needi{$c}>0) { - ++$need; - } - } - if ($need) { - foreach $c (@classes) { - &worktime($c, $NOW-($S{"normaltime"}*$c/100)); - $Dart+=$dart; $Dcaf+=$dcaf; $Dkb+=$dbb>>10; $Dino+=$dino; - $Dart{$c}+=$dart; $Dcaf{$c}+=$dcaf; - $Dkb{$c}+=$dbb>>10; $Dino{$c}+=$dino; - last if ($error); - } - } - if ($Dart+$Dcaf) { - printf " pass %d deleted %d arts, %d CAFs, %d kb\n", - $pass, $Dart, $Dcaf, $Dkb if ($opt_v>1); - $decrement-=$decrement>>2 if ($decrement>10*60); - } else { - $decrement+=$decrement>>1 if ($decrement<4*60*60); - } - } - $Dkb=$Dart=$Dcaf=$Dino=0; - foreach $c (@classes) { - printf " class %3d: deleted %6d arts %6d CAFs %10d kb\n", - $c, $Dart{$c}, $Dcaf{$c}, $Dkb{$c} if ($opt_v>1); - $Dkb+=$Dkb{$c}; $Dart+=$Dart{$c}; $Dcaf+=$Dcaf{$c}; - } - $tt=time-$NOW; - printf " deleted %d articles, %d CAFs, %d kb in %d seconds\n", - $Dart, $Dcaf, $Dkb, time-$NOW if ($opt_v>0); - if ($tt>$opt_t*60) { - printf STDERR "Round needed %d seconds, interval is %d\n", - $tt, $opt_t*60; - $tt=$opt_t*60; - } - } - sleep $opt_t*60-$tt; -} -&finish(0); - - -sub initclass -{ - my $C=shift; - if (!$S{"blocksize$;$C$;CAF"}) { - # Determine filesystem blocksize - # unfortunately no way in perl to statfs - my $x=sprintf("%s/timecaf-%02x/test%d", $inn::spool, $C, $$); - if (open(A, ">$x")) { - print A "X" x 4096; - close A; - @S=stat $x; - $#S>=12 || die "stat: $!"; - if ($S[12]) { - $S{"blocksize$;$C$;CAF"}=$S[7]/$S[12]; - } else { - $S{"blocksize$;$C$;CAF"}=512; - warn "hack around broken stat blocksize"; - } - unlink $x; - } - } - return if ($S{"oldest$;$C"}); - my $oldest=time; - $S{"oldest$;$C"}=$oldest; - my $base=sprintf("%s/time-%02x", $inn::spool, $C); - my $count=0; - if (chdir $base) { - printf "Finding oldest in class %d (%s)\n", $C, $base if ($opt_v>0); - opendir(D0, "."); - while ($d1=readdir(D0), defined($d1)) { - $d1=~/^[0-9a-f][0-9a-f]$/ || next; - chdir $d1; - opendir(D1, ".") || next; - while ($d2=readdir(D1), defined($d2)) { - $d2=~/^[0-9a-f][0-9a-f]$/ || next; - chdir $d2; - opendir(D2, ".") || next; - while ($a=readdir(D2), defined($a)) { - $a=~/^\./ && next; - @S=stat($a); - $oldest=$S[9] if ($S[9]<$oldest); - ++$count; - } - closedir D2; - chdir ".."; - } - closedir D1; - chdir ".."; - } - closedir D0; - $ac+=$count; - } - $base=sprintf("%s/timecaf-%02x", $inn::spool, $C); - if (chdir $base) { - printf "Finding oldest in class %d (%s)\n", $C, $base if ($opt_v>0); - opendir(D0, "."); - while ($d1=readdir(D0), defined($d1)) { - $d1=~/^[0-9a-f][0-9a-f]$/ || next; - chdir $d1; - opendir(D1, ".") || next; - while ($a=readdir(D1), defined($a)) { - $a=~/^\./ && next; - @S=stat($a); - $oldest=$S[9] if ($S[9]<$oldest); - ++$count; - } - closedir D1; - chdir ".."; - } - closedir D0; - $cc+=$count; - } - $S{"count$;$C"}=$count; - $S{"oldest$;$C"}=$oldest; -} - -sub worktime -{ - my $C=shift; - my $goal=shift; - $goal&=0xFFFFFF00; - printf " goal for class %d becomes %s\n", $C, &xtime($goal) - if ($opt_v>2); - if ($goal>$NOW-$opt_x) { - printf " goal for class %d cut off\n", $C - if ($opt_v>1); - $error=1; - return; - } - $dart=$dcaf=$dbb=$dino=0; - $hdir=sprintf("time-%02x", $C); - $cdir=sprintf("timecaf-%02x", $C); - while (($_=$S{"work$;$C"})<$goal) { - printf " running: %08x\n", $_ if ($opt_v>2); - ($aa,$bb,$cc) = (($_>>24)&0xFF, ($_>>16)&0xFF, ($_>>8)&0xFF); - $dir=sprintf("%s/%02x/%02x", $hdir, $bb, $cc); - $pat=sprintf("[0-9a-f]{4}-%02x[0-9a-f]{2}", $aa); - if (opendir(D, $dir)) { - while ($_=readdir(D), defined($_)) { - /^$pat$/ || next; - $art="$dir/$_"; - @S=stat($art); - if ($#S>=7) { - if ($opt_N) { - print " would delete $art" if ($opt_v>2); - } else { - print " deleting $art" if ($opt_v>2); - unlink $art; - } - ++$dart; ++$dino; - printf " %d kb\n", $S[7]>>10 if ($opt_v>2); - $dbb+=$S[7]; - $needk{$dev{$hdir}}-=$S[7]>>10; - $needi{$dev{$hdir}}--; - } - } - } else { - printf " (no dir %s)\n", $dir if ($opt_v>2); - } - $caf=sprintf("%s/%02x/%02x%02x.CF", $cdir, $bb, $aa, $cc); - @S=stat($caf); - if ($#S>=12) { - if ($opt_N) { - print " would delete $caf" if ($opt_v>2); - } else { - print " deleting $caf" if ($opt_v>2); - unlink $caf; - } - $y=0; - if (open(C, $caf)) { - # try to find how much there is in the CAF - sysread(C, $_, 16); - @C=unpack("a4LLL", $_); - if ($C[0] eq "CRMT") { - $y=$C[3]-$C[1]; - $dart+=$y; - } - close C; - } - ++$dcaf; ++$dino; - if ($S[12]) { - $x=$S[12]*$S{"blocksize$;$C$;CAF"}; - } else { - $x=$S[7]; - warn "hack around broken stat blocksize"; - } - printf " %d arts %d kb\n", $y, $x>>10 if ($opt_v>2); - $dbb+=$x; - $needk{$dev{$cdir}}-=$x>>10; - $needi{$dev{$cdir}}--; - } - $S{"work$;$C"}+=0x100; - $S{"oldest$;$C"}=$S{"work$;$C"} unless ($opt_N); - } -} - -sub report -{ - $NOW=time; - my $cc=$S{"classes"}; - my $nt=$S{"normaltime"}; - unless ($cc && $nt) { - print "Not initialized.\n"; - return; - } - printf "Version: %s (this: %s)\n", $S{"ID"}, $ID; - printf "Started at: %s\n", &xtime($S{"inittime"}) if ($S{"inittime"}); - printf "Last run: %s\n", &xtime($S{"lastrun"}) if ($S{"lastrun"}); - printf "Classes: %s\n", $cc; - foreach $c (split(/,/, $cc)) { - printf "Class %d:\n", $c; - #printf " Initial count %d articles\n", $S{"count$;$c"}; - printf " Oldest article: %s\n", &xtime($S{"oldest$;$c"}); - printf " Expiring at: %s\n", &xtime($S{"work$;$c"}); - printf " Normal time: %s\n", &xtime($NOW-$nt*$c/100); - printf " Filesystem block size (CAF): %d\n", $S{"blocksize$;$c$;CAF"}; - } -} - -sub wtime -{ - my $t=shift; - my @T=localtime($t); - sprintf("%04d-%02d-%02d %02d:%02d", - $T[5]+1900, $T[4]+1, $T[3], $T[2], $T[1]); -} - -sub xtime -{ - my $t=shift; - if ($NOW-$t<0 || $NOW-$t>350*24*60*60) { - return &wtime($t); - } - my @T=localtime($t); - my @D=gmtime($NOW-$t); - sprintf("%04d-%02d-%02d %02d:%02d (%dd %dh %dm)", - $T[5]+1900, $T[4]+1, $T[3], $T[2], $T[1], - $D[7], $D[2], $D[1]); -} - -sub err -{ - printf STDERR "%s\n", shift; - &finish(0); -} - -sub finish -{ - untie(%S); - unlink "$inn::innddir/thdexpire.pid"; - exit 0; -} -#----------------------------------------------------------------------------- diff --git a/contrib/tunefeed.in b/contrib/tunefeed.in deleted file mode 100644 index 52616ae..0000000 --- a/contrib/tunefeed.in +++ /dev/null @@ -1,474 +0,0 @@ -#!/usr/bin/perl -$version = q$Id: tunefeed.in 4329 2001-01-14 13:47:52Z rra $; -# -# tunefeed -- Compare active files with a remote site to tune a feed. -# Copyright 1998 by Russ Allbery -# -# This program is free software; you can redistribute it and/or modify it -# under the same terms as Perl itself. - -############################################################################ -# Site configuration -############################################################################ - -# A list of hierarchies in the Big Eight. -%big8 = map { $_ => 1 } qw(comp humanities misc news rec sci soc talk); - -# A list of hierarchies that are considered global and not language -# hierarchies. -%global = map { $_ => 1 } qw(bionet bit biz borland ddn gnu gov ieee info - linux k12 microsoft netscape tnn vmsnet); - -# The pattern matching local-only hierarchies (that we should disregard when -# doing feed matching). -%ignore = map { $_ => 1 } qw(clari control junk); - - -############################################################################ -# Modules and declarations -############################################################################ - -require 5.003; - -use Getopt::Long qw(GetOptions); - -use strict; -use vars qw(%big8 $days %global %ignore $threshold %traffic $version); - - -############################################################################ -# Active file hashing and analysis -############################################################################ - -# Read in an active file, putting those groups into a hash where the key is -# the name of the group and the value is always 1. If the optional third -# argument is true, exclude any groups in the hierarchies listed in %local -# and use this active file to store traffic information (in a rather -# simple-minded fashion). -sub hash { - my ($file, $hash, $local) = @_; - open (ACTIVE, $file) or die "$0: cannot open $file: $!\n"; - local $_; - while () { - my ($group, $high, $low, $flags) = split; - next if ($flags =~ /^=|^x/); - my $hierarchy = (split (/\./, $group, 2))[0]; - next if ($local && $ignore{$hierarchy}); - $$hash{$group} = 1; - $traffic{$group} = ($high - $low) / $days if $local; - } - close ACTIVE; -} - -# Read in a file that gives traffic statistics. We assume it's in the form -# group, whitespace, number of articles per day, and we just read it -# directly into the %traffic hash. -sub traffic { - my ($file) = @_; - open (TRAFFIC, $file) or die "$0: cannot open $file: $!\n"; - local $_; - while () { - my ($group, $traffic) = split; - $traffic{$group} = $traffic; - } - close TRAFFIC; -} - -# Pull off the first X nodes of a group name. -sub prefix { - my ($group, $count) = @_; - my @group = split (/\./, $group); - splice (@group, $count); - join ('.', @group); -} - -# Find the common hierarchical prefix of a list. -sub common { - my (@list) = @_; - my @prefix = split (/\./, shift @list); - local $_; - while (defined ($_ = shift @list)) { - my @group = split /\./; - my $i; - $i++ while ($prefix[$i] && $prefix[$i] eq $group[$i]); - if ($i <= $#prefix) { splice (@prefix, $i) } - } - join ('.', @prefix); -} - -# Given two lists, a list of groups that the remote site does have and a -# list of groups that the remote site doesn't have, in a single hierarchy, -# perform a smash. The object is to find the minimal pattern that expresses -# just the groups they want. We're also given the common prefix of all the -# groups in the have and exclude lists, and a flag indicating whether we're -# coming in with a positive assumption (all groups sent unless excluded) or -# a negative assumption (no groups sent unless added). -sub smash { - my ($have, $exclude, $top, $positive) = @_; - my (@positive, @negative); - my $level = ($top =~ tr/././) + 1; - - # Start with the positive assumption. We make copies of our @have and - # @exclude arrays since we're going to be needing the virgin ones again - # later for the negative assumption. If we're coming in with the - # negative assumption, we have to add a wildcarded entry to switch - # assumptions, and we also have to deal with the cases where there is a - # real group at the head of the hierarchy. - my @have = @$have; - my @exclude = @$exclude; - if ($top eq $have[0]) { - shift @have; - push (@positive, "$top*") unless $positive; - } else { - if ($top eq $exclude[0]) { - if ($positive && $traffic{$top} > $threshold) { - push (@positive, "!$top"); - } - shift @exclude; - } - push (@positive, "$top.*") unless $positive; - } - - # Now that we've got things started, keep in mind that we're set up so - # that every group will be sent *unless* it's excluded. So we step - # through the list of exclusions. The idea here is to pull together all - # of the exclusions with the same prefix (going one level deeper into - # the newsgroup names than we're currently at), and then find all the - # groups with the same prefix that the remote site *does* want. If - # there aren't any, then we can just exclude that whole prefix provided - # that we're saving enough traffic to make it worthwhile (checked - # against the threshold). If there are, and if the threshold still - # makes it worthwhile to worry about this, we call this sub recursively - # to compute the best pattern for that prefix. - while (defined ($_ = shift @exclude)) { - my ($prefix) = prefix ($_, $level + 1); - my @drop = ($_); - my @keep; - my $traffic = $traffic{$_}; - while ($exclude[0] =~ /^\Q$prefix./) { - $traffic += $traffic{$exclude[0]}; - push (@drop, shift @exclude); - } - $prefix = common (@drop); - my $saved = $traffic; - while (@have && $have[0] le $prefix) { shift @have } - while ($have[0] =~ /^\Q$prefix./) { - $traffic += $traffic{$have[0]}; - push (@keep, shift @have); - } - next unless $saved > $threshold; - if (@keep) { - $traffic{"$prefix*"} = $traffic; - push (@positive, smash (\@keep, \@drop, $prefix, 1)); - } elsif (@drop == 1) { - push (@positive, "!$_"); - } elsif ($prefix eq $_) { - push (@positive, "!$prefix*"); - } else { - push (@positive, "!$prefix.*"); - } - } - - # Now we do essentially the same thing, but from the negative - # perspective (adding a wildcard pattern as necessary to make sure that - # we're not sending all groups and then finding the groups we are - # sending and trying to smash them into minimal wildcard patterns). - @have = @$have; - @exclude = @$exclude; - if ($top eq $exclude[0]) { - shift @exclude; - push (@negative, "!$top*") if $positive; - } else { - if ($top eq $have[0]) { - push (@negative, $top) unless $positive; - shift @have; - } - push (@negative, "!$top.*") if $positive; - } - - # This again looks pretty much the same as what we do for the positive - # case; the primary difference is that we have to make sure that we send - # them every group that they want, so we still err on the side of - # sending too much, rather than too little. - while (defined ($_ = shift @have)) { - my ($prefix) = prefix ($_, $level + 1); - my @keep = ($_); - my @drop; - my $traffic = $traffic{$_}; - while ($have[0] =~ /^\Q$prefix./) { - $traffic += $traffic{$have[0]}; - push (@keep, shift @have); - } - $prefix = common (@keep); - while (@exclude && $exclude[0] le $prefix) { shift @exclude } - my $saved = 0; - while ($exclude[0] =~ /^\Q$prefix./) { - $saved += $traffic{$exclude[0]}; - push (@drop, shift @exclude); - } - if (@drop && $saved > $threshold) { - $traffic{"$prefix*"} = $traffic + $saved; - push (@negative, smash (\@keep, \@drop, $prefix, 0)); - } elsif (@keep == 1) { - push (@negative, $_); - } elsif ($prefix eq $_) { - push (@negative, "$prefix*"); - } else { - push (@negative, "$prefix.*"); - } - } - - # Now that we've built both the positive and negative case, we decide - # which to return. We want the one that's the most succinct, and if - # both descriptions are equally succinct, we return the negative case on - # the grounds that it's likely to send less of what they don't want. - (@positive < @negative) ? @positive : @negative; -} - - -############################################################################ -# Output -############################################################################ - -# We want to sort Big Eight ahead of alt.* ahead of global non-language -# hierarchies ahead of regionals and language hierarchies. -sub score { - my ($hierarchy) = @_; - if ($big8{$hierarchy}) { return 1 } - elsif ($hierarchy eq 'alt') { return 2 } - elsif ($global{$hierarchy}) { return 3 } - else { return 4 } -} - -# Our special sort routine for hierarchies. It calls score to get a -# hierarchy score and sorts on that first. -sub by_hierarchy { - (score $a) <=> (score $b) || $a cmp $b; -} - -# Given a reference to a list of patterns, output it in some reasonable -# form. Currently, this is lines prefixed by a tab, with continuation lines -# like INN likes to have in newsfeeds, 76 column margin, and with a line -# break each time the hierarchy score changes. -sub output { - my ($patterns) = @_; - my ($last, $line); - for (@$patterns) { - my ($hierarchy) = /^!?([^.]+)/; - my $score = score $hierarchy; - $line += 1 + length $_; - if (($last && $score > $last) || $line > 76) { - print ",\\\n\t"; - $line = 8 + length $_; - } elsif ($last) { - print ','; - } else { - print "\t"; - $line += 8; - } - print; - $last = $score; - } - print "\n"; -} - - -############################################################################ -# Main routine -############################################################################ - -# Clean up the name of this program for error messages. -my $fullpath = $0; -$0 =~ s%.*/%%; - -# Parse the command line. Our argument is the path to an active file (we -# tell the difference by seeing if it contains a /). -my ($help, $print_version); -Getopt::Long::config ('bundling'); -GetOptions ('help|h' => \$help, - 'days|d=i' => \$days, - 'threshold|t=i' => \$threshold, - 'version|v' => \$print_version) or exit 1; - -# Set a default for the minimum threshold traffic required to retain an -# exclusion, and assume that active file differences represent one day of -# traffic unless told otherwise. -$threshold = (defined $threshold) ? $threshold : 250; -$days ||= 1; - -# If they asked for our version number, abort and just print that. -if ($print_version) { - my ($program, $ver) = (split (' ', $version))[1,2]; - $program =~ s/,v$//; - die "$program $ver\n"; -} - -# If they asked for help, give them the documentation. -if ($help) { - print "Feeding myself to perldoc, please wait....\n"; - exec ('perldoc', '-t', $fullpath) or die "$0: can't fork: $!\n"; -} - -# Hash the active files, skipping groups we ignore in the local one. Make -# sure we have our two files listed first. -unless (@ARGV == 2 || @ARGV == 3) { - die "Usage: $0 [-hv] [-t ] []\n"; -} -my (%local, %remote); -hash (shift, \%local, 1); -hash (shift, \%remote); -traffic (shift) if @ARGV; - -# Now, we analyze the differences between the two feeds. We're trying to -# build a pattern of what *we* should send *them*, so stuff that's in -# %remote and not in %local doesn't concern us. Rather, we're looking for -# stuff that we carry that they don't, since that's what we'll want to -# exclude from a full feed. -my (%have, %exclude, %count, $have, $exclude, $positive); -for (sort keys %local) { - my ($hierarchy) = (split /\./); - $count{$hierarchy}++; - $traffic{"$hierarchy*"} += $traffic{$_}; - if ($remote{$_}) { push (@{$have{$hierarchy}}, $_); $have++ } - else { push (@{$exclude{$hierarchy}}, $_); $exclude++ } -} -my @patterns; -if ($have > $exclude * 4) { - push (@patterns, "*"); - $positive = 1; -} -for (sort by_hierarchy keys %count) { - if ($have{$_} && !$exclude{$_}) { - push (@patterns, "$_.*") unless $positive; - } elsif ($exclude{$_} && !$have{$_}) { - push (@patterns, "!$_.*") if $positive; - } else { - push (@patterns, smash ($have{$_}, $exclude{$_}, $_, $positive)); - } -} -output (\@patterns); -__END__ - - -############################################################################ -# Documentation -############################################################################ - -=head1 NAME - -tunefeed - Build a newsgroups pattern for a remote feed - -=head1 SYNOPSIS - -B [B<-hv>] [B<-t> I] [B<-d> I] I -I [I] - -=head1 DESCRIPTION - -Given two active files, B generates an INN newsfeeds pattern for -a feed from the first site to the second, that sends the second site -everything in its active file carried by the first site but tries to -minimize the number of rejected articles. It does this by noting -differences between the two active files and then trying to generate -wildcard patterns that cover the similarities without including much (or -any) unwanted traffic. - -I and I should be standard active files. You can probably -get the active file of a site that you feed (provided they're running INN) -by connecting to their NNTP port and typing C. - -B makes an effort to avoid complex patterns when they're of -minimal gain. I is the number of messages per day at which to -worry about excluding a group; if a group the remote site doesn't want to -receive gets below that number of messages per day, then that group is -either sent or not sent depending on which choice results in the simplest -(shortest) wildcard pattern. If you want a pattern that exactly matches -what the remote site wants, use C<-t 0>. - -Ideally, B likes to be given the optional third argument, -I, which points at a file listing traffic numbers for each group. -The format of this file is a group name, whitespace, and then the number -of messages per day it receives. Without such a file, B will -attempt to guess traffic by taking the difference between the high and low -numbers in the active file as the amount of traffic in that group per day. -This will almost always not be accurate, but it should at least be a -ballpark figure. If you know approximately how many days of traffic the -active file numbers represent, you can tell B this information -using the B<-d> flag. - -B's output will look something like: - - comp.*,humanities.classics,misc.*,news.*,rec.*,sci.*,soc.*,talk.*,\ - alt.*,!alt.atheism,!alt.binaries.*,!alt.nocem.misc,!alt.punk*,\ - !alt.sex*,!alt.video.dvd,\ - bionet.*,biz.*,gnu.*,vmsnet.*,\ - ba.*,!ba.jobs.agency,ca.*,sbay.* - -(with each line prefixed by a tab, and with standard INN newsfeeds -continuation syntax). Due to the preferences of the author, it will also -be sorted as Big Eight, then alt.*, then global non-language hierarchies, -then regional and language hierarchies. - -=head1 OPTIONS - -=over 4 - -=item B<-h>, B<--help> - -Print out this documentation (which is done simply by feeding the script -to C. - -=item B<-v>, B<--version> - -Print out the version of B and exit. - -=item B<-d> I, B<--days>=I - -Assume that the difference between the high and low numbers in the active -file represent I days of traffic. - -=item B<-t> I, B<--threshold>=I - -Allow any group with less than I articles per day in traffic to -be either sent or not sent depending on which choice makes the wildcard -patterns simpler. If a threshold isn't specified, the default value is -250. - -=back - -=head1 BUGS - -This program takes a long time to run, not to mention being a nasty memory -hog. The algorithm is thorough, but definitely not very optimized, and -isn't all that friendly. - -Guessing traffic from active file numbers is going to produce very skewed -results on sites with expiration policies that vary widely by group. - -There is no way to optimize for size in avoiding rejections, only quantity -of articles. - -There should be a way to turn off the author's idiosyncratic ordering of -hierarchies, or to specify a different ordering, without editing this -script. - -This script should attempt to retrieve the active file from the remote -site automatically if so desired. - -This script should be able to be given some existing wildcard patterns and -take them into account when generating new ones. - -=head1 CAVEATS - -Please be aware that your neighbor's active file may not accurately -represent the groups they wish to receive from you. As with everything, -choices made by automated programs like this one should be reviewed by a -human and the remote site should be notified, and if they have sent -explicit patterns, those should be honored instead. I definitely do *not* -recommend running this program on any sort of automated basis. - -=head1 AUTHOR - -Russ Allbery Erra@stanford.eduE - -=cut diff --git a/control/Makefile b/control/Makefile deleted file mode 100644 index 0d99310..0000000 --- a/control/Makefile +++ /dev/null @@ -1,51 +0,0 @@ -## $Id: Makefile 6806 2004-05-18 01:18:57Z rra $ - -include ../Makefile.global - -top = .. - -ALL = controlbatch controlchan docheckgroups gpgverify perl-nocem \ - pgpverify signcontrol - -MAN = ../doc/man/perl-nocem.8 ../doc/man/pgpverify.1 - -all: $(ALL) - -install: all - for F in $(ALL) ; do \ - $(CP_XPUB) $$F $D$(PATHBIN)/$$F ; \ - done - for M in modules/*.pl ; do \ - $(CP_RPUB) $$M $D$(PATHCONTROL)/`basename $$M` ; \ - done - -man: $(MAN) - -clean clobber distclean: - rm -f $(ALL) - -profiled: all -depend: - -$(FIXSCRIPT): - @echo Run configure before running make. See INSTALL for details. - @exit 1 - - -## Build rules. - -FIX = $(FIXSCRIPT) - -controlbatch: controlbatch.in $(FIX) ; $(FIX) controlbatch.in -controlchan: controlchan.in $(FIX) ; $(FIX) controlchan.in -docheckgroups: docheckgroups.in $(FIX) ; $(FIX) docheckgroups.in -gpgverify: gpgverify.in $(FIX) ; $(FIX) gpgverify.in -perl-nocem: perl-nocem.in $(FIX) ; $(FIX) perl-nocem.in -pgpverify: pgpverify.in $(FIX) ; $(FIX) pgpverify.in -signcontrol: signcontrol.in $(FIX) ; $(FIX) -i signcontrol.in - -../doc/man/perl-nocem.8: perl-nocem - $(POD2MAN) -s 8 $? > $@ - -../doc/man/pgpverify.1: pgpverify - $(POD2MAN) -s 1 $? > $@ diff --git a/control/controlbatch.in b/control/controlbatch.in deleted file mode 100644 index 72035a8..0000000 --- a/control/controlbatch.in +++ /dev/null @@ -1,90 +0,0 @@ -#! /bin/sh -# fixscript will replace this line with code to load innshellvars - -######################################################################## -# controlbatch - Run controlchan against a batch file. -# -# Command usage: controlbatch [feedsite batchfile] -# Defaults are feedsite: controlchan!, batchfile: ${BATCH}/controlchan! -######################################################################## -# -# This script will run controlchan against a batch file. You can use -# it to clear occasional backlogs while running controls from a -# channel, or even skip the channel and run control messages as a file -# feed. -# -######################################################################## -# -# If you're doing the channel thing, you might want to put something -# like this in your crontab to do a cleanup in the wee hours: -# -# 00 04 * * * @prefix@/bin/controlbatch -# -######################################################################## -# -# If you would rather skip the channel and just process controls each -# hour in a batch, use this newsfeeds entry instead of the "stock" -# version: -# -# controlchan!\ -# :!*,control,control.*,!control.cancel\ -# :Tf,Wnsm: -# -# And, a crontab entry something like this: -# -# 30 * * * * @prefix@/bin/controlbatch -# -######################################################################## - -batchlock="${LOCKS}/LOCK.controlbatch" -mypid=$$ - -# A concession to INN 1.x -if [ me${PATHBIN}ow = meow ] ; then - PATHBIN=${NEWSBIN} - export PATHBIN -fi - -# See if we have no arguments and should use the defaults. If there are -# arguments, make sure we have enough to attempt something useful. -if [ me${1}ow != meow ] ; then - if [ me${2}ow = meow ] ; then - echo "Usage: ${0} [feedsite batchfile]" >&2 - exit 0 - else - feedsite=${1} - batchfile=${2} - fi -else - feedsite=controlchan\! - batchfile=controlchan\! -fi - -# Check if any other copies of controlbatch are running. If we are not -# alone, give up here and now. -${PATHBIN}/shlock -p $mypid -f ${batchlock} || exit 0 - -cd ${BATCH} - -if [ -s ${batchfile}.work ] ; then - cat ${batchfile}.work >>${batchfile}.doit - rm -f ${batchfile}.work -fi - -if [ -s ${batchfile} ] ; then - mv ${batchfile} ${batchfile}.work - if ${PATHBIN}/ctlinnd -s -t30 flush ${feedsite} ; then - cat ${batchfile}.work >>${batchfile}.doit - rm -f ${batchfile}.work - fi -fi - -if [ -s ${batchfile}.doit ] ; then - ${PATHBIN}/controlchan \ - < ${batchfile}.doit >> ${MOST_LOGS}/controlbatch.log 2>&1 - # if you want extra assurance that nothing gets lost... - # cat ${batchfile}.doit >> ${batchfile}.done - rm -f ${batchfile}.doit -fi - -rm -f ${batchlock} diff --git a/control/controlchan.in b/control/controlchan.in deleted file mode 100644 index 7fe7338..0000000 --- a/control/controlchan.in +++ /dev/null @@ -1,467 +0,0 @@ -#! /usr/bin/perl -w -require "/usr/local/news/lib/innshellvars.pl"; - -## $Id: controlchan.in 7591 2006-11-22 07:20:46Z eagle $ -## -## Channel feed program to route control messages to an appropriate handler. -## -## Copyright 2001 by Marco d'Itri -## -## Redistribution and use in source and binary forms, with or without -## modification, are permitted provided that the following conditions -## are met: -## -## 1. Redistributions of source code must retain the above copyright -## notice, this list of conditions and the following disclaimer. -## -## 2. Redistributions in binary form must reproduce the above copyright -## notice, this list of conditions and the following disclaimer in the -## documentation and/or other materials provided with the distribution. -## -## Give this program its own newsfeed. Make sure that you've created -## the newsgroup control.cancel so that you don't have to scan through -## cancels, which this program won't process anyway. -## -## Make a newsfeeds entry like this: -## -## controlchan!\ -## :!*,control,control.*,!control.cancel\ -## :Tc,Wnsm\ -## :@prefix@/bin/controlchan - -require 5.004_03; -use strict; - -delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'}; - -# globals -my ($cachedctl, $curmsgid); -my $lastctl = 0; -my $use_syslog = 0; -my $debug = 0; - -# setup logging ########################################################### -# do not log to syslog if stderr is connected to a console -if (not -t 2) { - eval { require INN::Syslog; import INN::Syslog; $use_syslog = 1; }; - eval { require Sys::Syslog; import Sys::Syslog; $use_syslog = 1; } - unless $use_syslog; -} - -if ($use_syslog) { - eval "sub Sys::Syslog::_PATH_LOG { '/dev/log' }" if $^O eq 'dec_osf'; - Sys::Syslog::setlogsock('unix') if $^O =~ /linux|dec_osf|freebsd|darwin/; - openlog('controlchan', 'pid', $inn::syslog_facility); -} -logmsg('starting'); - -# load modules from the control directory ################################# -opendir(CTL, $inn::controlprogs) - or logdie("Cannot open $inn::controlprogs: $!", 'crit'); -foreach (readdir CTL) { - next if not /^([a-z\.]+\.pl)$/ or not -f "$inn::controlprogs/$_"; - eval { require "$inn::controlprogs/$1" }; - if ($@) { - $@ =~ s/\n/ /g; - logdie($@, 'crit'); - } - logmsg("loaded $inn::controlprogs/$1", 'debug'); -} -closedir CTL; - -# main loop ############################################################### -while () { - chop; - my ($token, $sitepath, $msgid) = split(/\s+/, $_); - next if not defined $token; - $sitepath ||= ''; - $curmsgid = $msgid || ''; - - my $artfh = open_article($token); - next if not defined $artfh; - - # suck in headers and body, normalize the strange ones - my (@headers, @body, %hdr); - if (not parse_article($artfh, \@headers, \@body, \%hdr)) { - close $artfh; - next; - } - close $artfh or logdie('sm died with status ' . ($? >> 8)); - - next if not exists $hdr{control}; - - $curmsgid = $hdr{'message-id'}; - my $sender = cleanaddr($hdr{sender} || $hdr{from}); - my $replyto = cleanaddr($hdr{'reply-to'} || $hdr{from}); - - my (@progparams, $progname); - if ($hdr{control} =~ /\s/) { - $hdr{control} =~ /^(\S+)\s+(.+)?/; - $progname = lc $1; - @progparams = split(/\s+/, lc $2) if $2; - } else { - $progname = lc $hdr{control}; - } - - next if $progname eq 'cancel'; - - if ($progname !~ /^([a-z]+)$/) { - logmsg("Naughty control in article $curmsgid ($progname)"); - next; - } - $progname = $1; - - # Do we want to process the message? Let's check the permissions. - my ($action, $logname, $newsgrouppats) = - ctlperm($progname, $sender, $progparams[0], - $token, \@headers, \@body); - - next if $action eq 'drop'; - - if ($action eq '_pgpfail') { - my $type = ''; - if ($progname and $progname eq 'newgroup') { - if ($progparams[1] and $progparams[1] eq 'moderated') { - $type = 'm '; - } else { - $type = 'y '; - } - } - logmsg("skipping $progname $type$sender" - . "(pgpverify failed) in $curmsgid"); - next; - } - - # used by checkgroups. Convert from perl regexp to grep regexp. - if (local $_ = $newsgrouppats) { - s/\$\|/|/g; - s/[^\\]\.[^*]/?/g; - s/\$//; - s/\.\*/*/g; - s/\\([\$\+\.])/$1/g; - $progparams[0] = $_; - } - - # find the appropriate module and call it - my $subname = "control_$progname"; - my $subfind = \&$subname; - if (not defined &$subfind) { - if ($logname) { - logger($logname, "Unknown control message by $sender", - \@headers, \@body); - } else { - logmsg("Unknown \"$progname\" control by $sender"); - } - next; - } - - my $approved = $hdr{approved} ? 1 : 0; - logmsg("$subname, " . join(' ', @progparams) - . " $sender $replyto $token, $sitepath, $action" - . ($logname ? "=$logname" : '') .", $approved"); - - &$subfind(\@progparams, $sender, $replyto, $sitepath, - $action, $logname, $approved, \@headers, \@body); -} - -closelog() if $use_syslog; -exit 0; - -print $inn::most_logs.$inn::syslog_facility.$inn::mta. - $inn::newsmaster.$inn::locks; # lint food - -# misc functions ########################################################## -sub parse_article { - my ($artfh, $headers, $body, $hdr) = @_; - my $h; - my %uniquehdr = map { $_ => 1 } qw(date followup-to from message-id - newsgroups path reply-to subject sender); - - while (<$artfh>) { - s/\r?\n$//; - last if /^$/; - push @$headers, $_; - if (/^(\S+):\s+(.+)/) { - $h = lc $1; - if (exists $hdr->{$h}) { - if (exists $uniquehdr{$h}) { - logmsg("Multiple $1 headers in article $curmsgid"); - return 0; - } - $hdr->{$h} .= ' ' . $2; - } else { - $hdr->{$h} = $2; - } - next; - } elsif (/^\s+(.+)/) { - if (defined $h) { - $hdr->{$h} .= ' ' . $1; - next; - } - } - logmsg("Broken headers in article $curmsgid"); - return 0; - } - - # article is empty or does not exist - return 0 if not @$headers; - - chop (@$body = <$artfh>); - return 1; -} - -# Strip a mail address, innd-style. -sub cleanaddr { - local $_ = shift; - s/(\s+)?\(.*\)(\s+)?//g; - s/.*<(.*)>.*/$1/; - s/[^-a-zA-Z0-9+_.@%]/_/g; # protect MTA - s/^-/_/; # protect MTA - return $_; -} - -# Read and cache control.ctl. -sub readctlfile { - my $mtime = (stat($inn::ctlfile))[9]; - return $cachedctl if $lastctl == $mtime; # mtime has not changed. - $lastctl = $mtime; - - my @ctllist; - open(CTLFILE, $inn::ctlfile) - or logdie("Cannot open $inn::ctlfile: $!", 'crit'); - while () { - chop; - # Not a comment or blank? Convert wildmat to regex - next if not /^(\s+)?[^\#]/ or /^$/; - if (not /:(?:doit|doifarg|drop|log|mail|verify-.*)(?:=.*)?$/) { - s/.*://; - logmsg("$_ is not a valid action for control.ctl", 'err'); - next; - } - # Convert to a : separated list of regexps - s/^all:/*:/i; - s/([\$\+\.])/\\$1/g; - s/\*/.*/g; - s/\?/./g; - s/(.*)/^$1\$/; - s/:/\$:^/g; - s/\|/\$|^/g; - push @ctllist, $_; - } - close CTLFILE; - - logmsg('warning: control.ctl is empty!', 'err') if not @ctllist; - return $cachedctl = [ reverse @ctllist ]; -} - -# Parse a control message's permissions. -sub ctlperm { - my ($type, $sender, $newsgroup, $token, $headers, $body) = @_; - - my $action = 'drop'; # default - my ($logname, $hier); - - # newgroup and rmgroup require newsgroup names; check explicitly for that - # here and return drop if the newsgroup is missing (to avoid a bunch of - # warnings from undefined values later on in permission checking). - if ($type eq 'newgroup' or $type eq 'rmgroup') { - unless ($newsgroup) { - return ('drop', undef, undef); - } - } - - my $ctllist = readctlfile(); - foreach (@$ctllist) { - my @ctlline = split /:/; - # 0: type 1: from@addr 2: group.* 3: action - if ($type =~ /$ctlline[0]/ and $sender =~ /$ctlline[1]/i and - ($type !~ /(?:new|rm)group/ or $newsgroup =~ /$ctlline[2]/)) { - $action = $ctlline[3]; - $action =~ s/\^(.+)\$/$1/; - $action =~ s/\\//g; - $hier = $ctlline[2] if $type eq 'checkgroups'; - last; - } - } - - ($action, $logname) = split(/=/, $action); - - if ($action =~ /^verify-(.+)/) { - my $keyowner = $1; - if ($inn::pgpverify and $inn::pgpverify =~ /^(?:true|on|yes)$/i) { - my $pgpresult = defined &local_pgpverify ? - local_pgpverify($token, $headers, $body) : pgpverify($token); - if ($keyowner eq $pgpresult) { - $action = 'doit'; - } else { - $action = '_pgpfail'; - } - } else { - $action = 'mail'; - } - } - - return ($action, $logname, $hier); -} - -# Write stuff to a log or send mail to the news admin. -sub logger { - my ($logfile, $message, $headers, $body) = @_; - - if ($logfile eq 'mail') { - my $mail = sendmail($message); - print $mail map { s/^~/~~/; "$_\n" } @$headers; - print $mail "\n" . join ('', map { s/^~/~~/; "$_\n" } @$body) - if $body; - close $mail or logdie("Cannot send mail: $!"); - return; - } - - if ($logfile =~ /^([^.\/].*)/) { - $logfile = $1; - } else { - logmsg("Invalid log file: $logfile", 'err'); - $logfile = 'control'; - } - - $logfile = "$inn::most_logs/$logfile.log" unless $logfile =~ /^\//; - my $lockfile = $logfile; - $lockfile =~ s#.*/##; - $lockfile = "$inn::locks/LOCK.$lockfile"; - shlock($lockfile); - - open(LOGFILE, ">>$logfile") or logdie("Cannot open $logfile: $!"); - print LOGFILE "$message\n"; - foreach (@$headers, '', @$body, '') { - print LOGFILE " $_\n"; - } - close LOGFILE; - unlink $lockfile; -} - -# write to syslog or errlog -sub logmsg { - my ($msg, $lvl) = @_; - - return if $lvl and $lvl eq 'debug' and not $debug; - if ($use_syslog) { - syslog($lvl || 'notice', '%s', $msg); - } else { - print STDERR (scalar localtime) . ": $msg\n"; - } -} - -# log a message and then die -sub logdie { - my ($msg, $lvl) = @_; - - $msg .= " ($curmsgid)" if $curmsgid; - logmsg($msg, $lvl || 'err'); - exit 1; -} - -# wrappers executing external programs #################################### - -# Open an article appropriately to our storage method (or lack thereof). -sub open_article { - my $token = shift; - - if ($token =~ /^\@.+\@$/) { - my $pid = open(ART, '-|'); - logdie('Cannot fork: ' . $!) if $pid < 0; - if ($pid == 0) { - exec("$inn::newsbin/sm", '-q', $token) or - logdie("Cannot exec sm: $!"); - } - return *ART; - } else { - return *ART if open(ART, $token); - logmsg("Cannot open article $token: $!"); - } - return undef; -} - -sub pgpverify { - my $token = shift; - - if ($token =~ /^\@.+\@$/) { - open(PGPCHECK, "$inn::newsbin/sm -q $token " - . "| $inn::newsbin/pgpverify |") or goto ERROR; - } else { - open(PGPCHECK, "$inn::newsbin/pgpverify < $token |") or goto ERROR; - } - my $pgpresult = ; - close PGPCHECK or goto ERROR; - $pgpresult ||= ''; - chop $pgpresult; - return $pgpresult; -ERROR: - logmsg("pgpverify failed: $!", 'debug'); - return ''; -} - -sub ctlinnd { - my ($cmd, @args) = @_; - - my $st = system("$inn::newsbin/ctlinnd", '-s', $cmd, @args); - logdie('Cannot run ctlinnd: ' . $!) if $st == -1; - logdie('ctlinnd returned status ' . ($st & 255)) if $st > 0; -} - -sub shlock { - my $lockfile = shift; - - my $locktry = 0; - while ($locktry < 60) { - if (system("$inn::newsbin/shlock", '-p', $$, '-f', $lockfile) == 0) { - return 1; - } - $locktry++; - sleep 2; - } - - my $lockreason; - if (open(LOCKFILE, $lockfile)) { - $lockreason = 'held by ' . ( || '?'); - close LOCKFILE; - } else { - $lockreason = $!; - } - logdie("Cannot get lock $lockfile: $lockreason"); - return undef; -} - -# If $body is not defined, returns a file handle which must be closed. -# Don't forget checking the return value of close(). -# $addresses may be a scalar or a reference to a list of addresses. -# If not defined, $inn::newsmaster is the default. -# parts of this code stolen from innmail.pl -sub sendmail { - my ($subject, $addresses, $body) = @_; - $addresses = [ $addresses || $inn::newsmaster ] if not ref $addresses; - $subject ||= '(no subject)'; - - # fix up all addresses - my @addrs = map { s#[^-a-zA-Z0-9+_.@%]##g; $_ } @$addresses; - - my $sm = $inn::mta; - if ($sm =~ /%s/) { - $sm = sprintf($sm, join(' ', @addrs)); - } else { - $sm .= ' ' . join(' ', @addrs); - } - - # fork and spawn the MTA whitout using the shell - my $pid = open(MTA, '|-'); - logdie('Cannot fork: ' . $!) if $pid < 0; - if ($pid == 0) { - exec(split(/\s+/, $sm)) or logdie("Cannot exec $sm: $!"); - } - - print MTA 'To: ' . join(",\n\t", @addrs) . "\nSubject: $subject\n\n"; - return *MTA if not defined $body; - $body = join("\n", @$body) if ref $body eq 'ARRAY'; - print MTA $body . "\n"; - close MTA or logdie("Execution of $sm failed: $!"); - return 1; -} diff --git a/control/docheckgroups.in b/control/docheckgroups.in deleted file mode 100644 index cee70d6..0000000 --- a/control/docheckgroups.in +++ /dev/null @@ -1,149 +0,0 @@ -#! /bin/sh -# fixscript will replace this line with code to load innshellvars - -## $Revision: 7743 $ -## Script to execute checkgroups text; results to stdout. - -T=${TMPDIR} - -cat /dev/null >${T}/$$out - -## Copy the article without headers, append local newsgroups. -cat >${T}/$$msg -test -f ${LOCALGROUPS} && cat ${LOCALGROUPS} >>${T}/$$msg - -## Get the top-level newsgroup names from the message and turn it into -## an egrep pattern. -PATS=`${SED} <${T}/$$msg \ - -e 's/[ ].*//' -e 's/\..*//' \ - -e 's/^!//' -e '/^$/d' \ - -e 's/^/^/' -e 's/$/[. ]/' \ - | sort -u \ - | (tr '\012' '|' ; echo '' )\ - | ${SED} -e 's/|$//'` - -${EGREP} "${PATS}" ${ACTIVE} | ${EGREP} "${1:-.}" | ${SED} 's/ .*//' | sort >${T}/$$active -${EGREP} "${PATS}" ${T}/$$msg | ${EGREP} "${1:-.}" | ${SED} 's/[ ].*//' | sort >${T}/$$newsgrps - -comm -13 ${T}/$$active ${T}/$$newsgrps >${T}/$$missing -comm -23 ${T}/$$active ${T}/$$newsgrps >${T}/$$remove - -${EGREP} "${PATS}" ${ACTIVE} | ${EGREP} "${1:-.}" | ${SED} -n '/ m$/s/ .*//p' | sort >${T}/$$amod.all -${EGREP} "${PATS}" ${T}/$$msg | ${EGREP} "${1:-.}" | ${SED} 's/\r\?$//' | -${SED} -n '/(Moderated)$/s/[ ].*//p' | sort >${T}/$$ng.mod - -comm -12 ${T}/$$missing ${T}/$$ng.mod >${T}/$$add.mod -comm -23 ${T}/$$missing ${T}/$$ng.mod >${T}/$$add.unmod -cat ${T}/$$add.mod ${T}/$$add.unmod >>${T}/$$add - -comm -23 ${T}/$$amod.all ${T}/$$remove >${T}/$$amod -comm -13 ${T}/$$ng.mod ${T}/$$amod >${T}/$$ismod -comm -23 ${T}/$$ng.mod ${T}/$$amod >${T}/$$nm.all -comm -23 ${T}/$$nm.all ${T}/$$add >${T}/$$notmod - -${EGREP} "${PATS}" ${NEWSGROUPS} | ${EGREP} "${1:-.}" | ${SED} 's/[ ]\+/ /' | sort >${T}/$$localdesc -${EGREP} "${PATS}" ${T}/$$msg | ${EGREP} "${1:-.}" | ${SED} 's/\r\?$//' | -${SED} 's/[ ]\+/ /' | sort >${T}/$$newdesc - -if ! (head -1 ${T}/$$newdesc | egrep " [[:digit:]]+ [[:digit:]]+ " > /dev/null) ; then - comm -13 ${T}/$$localdesc ${T}/$$newdesc >${T}/$$missingdesc - comm -23 ${T}/$$localdesc ${T}/$$newdesc >${T}/$$removedesc -fi - -if [ -s ${T}/$$remove ] ; then - ( - echo "# The following newsgroups are non-standard." - ${SED} "s/^/# /" ${T}/$$remove - echo "# You can remove them by executing the commands:" - for i in `cat ${T}/$$remove` ; do - echo " ${PATHBIN}/ctlinnd rmgroup $i" - ${EGREP} "^$i " ${NEWSGROUPS} >>${T}/$$ngdel - done - echo '' - ) >>${T}/$$out -fi - -if [ -s ${T}/$$add ] ; then - ( - echo "# The following newsgroups were missing and should be added." - ${SED} "s/^/# /" ${T}/$$add - echo "# You can do this by executing the command(s):" - for i in `cat ${T}/$$add.unmod` ; do - echo " ${PATHBIN}/ctlinnd newgroup $i y ${FROM}" - ${EGREP} "^$i " ${T}/$$msg >>${T}/$$ngadd - done - for i in `cat ${T}/$$add.mod` ; do - echo " ${PATHBIN}/ctlinnd newgroup $i m ${FROM}" - ${EGREP} "^$i " ${T}/$$msg >>${T}/$$ngadd - done - echo '' - ) >>${T}/$$out -fi - -if [ -s ${T}/$$ismod ] ; then - ( - echo "# The following groups are incorrectly marked as moderated:" - ${SED} "s/^/# /" ${T}/$$ismod - echo "# You can correct this by executing the following:" - for i in `cat ${T}/$$ismod` ; do - echo " ${PATHBIN}/ctlinnd changegroup $i y" - ${EGREP} "^$i " ${T}/$$msg >>${T}/$$ngchng - done - echo '' - ) >>${T}/$$out -fi - -if [ -s ${T}/$$notmod ] ; then - ( - echo "# The following groups are incorrectly marked as unmoderated:" - ${SED} "s/^/# /" ${T}/$$notmod - echo "# You can correct this by executing the following:" - for i in `cat ${T}/$$notmod` ;do - echo " ${PATHBIN}/ctlinnd changegroup $i m" - ${EGREP} "^$i " ${T}/$$msg >>${T}/$$ngchng - done - echo '' - ) >>${T}/$$out -fi - -if [ -s ${T}/$$removedesc ] ; then - ( - echo "# The following newsgroups descriptions are obsolete." - ${SED} "s/^/# /" ${T}/$$removedesc - echo "# You can remove them by editing ${NEWSGROUPS}." - echo '' - ) >>${T}/$$out -fi - -if [ -s ${T}/$$missingdesc ] ; then - ( - echo "# The following newsgroups descriptions were missing and should be added." - ${SED} "s/^/# /" ${T}/$$missingdesc - echo "# You can add them by editing ${NEWSGROUPS}." - echo '' - ) >>${T}/$$out -fi - - -test -s ${T}/$$out && { - cat ${T}/$$out - echo 'exit # so you can feed this message into the shell' - echo "# And remember to update ${NEWSGROUPS}." - test -s ${T}/$$ngdel && { - echo "# Remove these lines:" - ${SED} "s/^/# /" ${T}/$$ngdel - echo '' - } - test -s ${T}/$$ngadd && { - echo "# Add these lines:" - ${SED} "s/^/# /" ${T}/$$ngadd - echo '' - } - test -s ${T}/$$ngchng && { - echo "# Change these lines:" - ${SED} "s/^/# /" ${T}/$$ngchng - echo '' - } -} - -rm -f ${T}/$$* diff --git a/control/gpgverify.in b/control/gpgverify.in deleted file mode 100644 index f3aecea..0000000 --- a/control/gpgverify.in +++ /dev/null @@ -1,237 +0,0 @@ -#!/usr/bin/perl -w -require '/etc/news/innshellvars.pl'; - -# written April 1996, tale@isc.org (David C Lawrence) -# mostly rewritten 2001-03-21 by Marco d'Itri -# -# requirements: -# - GnuPG -# - perl 5.004_03 and working Sys::Syslog -# - syslog daemon -# -# There is no locking because gpg is supposed to not need it and controlchan -# will serialize control messages processing anyway. - -require 5.004_03; -use strict; - -# if you keep your keyring somewhere that is not the default used by gpg, -# change the location below. -my $keyring; -if ($inn::newsetc && -d "$inn::newsetc/pgp") { - $keyring = $inn::newsetc . '/pgp/pubring.gpg'; -} - -# If you have INN and the script is able to successfully include your -# innshellvars.pl file, the value of the next two variables will be -# overridden. -my $tmpdir = '/var/log/news/'; -my $syslog_facility = 'news'; - -# 1: print PGP output -my $debug = 0; -#$debug = 1 if -t 1; - -### Exit value: -### 0 good signature -### 1 no signature -### 2 unknown signature -### 3 bad signature -### 255 problem not directly related to gpg analysis of signature - -############################################################################## -################ NO USER SERVICEABLE PARTS BELOW THIS COMMENT ################ -############################################################################## -my $tmp = ($inn::pathtmp ? $inn::pathtmp : $tmpdir) . "/pgp$$"; -$syslog_facility = $inn::syslog_facility if $inn::syslog_facility; - -my $nntp_format = 0; -$0 =~ s#^.*/##; # trim /path/to/prog to prog - -die "Usage: $0 < message\n" if $#ARGV != -1; - -# Path to gpg binary -my $gpg; -if ($inn::gpgv) { - $gpg = $inn::gpgv; -} else { - foreach (split(/:/, $ENV{PATH}), qw(/usr/local/bin /opt/gnu/bin)) { - if (-x "$_/gpgv") { - $gpg = "$_/gpgv"; last; - } - } -} -fail('cannot find the gpgv binary') if not $gpg; - -# this is, by design, case-sensitive with regards to the headers it checks. -# it's also insistent about the colon-space rule. -my ($label, $value, %dup, %header); -while () { - # if a header line ends with \r\n, this article is in the encoding - # it would be in during an NNTP session. some article storage - # managers keep them this way for efficiency. - $nntp_format = /\r\n$/ if $. == 1; - s/\r?\n$//; - - last if /^$/; - if (/^(\S+):[ \t](.+)/) { - ($label, $value) = ($1, $2); - $dup{$label} = 1 if $header{$label}; - $header{$label} = $value; - } elsif (/^\s/) { - fail("non-header at line $.: $_") unless $label; - $header{$label} .= "\n$_"; - } else { - fail("non-header at line $.: $_"); - } -} - -my $pgpheader = 'X-PGP-Sig'; -$_ = $header{$pgpheader}; -exit 1 if not $_; # no signature - -# the $sep value means the separator between the radix64 signature lines -# can have any amount of spaces or tabs, but must have at least one space -# or tab, if there is a newline then the space or tab has to follow the -# newline. any number of newlines can appear as long as each is followed -# by at least one space or tab. *phew* -my $sep = "[ \t]*(\n?[ \t]+)+"; -# match all of the characters in a radix64 string -my $r64 = '[a-zA-Z0-9+/]'; -fail("$pgpheader not in expected format") - unless /^(\S+)$sep(\S+)(($sep$r64{64})+$sep$r64+=?=?$sep=$r64{4})$/; - -my ($version, $signed_headers, $signature) = ($1, $3, $4); -$signature =~ s/$sep/\n/g; - -my $message = "-----BEGIN PGP SIGNED MESSAGE-----\n\n" - . "X-Signed-Headers: $signed_headers\n"; - -foreach $label (split(',', $signed_headers)) { - fail("duplicate signed $label header, can't verify") if $dup{$label}; - $message .= "$label: "; - $message .= $header{$label} if $header{$label}; - $message .= "\n"; -} -$message .= "\n"; # end of headers - -while () { # read body lines - if ($nntp_format) { - # check for end of article; some news servers (eg, Highwind's - # "Breeze") include the dot-CRLF of the NNTP protocol in the - # article data passed to this script - last if $_ eq ".\r\n"; - - # remove NNTP encoding - s/^\.\./\./; - s/\r\n$/\n/; - } - - s/^-/- -/; # pgp quote ("ASCII armor") dashes - $message .= $_; -} - -$message .= - "\n-----BEGIN PGP SIGNATURE-----\n" . - "Version: $version\n" . - $signature . - "\n-----END PGP SIGNATURE-----\n"; - -open(TMP, ">$tmp") or fail("open $tmp: $!"); -print TMP $message; -close TMP or errmsg("close $tmp: $!"); - -my $opts = '--quiet --status-fd=1 --logger-fd=1'; -$opts .= " --keyring=$keyring" if $keyring; - -open(PGP, "$gpg $opts $tmp |") or fail("failed to execute $gpg: $!"); - -undef $/; -$_ = ; - -unlink $tmp or errmsg("unlink $tmp: $!"); - -if (not close PGP) { - if ($? >> 8) { - my $status = $? >> 8; - errmsg("gpg exited status $status") if $status > 1; - } else { - errmsg('gpg died on signal ' . ($? & 255)); - } -} - -print STDERR $_ if $debug; - -my $ok = 255; # default exit status -my $signer; -if (/^\[GNUPG:\]\s+GOODSIG\s+\S+\s+(\S+)/m) { - $ok = 0; - $signer = $1; -} elsif (/^\[GNUPG:\]\s+NODATA/m or /^\[GNUPG:\]\s+UNEXPECTED/m) { - $ok = 1; -} elsif (/^\[GNUPG:\]\s+NO_PUBKEY/m) { - $ok = 2; -} elsif (/^\[GNUPG:\]\s+BADSIG\s+/m) { - $ok = 3; -} - -print "$signer\n" if $signer; -exit $ok; - -sub errmsg { - my $msg = $_[0]; - - eval 'use Sys::Syslog qw(:DEFAULT setlogsock)'; - die "$0: cannot use Sys::Syslog: $@ [$msg]\n" if $@; - - die "$0: cannot set syslog method [$msg]\n" - if not (setlogsock('unix') or setlogsock('inet')); - - $msg .= " processing $header{'Message-ID'}" if $header{'Message-ID'}; - - openlog($0, 'pid', $syslog_facility); - syslog('err', '%s', $msg); - closelog(); -} - -sub fail { - errmsg($_[0]); - unlink $tmp; - exit 255; -} - -__END__ - -# Copyright 2000 by Marco d'Itri - -# License of the original version distributed by David C. Lawrence: - -# Copyright (c) 1996 UUNET Technologies, Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# 3. All advertising materials mentioning features or use of this software -# must display the following acknowledgement: -# This product includes software developed by UUNET Technologies, Inc. -# 4. The name of UUNET Technologies ("UUNET") may not be used to endorse or -# promote products derived from this software without specific prior -# written permission. -# -# THIS SOFTWARE IS PROVIDED BY UUNET ``AS IS'' AND ANY EXPRESS OR -# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL UUNET BE LIABLE FOR ANY DIRECT, -# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED -# OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/control/modules/checkgroups.pl b/control/modules/checkgroups.pl deleted file mode 100644 index 56366ad..0000000 --- a/control/modules/checkgroups.pl +++ /dev/null @@ -1,89 +0,0 @@ -## $Id: checkgroups.pl 7743 2008-04-06 10:04:43Z iulius $ -## -## checkgroups control message handler. -## -## Copyright 2001 by Marco d'Itri -## -## Redistribution and use in source and binary forms, with or without -## modification, are permitted provided that the following conditions -## are met: -## -## 1. Redistributions of source code must retain the above copyright -## notice, this list of conditions and the following disclaimer. -## -## 2. Redistributions in binary form must reproduce the above copyright -## notice, this list of conditions and the following disclaimer in the -## documentation and/or other materials provided with the distribution. - -use strict; - -sub control_checkgroups { - my ($par, $sender, $replyto, $site, $action, $log, $approved, - $headers, $body) = @_; - my ($newsgrouppats) = @$par; - - if ($action eq 'mail') { - my $mail = sendmail("checkgroups by $sender"); - print $mail "$sender posted the following checkgroups message:\n"; - print $mail map { s/^~/~~/; "$_\n" } @$headers; - print $mail <$tempfile.art") - or logdie("Cannot open $tempfile.art: $!"); - print TEMPART map { s/^~/~~/; "$_\n" } @$body; - close TEMPART; - - open(OLDIN, '<&STDIN') or die $!; - open(OLDOUT, '>&STDOUT') or die $!; - open(STDIN, "$tempfile.art") or die $!; - open(STDOUT, ">$tempfile") or die $!; - my $st = system("$inn::pathbin/docheckgroups", $newsgrouppats); - logdie('Cannot run docheckgroups: ' . $!) if $st == -1; - logdie('docheckgroups returned status ' . ($st & 255)) if $st > 0; - close(STDIN); - close(STDOUT); - open(STDIN, '<&OLDIN') or die $!; - open(STDOUT, '>&OLDOUT') or die $!; - - open(TEMPFILE, $tempfile) or logdie("Cannot open $tempfile: $!"); - my @output = ; - chop @output; - # There is no need to send an empty mail. - if ($#output > 0) { - logger($log || 'mail', "checkgroups by $sender", \@output); - } else { - logmsg("checkgroups by $sender processed (no change)"); - } - close TEMPFILE; - unlink($tempfile, "$tempfile.art"); -} - -1; diff --git a/control/modules/ihave.pl b/control/modules/ihave.pl deleted file mode 100644 index a64c235..0000000 --- a/control/modules/ihave.pl +++ /dev/null @@ -1,58 +0,0 @@ -## $Id: ihave.pl 4932 2001-07-19 00:32:56Z rra $ -## -## ihave control message handler. -## -## Copyright 2001 by Marco d'Itri -## -## Redistribution and use in source and binary forms, with or without -## modification, are permitted provided that the following conditions -## are met: -## -## 1. Redistributions of source code must retain the above copyright -## notice, this list of conditions and the following disclaimer. -## -## 2. Redistributions in binary form must reproduce the above copyright -## notice, this list of conditions and the following disclaimer in the -## documentation and/or other materials provided with the distribution. - -use strict; - -sub control_ihave { - my ($par, $sender, $replyto, $site, $action, $log, $approved, - $headers, $body) = @_; - - if ($action eq 'mail') { - my $mail = sendmail("ihave by $sender"); - print $mail map { s/^~/~~/; "$_\n" } @$body; - close $mail or logdie('Cannot send mail: ' . $!); - } elsif ($action eq 'log') { - if ($log) { - logger($log, "ihave $sender", $headers, $body); - } else { - logmsg("ihave $sender"); - } - } elsif ($action eq 'doit') { - my $tempfile = "$inn::tmpdir/ihave.$$"; - open(GREPHIST, "|grephistory -i > $tempfile") - or logdie('Cannot run grephistory: ' . $!); - foreach (@$body) { - print GREPHIST "$_\n"; - } - close GREPHIST; - - if (-s $tempfile) { - my $inews = open("$inn::inews -h") - or logdie('Cannot run inews: ' . $!); - print $inews "Newsgroups: to.$site\n" - . "Subject: cmsg sendme $inn::pathhost\n" - . "Control: sendme $inn::pathhost\n\n"; - open(TEMPFILE, $tempfile) or logdie("Cannot open $tempfile: $!"); - print $inews $_ while ; - close $inews or die $!; - close TEMPFILE; - } - unlink $tempfile; - } -} - -1; diff --git a/control/modules/newgroup.pl b/control/modules/newgroup.pl deleted file mode 100644 index 94eef22..0000000 --- a/control/modules/newgroup.pl +++ /dev/null @@ -1,214 +0,0 @@ -## $Id: newgroup.pl 7849 2008-05-25 17:11:32Z iulius $ -## -## newgroup control message handler. -## -## Copyright 2001 by Marco d'Itri -## -## Redistribution and use in source and binary forms, with or without -## modification, are permitted provided that the following conditions -## are met: -## -## 1. Redistributions of source code must retain the above copyright -## notice, this list of conditions and the following disclaimer. -## -## 2. Redistributions in binary form must reproduce the above copyright -## notice, this list of conditions and the following disclaimer in the -## documentation and/or other materials provided with the distribution. - -use strict; - -sub control_newgroup { - my ($par, $sender, $replyto, $site, $action, $log, $approved, - $headers, $body) = @_; - my ($groupname, $modflag) = @$par; - - $modflag ||= ''; - my $modcmd = $modflag eq 'moderated' ? 'm' : 'y'; - - my $errmsg; - $errmsg= local_checkgroupname($groupname) if defined &local_checkgroupname; - if ($errmsg) { - $errmsg = checkgroupname($groupname) if $errmsg eq 'DONE'; - - if ($log) { - logger($log, "skipping newgroup ($errmsg)", $headers, $body); - } else { - logmsg("skipping newgroup ($errmsg)"); - } - return; - } - - # Scan active to see what sort of change we are making. - open(ACTIVE, $inn::active) or logdie("Cannot open $inn::active: $!"); - my @oldgroup; - while () { - next unless /^(\Q$groupname\E)\s\d+\s\d+\s(\w)/; - @oldgroup = split /\s+/; - last; - } - close ACTIVE; - - my $status; - my $ngdesc = 'No description.'; - my $olddesc = ''; - my $ngname = $groupname; - - # If there is a tag line, search whether the description has changed. - my $found = 0; - my $ngline = ''; - foreach (@$body) { - if ($found) { - # It is the line which contains the description. - $ngline = $_; - last; - } - $found = 1 if $_ =~ /^For your newsgroups file:\s*$/; - } - - if ($found) { - ($ngname, $ngdesc) = split(/\s+/, $ngline, 2); - if ($ngdesc) { - $ngdesc =~ s/\s+$//; - $ngdesc =~ s/\s+\(moderated\)\s*$//i; - $ngdesc .= ' (Moderated)' if $modflag eq 'moderated'; - } - # Scan newsgroups to see the previous description, if any. - open(NEWSGROUPS, $inn::newsgroups) - or logdie("Cannot open $inn::newsgroups: $!"); - while () { - if (/^\Q$groupname\E\s+(.*)/) { - $olddesc = $1; - last; - } - } - close NEWSGROUPS; - } - - if (@oldgroup) { - if ($oldgroup[3] eq 'm' and $modflag ne 'moderated') { - $status = 'be made unmoderated'; - } elsif ($oldgroup[3] ne 'm' and $modflag eq 'moderated') { - $status = 'be made moderated'; - } else { - if ($ngdesc eq $olddesc) { - $status = 'no change'; - } else { - $status = 'have a new description'; - } - } - } elsif (not $approved) { - $status = 'unapproved'; - } else { - $status = 'be created'; - } - - if ($action eq 'mail' and $status !~ /(no change|unapproved)/) { - my $mail = sendmail("newgroup $groupname $modcmd $sender"); - print $mail <$tempfile") or logdie("Cannot open $tempfile: $!"); - while () { - next if (/^\Q$name\E\s+(.*)/); - print TEMPFILE $_; - } - # We now write a pretty line for the description. - if (length $name < 8) { - print TEMPFILE "$name\t\t\t$desc\n"; - } elsif (length $name < 16) { - print TEMPFILE "$name\t\t$desc\n"; - } else { - print TEMPFILE "$name\t$desc\n"; - } - close TEMPFILE; - close NEWSGROUPS; - rename($tempfile, $inn::newsgroups) - or logdie("Cannot rename $tempfile: $!"); - unlink("$inn::locks/LOCK.newsgroups", $tempfile); -} - -# Check the group name. This is partially derived from C News. -# Some checks are commented out if I think they're too strict or -# language-dependent. Your mileage may vary. -sub checkgroupname { - local $_ = shift; - - # whole-name checking - return 'Empty group name' if /^$/; - return 'Whitespace in group name' if /\s/; - return 'Unsafe group name' if /[\`\/:;]/; - return 'Bad dots in group name' if /^\./ or /\.$/ or /\.\./; -# return 'Group name does not begin/end with alphanumeric' -# if (/^[a-zA-Z0-9].+[a-zA-Z0-9]$/; - return 'Group name begins in control., junk. or to.' if /^(?:control|junk|to)\./; -# return 'Group name too long' if length $_ > 128; - - my @components = split(/\./); - # prevent alt.a.b.c.d.e.f.g.w.x.y.z... - return 'Too many components' if $#components > 9; - - # per-component checking - for (my $i = 0; $i <= $#components; $i++) { - local $_ = $components[$i]; - return 'all-numeric name component' if /^[0-9]+$/; -# return 'name component starts with non-alphanumeric' if /^[a-zA-Z0-9]/; -# return 'name component does not contain letter' if not /[a-zA-Z]/; - return "`all' or `ctl' used as name component" if /^(?:all|ctl)$/; -# return 'name component longer than 30 characters' if length $_ > 30; -# return 'uppercase letter(s) in name' if /[A-Z]/; - return 'illegal character(s) in name' if /[^a-z0-9+_\-.]/; - # sigh, c++ etc must be allowed - return 'repeated punctuation in name' if /--|__|\+\+./; -# return 'repeated component(s) in name' if ($i + 2 <= $#components -# and $_ eq $components[$i + 1] and $_ eq $components[$i + 2]); - } - return ''; -} - -1; diff --git a/control/modules/rmgroup.pl b/control/modules/rmgroup.pl deleted file mode 100644 index d78b014..0000000 --- a/control/modules/rmgroup.pl +++ /dev/null @@ -1,92 +0,0 @@ -## $Id: rmgroup.pl 7743 2008-04-06 10:04:43Z iulius $ -## -## rmgroup control message handler. -## -## Copyright 2001 by Marco d'Itri -## -## Redistribution and use in source and binary forms, with or without -## modification, are permitted provided that the following conditions -## are met: -## -## 1. Redistributions of source code must retain the above copyright -## notice, this list of conditions and the following disclaimer. -## -## 2. Redistributions in binary form must reproduce the above copyright -## notice, this list of conditions and the following disclaimer in the -## documentation and/or other materials provided with the distribution. - -use strict; - -sub control_rmgroup { - my ($par, $sender, $replyto, $site, $action, $log, $approved, - $headers, $body) = @_; - my ($groupname) = @$par; - - # Scan active to see what sort of change we are making. - open(ACTIVE, $inn::active) or logdie("Cannot open $inn::active: $!"); - my @oldgroup; - while () { - next unless /^(\Q$groupname\E)\s\d+\s\d+\s(\w)/; - @oldgroup = split /\s+/; - last; - } - close ACTIVE; - my $status; - if (not @oldgroup) { - $status = 'no change'; - } elsif (not $approved) { - $status = 'unapproved'; - } else { - $status = 'removed'; - } - - if ($action eq 'mail' and $status !~ /(no change|unapproved)/) { - my $mail = sendmail("rmgroup $groupname $sender"); - print $mail <$tempfile") or logdie("Cannot open $tempfile: $!"); - while () { - print TEMPFILE $_ if not /^\Q$groupname\E\s/; - } - close TEMPFILE; - close NEWSGROUPS; - rename($tempfile, $inn::newsgroups) - or logdie("Cannot rename $tempfile: $!"); - unlink "$inn::locks/LOCK.newsgroups"; - unlink $tempfile; - - logger($log, "rmgroup $groupname $status $sender", $headers, $body) - if $log; - } -} - -1; diff --git a/control/modules/sendme.pl b/control/modules/sendme.pl deleted file mode 100644 index d53ab5a..0000000 --- a/control/modules/sendme.pl +++ /dev/null @@ -1,55 +0,0 @@ -## $Id: sendme.pl 4932 2001-07-19 00:32:56Z rra $ -## -## sendme control message handler. -## -## Copyright 2001 by Marco d'Itri -## -## Redistribution and use in source and binary forms, with or without -## modification, are permitted provided that the following conditions -## are met: -## -## 1. Redistributions of source code must retain the above copyright -## notice, this list of conditions and the following disclaimer. -## -## 2. Redistributions in binary form must reproduce the above copyright -## notice, this list of conditions and the following disclaimer in the -## documentation and/or other materials provided with the distribution. - -use strict; - -sub control_sendme { - my ($par, $sender, $replyto, $site, $action, $log, $approved, - $headers, $body) = @_; - - if ($action eq 'mail') { - my $mail = sendmail("sendme by $sender"); - print $mail map { s/^~/~~/; "$_\n" } @$body; - close $mail or logdie('Cannot send mail: ' . $!); - } elsif ($action eq 'log') { - if ($log) { - logger($log, "sendme $sender", $headers, $body); - } else { - logmsg("sendme from $sender"); - } - } elsif ($action eq 'doit') { - my $tempfile = "$inn::tmpdir/sendme.$$"; - open(GREPHIST, "|grephistory -s > $tempfile") - or logdie("Cannot run grephistory: $!"); - foreach (@$body) { - print GREPHIST "$_\n"; - } - close GREPHIST or logdie("Cannot run grephistory: $!"); - - if (-s $tempfile and $site =~ /^[a-zA-Z0-9.-_]+$/) { - open(TEMPFILE, $tempfile) or logdie("Cannot open $tempfile: $!"); - open(BATCH, ">>$inn::batch/$site.work") - or logdie("Cannot open $inn::batch/$site.work: $!"); - print BATCH $_ while ; - close BATCH; - close TEMPFILE; - } - unlink $tempfile; - } -} - -1; diff --git a/control/modules/sendsys.pl b/control/modules/sendsys.pl deleted file mode 100644 index 6f086ba..0000000 --- a/control/modules/sendsys.pl +++ /dev/null @@ -1,64 +0,0 @@ -## $Id: sendsys.pl 4932 2001-07-19 00:32:56Z rra $ -## -## sendsys control message handler. -## -## Copyright 2001 by Marco d'Itri -## -## Redistribution and use in source and binary forms, with or without -## modification, are permitted provided that the following conditions -## are met: -## -## 1. Redistributions of source code must retain the above copyright -## notice, this list of conditions and the following disclaimer. -## -## 2. Redistributions in binary form must reproduce the above copyright -## notice, this list of conditions and the following disclaimer in the -## documentation and/or other materials provided with the distribution. - -use strict; - -sub control_sendsys { - my ($par, $sender, $replyto, $site, $action, $log, $approved, - $headers, $body) = @_; - my ($where) = @$par; - - if ($action eq 'mail') { - my $mail = sendmail("sendsys $sender"); - print $mail <; - print $mail "\n"; - close NEWSFEEDS; - close $mail or logdie("Cannot send mail: $!"); - - logger($log, "sendsys $sender to $replyto", $headers, $body) if $log; - } -} - -1; diff --git a/control/modules/senduuname.pl b/control/modules/senduuname.pl deleted file mode 100644 index a2f71e5..0000000 --- a/control/modules/senduuname.pl +++ /dev/null @@ -1,61 +0,0 @@ -## $Id: senduuname.pl 4932 2001-07-19 00:32:56Z rra $ -## -## senduuname control message handler. -## -## Copyright 2001 by Marco d'Itri -## -## Redistribution and use in source and binary forms, with or without -## modification, are permitted provided that the following conditions -## are met: -## -## 1. Redistributions of source code must retain the above copyright -## notice, this list of conditions and the following disclaimer. -## -## 2. Redistributions in binary form must reproduce the above copyright -## notice, this list of conditions and the following disclaimer in the -## documentation and/or other materials provided with the distribution. - -use strict; - -sub control_senduuname { - my ($par, $sender, $replyto, $site, $action, $log, $approved, - $headers, $body) = @_; - my ($where) = @$par; - - if ($action eq 'mail') { - my $mail = sendmail("senduuname $sender"); - print $mail <; - close UUNAME or logdie("Cannot run uuname: $!"); - close $mail or logdie("Cannot send mail: $!"); - - logger($log, "senduuname $sender to $replyto", $headers, $body) if $log; - } -} - -1; diff --git a/control/modules/version.pl b/control/modules/version.pl deleted file mode 100644 index f06096f..0000000 --- a/control/modules/version.pl +++ /dev/null @@ -1,61 +0,0 @@ -## $Id: version.pl 4932 2001-07-19 00:32:56Z rra $ -## -## version control message handler. -## -## Copyright 2001 by Marco d'Itri -## -## Redistribution and use in source and binary forms, with or without -## modification, are permitted provided that the following conditions -## are met: -## -## 1. Redistributions of source code must retain the above copyright -## notice, this list of conditions and the following disclaimer. -## -## 2. Redistributions in binary form must reproduce the above copyright -## notice, this list of conditions and the following disclaimer in the -## documentation and/or other materials provided with the distribution. - -use strict; - -sub control_version { - my ($par, $sender, $replyto, $site, $action, $log, $approved, - $headers, $body) = @_; - my ($where) = @$par; - - my $version = $inn::version || '(unknown version)'; - - if ($action eq 'mail') { - my $mail = sendmail("version $sender"); - print $mail < -# Copyright 2001 by Marco d'Itri -# This program is licensed under the terms of the GNU General Public License. -# -# List of changes: -# -# 2002: Patch by Steven M. Christey for untrusted printf input. -# 2007: Patch by Christoph Biedl for checking a timeout. -# Documentation improved by Jeffrey M. Vinocur (2002), Russ Allbery (2006) -# and Julien Elie (2007). -# -############################################################################## - -require 5.00403; -use strict; - -# XXX FIXME I haven't been able to load it only when installed. -# If nobody can't fix it just ship the program with this line commented. -#use Time::HiRes qw(time); - -my $keyring = $inn::pathetc . '/pgp/ncmring.gpg'; - -# XXX To be moved to a config file. -#sub local_want_cancel_id { -# my ($group, $hdrs) = @_; -# -## Hippo has too many false positives to be useful outside of pr0n groups -# if ($hdrs->{issuer} =~ /(?:Ultra|Spam)Hippo/) { -# foreach (split(/,/, $group)) { -# return 1 if /^alt\.(?:binar|sex)/; -# } -# return 0; -# } -# return 1; -#} - -# no user serviceable parts below this line ################################### - -# global variables -my ($working, $got_sighup, $got_sigterm, @ncmperm, $cancel); -my $use_syslog = 0; -my $log_open = 0; -my $nntp_open = 0; -my $last_cancel = 0; -my $socket_timeout = $inn::peertimeout - 100; - -my $logfile = $inn::pathlog . '/perl-nocem.log'; - -# initialization and main loop ############################################### - -eval { require Sys::Syslog; import Sys::Syslog; $use_syslog = 1; }; - -if ($use_syslog) { - eval "sub Sys::Syslog::_PATH_LOG { '/dev/log' }" if $^O eq 'dec_osf'; - Sys::Syslog::setlogsock('unix') if $^O =~ /linux|dec_osf/; - openlog('nocem', '', $inn::syslog_facility); -} - -if (not $inn::gpgv) { - logmsg('cannot find the gpgv binary', 'err'); - sleep 5; - exit 1; -} - -if ($inn::version and not $inn::version =~ /^INN 2\.[0123]\./) { - $cancel = \&cancel_nntp; -} else { - $cancel = \&cancel_ctlinnd; -} - -$SIG{HUP} = \&hup_handler; -$SIG{INT} = \&term_handler; -$SIG{TERM} = \&term_handler; -$SIG{PIPE} = \&term_handler; - -logmsg('starting up'); - -unless (read_ctlfile()) { - sleep 5; - exit 1; -} - -while () { - chop; - $working = 1; - do_nocem($_); - $working = 0; - term_handler() if $got_sigterm; - hup_handler() if $got_sighup; -} - -logmsg('exiting because of EOF', 'debug'); -exit 0; - -############################################################################## - -# Process one NoCeM notice. -sub do_nocem { - my $token = shift; - my $start = time; - - # open the article and verify the notice - my $artfh = open_article($token); - return if not defined $artfh; - my ($msgid, $nid, $issuer, $nocems) = read_nocem($artfh); - close $artfh; - return unless $nocems; - - &$cancel($nocems); - logmsg("Articles cancelled: " . join(' ', @$nocems), 'debug'); - my $diff = (time - $start) || 0.01; - my $nr = scalar @$nocems; - logmsg(sprintf("processed notice %s by %s (%d ids, %.5f s, %.1f/s)", - $nid, $issuer, $nr, $diff, $nr / $diff)); -} - -# - Check if it is a PGP signed NoCeM notice -# - See if we want it -# - Then check PGP signature -sub read_nocem { - my $artfh = shift; - - # Examine the first 200 lines to see if it is a PGP signed NoCeM. - my $ispgp = 0; - my $isncm = 0; - my $inhdr = 1; - my $i = 0; - my $body = ''; - my ($from, $msgid); - while (<$artfh>) { - last if $i++ > 200; - s/\r\n$/\n/; - if ($inhdr) { - if (/^$/) { - $inhdr = 0; - } elsif (/^From:\s+(.*)\s*$/i) { - $from = $1; - } elsif (/^Message-ID:\s+(<.*>)/i) { - $msgid = $1; - } - } else { - $body .= $_; - $ispgp = 1 if /^-----BEGIN PGP SIGNED MESSAGE-----/; - if (/^\@\@BEGIN NCM HEADERS/) { - $isncm = 1; - last; - } - } - } - - # must be a PGP signed NoCeM. - if (not $ispgp) { - logmsg("Article $msgid: not PGP signed", 'debug'); - return; - } - if (not $isncm) { - logmsg("Article $msgid: not a NoCeM", 'debug'); - return; - } - - # read the headers of this NoCeM, and check if it's supported. - my %hdrs; - while (<$artfh>) { - s/\r\n/\n/; - $body .= $_; - last if /^\@\@BEGIN NCM BODY/; - my ($key, $val) = /^([^:]+)\s*:\s*(.*)$/; - $hdrs{lc $key} = $val; - } - foreach (qw(action issuer notice-id type version)) { - next if $hdrs{$_}; - logmsg("Article $msgid: missing $_ pseudo header", 'debug'); - return; - } - return if not supported_nocem($msgid, \%hdrs); - - # decide if we want it. - if (not want_nocem(\%hdrs)) { - logmsg("Article $msgid: unwanted ($hdrs{issuer}/$hdrs{type})", 'debug'); - return; - } -# XXX want_hier() not implemented -# if ($hdrs{hierarchies} and not want_hier($hdrs{hierarchies})) { -# logmsg("Article $msgid: unwanted hierarchy ($hdrs{hierarchies})", -# 'debug'); -# return; -# } - - # We do want it, so read the entire article. Also copy it to - # a temp file so that we can check the PGP signature when done. - my $tmpfile = "$inn::pathtmp/nocem.$$"; - if (not open(OFD, ">$tmpfile")) { - logmsg("cannot open temp file $tmpfile: $!", 'err'); - return; - } - print OFD $body; - undef $body; - - # process NoCeM body. - my $inbody = 1; - my @nocems; - my ($lastid, $lastgrp); - while (<$artfh>) { - s/\r\n$/\n/; - print OFD; - $inbody = 0 if /^\@\@END NCM BODY/; - next if not $inbody or /^#/; - - my ($id, $grp) = /^(\S*)\s+(\S+)/; - next if not $grp; - if ($id) { - push @nocems, $lastid - if $lastid and want_cancel_id($lastgrp, \%hdrs); - $lastid = $id; - $lastgrp = $grp; - } else { - $lastgrp .= ',' . $grp; - } - } - push @nocems, $lastid if $lastid and want_cancel_id($lastgrp, \%hdrs); - close OFD; - - # at this point we need to verify the PGP signature. - return if not @nocems; - my $e = pgp_check($hdrs{issuer}, $msgid, $tmpfile); - unlink $tmpfile; - return if not $e; - - return ($msgid, $hdrs{'notice-id'}, $hdrs{issuer}, \@nocems); -} - -# XXX not implemented: code to discard notices for groups we don't carry -sub want_cancel_id { - my ($group, $hdrs) = @_; - - return local_want_cancel_id(@_) if defined &local_want_cancel_id; - 1; -} - -# Do we actually want this NoCeM? -sub want_nocem { - my $hdrs = shift; - - foreach (@ncmperm) { - my ($issuer, $type) = split(/\001/); - if ($hdrs->{issuer} =~ /$issuer/i) { - return 1 if '*' eq $type or lc $hdrs->{type} eq $type; - } - } - return 0; -} - -sub supported_nocem { - my ($msgid, $hdrs) = @_; - - if ($hdrs->{version} !~ /^0\.9[0-9]?$/) { - logmsg("Article $msgid: version $hdrs->{version} not supported", - 'debug'); - return 0; - } - if ($hdrs->{action} ne 'hide') { - logmsg("Article $msgid: action $hdrs->{action} not supported", - 'debug'); - return 0; - } - return 1; -} - -# Check the PGP signature on an article. -sub pgp_check { - my ($issuer, $msgid, $art) = @_; - - # fork and spawn a child - my $pid = open(PFD, '-|'); - if (not defined $pid) { - logmsg("pgp_check: cannot fork: $!", 'err'); - return 0; - } - if ($pid == 0) { - open(STDERR, '>&STDOUT'); - exec($inn::gpgv, '--status-fd=1', - $keyring ? '--keyring=' . $keyring : '', $art); - exit 126; - } - - # Read the result and check status code. - local $_ = join('', ); - my $status = 0; - if (not close PFD) { - if ($? >> 8) { - $status = $? >> 8; - } else { - logmsg("Article $msgid: $inn::gpgv killed by signal " . ($? & 255)); - return 0; - } - } -# logmsg("Command line was: $inn::gpgv --status-fd=1" -# . ($keyring ? ' --keyring=' . $keyring : '') . " $art", 'debug'); -# logmsg("Full PGP output: >>>$_<<<", 'debug'); - - if (/^\[GNUPG:\]\s+GOODSIG\s+\S+\s+(.*)/m) { - return 1 if $1 =~ /\Q$issuer\E/; - logmsg("Article $msgid: signed by $1 instead of $issuer"); - } elsif (/^\[GNUPG:\]\s+NO_PUBKEY\s+(\S+)/m) { - logmsg("Article $msgid: $issuer (ID $1) not in keyring"); - } elsif (/^\[GNUPG:\]\s+BADSIG\s+\S+\s+(.*)/m) { - logmsg("Article $msgid: bad signature from $1"); - } elsif (/^\[GNUPG:\]\s+BADARMOR/m or /^\[GNUPG:\]\s+UNEXPECTED/m) { - logmsg("Article $msgid: malformed signature"); - } elsif (/^\[GNUPG:\]\s+ERRSIG\s+(\S+)/m) { - # safety net: we get there if we don't know about some token - logmsg("Article $msgid: unknown error (ID $1)"); - } else { - # some other error we don't know about happened. - # 126 is returned by the child if exec fails. - s/ at \S+ line \d+\.\n$//; s/\n/_/; - logmsg("Article $msgid: $inn::gpgv exited " - . (($status == 126) ? "($_)" : "with status $status"), 'err'); - } - return 0; -} - -# Read article. -sub open_article { - my $token = shift; - - if ($token =~ /^\@.+\@$/) { - my $pid = open(ART, '-|'); - if ($pid < 0) { - logmsg('Cannot fork: ' . $!, 'err'); - return undef; - } - if ($pid == 0) { - exec("$inn::newsbin/sm", '-q', $token) or - logmsg("Cannot exec sm: $!", 'err'); - return undef; - } - return *ART; - } else { - return *ART if open(ART, $token); - logmsg("Cannot open article $token: $!", 'err'); - } - return undef; -} - -# Cancel a number of Message-IDs. We use ctlinnd to do this, -# and we run up to 15 of them at the same time (10 usually). -sub cancel_ctlinnd { - my @ids = @{$_[0]}; - - while (@ids > 0) { - my $max = @ids <= 15 ? @ids : 10; - for (my $i = 1; $i <= $max; $i++) { - my $msgid = shift @ids; - my $pid; - sleep 5 until (defined ($pid = fork)); - if ($pid == 0) { - exec "$inn::pathbin/ctlinnd", '-s', '-t', '180', - 'cancel', $msgid; - exit 126; - } -# logmsg("cancelled: $msgid [$i/$max]", 'debug'); - } - # Now wait for all children. - while ((my $pid = wait) > 0) { - next unless $?; - if ($? >> 8) { - logmsg("Child $pid died with status " . ($? >> 8), 'err'); - } else { - logmsg("Child $pid killed by signal " . ($? & 255), 'err'); - } - } - } -} - -sub cancel_nntp { - my $ids = shift; - my $r; - - if ($nntp_open and time - $socket_timeout > $last_cancel) { - logmsg('Close socket for timeout'); - close (NNTP); - $nntp_open = 0; - } - if (not $nntp_open) { - use Socket; - if (not socket(NNTP, PF_UNIX, SOCK_STREAM, 0)) { - logmsg("socket: $!", 'err'); - goto ERR; - } - if (not connect(NNTP, sockaddr_un($inn::pathrun . '/nntpin'))) { - logmsg("connect: $!", 'err'); - goto ERR; - } - if (($r = ) !~ /^200 /) { - $r =~ s/\r\n$//; - logmsg("bad reply from server: $r", 'err'); - goto ERR; - } - select NNTP; $| = 1; select STDOUT; - print NNTP "MODE CANCEL\r\n"; - if (($r = ) !~ /^284 /) { - $r =~ s/\r\n$//; - logmsg("MODE CANCEL not supported: $r", 'err'); - goto ERR; - } - $nntp_open = 1; - } - foreach (@$ids) { - print NNTP "$_\r\n"; - if (($r = ) !~ /^289/) { - $r =~ s/\r\n$//; - logmsg("cannot cancel $_: $r", 'err'); - goto ERR; - } - } - $last_cancel = time; - return; - -ERR: - # discard unusable socket - close (NNTP); - logmsg('Switching to ctlinnd...', 'err'); - cancel_ctlinnd($ids); - $cancel = \&cancel_ctlinnd; -} - -sub read_ctlfile { - my $permfile = $inn::pathetc . '/nocem.ctl'; - - unless (open(CTLFILE, $permfile)) { - logmsg("Cannot open $permfile: $!", 'err'); - return 0; - } - while () { - chop; - s/^\s+//; s/\s+$//; - next if /^#/ or /^$/; - my ($issuer, $type) = split(/:/, lc $_); - logmsg("Cannot parse nocem.ctl line <<$_>>", 'err') - if not $issuer and $type; - $type =~ s/\s//g; - push @ncmperm, "$issuer\001$_" foreach split(/,/, $type); - } - close CTLFILE; - return 1; -} - -sub logmsg { - my ($msg, $lvl) = @_; - - if (not $use_syslog) { - if ($log_open == 0) { - open(LOG, ">>$logfile") or die "Cannot open log: $!"; - $log_open = 1; - select LOG; $| = 1; select STDOUT; - } - $lvl ||= 'notice'; - print LOG "$lvl: $msg\n"; - return; - } - syslog($lvl || 'notice', '%s', $msg); -} - -sub hup_handler { - $got_sighup = 1; - return if $working; - close LOG; - $log_open = 0; -} - -sub term_handler { - $got_sigterm = 1; - return if $working; - logmsg('exiting because of signal'); - exit 1; -} - -# lint food -print $inn::pathrun.$inn::pathlog.$inn::pathetc.$inn::newsbin.$inn::pathbin - .$inn::pathtmp.$inn::peertimeout.$inn::syslog_facility; - -__END__ - -=head1 NAME - -perl-nocem - A NoCeM-on-spool implementation for S - -=head1 SYNOPSIS - -perl-nocem - -=head1 DESCRIPTION - -NoCeM, which is pronounced I, is a protocol enabling -authenticated third-parties to issue notices which can be used -to cancel unwanted articles (like spam and articles in moderated -newsgroups which were not approved by their moderators). It can -also be used by readers as a I. It is -intended to eventually replace the protocol for third-party cancel -messages. - -B processes third-party, PGP-signed article cancellation -notices. It is possible not to honour all NoCeM notices but only those -which are sent by people whom you trust (that is to say if you trust -the PGP key they use to sign their NoCeM notices). Indeed, it is up -to you to decide whether you wish to honour their notices, depending -on the criteria they use. - -Processing NoCeM notices is easy to set up: - -=over 4 - -=item 1. - -Import the keys of the NoCeM issuers you trust in order to check -the authenticity of their notices. You can do: - - gpg --no-default-keyring --primary-keyring /pgp/ncmring.gpg \ - --no-options --allow-non-selfsigned-uid --no-permission-warning \ - --batch --import - -where is the value of the I parameter set in F -and the file containing the key(s) to import. The keyring -must be located in I/pgp/ncmring.gpg (create the directory -before using B). For old PGP-generated keys, you may have to use -B<--allow-non-selfsigned-uid> if they are not properly self-signed, -but anyone creating a key really should self-sign the key. Current -PGP implementations do this automatically. - -The keys of NoCeM issuers can be found in the web site of I: -L. You can even -download there a unique file which contains all the keys. - -=item 2. - -Create a F config file in I indicating the NoCeM issuers -and notices you want to follow. This permission file contains lines like: - - annihilator-1:* - clewis@ferret.ocunix:mmf - stephane@asynchrone:mmf,openproxy,spam - -This will remove all articles for which the issuer (first part of the line, -before the colon C<:>) has issued NoCeM notices corresponding to the -criteria specified after the colon. - -You will also find information about that on the web site of -I. - -=item 3. - -Add to the F file an entry like this one in order to feed -B the NoCeM notices posted to alt.nocem.misc and -news.lists.filters: - - nocem!\ - :!*,alt.nocem.misc,news.lists.filters\ - :Tc,Wf,Ap:/perl-nocem - -with the correct path to B, located in . Then, reload -the F file (C). - -Note that you should at least carry news.lists.filters on your news -server (or other newsgroups where NoCeM notices are sent) if you wish -to process them. - -=item 4. - -Everything should now work. However, do not hesitate to manually test -B with a NoCeM notice, using: - - grephistory '' | perl-nocem - -Indeed, B expects tokens on its standard input, and -B can easily give it the token of a known article, -thanks to its Message-ID. - -=back - -When you have verified that everything works, you can eventually turn -off regular spam cancels, if you want, not processing any longer -cancels containing C in the Path: header (see the -I parameter in F). - -=head1 FILES - -=over 4 - -=item I/perl-nocem - -The Perl script itself used to process NoCeM notices. - -=item I/nocem.ctl - -The configuration file which specifies the NoCeM notices to be processed. - -=item I/pgp/ncmring.gpg - -The keyring which contains the public keys of trusted NoCeM issuers. - -=back - -=head1 BUGS - -The Subject: header is not checked for the @@NCM string and there is no -check for the presence of the References: header. - -The Newsgroups: pseudo header is not checked, but this can be done in -local_want_cancel_id(). - -The Hierarchies: header is ignored. - -=head1 HISTORY - -Copyright 2000 by Miquel van Smoorenburg . - -Copyright 2001 by Marco d'Itri . - -$Id: perl-nocem.in 7733 2008-04-06 09:16:20Z iulius $ - -=head1 SEE ALSO - -gpgv(1), grephistory(1), inn.conf(5), newsfeeds(5), pgp(1). - -=cut diff --git a/control/pgpverify.in b/control/pgpverify.in deleted file mode 100644 index feee446..0000000 --- a/control/pgpverify.in +++ /dev/null @@ -1,876 +0,0 @@ -#! /usr/bin/perl -w -# do '@LIBDIR@/innshellvars.pl'; -# If running inside INN, uncomment the above and point to innshellvars.pl. -# -# Written April 1996, (David C Lawrence) -# Currently maintained by Russ Allbery -# Version 1.27, 2005-07-02 -# -# NOTICE TO INN MAINTAINERS: The version that is shipped with INN is the -# same as the version that I make available to the rest of the world -# (including non-INN sites), so please make all changes through me. -# -# This program requires Perl 5, probably at least about Perl 5.003 since -# that's when FileHandle was introduced. If you want to use this program -# and your Perl is too old, please contact me (rra@stanford.edu) and tell -# me about it; I want to know what old versions of Perl are still used in -# practice. -# -# Changes from 1.26 -> 1.27 -# -- Default to pubring.gpg when trustedkeys.gpg is not found in the -# default key location, for backward compatibility. -# -# Changes from 1.25 -> 1.26 -# -- Return the correct status code when the message isn't verified -# instead of always returning 255. -# -# Changes from 1.24 -> 1.25 -# -- Fix the -test switch to actually do something. -# -- Improve date generation when logging to standard output. -# -# Changes from 1.23 -> 1.24 -# -- Fix bug in the recognition of wire-format articles. -# -# Changes from 1.15 -> 1.23 -# -- Bump version number to match CVS revision number. -# -- Replaced all signature verification code with code that uses detached -# signatures. Signatures generated by GnuPG couldn't be verified using -# attached signatures without adding a Hash: header, and this was the -# path of least resistance plus avoids munging problems in the future. -# Code taken from PGP::Sign. -# -# Changes from 1.14 -> 1.15 -# -- Added POD documentation. -# -- Fixed the -test switch so that it works again. -# -- Dropped Perl 4 compatibility and reformatted. Now passes use strict. -# -# Changes from 1.13.1 -> 1.14 -# -- Native support for GnuPG without the pgpgpg wrapper, using GnuPG's -# program interface by Marco d'Itri. -# -- Always use Sys::Syslog without any setlogsock call for Perl 5.6.0 or -# later, since Sys::Syslog in those versions of Perl uses the C library -# interface and is now portable. -# -- Default to expecting the key ring in $inn'newsetc/pgp if it exists. -# -- Fix a portability problem for Perl 4 introduced in 1.12. -# -# Changes from 1.13 -> 1.13.1 -# -- Nothing functional, just moved the innshellvars.pl line to the head of -# the script, to accomodate the build process of INN. -# -# Changes from 1.12 -> 1.13 -# -- Use INN's syslog_facility if available. -# -# Changes from 1.11 -> 1.12 -# -- Support for GnuPG. -# -- Use /usr/ucb/logger, if present, instead of /usr/bin/logger (the latter -# of which, on Solaris at least, is some sort of brain damaged POSIX.2 -# command which doesn't use syslog). -# -- Made syslog work for dec_osf (version 4, at least). -# -- Fixed up priority of '.' operator vs bitwise operators. -# -# Changes from 1.10 -> 1.11 -# -- Code to log error messages to syslog. -# See $syslog and $syslog_method configurable variables. -# -- Configurably allow date stamp on stderr error messages. -# -- Added locking for multiple concurrent pgp instances. -# -- More clear error message if pgp exits abnormally. -# -- Identify PGP 5 "BAD signature" string. -# -- Minor diddling for INN (path to innshellvars.pl changed). -# -# Changes from 1.9 -> 1.10 -# -- Minor diddling for INN 2.0: use $inn'pathtmp if it exists, and -# work with the new subst method to find innshellvars.pl. -# -- Do not truncate the tmp file when opening, in case it is really -# linked to another file. -# -# Changes from 1.8 -> 1.9 -# -- Match 'Bad signature' pgp output to return exit status 3 by removing -# '^' in regexp matched on multiline string. -# -# Changes from 1.7 -> 1.8 -# -- Ignore final dot-CRLF if article is in NNTP format. -# -# Changes from 1.6 -> 1.7 -# -- Parse PGP 5.0 'good signature' lines. -# -- Allow -test switch; prints pgp input and output. -# -- Look for pgp in INN's innshellvars.pl. -# -- Changed regexp delimiters for stripping $0 to be compatible with old -# Perl. -# -# Changes from 1.5 -> 1.6 -# -- Handle articles encoded in NNTP format ('.' starting line is doubled, -# \r\n at line end) by stripping NNTP encoding. -# -- Exit 255 with pointer to $HOME or $PGPPATH if pgp can't find key -# ring. (It probably doesn't match the necessary error message with -# ViaCrypt PGP.) -# -- Failures also report Message-ID so the article can be looked up to -# retry. -# -# Changes from 1.4 -> 1.5 -# -- Force English language for 'Good signature from user' by passing -# +language=en on pgp command line, rather than setting the -# environment variable LANGUAGE to 'en'. -# -# Changes from 1.3 -> 1.4 -# -- Now handles wrapped headers that have been unfolded. -# (Though I do believe news software oughtn't be unfolding them.) -# -- Checks to ensure that the temporary file is really a file, and -# not a link or some other weirdness. - -# Path to the GnuPG gpgv binary, if you have GnuPG. If you do, this will -# be used in preference to PGP. For most current control messages, you -# need a version of GnuPG that can handle RSA signatures. If you have INN -# and the script is able to successfully include your innshellvars.pl -# file, the value of $inn::gpgv will override this. -# $gpgv = '/usr/local/bin/gpgv'; - -# Path to pgp binary; for PGP 5.0, set the path to the pgpv binary. If -# you have INN and the script is able to successfully include your -# innshellvars.pl file, the value of $inn::pgp will override this. -$pgp = '/usr/local/bin/pgp'; - -# If you keep your keyring somewhere that is not the default used by pgp, -# uncomment the next line and set appropriately. If you have INN and the -# script is able to successfully include your innshellvars.pl file, this -# will be set to $inn::newsetc/pgp if that directory exists unless you set -# it explicitly. GnuPG will use a file named pubring.gpg in this -# directory. -# $keyring = '/path/to/your/pgp/config'; - -# If you have INN and the script is able to successfully include your -# innshellvars.pl file, the value of $inn::pathtmp and $inn::locks will -# override these. -$tmpdir = "/tmp"; -$lockdir = $tmpdir; - -# How should syslog be accessed? -# -# As it turns out, syslogging is very hard to do portably in versions of -# Perl prior to 5.6.0. Sys::Syslog should work without difficulty in -# 5.6.0 or later and will be used automatically for those versions of Perl -# (unless $syslog_method is ''). For earlier versions of Perl, 'inet' is -# all that's available up to version 5.004_03. If your syslog does not -# accept UDP log packets, such as when syslogd runs with the -l flag, -# 'inet' will not work. A value of 'unix' will try to contact syslogd -# directly over a Unix domain socket built entirely in Perl code (no -# subprocesses). If that is not working for you, and you have the -# 'logger' program on your system, set this variable to its full path name -# to have a subprocess contact syslogd. If the method is just "logger", -# the script will search some known directories for that program. If it -# can't be found & used, everything falls back on stderr logging. -# -# You can test the script's syslogging by running "pgpverify < -# /some/text/file" on a file that is not a valid news article. The -# "non-header at line #" error should be syslogged. -# -# $syslog_method = 'unix'; # Unix doman socket, Perl 5.004_03 or higher. -# $syslog_method = 'inet'; # UDP to port 514 of localhost. -# $syslog_method = ''; # Don't ever try to do syslogging. -$syslog_method = 'logger'; # Search for the logger program. - -# The next two variables are the values to be used for syslog's facility -# and level to use, as would be found in syslog.conf. For various -# reasons, it is impossible to economically have the script figure out how -# to do syslogging correctly on the machine. If you have INN and the -# script is able to successfully include you innshellvars.pl file, then -# the value of $inn::syslog_facility will override this value of -# $syslog_facility; $syslog_level is unaffected. -$syslog_facility = 'news'; -$syslog_level = 'err'; - -# Prepend the error message with a timestamp? This is only relevant if -# not syslogging, when errors go to stderr. -# -# $log_date = 0; # Zero means don't do it. -# $log_date = 1; # Non-zero means do it. -$log_date = -t STDOUT; # Do it if STDOUT is to a terminal. - -# End of configuration section. - - -require 5; - -use strict; -use vars qw($gpgv $pgp $keyring $tmp $tmpdir $lockdir $syslog_method - $syslog_facility $syslog_level $log_date $test $messageid); - -use Fcntl qw(O_WRONLY O_CREAT O_EXCL); -use FileHandle; -use IPC::Open3 qw(open3); -use POSIX qw(strftime); - -# Turn on test mode if the first argument is '-test'. -if (@ARGV && $ARGV[0] eq '-test') { - shift @ARGV; - $test = 1; -} - -# Not syslogged, such an error is almost certainly from someone running -# the script manually. -die "Usage: $0 < message\n" if @ARGV != 0; - -# Grab various defaults from innshellvars.pl if running inside INN. -$pgp = $inn::pgp - if $inn::pgp && $inn::pgp ne "no-pgp-found-during-configure"; -$gpgv = $inn::gpgv if $inn::gpgv; -$tmp = ($inn::pathtmp ? $inn::pathtmp : $tmpdir) . "/pgp$$"; -$lockdir = $inn::locks if $inn::locks; -$syslog_facility = $inn::syslog_facility if $inn::syslog_facility; -if (! $keyring && $inn::newsetc) { - $keyring = $inn::newsetc . '/pgp' if -d $inn::newsetc . '/pgp'; -} - -# Trim /path/to/prog to prog for error messages. -$0 =~ s%^.*/%%; - -# Make sure that the signature verification program can be executed. -if ($gpgv) { - if (! -x $gpgv) { - &fail("$0: $gpgv: " . (-e _ ? "cannot execute" : "no such file") . "\n"); - } -} elsif (! -x $pgp) { - &fail("$0: $pgp: " . (-e _ ? "cannot execute" : "no such file") . "\n"); -} - -# Parse the article headers and generate the PGP message. -my ($nntp_format, $header, $dup) = &parse_header(); -exit 1 unless $$header{'X-PGP-Sig'}; -my ($message, $signature, $version) - = &generate_message($nntp_format, $header, $dup); -if ($test) { - print "-----MESSAGE-----\n$message\n-----END MESSAGE-----\n\n"; - print "-----SIGNATURE-----\n$signature\n-----SIGNATURE-----\n\n"; -} - -# The call to pgp needs to be locked because it tries to both read and -# write a file named randseed.bin but doesn't do its own locking as it -# should, and the consequences of a multiprocess conflict is failure to -# verify. -my $lock; -unless ($gpgv) { - $lock = "$lockdir/LOCK.$0"; - until (&shlock($lock) > 0) { - sleep(2); - } -} - -# Verify the message. -my ($ok, $signer) = pgp_verify($signature, $version, $message); -unless ($gpgv) { - unlink ($lock) or &errmsg("$0: unlink $lock: $!\n"); -} -print "$signer\n" if $signer; -unless ($ok == 0) { - &errmsg("$0: verification failed\n"); -} -exit $ok; - - -# Parse the article headers and return a flag saying whether the message -# is in NNTP format and then two references to hashes. The first hash -# contains all the header/value pairs, and the second contains entries for -# every header that's duplicated. This is, by design, case-sensitive with -# regards to the headers it checks. It's also insistent about the -# colon-space rule. -sub parse_header { - my (%header, %dup, $label, $value, $nntp_format); - while (<>) { - # If the first header line ends with \r\n, this article is in the - # encoding it would be in during an NNTP session. Some article - # storage managers keep them this way for efficiency. - $nntp_format = /\r\n$/ if $. == 1; - s/\r?\n$//; - - last if /^$/; - if (/^(\S+):[ \t](.+)/) { - ($label, $value) = ($1, $2); - $dup{$label} = 1 if $header{$label}; - $header{$label} = $value; - } elsif (/^\s/) { - &fail("$0: non-header at line $.: $_\n") unless $label; - $header{$label} .= "\n$_"; - } else { - &fail("$0: non-header at line $.: $_\n"); - } - } - $messageid = $header{'Message-ID'}; - return ($nntp_format, \%header, \%dup); -} - -# Generate the PGP message to verify. Takes a flag indicating wire -# format, the hash of headers and header duplicates returned by -# parse_header and returns a list of three elements. The first is the -# message to verify, the second is the signature, and the third is the -# version number. -sub generate_message { - my ($nntp_format, $header, $dup) = @_; - - # The regexp below might be too strict about the structure of PGP - # signature lines. - - # The $sep value means the separator between the radix64 signature lines - # can have any amount of spaces or tabs, but must have at least one - # space or tab; if there is a newline then the space or tab has to - # follow the newline. Any number of newlines can appear as long as each - # is followed by at least one space or tab. *phew* - my $sep = "[ \t]*(\n?[ \t]+)+"; - - # Match all of the characters in a radix64 string. - my $r64 = '[a-zA-Z0-9+/]'; - - local $_ = $$header{'X-PGP-Sig'}; - &fail("$0: X-PGP-Sig not in expected format\n") - unless /^(\S+)$sep(\S+)(($sep$r64{64})+$sep$r64+=?=?$sep=$r64{4})$/; - - my ($version, $signed_headers, $signature) = ($1, $3, $4); - $signature =~ s/$sep/\n/g; - $signature =~ s/^\s+//; - - my $message = "X-Signed-Headers: $signed_headers\n"; - my $label; - foreach $label (split(",", $signed_headers)) { - &fail("$0: duplicate signed $label header, can't verify\n") - if $$dup{$label}; - $message .= "$label: "; - $message .= "$$header{$label}" if $$header{$label}; - $message .= "\n"; - } - $message .= "\n"; # end of headers - - while (<>) { # read body lines - if ($nntp_format) { - # Check for end of article; some news servers (eg, Highwind's - # "Breeze") include the dot-CRLF of the NNTP protocol in the article - # data passed to this script. - last if $_ eq ".\r\n"; - - # Remove NNTP encoding. - s/^\.\./\./; - s/\r\n$/\n/; - } - $message .= $_; - } - - # Strip off all trailing whitespaces for compatibility with the way that - # pgpverify used to work, using attached signatures. - $message =~ s/[ \t]+\n/\n/g; - - return ($message, $signature, $version); -} - -# Check a detached signature for given data. Takes a signature block (in -# the form of an ASCII-armored string with embedded newlines), a version -# number (which may be undef), and the message. We return an exit status -# and the key id if the signature is verified. 0 means good signature, 1 -# means bad data, 2 means an unknown signer, and 3 means a bad signature. -# In the event of an error, we report with errmsg. -# -# This code is taken almost verbatim from PGP::Sign except for the code to -# figure out the PGP style. -sub pgp_verify { - my ($signature, $version, $message) = @_; - chomp $signature; - - # Ignore SIGPIPE, since we're going to be talking to PGP. - local $SIG{PIPE} = 'IGNORE'; - - # Set the PGP style based on whether $gpgv is set. - my $pgpstyle = ($gpgv ? 'GPG' : 'PGP2'); - - # Because this is a detached signature, we actually need to save both - # the signature and the data to files and then run PGP on the signature - # file to make it verify the signature. Because this is a detached - # signature, though, we don't have to do any data mangling, which makes - # our lives much easier. It would be nice to do this without having to - # use temporary files, but I don't see any way to do so without running - # into mangling problems. - # - # PGP v5 *requires* there be some subheader or another. *sigh*. So we - # supply one if Version isn't given. :) - my $umask = umask 077; - my $filename = $tmpdir . '/pgp' . time . '.' . $$; - my $sigfile = new FileHandle "$filename.asc", O_WRONLY|O_EXCL|O_CREAT; - unless ($sigfile) { - &errmsg ("Unable to open temp file $filename.asc: $!\n"); - return (255, undef); - } - if ($pgpstyle eq 'PGP2') { - print $sigfile "-----BEGIN PGP MESSAGE-----\n"; - } else { - print $sigfile "-----BEGIN PGP SIGNATURE-----\n"; - } - if (defined $version) { - print $sigfile "Version: $version\n"; - } elsif ($pgpstyle ne 'GPG') { - print $sigfile "Comment: Use GnuPG; it's better :)\n"; - } - print $sigfile "\n", $signature; - if ($pgpstyle eq 'PGP2') { - print $sigfile "\n-----END PGP MESSAGE-----\n"; - } else { - print $sigfile "\n-----END PGP SIGNATURE-----\n"; - } - close $sigfile; - - # Signature saved. Now save the actual message. - my $datafile = new FileHandle "$filename", O_WRONLY|O_EXCL|O_CREAT; - unless ($datafile) { - &errmsg ("Unable to open temp file $filename: $!\n"); - unlink "$filename.asc"; - return (255, undef); - } - print $datafile $message; - close $datafile; - - # Figure out what command line we'll be using. - my @command; - if ($pgpstyle eq 'GPG') { - @command = ($gpgv, qw/--quiet --status-fd=1 --logger-fd=1/); - } else { - @command = ($pgp, '+batchmode', '+language=en'); - } - - # Now, call PGP to check the signature. Because we've written - # everything out to a file, this is actually fairly simple; all we need - # to do is grab stdout. PGP prints its banner information to stderr, so - # just ignore stderr. Set PGPPATH if desired. - # - # For GnuPG, use pubring.gpg if an explicit keyring was configured or - # found. Otherwise, use trustedkeys.gpg in the default keyring location - # if found and non-zero, or fall back on pubring.gpg. This is - # definitely not the logic that I would use if writing this from - # scratch, but it has the most backward compatibility. - local $ENV{PGPPATH} = $keyring if ($keyring && $pgpstyle ne 'GPG'); - if ($pgpstyle eq 'GPG') { - if ($keyring) { - push (@command, "--keyring=$keyring/pubring.gpg"); - } else { - my $home = $ENV{GNUPGHOME} || $ENV{HOME}; - $home .= '/.gnupg' if $home; - if ($home && ! -s "$home/trustedkeys.gpg" && -f "$home/pubring.gpg") { - push (@command, "--keyring=pubring.gpg"); - } - } - } - push (@command, "$filename.asc"); - push (@command, $filename); - my $input = new FileHandle; - my $output = new FileHandle; - my $pid = eval { open3 ($input, $output, $output, @command) }; - if ($@) { - &errmsg ($@); - &errmsg ("Execution of $command[0] failed.\n"); - unlink ($filename, "$filename.asc"); - return (255, undef); - } - close $input; - - # Check for the message that gives us the key status and return the - # appropriate thing to our caller. This part is a zoo due to all of the - # different formats used. GPG has finally done the right thing and - # implemented a separate status stream with parseable data. - # - # MIT PGP 2.6.2 and PGP 6.5.2: - # Good signature from user "Russ Allbery ". - # ViaCrypt PGP 4.0: - # Good signature from user: Russ Allbery - # PGP 5.0: - # Good signature made 1999-02-10 03:29 GMT by key: - # 1024 bits, Key ID 0AFC7476, Created 1999-02-10 - # "Russ Allbery " - # - # Also, PGP v2 prints out "Bad signature" while PGP v5 uses "BAD - # signature", and PGP v6 reverts back to "Bad signature". - local $_; - local $/ = ''; - my $signer; - my $ok = 255; - while (<$output>) { - print if $test; - if ($pgpstyle eq 'GPG') { - if (/\[GNUPG:\]\s+GOODSIG\s+\S+\s+(\S+)/) { - $ok = 0; - $signer = $1; - } elsif (/\[GNUPG:\]\s+NODATA/ || /\[GNUPG:\]\s+UNEXPECTED/) { - $ok = 1; - } elsif (/\[GNUPG:\]\s+NO_PUBKEY/) { - $ok = 2; - } elsif (/\[GNUPG:\]\s+BADSIG\s+/) { - $ok = 3; - } - } else { - if (/^Good signature from user(?::\s+(.*)|\s+\"(.*)\"\.)$/m) { - $signer = $+; - $ok = 0; - last; - } elsif (/^Good signature made .* by key:\n.+\n\s+\"(.*)\"/m) { - $signer = $1; - $ok = 0; - last; - } elsif (/^\S+: Good signature from \"(.*)\"/m) { - $signer = $1; - $ok = 0; - last; - } elsif (/^(?:\S+: )?Bad signature /im) { - $ok = 3; - last; - } - } - } - close $input; - waitpid ($pid, 0); - unlink ($filename, "$filename.asc"); - umask $umask; - return ($ok, $signer || ''); -} - -# Log an error message, attempting syslog first based on $syslog_method -# and falling back on stderr. -sub errmsg { - my ($message) = @_; - $message =~ s/\n$//; - - my $date = ''; - if ($log_date) { - $date = strftime ('%Y-%m-%d %T ', localtime); - } - - if ($syslog_method && $] >= 5.006) { - eval "use Sys::Syslog"; - $syslog_method = 'internal'; - } - - if ($syslog_method eq "logger") { - my @loggers = ('/usr/ucb/logger', '/usr/bin/logger', - '/usr/local/bin/logger'); - my $try; - foreach $try (@loggers) { - if (-x $try) { - $syslog_method = $try; - last; - } - } - $syslog_method = '' if $syslog_method eq 'logger'; - } - - if ($syslog_method ne '' && $syslog_method !~ m%/logger$%) { - eval "use Sys::Syslog"; - } - - if ($@ || $syslog_method eq '') { - warn $date, "$0: trying to use Perl's syslog: $@\n" if $@; - warn $date, $message, "\n"; - warn $date, "... while processing $messageid\n" - if $messageid; - - } else { - $message .= " processing $messageid" - if $messageid; - - if ($syslog_method =~ m%/logger$%) { - unless (system($syslog_method, "-i", "-p", - "$syslog_facility.$syslog_level", $message) == 0) { - if ($? >> 8) { - warn $date, "$0: $syslog_method exited status ", $? >> 8, "\n"; - } else { - warn $date, "$0: $syslog_method died on signal ", $? & 255, "\n"; - } - $syslog_method = ''; - &errmsg($message); - } - - } else { - # setlogsock arrived in Perl 5.004_03 to enable Sys::Syslog to use a - # Unix domain socket to talk to syslogd, which is the only way to do - # it when syslog runs with the -l switch. - if ($syslog_method eq "unix") { - if ($^O eq "dec_osf" && $] >= 5) { - eval 'sub Sys::Syslog::_PATH_LOG { "/dev/log" }'; - } - if ($] <= 5.00403 || ! eval "setlogsock('unix')") { - warn $date, "$0: cannot use syslog_method 'unix' on this system\n"; - $syslog_method = ''; - &errmsg($message); - return; - } - } - - # Unfortunately, there is no way to definitively know in this - # program if the message was logged. I wish there were a way to - # send a message to stderr if and only if the syslog attempt failed. - &openlog($0, 'pid', $syslog_facility); - &syslog($syslog_level, $_[0]); - &closelog(); - } - } -} - -sub fail { - &errmsg($_[0]); - exit 255; -} - -# Get a lock in essentially the same fashion as INN's shlock. return 1 on -# success, 0 for normal failure, -1 for abnormal failure. "normal -# failure" is that a lock is apparently in use by someone else. -sub shlock { - my ($file) = @_; - my ($ltmp, $pid); - - unless (defined(&ENOENT)) { - eval "require POSIX qw(:errno_h)"; - if ($@) { - # values taken from BSD/OS 3.1 - sub ENOENT { 2 } - sub ESRCH { 3 } - sub EEXIST { 17 } - } - } - - $ltmp = ($file =~ m%(.*/)%)[0] . "shlock$$"; - - # This should really attempt to use another temp name. - -e $ltmp && (unlink($ltmp) || return -1); - - open(LTMP, ">$ltmp") || return -1; - print LTMP "$$\n" || (unlink($ltmp), return -1); - close(LTMP) || (unlink($ltmp), return -1); - - if (!link($ltmp, $file)) { - if ($! == &EEXIST) { - if (open(LOCK, "<$file")) { - $pid = ; - if ($pid =~ /^\d+$/ && (kill(0, $pid) == 1 || $! != &ESRCH)) { - unlink($ltmp); - return 0; - } - - # OK, the pid in the lockfile is not a number or no longer exists. - close(LOCK); # silent failure is ok here - - # Unlink failed. - if (unlink($file) != 1 && $! != &ENOENT) { - unlink($ltmp); - return 0; - } - - # Check if open failed for reason other than file no longer present. - } elsif ($! != &ENOENT) { - unlink($ltmp); - return -1; - } - - # Either this process unlinked the lockfile because it was bogus, or - # between this process's link() and open() the other process holding - # the lock unlinked it. This process can now try to acquire. - if (! link($ltmp, $file)) { - unlink($ltmp); - return $! == &EEXIST ? 0 : -1; # Maybe another proc grabbed the lock. - } - - } else { # First attempt to link failed. - unlink($ltmp); - return 0; - } - } - unlink($ltmp); - return 1; -} - -=head1 NAME - -pgpverify - Cryptographically verify Usenet control messages - -=head1 SYNOPSIS - -B [B<-test>] < I - -=head1 DESCRIPTION - -The B program reads (on standard input) a Usenet control -message that has been cryptographically signed using the B -program (or some other program that produces a compatible format). -B then uses a PGP implementation to determine who signed the -control message. If the control message has a valid signature, -B prints (to stdout) the user ID of the key that signed the -message. Otherwise, it exits with a non-zero exit status. - -If B is installed as part of INN, it uses INN's configuration -to determine what signature verification program to use, how to log -errors, what temporary directory to use, and what keyring to use. -Otherwise, all of those parameters can be set by editing the beginning of -this script. - -By default, when running as part of INN, B expects the PGP key -ring to be found in I/pgp (as either F or -F depending on whether PGP or GnuPG is used to verify -signatures). If that directory doesn't exist, it will fall back on using -the default key ring, which is in a F<.pgp> or F<.gnupg> subdirectory of -the running user's home directory. - -INN, when using GnuPG, configures B to use B, which by -default expects keys to be in a keyring named F, since it -doesn't implement trust checking directly. B uses that file if -present but falls back to F if it's not found. This bypasses -the trust model for checking keys, but is compatible with the way that -B used to behave. Of course, if a keyring is found in -I/pgp or configured at the top of the script, that overrides all of -this behavior. - -=head1 OPTIONS - -The B<-test> flag causes B to print out the input that it is -passing to PGP (which is a reconstructed version of the input that -supposedly created the control message) as well as the output from PGP's -analysis of the message. - -=head1 EXIT STATUS - -B may exit with the following statuses: - -=over 4 - -=item 0Z<> - -The control message had a good PGP signature. - -=item 1 - -The control message had no PGP signature. - -=item 2 - -The control message had an unknown PGP signature. - -=item 3 - -The control message had a bad PGP signature. - -=item 255 - -A problem occurred not directly related to PGP analysis of signature. - -=back - -=head1 ENVIRONMENT - -B does not modify or otherwise alter the environment before -invoking the B or B program. It is the responsibility of the -person who installs B to ensure that when B or B -runs, it has the ability to locate and read a PGP key file that contains -the PGP public keys for the appropriate Usenet hierarchy administrators. -B can be pointed to an appropriate key ring by editing -variables at the beginning of this script. - -=head1 NOTES - -Historically, Usenet news server administrators have configured their news -servers to automatically honor Usenet control messages based on the -originator of the control messages and the hierarchies for which the -control messages applied. For example, in the past, David Lawrence always -issued control messages for the S<"Big 8"> hierarchies (comp, humanities, -misc, news, rec, sci, soc, talk). Usenet news administrators would -configure their news server software to automatically honor newgroup and -rmgroup control messages that originated from David Lawrence and applied -to any of the S hierarchies. - -Unfortunately, Usenet news articles (including control messages) are -notoriously easy to forge. Soon, malicious users realized they could -create or remove (at least temporarily) any S newsgroup they wanted by -simply forging an appropriate control message in David Lawrence's name. -As Usenet became more widely used, forgeries became more common. - -The B program was designed to allow Usenet news administrators -to configure their servers to cryptographically verify control messages -before automatically acting on them. Under the B system, a Usenet -hierarchy maintainer creates a PGP public/private key pair and -disseminates the public key. Whenever the hierarchy maintainer issues a -control message, he uses the B program to sign the control -message with the PGP private key. Usenet news administrators configure -their news servers to run the B program on the appropriate -control messages, and take action based on the PGP key User ID that signed -the control message, not the name and address that appear in the control -message's From: or Sender: headers. - -Thus, appropriate use of the B and B programs -essentially eliminates the possibility of malicious users forging Usenet -control messages that sites will act upon, as such users would have to -obtain the PGP private key in order to forge a control message that would -pass the cryptographic verification step. If the hierarchy administrators -properly protect their PGP private keys, the only way a malicious user -could forge a validly-signed control message would be by breaking the -public key encryption algorithm, which (at least at this time) is believed -to be prohibitively difficult for PGP keys of a sufficient bit length. - -=head1 HISTORY - -B was written by David C Lawrence . Manual page -provided by James Ralston. It is currently maintained by Russ Allbery -. - -=head1 COPYRIGHT AND LICENSE - -David Lawrence wrote: "Our lawyer told me to include the following. The -upshot of it is that you can use the software for free as much as you -like." - -Copyright (c) 1996 UUNET Technologies, Inc. -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - -=over 4 - -=item 1. - -Redistributions of source code must retain the above copyright notice, -this list of conditions and the following disclaimer. - -=item 2. - -Redistributions in binary form must reproduce the above copyright notice, -this list of conditions and the following disclaimer in the documentation -and/or other materials provided with the distribution. - -=item 3. - -All advertising materials mentioning features or use of this software must -display the following acknowledgement: - - This product includes software developed by UUNET Technologies, Inc. - -=item 4. - -The name of UUNET Technologies ("UUNET") may not be used to endorse or -promote products derived from this software without specific prior written -permission. - -=back - -THIS SOFTWARE IS PROVIDED BY UUNET "AS IS" AND ANY EXPRESS OR IMPLIED -WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN -NO EVENT SHALL UUNET BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED -TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -=head1 SEE ALSO - -gpgv(1), pgp(1). - -L is where the most recent versions of -B and B live, along with PGP public keys used for -hierarchy administration. - -=cut - -# Local variables: -# cperl-indent-level: 2 -# fill-column: 74 -# End: diff --git a/control/signcontrol.in b/control/signcontrol.in deleted file mode 100644 index c1951e7..0000000 --- a/control/signcontrol.in +++ /dev/null @@ -1,600 +0,0 @@ -#! /usr/bin/perl -w -# written April 1996, tale@isc.org (David C Lawrence) -# Currently maintained by Russ Allbery -# Version 1.8, 2003-07-06 -# -# Changes from 1.6 -> 1.8 -# -- Added support for GnuPG. -# -- Replace signing code with code from PGP::Sign that generates detached -# signatures instead. Otherwise, GnuPG signatures with DSA keys could -# not be verified. Should still work the same as before with RSA keys. -# -- Thanks to new signing code, no longer uses a temporary file. -# -- Only lock when using PGP; GnuPG shouldn't need it. -# -# Changes from 1.5 -> 1.6 -# -- eliminated subprocess use (except pgp, of course). -# -- interlock against competing signing processes. -# -- allow optional headers; see $use_or_add. -# -- added simple comments about why particular headers are signed. -# -- made error messages a tad more helpful for situations when it is hard -# to know what message was trying to be signed (such as via an "at" -# job). -# -- set $action, $group, $moderated to "" to prevent unusued variable -# warnings in the event a Control header can't be parsed. -# -- moved assignment of $pgpend out of loop. -# -# Changes from 1.4 -> 1.5 -# -- need to require Text::Tabs to get 'expand' for tabs in checkgroups. -# -# Changes from 1.3 -> 1.4 -# -- added checkgroups checking. -# -- added group name in several error messages (for help w/batch -# processing). -# -- disabled moderator address checking. -# -- adjusted newsgroups line (ie, tabbing fixed) now correctly -# substituted into control message. -# -# Changes from 1.2.3 -> 1.3 -# -- skip minor pgp signature headers like "charset:" after "version:" -# header and until the empty line that starts the base64 signature block. - -# CONFIGURATION - -# PGP variables. -# -# $pgp can be set to the path to GnuPG to use GnuPG instead. The program -# name needs to end in gpg so that signcontrol knows GnuPG is being used. -# -# STORING YOUR PASS PHRASE IN A FILE IS A POTENTIAL SECURITY HOLE. -# make sure you know what you're doing if you do it. -# if you don't use pgppassfile, you can only use this script interactively. -# if you DO use pgppassfile, it is possible that someone could steal -# your passphrase either by gaining access to the file or by seeing -# the environment of a running pgpverify program. -# -# $pgplock is used because pgp does not guard itself against concurrent -# read/write access to its randseed.bin file. A writable file is needed; -# The default value is to use the .pgp/config.txt file in the home -# directory of the user running the program. Note that this will only -# work to lock against other instances of signcontrol, not all pgp uses. -# $pgplock is not used if $pgp ends in 'gpg' since GnuPG doesn't need -# this. -$pgpsigner = 'INSERT_YOUR_PGP_USERID'; -$pgppassfile = ''; # file with pass phrase for $pgpsigner -$pgp = "/usr/local/bin/pgp"; -$pgpheader = "X-PGP-Sig"; -$pgplock = (getpwuid($<))[7] . '/.pgp/config.txt'; - -# this program is strict about always wanting to be consistent about what -# headers appear in the control messages. the defaults for the -# @... arrays are reasonable, but you should edit the force values. - -# these headers are acceptable in input, but they will be overwritten with -# these values. no sanity checking is done on what you put here. also, -# Subject: is forced to be the Control header prepending by "cmsg". also, -# Newsgroups: is forced to be just the group being added/removed. -# (but is taken as-is for checkgroups) -$force{'Path'} = 'bounce-back'; -$force{'From'} = 'YOUR_ADDRESS_AND_NAME'; -$force{'Approved'} = 'ADDRESS_FOR_Approved_HEADER'; -$force{'X-Info'}='ftp://ftp.isc.org/pub/pgpcontrol/README.html' - . "\n\t" - . 'ftp://ftp.isc.org/pub/pgpcontrol/README'; - -# these headers are acceptable in input, or if not present then will be -# created with the given value. None are enabled by default, because they -# should not be necessary. Setting one to a null string will pass through -# any instance of it found in the input, but not generate one if it is -# missing. If you set any $default{} variables, you must also put it in -# @orderheaders below. -# -# Note that Distribution nearly never works correctly, so use it only if -# you are really sure the propagation of the article will be limited as -# you intend. This normally means that you control all servers the -# distribution will go to with an iron fist. -# -# $use_or_add{'Reply-To'} = 'YOUR_REPLY_ADDRESS'; -# $use_or_add{'Oranization'} = 'YOUR_ORGANIZATION'; -# $use_or_add{'Distribution'} = 'MESSAGE_DISTRIBUTION'; - -# host for message-id; this could be determined automatically based on -# where it is run, but consistency is the goal here -$id_host = 'FULL_HOST_NAME'; - -# headers to sign. Sender is included because non-PGP authentication uses -# it. The following should always be signed: -# Subject -- some older news systems use it to identify the control action. -# Control -- most news systems use this to determine what to do. -# Message-ID -- guards against replay attacks. -# Date -- guards against replay attacks. -# From -- used by news systems as part of authenticating the message. -# Sender -- used by news systems as part of authenticating the message. -@signheaders = ('Subject', 'Control', 'Message-ID', 'Date', 'From', 'Sender'); - -# headers to remove from real headers of final message. -# If it is a signed header, it is signed with an empty value. -# set to () if you do not want any headers removed. -@ignoreheaders = ('Sender'); - -# headers that will appear in final message, and their order of -# appearance. all _must_ be set, either in input or via the $force{} and -# $use_or_add{} variables above. -# (exceptions: Date, Lines, Message-ID are computed by this program) -# if header is in use_or_add with a null value, it will not appear in output. -# several are required by the news article format standard; if you remove -# these, your article will not propagate: -# Path, From, Newsgroups, Subject, Message-ID, Date -# if you take out these, your control message is not very useful: -# Control, Approved -# any headers in @ignoreheaders also in @orderheaders are silently dropped. -# any non-null header in the input but not in @orderheaders or @ignoreheaders -# is an error. -# null headers are silently dropped. -@orderheaders = - ('Path', 'From', 'Newsgroups', 'Subject', 'Control', 'Approved', - 'Message-ID', 'Date', 'Lines', 'X-Info', $pgpheader); - -# this program tries to help you out by not letting you sign erroneous -# names, especially ones that are so erroneous they run afoul of naming -# standards. -# -# set to match only hierarchies you will use it on -# include no '|' for a single hierarchy (eg, "$hierarchies = 'uk';"). - -$hierarchies = 'HIERARCHIES'; - -# the draft news article format standard says: -# "subsequent components SHOULD begin with a letter" -# where "SHOULD" means: -# means that the item is a strong recommendation: there may be -# valid reasons to ignore it in unusual circumstances, but -# this should be done only after careful study of the full -# implications and a firm conclusion that it is necessary, -# because there are serious disadvantages to doing so. -# as opposed to "MUST" which means: -# means that the item is an absolute requirement of the specification -# MUST is preferred, but might not be acceptable if you have legacy -# newsgroups that have name components that begin with a letter, like -# news.announce.newgroups does with comp.sys.3b1 and 17 other groups. - -$start_component_with_letter = 'MUST'; - -## END CONFIGURATION - -use Fcntl qw(F_SETFD); -use FileHandle; -use IPC::Open3 qw(open3); -use POSIX qw(setlocale strftime LC_TIME); -use Text::Tabs; # to get 'expand' for tabs in checkgroups - -$0 =~ s#^.*/##; - -die "Usage: $0 < message\n" if @ARGV > 0; - -umask(0022); # flock needs a writable file, if we create it -if ($pgp !~ /gpg$/) { - open(LOCK, ">>$pgplock") || die "$0: open $lock: $!, exiting\n"; - flock(LOCK, 2); # block until locked -} - -&setgrouppat; - -$die = ''; - -&readhead; -&readbody; - -if ($die) { - if ($group) { - die "$0: ERROR PROCESSING ${action}group $group:\n", $die; - } elsif ($action eq 'check') { - die "$0: ERROR PROCESSING checkgroups:\n", $die; - } elsif ($header{'Subject'}) { - die "$0: ERROR PROCESSING Subject: $header{'Subject'}\n", $die; - } else { - die $die; - } -} - -&signit; - -if ($pgp !~ /gpg$/) { - close(LOCK) || warn "$0: close $lock: $!\n"; -} -exit 0; - -sub -setgrouppat - -{ - my ($hierarchy, $plain_component, $no_component); - my ($must_start_letter, $should_start_letter); - my ($eval); - - # newsgroup name checks based on RFC 1036bis (not including encodings) rules: - # "component MUST contain at least one letter" - # "[component] MUST not contain uppercase letters" - # "[component] MUST begin with a letter or digit" - # "[component] MUST not be longer than 14 characters" - # "sequences 'all' and 'ctl' MUST not be used as components" - # "first component MUST begin with a letter" - # and enforcing "subsequent components SHOULD begin with a letter" as MUST - # and enforcing at least a 2nd level group (can't use to newgroup "general") - # - # DO NOT COPY THIS PATTERN BLINDLY TO OTHER APPLICATIONS! - # It has special construction based on the pattern it is finally used in. - - $plain_component = '[a-z][-+_a-z\d]{0,13}'; - $no_component = '(.*\.)?(all|ctl)(\.|$)'; - $must_start_letter = '(\.' . $plain_component . ')+'; - $should_start_letter = '(\.(?=\d*[a-z])[a-z\d]+[-+_a-z\d]{0,13})+'; - - $grouppat = "(?!$no_component)($hierarchies)"; - if ($start_component_with_letter eq 'SHOULD') { - $grouppat .= $should_start_letter; - } elsif ($start_component_with_letter eq 'MUST') { - $grouppat .= $must_start_letter; - } else { - die "$0: unknown value configured for \$start_component_with_letter\n"; - } - - foreach $hierarchy (split(/\|/, $hierarchies)) { - die "$0: hierarchy name $hierarchy not standards-compliant\n" - if $hierarchy !~ /^$plain_component$/o; - } - - $eval = "\$_ = 'test'; /$grouppat/;"; - eval $eval; - die "$0: bad regexp for matching group names:\n $@" if $@; -} - -sub -readhead - -{ - my($head, $label, $value); - local($_, $/); - - $/ = ""; - $head = ; # get the whole news header - $die .= "$0: continuation lines in headers not allowed\n" - if $head =~ s/\n[ \t]+/ /g; # rejoin continued lines - - for (split(/\n/, $head)) { - if (/^(\S+): (.*)/) { - $label = $1; - $value = $2; - - $die .= "$0: duplicate header $label\n" if $header{$label}; - - $header{$label} = $value; - $header{$label} =~ s/^\s+//; - $header{$label} =~ s/\s+$//; - } elsif (/^$/) { - ; # the empty line separator(s) - } else { - $die .= "$0: non-header line:\n $_\n"; - } - } - - $header{'Message-ID'} = '<' . time . ".$$\@$id_host>"; - - setlocale(LC_TIME, "C"); - $header{'Date'} = strftime("%a, %d %h %Y %T -0000", gmtime); - - for (@ignoreheaders) { - $die .= "ignored header $_ also has forced value set\n" if $force{$_}; - $header{$_} = ''; - } - - for (@orderheaders) { - $header{$_} = $force{$_} if defined($force{$_}); - next if /^(Lines|\Q$pgpheader\E)$/; # these are set later - unless ($header{$_}) { - if (defined($use_or_add{$_})) { - $header{$_} = $use_or_add{$_} if $use_or_add{$_} ne ''; - } else { - $die .= "$0: missing $_ header\n"; - } - } - } - - $action = $group = $moderated = ""; - if ($header{'Control'}) { - if ($header{'Control'} =~ /^(new)group (\S+)( moderated)?$/o || - $header{'Control'} =~ /^(rm)group (\S+)()$/o || - $header{'Control'} =~ /^(check)groups()()$/o) { - ($action, $group, $moderated) = ($1, $2, $3); - $die .= "$0: group name $group is not standards-compliant\n" - if $group !~ /^$grouppat$/ && $action eq 'new'; - $die .= "$0: no group to rmgroup on Control: line\n" - if ! $group && $action eq 'rm'; - $header{'Subject'} = "cmsg $header{'Control'}"; - $header{'Newsgroups'} = $group unless $action eq 'check'; - } else { - $die .= "$0: bad Control format: $header{'Control'}\n"; - } - } else { - $die .= "$0: can't verify message content; missing Control header\n"; - } -} - -sub -readbody - -{ - local($_, $/); - local($status, $ngline, $fixline, $used, $desc, $mods); - - undef $/; - $body = $_ = ; - $header{'Lines'} = $body =~ tr/\n/\n/ if $body; - - # the following tests are based on the structure of a - # news.announce.newgroups newgroup message; even if you comment out the - # "first line" test, please leave the newsgroups line and moderators - # checks - if ($action eq 'new') { - $status = $moderated ? 'a\smoderated' : 'an\sunmoderated'; - $die .= "$0: nonstandard first line in body for $group\n" - if ! /^\Q$group\E\sis\s$status\snewsgroup\b/; - - my $intro = "For your newsgroups file:\n"; - $ngline = - (/^$intro\Q$group\E[ \t]+(.+)\n(\n|\Z(?!\n))/mi)[0]; - if ($ngline) { - $_ = $group; - $desc = $1; - $fixline = $_; - $fixline .= "\t" x ((length) > 23 ? 1 : (4 - ((length) + 1) / 8)); - $used = (length) < 24 ? 24 : (length) + (8 - (length) % 8); - $used--; - $desc =~ s/ \(Moderated\)//i; - $desc =~ s/\s+$//; - $desc =~ s/\w$/$&./; - $die .= "$0: $group description too long\n" if $used + length($desc) > 80; - $fixline .= $desc; - $fixline .= ' (Moderated)' if $moderated; - $body =~ s/^$intro(.+)/$intro$fixline/mi; - } else { - $die .= "$0: $group newsgroup line not formatted correctly\n"; - } - # moderator checks are disabled; some sites were trying to - # automatically maintain aliases based on this, which is bad policy. - if (0 && $moderated) { - $die .= "$0: $group submission address not formatted correctly\n" - if $body !~ /\nGroup submission address: ?\S+@\S+\.\S+\n/m; - $mods = "( |\n[ \t]+)\\([^)]+\\)\n\n"; - $die .= "$0: $group contact address not formatted correctly\n" - if $body !~ /\nModerator contact address: ?\S+@\S+\.\S+$mods/m; - } - } - # rmgroups have freeform bodies - - # checkgroups have structured bodies - if ($action eq 'check') { - for (split(/\n/, $body)) { - my ($group, $description) = /^(\S+)\t+(.+)/; - $die .= "$0: no group:\n $_\n" unless $group; - $die .= "$0: no description:\n $_\n" unless $description; - $die .= "$0: bad group name \"$group\"\n" if $group !~ /^$grouppat$/; - $die .= "$0: tab in description\n" if $description =~ /\t/; - s/ \(Moderated\)$//; - $die .= "$0: $group line too long\n" if length(expand($_)) > 80; - } - } -} - -# Create a detached signature for the given data. The first argument -# should be a key id, the second argument the PGP passphrase (which may be -# null, in which case PGP will prompt for it), and the third argument -# should be the complete message to sign. -# -# In a scalar context, the signature is returned as an ASCII-armored block -# with embedded newlines. In array context, a list consisting of the -# signature and the PGP version number is returned. Returns undef in the -# event of an error, and the error text is then stored in @ERROR. -# -# This function is taken almost verbatim from PGP::Sign except the PGP -# style is determined from the name of the program used. -sub pgp_sign { - my ($keyid, $passphrase, $message) = @_; - - # Ignore SIGPIPE, since we're going to be talking to PGP. - local $SIG{PIPE} = 'IGNORE'; - - # Determine the PGP style. - my $pgpstyle = 'PGP2'; - if ($pgp =~ /pgps$/) { $pgpstyle = 'PGP5' } - elsif ($pgp =~ /gpg$/) { $pgpstyle = 'GPG' } - - # Figure out what command line we'll be using. PGP v6 and PGP v2 use - # compatible syntaxes for what we're trying to do. PGP v5 would have, - # except that the -s option isn't valid when you call pgps. *sigh* - my @command; - if ($pgpstyle eq 'PGP5') { - @command = ($pgp, qw/-baft -u/, $keyid); - } elsif ($pgpstyle eq 'GPG') { - @command = ($pgp, qw/--detach-sign --armor --textmode -u/, $keyid, - qw/--force-v3-sigs --pgp2/); - } else { - @command = ($pgp, qw/-sbaft -u/, $keyid); - } - - # We need to send the password to PGP, but we don't want to use either - # the command line or an environment variable, since both may expose us - # to snoopers on the system. So we create a pipe, stick the password in - # it, and then pass the file descriptor to PGP. PGP wants to know about - # this in an environment variable; GPG uses a command-line flag. - # 5.005_03 started setting close-on-exec on file handles > $^F, so we - # need to clear that here (but ignore errors on platforms where fcntl or - # F_SETFD doesn't exist, if any). - # - # Make sure that the file handles are created outside of the if - # statement, since otherwise they leave scope at the end of the if - # statement and are automatically closed by Perl. - my $passfh = new FileHandle; - my $writefh = new FileHandle; - local $ENV{PGPPASSFD}; - if ($passphrase) { - pipe ($passfh, $writefh); - eval { fcntl ($passfh, F_SETFD, 0) }; - print $writefh $passphrase; - close $writefh; - if ($pgpstyle eq 'GPG') { - push (@command, '--batch', '--passphrase-fd', $passfh->fileno); - } else { - push (@command, '+batchmode'); - $ENV{PGPPASSFD} = $passfh->fileno; - } - } - - # Fork off a pgp process that we're going to be feeding data to, and tell - # it to just generate a signature using the given key id and pass phrase. - my $pgp = new FileHandle; - my $signature = new FileHandle; - my $errors = new FileHandle; - my $pid = eval { open3 ($pgp, $signature, $errors, @command) }; - if ($@) { - @ERROR = ($@, "Execution of $command[0] failed.\n"); - return undef; - } - - # Write the message to the PGP process. Strip all trailing whitespace - # for compatibility with older pgpverify and attached signature - # verification. - $message =~ s/[ \t]+\n/\n/g; - print $pgp $message; - - # All done. Close the pipe to PGP, clean up, and see if we succeeded. - # If not, save the error output and return undef. - close $pgp; - local $/ = "\n"; - my @errors = <$errors>; - my @signature = <$signature>; - close $signature; - close $errors; - close $passfh if $passphrase; - waitpid ($pid, 0); - if ($? != 0) { - @ERROR = (@errors, "$command[0] returned exit status $?\n"); - return undef; - } - - # Now, clean up the returned signature and return it, along with the - # version number if desired. PGP v2 calls this a PGP MESSAGE, whereas - # PGP v5 and v6 and GPG both (more correctly) call it a PGP SIGNATURE, - # so accept either. - while ((shift @signature) !~ /-----BEGIN PGP \S+-----\n/) { - unless (@signature) { - @ERROR = ("No signature from PGP (command not found?)\n"); - return undef; - } - } - my $version; - while ($signature[0] ne "\n" && @signature) { - $version = $1 if ((shift @signature) =~ /^Version:\s+(.*?)\s*$/); - } - shift @signature; - pop @signature; - $signature = join ('', @signature); - chomp $signature; - undef @ERROR; - return wantarray ? ($signature, $version) : $signature; -} - -sub -signit - -{ - my($head, $header, $signheaders, $pgpflags, $pgpbegin, $pgpend); - - # Form the message to be signed. - $signheaders = join(",", @signheaders); - $head = "X-Signed-Headers: $signheaders\n"; - foreach $header (@signheaders) { - $head .= "$header: $header{$header}\n"; - } - my $message = "$head\n$body"; - - # Get the passphrase if available. - my $passphrase; - if ($pgppassfile && -f $pgppassfile) { - $pgppassfile =~ s%^(\s)%./$1%; - if (open (PGPPASS, "< $pgppassfile\0")) { - $passphrase = ; - close PGPPASS; - chomp $passphrase; - } - } - - # Sign the message, getting the signature and PGP version number. - my ($signature, $version) = pgp_sign ($pgpsigner, $passphrase, $message); - unless ($signature) { - die "@ERROR\n$0: could not generate signature\n"; - } - - # GnuPG has version numbers containing spaces, which breaks our header - # format. Find just some portion that contains a digit. - ($version) = ($version =~ /(\S*\d\S*)/); - - # Put the signature into the headers. - $signature =~ s/^/\t/mg; - $header{$pgpheader} = "$version $signheaders\n$signature"; - - for (@ignoreheaders) { - delete $header{$_} if defined $header{$_}; - } - - $head = ''; - foreach $header (@orderheaders) { - $head .= "$header: $header{$header}\n" if $header{$header}; - delete $header{$header}; - } - - foreach $header (keys %header) { - die "$0: unexpected header $header left in header array\n"; - } - - print STDOUT $head; - print STDOUT "\n"; - print STDOUT $body; -} - -# Our lawyer told me to include the following. The upshot of it is that -# you can use the software for free as much as you like. - -# Copyright (c) 1996 UUNET Technologies, Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# 3. All advertising materials mentioning features or use of this software -# must display the following acknowledgement: -# This product includes software developed by UUNET Technologies, Inc. -# 4. The name of UUNET Technologies ("UUNET") may not be used to endorse or -# promote products derived from this software without specific prior -# written permission. -# -# THIS SOFTWARE IS PROVIDED BY UUNET ``AS IS'' AND ANY EXPRESS OR -# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL UUNET BE LIABLE FOR ANY DIRECT, -# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED -# OF THE POSSIBILITY OF SUCH DAMAGE. - -# Local variables: -# cperl-indent-level: 2 -# fill-column: 74 -# End: diff --git a/debian/changelog b/debian/changelog deleted file mode 100644 index 838c48d..0000000 --- a/debian/changelog +++ /dev/null @@ -1,339 +0,0 @@ -inn2 (2.4.5-5) unstable; urgency=medium - - * Added patches u_*: bug fixes from SVN chosen by the upstream maintainer: - - misc innreport bugs - - incorrect TLS error handling - - correctly initialize the status file IP address variables - - do not send a duplicate reply when TLS negotiation fails - - correct the permissions checking for XHDR and XPAT - - do not send a duplicate reply to XOVER/XHDR/XPAT in a empty group - * Install again our own sasl.conf with the correct paths. - * Document in README.Debian that STARTTLS and MODE READER do not work - together. (Closes: #503495) - * Added patch typo_inn_conf_man fixes a typo in inn.conf(5). - (Closes: #507256) - * Updated the md5.c license in debian/copyright. - - -- Marco d'Itri Mon, 15 Dec 2008 00:50:17 +0100 - -inn2 (2.4.5-4) unstable; urgency=low - - * Backported fixes from SVN: honour the Ad newsfeeds flag and create a - valid SV for the article body which will correctly match regexps. - - -- Marco d'Itri Wed, 10 Sep 2008 01:36:04 +0200 - -inn2 (2.4.5-3) unstable; urgency=medium - - * Do not FTBFS with old versions of find. (Closes: #495508) - - -- Marco d'Itri Thu, 28 Aug 2008 04:21:48 +0200 - -inn2 (2.4.5-2) unstable; urgency=medium - - * Rebuilt with libdb4.6-dev. - - -- Marco d'Itri Sun, 27 Jul 2008 19:23:55 +0200 - -inn2 (2.4.5-1) unstable; urgency=low - - * New upstream STABLE release. - - -- Marco d'Itri Tue, 01 Jul 2008 01:18:29 +0200 - -inn2 (2.4.4r-1) unstable; urgency=low - - * New upstream STABLE release. (For real, this time.) - * On 32 bit architectures, build a new inn2-lfs package with Larges - Files Support enabled. (Closes: #433751) - * Enabled support for Kerberos. (Closes: #478775) - * Rebuilt with perl 5.10. (Closes: #479244) - * Removed usage of debconf. - - -- Marco d'Itri Sun, 11 May 2008 12:31:56 +0200 - -inn2 (2.4.4-1) unstable; urgency=low - - * New upstream STABLE snapshot. - + Rotates innfeed.log. (Closes: #407752) - + Make inews not fail if MODE READER fails because the connection has - not been authenticated yet. (Closes: #475059) - * Removed S from Default-Stop in the init script. (Closes: #471081) - * Updated debconf translation: pt. (Closes: #444720) - * Fixed a typo in the name of debian/inn2.logcheck.violations.ignore. - * Stop overwriting active.times(5) with a symlink, inn now has it. - * Fixed many minor issues pointed out by Julien Élie. (Closes: #455882) - * Removed patches merged upstream: daemonize-ovdb_init, - fix-crash-on-reload, hashfeeds. - * Remove /var/lib/news/ on purge. (Closes: #455104) - - -- Marco d'Itri Mon, 14 Apr 2008 22:01:48 +0200 - -inn2 (2.4.3+20070806-1) unstable; urgency=low - - * New upstream STABLE snapshot. - * Package converted to quilt. - * Added patch fix-crash-on-reload to fix segfaults when reloading - incoming.conf (Closes: #361073, #429802, #430190, #430191) - * Added patch daemonize-ovdb_init to make ovdb_init properly close - stdin/out/err when it becomes a daemon. (Closes: #433522) - * Added patch inndstart-sockets-v6only to suppress a startup warning - about an already opened socket. - * Fixed the bzip2 path in bunbatch. (Closes: #419429) - * Removed patches merged upstream: ckpasswd_use_libdb, fix_radius.conf, - innfeed-fix-getaddrinfo, innfeed-force-ipv4, libdb-4.4. - * Use --as-needed to not link superfluous libraries. - * New debconf translations: pt, nl. (Closes: #414921, #415511) - * Added a logcheck file. (Closes: #405536) - - -- Marco d'Itri Tue, 07 Aug 2007 16:35:06 +0200 - -inn2 (2.4.3-1) unstable; urgency=low - - * New upstream release. (Closes: #381415) - + Fixes nnrpd when "localmaxartsize: 0". (Closes: #357370) - * Removed support for his64v6 and cnfs64, which do not work anyway. - ****** I am looking for a co-maintainer interested in adding ****** - ****** support to build a inn2-lfs package. ****** - * Switched to libdb4.4. - * New debconf translations: vi, cs, sv. (Closes: #314245, #315211, #339811) - * Pre-Depends on debconf-2.0 too. (Closes: #331859) - * Added to innfeed support for a "force-ipv4" configuration option. - Based on a patch contributed by Henning Makholm. (Closes: #336264) - * Added to innfeed support for hashed feeds. - * pgpverify: try harder to find the home directory. (Closes: #307765) - * Moved nnrpd-ssl to the main package. - * Added support for libdb to ckpasswd. (Closes: #380644) - * Use FHS paths in the perl-nocem documentation. (Closes: #365639) - * Create /var/run/news in the init script if it does not exist. - - -- Marco d'Itri Fri, 18 Aug 2006 11:19:21 +0200 - -inn2 (2.4.2-3) unstable; urgency=high - - * Fixed upgrades on systems with a non-default pathdb. (Closes: #306765) - * Added the showtoken program. (Closes: #306837) - - -- Marco d'Itri Sat, 14 May 2005 15:03:56 +0200 - -inn2 (2.4.2-2) unstable; urgency=medium - - * New upstream snapshot (20050407). - * Stop providing the inn package. (Closes: #288659) - * Made postinst continue when makehistory or makedbz fail. (Closes: #292167) - * Switched to libdb4.3. - - -- Marco d'Itri Fri, 8 Apr 2005 14:51:22 +0200 - -inn2 (2.4.2-1) unstable; urgency=low - - * New upstream release. - + Removed patch innreport_nnrpd-ssl. - + Fixed news2mail, CNFS buffers reporting. (Closes: #282664, #276819) - - -- Marco d'Itri Fri, 24 Dec 2004 17:05:33 +0100 - -inn2 (2.4.1+20040820-2) unstable; urgency=medium - - * New upstream snapshot (upstream/patches/20040820-to-20040929.diff). - + make Norbert Tretkowski happy. (Closes: #255324) - + fix inn2-ssl segfaults on ia64. (Closes: #270875) - * Conflict with inn and cnews instead of news-transport-system. - (Closes: #269874) - - -- Marco d'Itri Wed, 29 Sep 2004 17:24:18 +0200 - -inn2 (2.4.1+20040820-1) unstable; urgency=medium - - * New upstream snapshot. - + Fixes headers folding in the overview. (Closes: #190207) - + Fixes headers for articles mailed to moderators. (Closes: #249151) - * Added a default CA file name to sasl.conf. (Closes: #250201) - * New patch innreport_nnrpd-ssl: makes innreport correctly parse the - nnrpd-ssl log entries. (Closes: #250252) - * New debconf translations: de, ja. (Closes: #263030, #251100) - - -- Marco d'Itri Fri, 20 Aug 2004 19:32:20 +0200 - -inn2 (2.4.1+20040403-1) unstable; urgency=medium - - * New upstream snapshot. (Closes: #141750) - * Switched to db4.2. (Closes: #241584) - * Added catalan debconf template. (Closes: #236668) - * Removed the patches fix_bindaddress, default-storage.diff and - fix_reiserfs26.diff because they have been merged upstream. - * Removed the patch libdb41-fix.diff because it's not needed anymore. - - -- Marco d'Itri Sat, 3 Apr 2004 21:00:31 +0200 - -inn2 (2.4.1-2) unstable; urgency=medium - - * Fix bindaddress. (Closes: #183812) - * Fix paths in inn2-ssl. (Closes: #229181) - - -- Marco d'Itri Sat, 24 Jan 2004 17:13:43 +0100 - -inn2 (2.4.1-1) unstable; urgency=high - - * New upstream release. - + Fixes buffer overflow, maybe remotely exploitable. (Closes: #226772) - * Add workaround for 2.6.x reiserfs brokeness. (Closes: #225940) - * Use pgpverify from -CURRENT to add useless DSA support. (Closes: #222634) - * Source package converted to DBS. - - -- Marco d'Itri Thu, 8 Jan 2004 20:30:49 +0100 - -inn2 (2.4.0+20031130-1) unstable; urgency=low - - * New upstream STABLE snapshot. (Closes: #213946) - * Added russian and spanish debconf messages. (Closes: #219235, #220884) - * Replaces: inn2-dev to improve upgrades from woody. (Closes: #217219) - * Added a new his64v6 history method with LFS support. Untested! - (Closes: #215877) - - -- Marco d'Itri Sun, 30 Nov 2003 22:54:02 +0100 - -inn2 (2.4.0+20030912-1) unstable; urgency=low - - * New upstream STABLE snapshot. - * Add again a default storage method to storage.conf. (Closes: #205001) - * Fix the getlist command line in actsyncd. (Closes: #206283) - * Added a new cnfs64 method for large cycbufs. The on disk format is not - compatible with 32-bit cycbufs. The storage tokens are not compatible - with the tokens of a standard inn package built with --enable-largefiles - (but they could be converted, let me know if you want to try this). - This is basically untested and may trash the data you feed it. Please - let me know if this works for you or not. (Closes: #206828) - - -- Marco d'Itri Fri, 12 Sep 2003 14:07:06 +0200 - -inn2 (2.4.0+20030808-1) unstable; urgency=medium - - * New upstream snapshot. - * Fix readers.conf(5) and ckpasswd(8). (Closes: #202098, #202300) - * Fix innupgrade invocation in postinst. (Closes: #202978) - * Misc debconf-related fixes courtesy of Christian Perrier - . (Closes: #200517, #200518) - * Added polish, spanish and french debconf messages. - (Closes: #202155, #201627) - - -- Marco d'Itri Fri, 8 Aug 2003 13:56:23 +0200 - -inn2 (2.4.0-3) unstable; urgency=medium - - * Add db_stop to postinst. - * Fixed inn.conf path in postinst. (Closes: #198578) - - -- Marco d'Itri Wed, 25 Jun 2003 15:15:54 +0200 - -inn2 (2.4.0-2) unstable; urgency=medium - - * Install all headers in /usr/include/inn. (Closes: #198463, #198464) - * Added debconf support, patch by . - - -- Marco d'Itri Mon, 23 Jun 2003 19:19:37 +0200 - -inn2 (2.4.0-1) unstable; urgency=medium - - * New upstream release. (Closes: #182751, #188740, #193967, #194273, #198395) - * send-uucp.pl is now send-uucp. - * Switched from db4.0 to db4.1. - * postinst should not fail if innd cannot start. (Closes: #189966) - * Depend on perlapi-5.8.0. (Closes: #187717, #192411) - * Depend on inn2-inews >= 2.3.999+20030227-1. (Closes: #196137) - * Do not scare admins with wrong postinsg messages. (Closes: #183103) - * Corrected typo in innupgrade. (Closes: #194444) - * Added fr.* to /etc/news/moderators. (Closes: #190202) - - -- Marco d'Itri Fri, 20 Jun 2003 18:39:21 +0200 - -inn2 (2.3.999+20030227-1) unstable; urgency=low - - * New upstream snapshot: - * Fix expireover segfaults. (Closes: #180462, #179898) - * Create /var/log/news/path. (Closes: #180168, #180602) - * Build-Depends on libssl-dev. (Closes: #180662) - * Fix missing feed name in the log. (Closes: #178842, #181740) - * Fix news2mail. (Closes: #181086) - * Fix minor bugs in the init script. (Closes: #180866, #180867) - - -- Marco d'Itri Thu, 27 Feb 2003 19:11:57 +0100 - -inn2 (2.3.999+20030205-2) unstable; urgency=low - - * New upstream snapshot. (Closes: #179294) - * Add a new inn2-ssl package. (Closes: #163672) - * Move wildmat(3) from inn2-dev to inn2. (Closes: #179441) - * Downgraded to extra priority. - Most people do not need a local news server, and definitely not INN 2.x. - * Create /var/{lib,run}/news in postinst. - - -- Marco d'Itri Thu, 6 Feb 2003 15:18:02 +0100 - -inn2 (2.3.999+20030125-3) unstable; urgency=low - - * Fix rnews breakage. (Closes: #178673) - * Remove hardcoded paths of egrep, awk, sed, sort, wget. (Closes: #176749) - - -- Marco d'Itri Tue, 28 Jan 2003 01:48:03 +0100 - -inn2 (2.3.999+20030125-2) unstable; urgency=low - - * Fix broken ctlinnd. (Closes: #178588) - - -- Marco d'Itri Mon, 27 Jan 2003 19:41:03 +0100 - -inn2 (2.3.999+20030125-1) unstable; urgency=low - - * BEWARE: this is a -CURRENT snapshot. If it breaks you keep both pieces! - (Closes: #172212, #174938, #176336). - * Make innreport generate valid HTML. (Closes: #166372) - * Pre-Depends on inn2-inews. (Closes: #166804) - * Update gnu.* data in control.ctl. (Closes: #167581) - * Do not ship rnews suid root! (Closes: #171757) - * Install /usr/share/doc/inn2/INSTALL.gz (Closes: #174493) - - -- Marco d'Itri Thu, 16 Jan 2003 01:12:53 +0100 - -inn2 (2.3.3+20020922-5) unstable; urgency=medium - - * Fixed pathtmp (Closes: #162686). - * Check if the usenet user exists before adding a mail alias - (Closes: #162731). - * Fixed a path in sendinpaths (Closes: #163022). - - -- Marco d'Itri Mon, 7 Oct 2002 20:24:16 +0200 - -inn2 (2.3.3+20020922-4) unstable; urgency=low - - * Applied OVDB fixes, courtesy of Ian Hastie @clara.net (Closes: #162643). - - -- Marco d'Itri Sat, 28 Sep 2002 16:46:57 +0200 - -inn2 (2.3.3+20020922-3) unstable; urgency=low - - * Fixed absolute path in Makefile (Closes: #162538). - - -- Marco d'Itri Fri, 27 Sep 2002 19:12:10 +0200 - -inn2 (2.3.3+20020922-1) unstable; urgency=low - - * New STABLE CVS snapshot (Closes: #128725, #137175, #157808, #159105). - * Made some changes to make INN compile with perl 5.8.0. May be broken. - * Fix inndf to convert the "infinite" inodes of reiserfs to 2^31 - 1 - (Closes: #124101). - * Suggests: gnupg instead of pgp. - * Brand new init script which uses ctlinnd. - * Removed debian changes to use mkstemp. INN uses a private temp - directory anyway. - * Conflicts+Replaces: ninpaths, added the scripts from the inpaths package. - * Do not depend anymore on libdb3-util, which is only needed by OVDB. - * Removed signcontrol. - * Changed control.* and junk groups to status n. - * Added gpgverify script (Closes: #131412). - * Added bunbatch script (Closes: #136860). - * Added /usr/share/doc/inn2/INSTALL.gz (Closes: #156685). - * Added buildinnkeyring script which downloads PGP keys from ftp.isc.org - (Closes: #86989). - - -- Marco d'Itri Sun, 22 Sep 2002 21:05:18 +0200 diff --git a/debian/changelog.old b/debian/changelog.old deleted file mode 100644 index 9adc435..0000000 --- a/debian/changelog.old +++ /dev/null @@ -1,688 +0,0 @@ -inn2 (2.3.999+20030114-1) unstable; urgency=low - - * BEWARE: this is a -CURRENT snapshot. If it breaks you keep both pieces! - (Closes: #172212, #174938). - * Make innreport generate valid HTML. (Closes: #166372) - * Pre-Depends on inn2-inews. (Closes: #166804) - * Update gnu.* data in control.ctl. (Closes: #167581) - * Do not ship rnews suid root! (Closes: #171757) - * Install /usr/share/doc/inn2/INSTALL.gz (Closes: #174493) - - -- Marco d'Itri Thu, 16 Jan 2003 01:12:53 +0100 - -inn2 (2.3.3+20020922-5) unstable; urgency=medium - - * Fixed pathtmp (Closes: #162686). - * Check if the usenet user exists before adding a mail alias - (Closes: #162731). - * Fixed a path in sendinpaths (Closes: #163022). - - -- Marco d'Itri Mon, 7 Oct 2002 20:24:16 +0200 - -inn2 (2.3.3+20020922-4) unstable; urgency=low - - * Applied OVDB fixes, courtesy of Ian Hastie @clara.net (Closes: #162643). - - -- Marco d'Itri Sat, 28 Sep 2002 16:46:57 +0200 - -inn2 (2.3.3+20020922-3) unstable; urgency=low - - * Fixed absolute path in Makefile (Closes: #162538). - - -- Marco d'Itri Fri, 27 Sep 2002 19:12:10 +0200 - -inn2 (2.3.3+20020922-1) unstable; urgency=low - - * New STABLE CVS snapshot (Closes: #128725, #137175, #157808, #159105). - * Made some changes to make INN compile with perl 5.8.0. May be broken. - * Fix inndf to convert the "infinite" inodes of reiserfs to 2^31 - 1 - (Closes: #124101). - * Suggests: gnupg instead of pgp. - * Brand new init script which uses ctlinnd. - * Removed debian changes to use mkstemp. INN uses a private temp - directory anyway. - * Conflicts+Replaces: ninpaths, added the scripts from the inpaths package. - * Do not depend anymore on libdb3-util, which is only needed by OVDB. - * Removed signcontrol. - * Changed control.* and junk groups to status n. - * Added gpgverify script (Closes: #131412). - * Added bunbatch script (Closes: #136860). - * Added /usr/share/doc/inn2/INSTALL.gz (Closes: #156685). - * Added buildinnkeyring script which downloads PGP keys from ftp.isc.org - (Closes: #86989). - - -- Marco d'Itri Sun, 22 Sep 2002 21:05:18 +0200 - -inn2 (2.3.3-1) unstable; urgency=low - - * new upstream version - * use 'unset' not 'declare -x' GZIP to clear environment in innshellvars, - closes: #136156, #136495, #136557, #142464 - * add a warning to inn.conf comments about avoiding tabs after values, - closes: #112657, #112665 - * modify cron.d to test for presence of programs before running them, - closes: #136563 - * modify init.d to redirect rc.news output to /var/log/news/rc.news so that - inn2 daemonizes properly when run manually with the positive side effect - that the startup messages now comply with Debian policy, - closes: #140794, #116716, #134459 - * deliver more upstream doc files, closes: #141963 - * procps is priority required, but not marked essential, so we need to - depend on it so innwatch can use 'uptime', closes: #146135 - * add a clause to postinst to make sure /var/spool/news has appropriate - owner/group/perms - - -- Bdale Garbee Fri, 24 May 2002 00:49:08 -0600 - -inn2 (2.3.2-3) unstable; urgency=low - - * apply patch from rene@seindal.dk to pullnews.in to keep a missing group - from killing a run, closes: #133571 - * apply patch from falcon@wysocki.lodz.pdi.net to dbprocs.in so that ovdb - will work correctly with libdb3, and add a runtime dependency on - libdb3-util to the inn2 package, closes: #128855 - * add manpage symlinks, closes: #99543, #99578 - * ensure backoff directory exists during postinst, closes: #127050 - * clean up some of the lintian warnings - - -- Bdale Garbee Sat, 16 Feb 2002 15:06:20 -0700 - -inn2 (2.3.2-2) unstable; urgency=low - - * edit provided buffindexed.conf to reflect our path structure - * apply patch to mailpost.in provided by Paul Seelig to prevent message - posting failures by stripping Received lines, closes: #120267 - * add remaining /etc files to conffiles, closes: #110647 - * make sure /var/log/news/OLD is news.news in postinst, closes: #116715 - * slightly tighten permissions on /var/run/news, closes: #117773 - * fix missing quotes around command in init.d,closes: #120105 - * explicitly unexport GZIP in innshellvars before defining it to avoid - clashes with GZIP set in external environment, closes: #120381 - * eliminate the task-news-server binary package - - -- Bdale Garbee Wed, 26 Dec 2001 16:02:44 -0700 - -inn2 (2.3.2-1) unstable; urgency=low - - * new upstream version, closes: #98247, #101601 - * remove authprogs/pwcheck.c and modify authprogs/Makefile in orig.tar.gz - since we don't use it and license is non-DFSG-compliant! Closes: #103477 - * make inn2-inews conflict with cnews, closes: #97662 - * modify news.daily to use tempfile(1) for safe tempfile creation, - closes: #104517 - * improve several instances of unsafe temp file handling using relevant - patches from the Debian security team, closes: #83734 - * patch to fix expireover seg faults from Andrew Stribblehill, closes: #95096 - * make 'server' in inn.conf be 'localhost' by default, closes: #90908 - * add a note in the sample newsfeeds file indicating that nntplink is not - part of INN, closes: #88120 - * depend on awk, closes: #87618 Note, I will *not* change the compress - definition in innshellvars, see README.Debian for details. - * only execute rnews in cron if it exists, so that removing but not purging - inn2 doesn't generate excessive email, closes: #89853 - * postinst forces owner of default log files to be correct, closes: #98490 - * enable support for ovdb, closes: #96612 - * remove references to non-existent newslog(8) man page, clean up wildmat(5) - references, closes: #90993 - * apply patches from Tollef Fog Heen for gnupg use in signcontrol and use - safer temp file handling, closes: #99021, #99242 - * the inn2 package really can't do anything about the way conffiles are - handled by dpkg when moving from inn to inn2. inn and inn2 are distinct - packages to Debian, despite their similar heritage, closes: #97443 - - -- Bdale Garbee Fri, 10 Aug 2001 13:48:38 -0600 - -inn2 (2.3.1-4) unstable; urgency=low - - * make /etc/news/filter/* conffiles, closes: #85315 - * update build-depends, changing perl5 to libperl-dev - - -- Bdale Garbee Tue, 20 Feb 2001 15:30:56 -0700 - -inn2 (2.3.1-3) unstable; urgency=low - - * conflict with current and prior versions of suck, since they use innxmit - in a way that no longer works, resulting in data loss as per bug 83727. - Reassign that bug to suck for implementation of a real solution. - * update the init.d script to use rc.news as upstream intends for start and - stop operations, since it handles the current set of INN daemons better - than our previous attempt to use start-stop-daemon does, closes: #84438 - * tag /etc/news/send-uucp.cf as a conffile, closes: #83282 - - -- Bdale Garbee Mon, 5 Feb 2001 16:04:12 -0700 - -inn2 (2.3.1-2) unstable; urgency=low - - * update send-uucp.pl's idea of where innshellvars.pl is, closes: #83194 - * go back to symlinks instead of moving inews and rnews, closes: #83224 - * have preinst clean up /usr/lib/news/bin/filter dregs, closes: #83515 - * have inn2-inews conflict/replace inn2 prior to 2.3.1 to account for moving - some files, closes: #83622 - - -- Bdale Garbee Tue, 30 Jan 2001 17:32:17 -0700 - -inn2 (2.3.1-1) unstable; urgency=low - - * new upstream release. thank you Marco d'Itri for help with - this update - * revert send-uucp to the upstream version, deliver Perl version as - send-uucp.pl, closes: #81074 - * add manual page for send-uucp.pl written by Mark Brown, closes: #81073 - * in 2.3.0-1, we accidentally shipped active, active.times, and newsgroups - as real files in /var/lib/news. Hack the preinst and postinst to protect - the files in place, and fix the mess. While we're at it, fix a few other - details in the postinst. Closes: #81274 - * update preinst warning and README.Debian to add an explicit pointer to the - NEWS file, which documents the 2.2 to 2.3 changes. Fix a few out of date - items in README.Debian. Closes: #81069 - * fix path of required file in send-uucp.pl, closes: #81075 - * move rnews and dependencies to the inn2-inews package, closes: #81268 - * freshen PGPKEYS file from ftp.isc.org, fixes fr.* key and adds a new one, - closes: #81272 - * pgpverify: use /etc/news/pgp as pgp/gnupg config dir and the syslog - socket instead of logger. (Md) - * innd/cc.c: added perl filter status patch (used by cleanfeed). (Md) - * debian/cron.d: added entry to reload incoming.conf and sample entries - for send-nntp and send-uucp.pl. (Md) closes: #81269 - * debian/init.d: first try to gracefully shut down innd with ctlinnd. (Md) - * Changed /usr/lib/news/bin/filter to /etc/news/filter. (Md) closes: #81273 - * Moved back the whole /etc/news/scripts to the standard location in - /usr/lib/news, none of these files is a conffile. (Md) This improves the - postinst questioning considerably, closes: #81072 - * Fixed permissions of many binaries and config files. (Md) closes: #82002 - * inews is not installed suid (suggested by upstream maintainer). (Md) - * Renamed send-uucp.pl.1 to send-uucp.pl.8. (Md) - * lose the "Recommends: trn | news-reader" on the inn2 package, it's not - particularly useful, and gets in the way for dedicated servers - * drop the "Suggests: inn2-dev" from inn2, the few who need it will find it, - and it confuses new users - * minor patch for actsyncd, closes: #80973 - * inews now supports a -p option to set the port, closes: #22242, #68875 - * touch the /var/lib/news/.news.daily file in the postinst to squelch the - email about it being missing before nightly cron runs begin. closes: #76195 - * suidregister is obsolete. newer dpkg's include 'dpkg-statoverride', which - is a superior solution requiring nothing from the package. closes: #81310 - * configure storage.conf for tradspool configuration by default - * modify configure/configure.in slightly so build hostname isn't embedded - in inn.conf, et al - * don't force alt.test to exist, not all servers want it - * add code to the preinst to clean up the scripts tagged as conffiles that - will still be around from 2.3.0-1. Sigh. - - -- Bdale Garbee Mon, 22 Jan 2001 17:23:45 -0700 - -inn2 (2.3.0-1) unstable; urgency=low - - * new upstream version, closes: #69623 - * sendbatch appears to be fixed now, closes: #69561 - * innreport now appears to use png if gif isn't available, closes: #76169 - * thanks to John Goerzen for help cleaning up this release - * hack around need to have pgp installed at build time, closes: #69745 - * add sanity checks for syslog files in the postinst, closes: #74707 - * move all the scripts in /usr/lib/news that must be conffiles into /etc, - backfilling symlinks. Closes: #57150 - * built against perl-5.6, closes: #80703 - * can't duplicate removal problem, closes: #77419 - * update pgpverify's default notion of where to find pgp, closes: #78989 - * ship the Perl send-uucp from Miquel van Smoorenburg, closes: #77836 - * give inews more reasonable owner/group/perms, closes: #70856 - * add another warning to the preinst since some file format changes defy - reasonable automation across the upgrade from pre-2.3.0 to 2.3.0, and some - manual actions will likely be required. - * as of 2.3.0, innshellvars now codes 'compress' as the path for the compress - program instead of an ugly token reporting that compress wasn't found if - there is no compress available at build time. This will work if the - non-free 'ncompress' package is installed. Since some news sites still - don't use gzip for uucp batches, this is probably the right default. Note - added to the README.Debian file. - Closes: #77030 - - -- Bdale Garbee Thu, 28 Dec 2000 16:17:47 -0700 - -inn2 (2.2.3-3) unstable; urgency=low - - * leave the real inews executable in /usr/lib/news/bin, and symlink to it - from /usr/bin instead of moving it, to reduce breakage. Closes: #68999 - * do the same thing with rnews, for good measure - - -- Bdale Garbee Mon, 14 Aug 2000 02:58:39 -0600 - -inn2 (2.2.3-2) unstable; urgency=medium - - * patch from upstream that fixes remote denial of service, closes: #66638 - * provide /usr/sbin/ctlinnd as a symlink so ctlinnd is in root's path, - closes: #67730 - * update the README.Debian file to explain the situation with 'compress' - and indicate willingness to receive patch suggestions for making inn2 - work better with uucp article transport, closes: #64284, #67629 - - -- Bdale Garbee Sun, 13 Aug 2000 22:39:21 -0600 - -inn2 (2.2.3-1) unstable; urgency=low - - * new upstream release, closes: #67635, #65492, #59345, #64405 - * ensure control.cancel exists since we like usecontrolchan=true, - closes: #57555 - * add some verbage to the README.Debian about anacron, closes: #59664 - * some of the code proposed by Raphael Bossek for the init.d is only - relevant for a 1.X to 2.X upgrade, and the rest could take quite a - while during boot. I therefore don't think this belongs in init.d. - I'm adding the interesting checks to the postinst, closes: #62045 - * provide PGPKEYS and some text about it in the README.Debian file, - closes: #66756 - - -- Bdale Garbee Tue, 25 Jul 2000 01:23:14 -0600 - -inn2 (2.2.2.2000.01.31-4) frozen unstable; urgency=low - - * add code to the postinst that calls 'hostname --fqdn' to make sure we can - determine the FQDN before we try to start the daemon. Not doing this - caused installs to fail on poorly-configured systems. Closes: #64681 - * target frozen since this was tagged important, and could indeed cause an - install or upgrade to fail in some (relatively rare?) cases. - - -- Bdale Garbee Fri, 26 May 2000 21:32:01 -0600 - -inn2 (2.2.2.2000.01.31-3) frozen unstable; urgency=low - - * target frozen since these are release critical - * fix a variety of permission problems including /var/lib/news, - closes: #61077 - * permit world execute of /usr/bin/rnews, closes: #61409 - - -- Bdale Garbee Thu, 6 Apr 2000 23:17:56 -0600 - -inn2 (2.2.2.2000.01.31-2) frozen unstable; urgency=low - - * target frozen since one of these is release critical - * fix owner, group, and permissions of /var/run/news on fresh installs, - closes: #61030 - * minor tweak to default inn.conf so build host isn't the value of pathhost - on new installs, closes: #60779 - * fix owner, group, and permissions of /usr/bin/rnews so that it actually - works, closes: #58964 - - -- Bdale Garbee Fri, 24 Mar 2000 01:01:57 -0700 - -inn2 (2.2.2.2000.01.31-1) frozen unstable; urgency=low - - * target frozen since some of the bug fixes here qualify as release critical - * roll to current stable CVS snapshot to acquire bug fixes (some significant) - since 2.2.2 release, closes: #55581 - * tag many scripts in /usr/lib/news/ as conffiles, so changes aren't lost on - upgrades. This makes particularly good sense given the apparent upstream - attitude that whacking scripts to configure a system is reasonable. Add - lintian overrides since it calls conffiles under /usr errors. - Closes: #55723, #56385 - * have inn2 "provide inn" so that other packages that depend on inn don't - get frustrated with us, closes: #56040 - * add -L to innflags and turn controlchan on in default inn.conf (to match - what we're shipping in default newsfeeds file), closes: #56383, #56384 - * don't remove /usr/lib/news explicitly in postrm, since other packages need - it, closes: #55467 - - -- Bdale Garbee Mon, 31 Jan 2000 23:48:44 -0700 - -inn2 (2.2.2-4) frozen unstable; urgency=low - - * change package names from inn to inn2 as part of Debian INN peace project, - which will reinstate 1.7.2 as 'inn'. Target frozen so we ship both 1.7.2 - and 2.2.2 with potato! - * add suitable conflicts with inn 1.X packages, leaving check for old - versions in preinst along since it does no harm - * add task-news-server to help new installs target inn2 by default - - -- Bdale Garbee Wed, 19 Jan 2000 11:07:16 -0700 - -inn (2.2.2-3) frozen unstable; urgency=low - - * target frozen since this fixes multiple release-critical bugs - * inewsinn needs to provide inews, closes: #55349 - * fix rnews path in all innshellvars flavors, closes: #55307 - * since rnews uses nnrpdpostport, inews should also, closes: #54975 - * allow inews to work when talking to servers that require authentication - for the "mode reader" command, closes: #31145 - * add some more information to README.Debian, and include an explicit - pointer to it from the upgrade check in the preinst - * remove needless leftover example maintainer scripts in debian/Examples - - -- Bdale Garbee Sun, 16 Jan 2000 14:43:12 -0700 - -inn (2.2.2-2) unstable; urgency=low - - * move more config files and related man pages from package inn to inewsinn - so that inews works correctly, closes: #55159 - * flag /etc/cron.d/inn as a conffile - * reviewing / closing bugs in inn reported against prior versions that are - fixed or no longer relevant in 2.2.2 ... - * innwatch startup is cleaner than it used to be, closes: #21586, #32416 - * logging id different than it used to be, closes: #24504 - * expire.ctl doesn't have sequence problem any more, closes: #37737 - * Old hosts.nntp and hosts.nntp.nolimit are merged, closes: #48739 - * nntpsend.ctl no longer specifies the path, closes: #49673 - * startup works fine now, closes: #51944 - * control.ctl template is new, and correct, closes: #54526 - * crosspost and overview directories are correct, closes: #55062 - * history corruption problem should be long since fixed, closes: #11614 - * client timeout is set to 10 minutes in /etc/news/inn.conf file by default, - which seems pretty reasonable, and is easy to change. Closes: #12358 - * the ancient problem with ctlinnd rmgroup appears fixed, closes: #12559 - * the current GetFQDN code appears to be coded to work in more cases than - it once was, closes: #29695 - * we use a cron.d script now, so send-uucp, et al, can be scheduled on any - desired interval. Closes: #43016 - - -- Bdale Garbee Sat, 15 Jan 2000 01:18:17 -0700 - -inn (2.2.2-1) unstable; urgency=low - - * New upstream release. Enough has changed since the 1.7.2 release that - this is repackaged entirely from scratch. - Closes: #25936, #26255, #43546, #52672, #43896, #54609, #54759 - * patch lib/parsedate.y to include "y2k fix" relating to acceptance of - articles with year of 1900. Closes: #53813 - * postinst no longer prompts on upgrades, closes: #26659, #44918, #37888 - * much newer innfeed, now integrated with inn sources, closes: #14326 - * install docs revised, formatted version provided, closes: #43898 - * large warning in preinst about upgrades from prior revisions of Debian - INN package requiring manual intervention. The degree of assistance - will improve in future uploads, but may never be fully automatic. - - -- Bdale Garbee Wed, 22 Dec 1999 02:22:33 -0700 - -inn (1.7.2-12) unstable; urgency=low - - * update to reflect current policy - * inndstart *is* provided setuid root, closes: #51944 - * fix path in nntpsend.ctl.5, closes: #49673 - * if we're upgrading, don't stop to ask user, just use existing config - information, closes: #44918 - * deliver Install.txt instead of Install.ms into the doc directory, - closes: #43898 - - -- Bdale Garbee Sun, 5 Dec 1999 20:46:07 -0700 - -inn (1.7.2-11) unstable; urgency=high - - * patch to inews.c to fix buffer overrun problem from Martin Schulze - - -- Bdale Garbee Mon, 6 Sep 1999 13:35:19 -0600 - -inn (1.7.2-10) unstable; urgency=low - - * rebuild to depend on perl 5.005, closes 41469, 41925, 41943. - * update postinst text to eliminate version bogosity, closes 41585. - * fix sample sendbatch, closes 41596 - * fix source-archive clause in sample newsfeeds file, closes 37862. - * document nntpport, closes 28588. - * fix type of inet_addr to reflect current libc. - - -- Bdale Garbee Mon, 2 Aug 1999 01:22:23 -0600 - -inn (1.7.2-9) unstable; urgency=low - - * fold in Roman Hodek's changes from his 6.1 NMU, closing 38621. This - fixes an ugly i386 dependency in the way inn calls Perl. - * update perl dependency managment to try and cope with new perl policy - - -- Bdale Garbee Sat, 17 Jul 1999 17:13:05 -0600 - -inn (1.7.2-6) unstable; urgency=low - - * new maintainer - * clean up a few lintian complaints - * folding in changes from Christian Kurz that he called -5. We'll call this - -6 even though his changes were not widely distributed, just to avoid any - confusion: - - Removed X-Server-Date-Patch as it's not needed. - default moderation address add to /etc/news/moderators (closes: #24549) - Inn now depends on perl (closes: #27754, #32313) - Added gunbatch for gzipped batches (closes: #29899) - Changed debian/rules so inncheck runs without errors. - Added Perl-Support to Inn (closes: #26254) - Changed the examples - - -- Bdale Garbee Wed, 26 May 1999 15:18:53 -0600 - -inn (1.7.2-4) frozen unstable; urgency=medium - - * Fixes: - #21583: inn: inn must replace inewsinn - #20763: inn sends me `not running' and `now running' each night - #21342: inn: install probs - #21582: inn: incorrect prerm fail-upgrade action - #21584: inn: postinst doesn't know abort-upgrade - #20048: inn: poison and REMEMBER_TRASH patch - #21644: inn: a way to not receive certain groups - * Wrt bug #20763: the ctlinnd timeout in innwatch has been increased - to 300 seconds (5 minutes). Hopefully that is enough.. There is no - good alternative, the fact that INN is slow while renumbering is - a basic design flaw. (Though the abp-scheduler patch might help) - - -- Miquel van Smoorenburg Fri, 22 May 1998 19:52:55 +0200 - -inn (1.7.2-3) frozen unstable; urgency=medium - - * Move moderators from inewsinn to inn. The server should keep the - moderators data, not inews. - * Fix lib/clientactive.c (still yucky, but should work..) - * Include latest pgpverify script, 1.9, and manpage - * Fix security hole (/tmp/pgp$$) in pgpverify script - * Fixes: - #18579: I can't uninstall INN package - #19776: inn.prerm buggy typos bah! - #18724: inn: /etc/init.d/inn contains sed that never terminates - #19206: inn: Crontab modifications not preserved - #20423: inn: error in removing - #20653: inn: Bug in send-uucp.pl, patch included - #20792: INN: Wrong sfnet maintainer - #20436: inn: on line 16 of the prerm script there is "fi" instead of "esac" - - -- Miquel van Smoorenburg Wed, 15 Apr 1998 17:34:23 +0200 - -inn (1.7.2-2) unstable; urgency=low - - * Change over to new crontab -l method - * Fix (pre|post)(inst|rm) scripts in several ways - * Fix inewsinn inn.conf installation - * Set NNRP_DBZINCORE_DELAY to -1 - * Fix lintian warnings - Fixes: - #18120: inn: Inn's crontab file should be a conffile - - -- Miquel van Smoorenburg Thu, 19 Feb 1998 22:46:25 +0100 - -inn (1.7.2-1) unstable; urgency=low - - * New upstream version - * Fix crontab -l | tail +4 - * Fixes bugs: - #15889: /etc/news/inn.conf missing - #16128: manpage uncompressed - #15103: egrep incorrectly searched in /bin by innshellvars* - #14404: /usr/doc/$(PACKAGE)/copyright should not be compressed - - -- Miquel van Smoorenburg Thu, 5 Feb 1998 12:52:14 +0100 - -inn (1.7-1) unstable; urgency=low - - * New upstream version - * Fixed bugs: - #9264: Unresolved dependency report for inn - #9315: inn: /etc/news/innshellvars* add /usr/ucb to the PATH - #9832: INN 1.5.1-1 throttled rmgroup really shreds active file ? - #10196: inn: inews complains about missnig subject header when there is one - #10505: Moderated postings fail - #11042: error in /usr/doc/inn/inn-README - #11057: inn: Confusing/dangerous instructions - #11453: inn: max signature length - #11691: libc6 - #11851: inn: Documentation for send-uucp.pl - #11852: inn: nntpsend looks for wrong config file - #11900: INN creates `local.*' by default - #11948: inn: nntpsend does not works - #12513: inewsinn should insert a linebreak - #13161: inn-makehistory - Bus error - #13425: inn: egrep moved to /bin - #13488: inewsinn: directs user to docs in a package it doesn't require - #13616: /etc/init.d/inn, /etc/news/hosts.nntp.nolimit are not conffiles - #13781: Can't feed by send-uucp.pl with ihave/sendme. - #13831: inn: scanlogs depends on hard coded path for egrep - #13899: inn: inn uses /usr/bin/egrep, grep doesn't provide that any longer - * Added BUFFSET fix - - -- Miquel van Smoorenburg Wed, 22 Oct 1997 14:08:37 +0200 - -inn (1.5.1-5) unstable; urgency=high - - * Fixed sendbatch script (comment in between backtics is illegal) - * libc6 version - - -- Miquel van Smoorenburg Wed, 10 Sep 1997 16:31:37 +0200 - -inn (1.5.1-4) stable unstable; urgency=high - - * Add new security patch (with fixed STRCPY): inn-1.5.1-bufferoverflow.patch4 - * Applied null-pointer.patch from Michael Shields - * Upped SIG_MAXLINES in configdata.h to 8 - * Fix inn-README (perl example). Fixes bug #11042 - * Update inn-README and postinst to fix bug #11057 - * Make ctlinnd addhist work in paused mode, and fail in throttled mode - * Change ID string - - -- Miquel van Smoorenburg Thu, 21 Aug 1997 12:37:48 +0200 - -inn (1.5.1-3) stable unstable; urgency=high - - * Add changelogs to docdir - * innshellvars*: change /usr/ucb -> /usr/sbin (Bug#9315) - * Changed Recommends: pgp to Suggests: (Bug#9264) - * Fix inews to fallback on local moderators file (Bug#10505) - * Fix buffer overruns all over the place - - -- Miquel van Smoorenburg Thu, 24 Jul 1997 18:29:33 +0200 - -inn (1.5.1-2) frozen unstable; urgency=high - - * Added security-patch.05 (mailx tilde exploit) - * inewsinn no longer conflicts: inn so installation should no - longer remove your original inn-1.4 package (and configuration). - Expect some dpkg trouble when upgrading from 1.4unoff4 to 1.5.1-2 though. - * Always create .incoming/.outgoing symlinks for backwards compat. - * Do not change ownerships/modes of existing directories - * Fix ownerships/modes of rnews, innd, inndstart, in.nnrpd - * Fix /etc/init.d/inn to comply with console messages standard - * Fix /usr/lib/news/bin/sendbatch - * Fix scanlogs not to nuke active file if log/news/OLD isn't there - * Console messages are a bit more standard now - * Use start-stop-daemon to kill innwatch in /etc/init.d/inn - * Fixed up inncheck - it almost doesn't complain anymore - - -- Miquel van Smoorenburg Mon, 28 Apr 1997 13:58:16 +0200 - -inn (1.5.1-1) unstable; urgency=low - - * Upgraded to 1.5.1 - * Fixed Bug#6387: expire-with-symlinks problem - * Fixed Bug#6246: inewsinn reconfigures on update - * Moved /var/spool/news,/var/lib/news back into package - * Saves removed conffiles in preinst, restores in postinst - * Set LIKE_PULLERS to DO - * Remove manpage stubs that are now real manpages - * Fix options to sendmail in _PATH_SENDMAIL - * Removed subdirectories from debian/ - * create /var/log/news/OLD in postinst - * Fixed most if not all other outstanding bugs - - -- Miquel van Smoorenburg Wed, 5 Feb 1997 10:58:16 +0100 - -inn (1.5-1) unstable; urgency=low - - * Upgraded to 1.5 - * Undid most patches to 1.4unoff4 because they are in 1.5 proper. - * Added security patch - * Added X-Server-Date: patch - * inn now depends on inewsinn - * Fixed all other outstanding bugs (well, almost). - - -- Miquel van Smoorenburg Tue, 17 Dec 1996 16:56:37 +0100 - -inn (1.4unoff4-2) unstable; urgency=low - - * Added inn-dev package for libinn.a and manpages. - * Increased hash table size in expire.c to 2048 (was 128) - * Moved ctlinnd to /usr/sbin - * Moved to new source packaging scheme - - -- Miquel van Smoorenburg Wed, 06 Oct 1996 15:38:30 +0200 - -INN (1.4unoff4-1) - Miquel van Smoorenburg - - * Took out the Linux 1.2 patches I put in unoff3. - * added the 64 bits patch (for Linux/Alpha) - * There are some other minor patches for Linux/Alpha - * Added "xmode" as alias for "mode" - * Using MMAP and setsockopt() now - NEEDS 1.3 kernel ! - -INN (1.4unoff3-1) - Miquel van Smoorenburg - - * Took inn1.4sec-8 and 1.4unoff3, folded in some Linux and - other patches. - * Changed all makefiles to support a "prefix" variable for install - * Removed the hacks in debian.rules for installation - * Locks are in /var/run/innd - * Rewrote post install script. - -inn (1.4sec-8); priority=MEDIUM - - * postinst configuration completely redone. It now sets up a minimal - local installation for you. - * prerm now exists and shuts the server down. - * init scripts changed to System V scheme. - * Descriptions in control files expanded. - * Package now contains /var/lock/news, and uses /var/log (not /var/adm). - * inewsinn postinst looks at and can write /etc/mailname. - -INN 1.4sec Debian 7 - iwj - -* libinn.a, , inn-sys2nf and inn-feedone installed - (in /usr/lib, /usr/include and /usr/bin). - -INN 1.4sec Debian 6 - iwj - -* innwatch now started by /etc/rc.misc/news. -* inewsinn postinst minor typos fixed. -* Leftover file `t' removed from source and diff distributions. - -INN 1.4sec Debian 5 - iwj - -* Added documentation about making active and history files. -* Added monthly makehistory -ru crontab run. -* Made postinst always do crontab -u news /etc/news/crontab . -* Removed HAVE_UNIX_DOMAIN - AF_UNIX+SOCK_DGRAM still broken in Linux. -* Fixed /usr/lib/news/bin/inncheck to conform to our permissions scheme. -* Added manpage links for makeactive(8), makehistory(8), newsrequeue(8). -* /var/adm/news now part of package. - -INN 1.4sec Debian 4 - iwj - -* Added $|=1 to inewsinn postinst script; a few cosmetic fixes. - -INN 1.4sec Debian 3 - iwj - -* Removed `inet' groups from distrib.pats. -* Put more version number information in ../*.{deb,gz} filenames. -* Added Package_Revision field to `control' file. -* Rationalised debian.rules somewhat, and added `build' stamp file. -* Permissions rationalised. -* Changed /etc/rc.d/rc.news to /etc/rc.misc/news. -* postinst calls Perl as /usr/bin/perl. -* Added this Changelog. - -INN 1.4sec Debian 2 - iwj -* inews moved to /usr/bin; rnews moved to /usr/sbin. -* fixed nntpsend not to use PPID variable (it's a bash builtin). - -INN 1.4sec Debian 1 - iwj -Initial release, completely untested. diff --git a/debian/compat b/debian/compat deleted file mode 100644 index b8626c4..0000000 --- a/debian/compat +++ /dev/null @@ -1 +0,0 @@ -4 diff --git a/debian/inn2-dev.files b/debian/inn2-dev.files deleted file mode 100644 index 229c7f7..0000000 --- a/debian/inn2-dev.files +++ /dev/null @@ -1,5 +0,0 @@ -usr/include/inn/ -usr/share/man/man3/ -usr/lib/news/libinn.a -usr/lib/news/libstorage.a -usr/lib/news/libinnhist.a diff --git a/debian/inn2-dev.links b/debian/inn2-dev.links deleted file mode 100644 index 00ac8c2..0000000 --- a/debian/inn2-dev.links +++ /dev/null @@ -1,4 +0,0 @@ -usr/share/man/man3/dbz.3 usr/share/man/man3/dbzclose.3 -usr/share/man/man3/dbz.3 usr/share/man/man3/dbzinit.3 -usr/share/man/man3/dbz.3 usr/share/man/man3/dbzfetch.3 -usr/share/man/man3/dbz.3 usr/share/man/man3/dbzstore.3 diff --git a/debian/inn2-inews.files b/debian/inn2-inews.files deleted file mode 100644 index c9833a1..0000000 --- a/debian/inn2-inews.files +++ /dev/null @@ -1,13 +0,0 @@ -etc/news/distrib.pats -etc/news/inn.conf -etc/news/moderators -etc/news/passwd.nntp -usr/lib/news/bin/inews -usr/lib/news/bin/rnews -usr/lib/news/bin/rnews.libexec -usr/share/man/man1/inews.1 -usr/share/man/man1/rnews.1 -usr/share/man/man5/distrib.pats.5 -usr/share/man/man5/inn.conf.5 -usr/share/man/man5/moderators.5 -usr/share/man/man5/passwd.nntp.5 diff --git a/debian/inn2-inews.links b/debian/inn2-inews.links deleted file mode 100644 index feaeeb3..0000000 --- a/debian/inn2-inews.links +++ /dev/null @@ -1,2 +0,0 @@ -usr/lib/news/bin/inews usr/bin/inews -usr/lib/news/bin/rnews usr/bin/rnews diff --git a/debian/inn2.README.Debian b/debian/inn2.README.Debian deleted file mode 100644 index 61adc45..0000000 --- a/debian/inn2.README.Debian +++ /dev/null @@ -1,102 +0,0 @@ -Some random notes about the Debian INN 2.X package. - -If you are upgrading from a previous version, please review the information -near the top of the NEWS file to learn what has changed, and what you may -need to do to update your system. - -If you plan to use INN at home you should really consider running INN 1.x, -which you can find in the inn package. - -INN 2.X is substantially different in terms of configuration file contents -and filesystem layout than previous versions. The Debian INN package installs -a minimal but functional local-only server configuration. Configuring feeds -to/from other servers, and many other details, is up to you. - -You will want to review the information in /usr/share/doc/inn2 to get started -on configuring the installation for your needs. All of the configuration files -in /etc/news are flagged as 'conffiles' in the packaging system, so your work -should not be overwritten without your permission if/when you upgrade the inn -package in the future. In particular, make sure to update /etc/news/inn.conf -to put in your organization name and related information before you establish -any network connections if you don't want to be embarrassed. - -Also, if you are moving over from INN 1.X, please note that the directory -structure under /var/spool/news has changed. At a minimum, you will need to -move the article database subdirectories from /var/spool/news to -/var/spool/news/articles. The set of directories that belong in -/var/spool/news for 2.2.2 and later are: - - archive articles incoming innfeed outgoing overview - -Anything else is left over from a previous version, and probably should be -moved or removed. - -It has been pointed out that inn2's use of /etc/cron.d/inn2 instead of -separate files in /etc/cron.daily and so forth poses a problem for users of -anacron on boxes that are not run continuously. Since the primary target -for an INN installation is a fully-connected system that might easily need -a variety of cron entries with different intervals, I don't intend to change -this default. However, if you're bothered by this, feel free to change the -cron configuration to suite your needs. - -If you want to use pgpverify (and you do if you're getting a real feed!), -you can use the /usr/lib/news/bin/buildinnkeyring program to download the -keys for some hierarchies from ftp.isc.org and add them to the gnupg -keyring used by pgpverify. -This package does not support the non-free PGP program anymore. - -The program 'compress' is not a part of Debian GNU/Linux due to patent issues -with the algorithm. By default, the innshellvars* files will try to call -'compress' if you try to transport compressed batches over UUCP. This will -work if you install the non-free 'ncompress' package. Since it's non-free, -this might be as unacceptable to you as it is to me! If you know that all of -your neighbors can handle gzip, a better solution might be to edit the -innshellvars* files to use '/bin/gzip -9' for the COMPRESS variable. I do not -intend to change this default to differ from the upstream source. - -Log files in /var/log/news need to be owned by user 'news' for the news -scanlogs tool to be able to rotate them properly. - -If you want to use the ckpasswd program you need to install the libgdbm3 -package. - - -SSL -~~~ -To enable SSL you need to start /usr/lib/news/bin/nnrpd-ssl with the -S -flag from inetd or the command line. -See nnrpd(8) and sasl.conf(5) for details. - -You need a certificate authority (CA) certificate in -/etc/news/nnrpd-ca-cert.pem. You will also need a certificate/key pair, -named /etc/news/nnrpd-cert.pem and /etc/news/nnrpd-key.pem respectively. - -If you do not already have a PKI in place, you can create them with a -command like: - -openssl req -new -x509 -nodes -days 1825 \ - -keyout /etc/news/nnrpd-key.pem -out /etc/news/nnrpd-cert.pem - -The private key must have the correct permissions: - -chown root:news /etc/news/nnrpd-key.pem -chmod 640 /etc/news/nnrpd-key.pem - - -STARTTLS -~~~~~~~~ -STARTTLS support will not work when nnrpd is started by innd using -"MODE READER" unless the nnrpd binary is replaced by nnrpd-ssl (e.g. -by using dpkg-divert(8)). -The upstream maintainer recommends running nnrpd as a standalone process. - - -Large Files Support -~~~~~~~~~~~~~~~~~~~ -On 32 bit architectures, the inn2-lfs package is built. -There is no transition procedure, so if you want to convert an existing -installation (this may or may not be possible depending on your choice -of storage and overview formats) then you are on your own. -When attempting such conversion do not forget that the package will -delete /var/{spool,lib,log}/news/ when removed so they should be renamed. - diff --git a/debian/inn2.cron.d b/debian/inn2.cron.d deleted file mode 100644 index 1691131..0000000 --- a/debian/inn2.cron.d +++ /dev/null @@ -1,37 +0,0 @@ -SHELL=/bin/sh -PATH=/usr/lib/news/bin:/sbin:/bin:/usr/sbin:/usr/bin - -# Expire old news and overview entries nightly, generate reports. - -15 4 * * * news test -x /usr/lib/news/bin/news.daily && news.daily expireover lowmark delayrm - -# Refresh the cached IP addresses every day. - -2 3 * * * news [ -x /usr/sbin/ctlinnd ] && ctlinnd -t 300 -s reload incoming.conf "flush cache" - -# Every hour, run an rnews -U. This is not only for UUCP sites, but -# also to process queud up articles put there by in.nnrpd in case -# innd wasn't accepting any articles. - -10 * * * * news [ -x /usr/bin/rnews ] && rnews -U - -# Enable this entry to send posted news back to your upstream provider. -# Also edit /etc/news/nntpsend.ctl ! -# Not if you use innfeed, of course. - -#*/15 * * * * news nntpsend - - -# Enable this if you want to send news by uucp to your provider. -# Also edit /etc/news/send-uucp.cf ! - -#22 * * * * news send-uucp.pl - -# NINPATHS ################################################################### -# To enable ninpaths please add this line to /etc/news/newsfeeds: -# inpaths!:*:Tc,WP:/usr/lib/news/bin/ginpaths2 -# -#6 6 * * * news ctlinnd -s -t 60 flush inpaths! -#8 6 1 * * news sendinpaths -# NINPATHS ################################################################### - diff --git a/debian/inn2.docs b/debian/inn2.docs deleted file mode 100644 index 8307807..0000000 --- a/debian/inn2.docs +++ /dev/null @@ -1,10 +0,0 @@ -CONTRIBUTORS -INSTALL -NEWS -README -doc/checklist -doc/external-auth -doc/history -doc/hook-perl -doc/IPv6-info -doc/compliance-nntp diff --git a/debian/inn2.examples b/debian/inn2.examples deleted file mode 100644 index 58759cf..0000000 --- a/debian/inn2.examples +++ /dev/null @@ -1,2 +0,0 @@ -extra/active -extra/newsgroups diff --git a/debian/inn2.init b/debian/inn2.init deleted file mode 100644 index ae5b687..0000000 --- a/debian/inn2.init +++ /dev/null @@ -1,63 +0,0 @@ -#!/bin/sh -e -### BEGIN INIT INFO -# Provides: inn2 -# Required-Start: $local_fs $remote_fs $syslog -# Required-Stop: $local_fs $remote_fs $syslog -# Default-Start: 2 3 4 5 -# Default-Stop: 0 1 6 -# Short-Description: INN news server -# Description: The InterNetNews news server. -### END INIT INFO -# -# Start/stop the news server. -# - -test -f /usr/lib/news/bin/rc.news || exit 0 - -start () { - if [ ! -d /var/run/news ]; then - mkdir -p /var/run/news - chown news:news /var/run/news - chmod 775 /var/run/news - fi - su news -c /usr/lib/news/bin/rc.news > /var/log/news/rc.news 2>&1 - # su news -c '/usr/lib/news/bin/nnrpd -D -c /etc/news/readers-ssl.conf -p 563 -S' -} - -stop () { - su news -c '/usr/lib/news/bin/rc.news stop' >> /var/log/news/rc.news 2>&1 - # start-stop-daemon --stop --name nnrpd --quiet --oknodo -} - -case "$1" in - start) - echo -n "Starting news server: " - start - echo "done." - ;; - stop) - echo -n "Stopping news server: " - stop - echo "done." - ;; - reload|force-reload) - echo -n "Reloading most INN configuration files: " - ctlinnd -t 20 reload '' /etc/init.d/inn2 - ;; - restart) - echo -n "Restarting innd: " - if [ -f /var/run/news/innd.pid ]; then - ctlinnd -t 20 throttle "init script" > /dev/null || true - ctlinnd -t 20 xexec inndstart > /dev/null || start - else - start - fi - echo "done." - ;; - *) - echo "Usage: /etc/init.d/inn start|stop|restart|reload">&2 - exit 1 - ;; -esac - -exit 0 diff --git a/debian/inn2.links b/debian/inn2.links deleted file mode 100644 index e55863e..0000000 --- a/debian/inn2.links +++ /dev/null @@ -1,6 +0,0 @@ -usr/lib/news/bin/ctlinnd usr/sbin/ctlinnd -usr/lib/news/bin/innstat usr/sbin/innstat -usr/lib/news/bin/send-uucp usr/lib/news/bin/send-uucp.pl -usr/share/man/man3/uwildmat.3 usr/share/man/man3/wildmat.3 -usr/share/man/man8/send-uucp.8 usr/share/man/man8/send-ihave.8 -usr/share/man/man8/send-uucp.8 usr/share/man/man8/send-nntp.8 diff --git a/debian/inn2.logcheck.ignore.server b/debian/inn2.logcheck.ignore.server deleted file mode 100644 index 25d80ea..0000000 --- a/debian/inn2.logcheck.ignore.server +++ /dev/null @@ -1,57 +0,0 @@ -\w{3} [ :0-9]{11} [._[:alnum:]-]+ (rnews|innd|batcher): Reading config from /etc/news/inn\.conf$ -^\w{3} [ :0-9]{11} [._[:alnum:]-]+ (expire|expireover|ctlinnd|nnrpd)\[[0-9]+\]: Reading config from /etc/news/inn\.conf$ -^\w{3} [ :0-9]{11} [._[:alnum:]-]+ rnews: offered <[^[:space:]]+> [._[:alnum:]-]+$ -^\w{3} [ :0-9]{11} [._[:alnum:]-]+ innd: localhost connected [0-9]+$ -^\w{3} [ :0-9]{11} [._[:alnum:]-]+ innd: [[:alpha:]]$ -^\w{3} [ :0-9]{11} [._[:alnum:]-]+ innd: [[:alpha:]]:$ -^\w{3} [ :0-9]{11} [._[:alnum:]-]+ innd: [[:alpha:]]:[-[:alnum:]]+$ -^\w{3} [ :0-9]{11} [._[:alnum:]-]+ innd: [[:alpha:]]:Expiring process [0-9]+$ -^\w{3} [ :0-9]{11} [._[:alnum:]-]+ innd: [[:alpha:]]:Flushing log and syslog files$ -^\w{3} [ :0-9]{11} [._[:alnum:]-]+ innd: [[:alpha:]]:/var/log/news/expire\.lowmark$ -^\w{3} [ :0-9]{11} [._[:alnum:]-]+ innd: [._[:alnum:]-]+ flush$ -^\w{3} [ :0-9]{11} [._[:alnum:]-]+ innd: [._[:alnum:]-]+ opened [^[:space:]]+$ -^\w{3} [ :0-9]{11} [._[:alnum:]-]+ innd: [._[:alnum:]-]+ closed$ -^\w{3} [ :0-9]{11} [._[:alnum:]-]+ innd: [._[:alnum:]-]+:[0-9]+ readclose$ -^\w{3} [ :0-9]{11} [._[:alnum:]-]+ innd: [._[:alnum:]-]+:[0-9]+ inactive [0-9]+$ -^\w{3} [ :0-9]{11} [._[:alnum:]-]+ innd: [._[:alnum:]-]+:[0-9]+ NCmode \"mode stream\" received$ -^\w{3} [ :0-9]{11} [._[:alnum:]-]+ innd: [._[:alnum:]-]+ connected [0-9]+ streaming allowed$ -^\w{3} [ :0-9]{11} [._[:alnum:]-]+ innd: ME HISstats [0-9]+ hitpos [0-9]+ hitneg [0-9]+ missed [0-9]+ dne$ -^\w{3} [ :0-9]{11} [._[:alnum:]-]+ innd: ME time [0-9]+ hishave [0-9]+\([0-9]+\) hiswrite [0-9]+\([0-9]+\) hissync [0-9]+\([0-9]+\) idle [0-9]+\([0-9]+\) artclean [0-9]+\([0-9]+\) artwrite [0-9]+\([0-9]+\) artcncl [0-9]+\([0-9]+\) hishave/artcncl [0-9]+\([0-9]+\) his(grep|write)/artcncl [0-9]+\([0-9]+\) artlog/artcncl [0-9]+\([0-9]+\) his(write|grep)/artcncl [0-9]+\([0-9]+\) sitesend [0-9]+\([0-9]+\) overv [0-9]+\([0-9]+\) perl [0-9]+\([0-9]+\) nntpread [0-9]+\([0-9]+\) artparse [0-9]+\([0-9]+\)( artlog/artparse [0-9]+\([0-9]+\))? artlog [0-9]+\([0-9]+\) datamove [0-9]+\([0-9]+\)$ -^\w{3} [ :0-9]{11} [._[:alnum:]-]+ innd: SERVER (servermode|flushlogs) (running|paused)$ -^\w{3} [ :0-9]{11} [._[:alnum:]-]+ innd: SERVER paused Flushing log and syslog files$ -^\w{3} [ :0-9]{11} [._[:alnum:]-]+ innd: SERVER running$ -^\w{3} [ :0-9]{11} [._[:alnum:]-]+ innd: SERVER paused Expiring process [0-9]+$ -^\w{3} [ :0-9]{11} [._[:alnum:]-]+ batcher\[[0-9]+\]: batcher [[:alnum:]]+ times user [.0-9]+ system [.0-9]+ elapsed [.0-9]+$ -^\w{3} [ :0-9]{11} [._[:alnum:]-]+ batcher\[[0-9]+\]: batcher [[:alnum:]]+ stats batches [0-9]+ articles [0-9]+ bytes [0-9]+$ -^\w{3} [ :0-9]{11} [._[:alnum:]-]+ nnrpd\[[0-9]+\]: Reading access from /etc/news/readers\.conf$ -^\w{3} [ :0-9]{11} [._[:alnum:]-]+ nnrpd\[[0-9]+\]: SERVER perl filtering enabled$ -^\w{3} [ :0-9]{11} [._[:alnum:]-]+ nnrpd\[[0-9]+\]: [._[:alnum:]-]+ \([.0-9]+\) connect$ -^\w{3} [ :0-9]{11} [._[:alnum:]-]+ nnrpd\[[0-9]+\]: [._[:alnum:]-]+ timeout$ -^\w{3} [ :0-9]{11} [._[:alnum:]-]+ nnrpd\[[0-9]+\]: [._[:alnum:]-]+ group [.[:alnum:]+-]+ [0-9]+$ -^\w{3} [ :0-9]{11} [._[:alnum:]-]+ nnrpd\[[0-9]+\]: Auth strategy '[[:alnum:]]+' does not match client\. Removing\.$ -^\w{3} [ :0-9]{11} [._[:alnum:]-]+ nnrpd\[[0-9]+\]: [._[:alnum:]-]+ (no_)?match_user [<>_[:alnum:]-]+(@[._[:alnum:]-]+)? [<>,_,\*,\![:alnum:][:punct:]-]+$ -^\w{3} [ :0-9]{11} [._[:alnum:]-]+ nnrpd\[[0-9]+\]: [._[:alnum:]-]+ res <[_[:alnum:]-]+>(@[._[:alnum:]-]+)?$ -^\w{3} [ :0-9]{11} [._[:alnum:]-]+ nnrpd\[[0-9]+\]: [._[:alnum:]-]+ time [0-9]+ (hisgrep [0-9]+\([0-9]+\) )?idle [0-9]+\([0-9]+\) (readart [0-9]+\([0-9]+\) )?nntpwrite [0-9]+\([0-9]+\)$ -^\w{3} [ :0-9]{11} [._[:alnum:]-]+ nnrpd\[[0-9]+\]: [._[:alnum:]-]+ times user [.0-9]+ system [.0-9]+ idle [.0-9]+ elapsed [.0-9]+$ -^\w{3} [ :0-9]{11} [._[:alnum:]-]+ nnrpd\[[0-9]+\]: [._[:alnum:]-]+ exit articles [0-9]+ groups [0-9]+$ -^\w{3} [ :0-9]{11} [._[:alnum:]-]+ nnrpd\[[0-9]+\]: [._[:alnum:]-]+ artstats get [0-9]+ time [0-9]+ size [0-9]+$ -^\w{3} [ :0-9]{11} [._[:alnum:]-]+ nnrpd\[[0-9]+\]: [._[:alnum:]-]+ post ok <[[:graph:]]+@[._[:alnum:]-]+>$ -^\w{3} [ :0-9]{11} [._[:alnum:]-]+ nnrpd\[[0-9]+\]: [._[:alnum:]-]+ \(unknown\) posttrack ok [[:graph:]]+<[[:graph:]]+@[._[:alnum:]-]+>$ -^\w{3} [ :0-9]{11} [._[:alnum:]-]+ nnrpd\[[0-9]+\]: [._[:alnum:]-]+ user [[:alnum:][:punct:]]+$ -^\w{3} [ :0-9]{11} [._[:alnum:]-]+ nnrpd\[[0-9]+\]: [._[:alnum:]-]+ Tracking Disabled \(unknown\)$ -^\w{3} [ :0-9]{11} [._[:alnum:]-]+ nnrpd\[[0-9]+\]: [._[:alnum:]-]+ auth authenticator successful, user [[:alnum:][:punct:]]+$ -^\w{3} [ :0-9]{11} [._[:alnum:]-]+ nnrpd\[[0-9]+\]: [._[:alnum:]-]+ auth starting authenticator [[:alnum:][:space:][:punct:]]+$ -^\w{3} [ :0-9]{11} [._[:alnum:]-]+ nnrpd\[[0-9]+\]: [._[:alnum:]-]+ no_access_realm$ -^\w{3} [ :0-9]{11} [._[:alnum:]-]+ cnfsstat\[[0-9]+\]: Class [[:alnum:]]+ for groups matching \"[^[:space:]]+\" Buffer [[:alnum:]]+, len: [0-9]+ Mbytes, used: [0-9]+\.[0-9]+ Mbytes \([0-9 ]+\.[0-9]%\) [ 0-9]+ cycles$ -^\w{3} [ :0-9]{11} [._[:alnum:]-]+ send-uucp\[[0-9]+\]: checking site [^[:space:]]+$ -^\w{3} [ :0-9]{11} [._[:alnum:]-]+ send-uucp\[[0-9]+\]: no articles for [^[:space:]]+$ -^\w{3} [ :0-9]{11} [._[:alnum:]-]+ send-uucp\[[0-9]+\]: Flushing [^[:space:]]+ for site [^[:space:]]+$ -^\w{3} [ :0-9]{11} [._[:alnum:]-]+ send-uucp\[[0-9]+\]: batched articles for [^[:space:]]+$ -^\w{3} [ :0-9]{11} [._[:alnum:]-]+ innfeed\[[0-9]+\]: ME time [0-9]+ idle [0-9]+\([0-9]+\) blstats [0-9]+\([0-9]+\) stsfile [0-9]+\([0-9]+\) newart [0-9]+\([0-9]+\) readart [0-9]+\([0-9]+\) prepart [0-9]+\([0-9]+\) read [0-9]+\([0-9]+\) write [0-9]+\([0-9]+\) cb [0-9]+\([0-9]+\)$ -^\w{3} [ :0-9]{11} [._[:alnum:]-]+ innfeed\[[0-9]+\]: [._[:alnum:]-]+ spooling no active connections$ -^\w{3} [ :0-9]{11} [._[:alnum:]-]+ innfeed\[[0-9]+\]: [._[:alnum:]-]+:[0-9]+ connected$ -^\w{3} [ :0-9]{11} [._[:alnum:]-]+ innfeed\[[0-9]+\]: [._[:alnum:]-]+ remote MODE STREAM$ -^\w{3} [ :0-9]{11} [._[:alnum:]-]+ innfeed\[[0-9]+\]: [._[:alnum:]-]+ (final|checkpoint) seconds [0-9]+ spooled [0-9]+ on_close [0-9]+ sleeping [0-9]+$ -^\w{3} [ :0-9]{11} [._[:alnum:]-]+ innfeed\[[0-9]+\]: [._[:alnum:]-]+ hostChkCxns - maxConnections was [0-9]+ now [0-9]+$ -^\w{3} [ :0-9]{11} [._[:alnum:]-]+ innfeed\[[0-9]+\]: ME articles (active|total) [0-9]+ bytes [0-9]+$ -^\w{3} [ :0-9]{11} [._[:alnum:]-]+ innfeed\[[0-9]+\]: [._[:alnum:]-]+:[0-9]+ cxnsleep connect: Connection refused$ diff --git a/debian/inn2.logcheck.violations.ignore b/debian/inn2.logcheck.violations.ignore deleted file mode 100644 index 4dc7ef7..0000000 --- a/debian/inn2.logcheck.violations.ignore +++ /dev/null @@ -1,10 +0,0 @@ -^\w{3} [ :0-9]{11} [._[:alnum:]-]+ innd: [-[:alnum:].]+:[0-9]+ (closed|checkpoint) seconds [0-9]+ accepted [0-9]+ refused [0-9]+ rejected [0-9]+ duplicate [0-9]+ accepted size [0-9]+ duplicate size [0-9]+$ -^\w{3} [ :0-9]{11} [._[:alnum:]-]+ innd: rejecting\[perl\] <[[:alnum:][:punct:]]+@[.[:alnum:]-]+> [0-9]+ [[:alnum:] ]+( \([._[:alnum:]-]+\))?$ -^\w{3} [ :0-9]{11} [._[:alnum:]-]+ rnews: rejected [0-9]+ Unwanted (newsgroup|distribution) "[._,[:alnum:]-]+"$ -^\w{3} [ :0-9]{11} [._[:alnum:]-]+ rnews: rejected [0-9]+ Too old -- "\w{3}, [0-9 ]+ \w{3} [0-9]{4} [0-9:]{8} (\+|-)[0-9]{4}"$ -^\w{3} [ :0-9]{11} [._[:alnum:]-]+ rnews: rejected [0-9]+ Too old -- "[0-9]+ \w{3} [0-9]{4} [0-9:]{8} ([[:upper:]]+|(\+|-)[0-9]{4})"$ -^\w{3} [ :0-9]{11} [._[:alnum:]-]+ rnews: rejected [0-9]+ No colon-space in "("|x-no-archive:yes)" header$ -^\w{3} [ :0-9]{11} [._[:alnum:]-]+ rnews: offered <[^[:space:]]+> [._[:alnum:]-]+$ -^\w{3} [ :0-9]{11} [._[:alnum:]-]+ nnrpd\[[0-9]+\]: [^[:space:]]+ posts received [0-9]+ rejected [0-9]+$ -^\w{3} [ :0-9]{11} [._[:alnum:]-]+ nnrpd\[[0-9]+\]: \? reverse lookup for [0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3} failed: Unknown host -- using IP address for access$ -^\w{3} [ :0-9]{11} [._[:alnum:]-]+ innfeed\[[0-9]+\]: [._[:alnum:]-]+(:[0-9]+)? (final|global|checkpoint) seconds [0-9]+ offered [0-9]+ accepted [0-9]+ refused [0-9]+ rejected [0-9]+ (missing [0-9]+ )?accsize [0-9]+ rejsize [0-9]+( spooled [0-9]+ (on_close [0-9]+ )?unspooled [0-9]+)?( deferred [0-9]+/[0-9.]+ requeued [0-9]+ queue [0-9.]+/[0-9\:\,]+)?$ diff --git a/debian/inn2.postinst b/debian/inn2.postinst deleted file mode 100644 index 40214d0..0000000 --- a/debian/inn2.postinst +++ /dev/null @@ -1,181 +0,0 @@ -#!/bin/sh -e - -init_inn_files() { - PATHDB=$(/usr/lib/news/bin/innconfval pathdb) - if [ -z "$PATHDB" ]; then - echo "Cannot determine the database path, aborting." - exit 1 - fi - cd $PATHDB - - local package='inn2' - if [ -e /usr/share/doc/inn2-lfs/ ]; then - package='inn2-lfs' - fi - - for file in active newsgroups; do - if [ ! -f $file ]; then - echo "Installing initial content for $PATHDB/$file" - install -m 644 -o news -g news \ - /usr/share/doc/$package/examples/$file . - fi - done - - if [ ! -f history.dir ]; then - echo -n "Building history database in $PATHDB... " - if ! /usr/lib/news/bin/makehistory; then - echo "failed!" - return - fi - if ! /usr/lib/news/bin/makedbz -i -o -s 300000; then - echo "failed!" - return - fi - chown news:news history* - chmod 664 history* - echo "done." - fi - - if [ ! -f active.times ]; then - touch active.times - chown news:news active.times - chmod 644 active.times - fi - - # squelch initial noise in email if this isn't present - if [ ! -f .news.daily ]; then - touch .news.daily - chown news:news .news.daily - fi - - # make sure typical log files exist, and can be rotated - if [ ! -d /var/log/news ]; then - install -d -m 775 -o news -g news /var/log/news - fi - cd /var/log/news - [ -f news.notice ] || touch news.crit news.err news.notice - chown news:news . OLD path news.crit news.err news.notice - - if [ -x /etc/init.d/inn2 ]; then - update-rc.d inn2 defaults > /dev/null - fi -} - -check_usenet_alias() { - # must have an alias for user usenet, point it to root by default - if [ -f /etc/aliases ] && ! grep -q '^usenet:' /etc/aliases \ - && ! getent passwd usenet; then - echo "Adding alias for pseudo-user usenet to /etc/aliases." - echo "usenet: root" >> /etc/aliases - [ -x /usr/bin/newaliases ] && /usr/bin/newaliases - fi -} - -upgrade_inn_conf() { - cd /etc/news - if [ "$2" ] && dpkg --compare-versions "$2" lt "2.3.999+20030125-1"; then - /usr/lib/news/bin/innupgrade -f inn.conf - fi -} - -rebuild_history_index() { - [ -f /var/lib/news/must-rebuild-history-index ] || return 0 - - cd /var/lib/news - HLINES=$(tail -1 history.dir | awk '{ print $1 }') - [ "$HLINES" ] || HLINES=1000000 - echo "Rebuilding the history index for $HLINES lines, please wait..." - rm history.hash history.index history.dir - su news -c "/usr/lib/news/bin/makedbz -s $HLINES -f history" - - rm /var/lib/news/must-rebuild-history-index -} - -rebuild_overview() { - [ -f /var/lib/news/must-rebuild-overview ] || return 0 - - OVENABLED=$(/usr/lib/news/bin/innconfval enableoverview) - if [ -z "$OVENABLED" ]; then - echo "Cannot determine the overview method used, stopping." - exit 1 - fi - if [ $OVENABLED = no -o $OVENABLED = false ]; then - return 0 - fi - - OVMETHOD=$(/usr/lib/news/bin/innconfval ovmethod) - if [ -z "$OVMETHOD" ]; then - echo "Cannot determine the overview method used, stopping." - exit 1 - elif [ $OVMETHOD = tradindexed -o $OVMETHOD = ovdb ]; then - OVPATH=$(/usr/lib/news/bin/innconfval pathoverview) - if [ -z "$OVPATH" ]; then - echo "Cannot determine the overview path, aborting." - exit 1 - fi - echo "Deleting the old overview database, please wait..." - find $OVPATH -type f -not -name DB_CONFIG -print0 | xargs -0 -r rm -f - elif [ $OVMETHOD = buffindexed ]; then - echo "Deleting the old overview database, please wait..." - awk -F : '/^[0-9]/ { print $2 }' < /etc/news/buffindexed.conf | \ - while read name size; do - dd if=/dev/zero of="$name" bs=1024 count="$size" - done - else - echo "Unknown overview method '$OVMETHOD', aborting." - exit 1 - fi - - echo "Rebuilding the overview database, please wait..." - su news -c "/usr/lib/news/bin/makehistory -F -O -x" - - rm /var/lib/news/must-rebuild-overview -} - -start_innd() { -# make sure we can determine the FQDN, since innd won't launch if we can't -if hostname --fqdn > /dev/null 2>&1; then - invoke-rc.d inn2 start || echo "Could not start INN!" -else -cat < /dev/null || true - ctlinnd -t 20 xexec inndstart > /dev/null \ - || echo "Could not restart INN!" - fi - ;; - - abort-upgrade|abort-remove|abort-deconfigure) - ;; - - *) - echo "postinst called with unknown argument '$1'" >&2 - ;; -esac - -#DEBHELPER# - -exit 0 - diff --git a/debian/inn2.postrm b/debian/inn2.postrm deleted file mode 100644 index 53101ec..0000000 --- a/debian/inn2.postrm +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/sh -e - -if [ "$1" = "purge" ]; then - update-rc.d inn2 remove >/dev/null - if [ -e /var/lib/news/ ]; then - rm -f /var/lib/news/.news.daily /var/lib/news/active* \ - /var/lib/news/newsgroups /var/lib/news/history* - rmdir --ignore-fail-on-non-empty /var/lib/news/ - fi -fi - -#DEBHELPER# - -exit 0 diff --git a/debian/inn2.preinst b/debian/inn2.preinst deleted file mode 100644 index 70a1001..0000000 --- a/debian/inn2.preinst +++ /dev/null @@ -1,28 +0,0 @@ -#!/bin/sh -e - -if [ "$2" ] && dpkg --compare-versions $2 gt 2.0.0 \ - && dpkg --compare-versions $2 lt 2.3.0; then - echo "Some configuration files have changed in INN 2.4 and will need to" - echo "be adjusted, most notably nnrp.access has mutated into readers.conf." - echo "Also, note that you may need to rebuild the history database." - echo "For more information, read the /usr/share/doc/inn2/NEWS.gz file." -fi - -if [ "$2" ] && dpkg --compare-versions $2 eq 2.3.0-1; then - echo 'Upgrade from 2.3.0-1 to >= 2.3.999+20030125-4 is not supported.' - echo 'Aborting inn upgrade.' - exit 1 -fi - -if [ "$2" ] && dpkg --compare-versions $2 lt 2.3.1-2; then - # remove any remaining symlinks under /usr/lib/news/bin/filter, then remove - # the directory if it's empty - if [ -d /usr/lib/news/bin/filter ]; then - find /usr/lib/news/bin/filter -type l -exec rm {} \; - rmdir /usr/lib/news/bin/filter 2> /dev/null || true - fi -fi - -#DEBHELPER# - -exit 0 diff --git a/debian/inn2.prerm b/debian/inn2.prerm deleted file mode 100644 index b111c76..0000000 --- a/debian/inn2.prerm +++ /dev/null @@ -1,25 +0,0 @@ -#!/bin/sh -e - -kill_innd() { - if [ -x /etc/init.d/inn2 ]; then - invoke-rc.d inn2 stop - fi -} - -case "$1" in - remove|deconfigure|failed-upgrade) - kill_innd - ;; - - upgrade) - ;; - - *) - echo "$0 called with unknown argument '$1'" >&2 - exit 1 - ;; -esac - -#DEBHELPER# - -exit 0 diff --git a/debian/patches/debian-paths b/debian/patches/debian-paths deleted file mode 100644 index 38327a5..0000000 --- a/debian/patches/debian-paths +++ /dev/null @@ -1,10 +0,0 @@ ---- a/samples/buffindexed.conf -+++ b/samples/buffindexed.conf -@@ -7,5 +7,5 @@ - # index(0-65535) : path to buffer file : - # length of buffer in kilobytes in decimal (1KB = 1024 bytes) - --0:/var/news/spool/overview/OV1:1536000 --1:/var/news/spool/overview/OV2:1536000 -+0:/var/spool/news/overview/OV1:1536000 -+1:/var/spool/news/overview/OV2:1536000 diff --git a/debian/patches/fix_ad_flag b/debian/patches/fix_ad_flag deleted file mode 100644 index a2e4862..0000000 --- a/debian/patches/fix_ad_flag +++ /dev/null @@ -1,15 +0,0 @@ -honour the Ad flag in newsfeeds - -http://inn.eyrie.org/viewcvs/branches/2.4/innd/art.c?r1=7748&r2=7936&pathrev=7936&view=patch - ---- 2.4/innd/art.c 2008/04/06 13:49:56 7748 -+++ 2.4/innd/art.c 2008/07/20 10:20:41 7936 -@@ -1725,7 +1725,7 @@ - !DISTwantany(sp->Distributions, list)) - /* Not in the site's desired list of distributions. */ - continue; -- if (sp->DistRequired && list == NULL) -+ if (sp->DistRequired && (list == NULL || *list == NULL)) - /* Site requires Distribution header and there isn't one. */ - continue; - diff --git a/debian/patches/fix_body_regexps b/debian/patches/fix_body_regexps deleted file mode 100644 index 9a0aedd..0000000 --- a/debian/patches/fix_body_regexps +++ /dev/null @@ -1,82 +0,0 @@ -Fix the correct handling of bodies (Perl regexps were sometimes -not properly working on SV * bodies). We now use a shared string. -For Perl < 5.7.1, fall back to a copy of such bodies. At least, -that method is reliable, even though it were 17% slower. - -http://inn.eyrie.org/viewcvs/branches/2.4/include/ppport.h?r1=7237&r2=7951&pathrev=7951&view=patch -http://inn.eyrie.org/viewcvs/branches/2.4/innd/perl.c?r1=7815&r2=7951&pathrev=7951&view=patch - ---- 2.4/innd/perl.c 2008/05/05 08:43:58 7815 -+++ 2.4/innd/perl.c 2008/08/05 19:41:17 7951 -@@ -69,7 +69,6 @@ - CV * filter; - int i, rc; - char * p; -- static SV * body = NULL; - static char buf[256]; - - if (!PerlFilterActive) return NULL; -@@ -87,23 +86,19 @@ - } - - /* Store the article body. We don't want to make another copy of it, -- since it could potentially be quite large. Instead, stash the -- pointer in the static SV * body. We set LEN to 0 and inc the -- refcount to tell Perl not to free it (either one should be enough). -- Requires 5.004. In testing, this produced a 17% speed improvement -- over making a copy of the article body for a fairly heavy filter. */ -+ * since it could potentially be quite large. In testing, this produced -+ * a 17% speed improvement over making a copy of the article body -+ * for a fairly heavy filter. -+ * Available since Perl 5.7.1, newSVpvn_share allows to avoid such -+ * a copy (getting round its use for older versions of Perl leads -+ * to unreliable SV * bodies as for regexps). And for Perl not to -+ * compute a hash for artBody, we give it "42". */ - if (artBody) { -- if (!body) { -- body = newSV(0); -- (void) SvUPGRADE(body, SVt_PV); -- } -- SvPVX(body) = artBody; -- SvCUR_set(body, artLen); -- SvLEN_set(body, 0); -- SvPOK_on(body); -- (void) SvREADONLY_on(body); -- (void) SvREFCNT_inc(body); -- hv_store(hdr, "__BODY__", 8, body, 0); -+#if (PERL_REVISION == 5) && ((PERL_VERSION < 7) || ((PERL_VERSION == 7) && (PERL_SUBVERSION < 1))) -+ hv_store(hdr, "__BODY__", 8, newSVpv(artBody, artLen), 0); -+#else -+ hv_store(hdr, "__BODY__", 8, newSVpvn_share(artBody, artLen, 42), 0); -+#endif /* Perl < 5.7.1 */ - } - - hv_store(hdr, "__LINES__", 9, newSViv(lines), 0); ---- 2.4/include/ppport.h 2005/06/05 21:57:50 7237 -+++ 2.4/include/ppport.h 2008/08/05 19:41:17 7951 -@@ -150,6 +150,7 @@ - # endif - #endif - #ifndef PERL_VERSION -+# define PERL_REVISION (5) - # ifdef PERL_PATCHLEVEL - # define PERL_VERSION PERL_PATCHLEVEL - # else -@@ -162,7 +163,7 @@ - # define ERRSV perl_get_sv("@",false) - #endif - --#if (PERL_VERSION < 4) || ((PERL_VERSION == 4) && (PERL_SUBVERSION <= 4)) -+#if (PERL_REVISION == 5) && ((PERL_VERSION < 4) || ((PERL_VERSION == 4) && (PERL_SUBVERSION <= 4))) - # define PL_sv_undef sv_undef - # define PL_sv_yes sv_yes - # define PL_sv_no sv_no -@@ -174,7 +175,7 @@ - # define PL_copline copline - #endif - --#if (PERL_VERSION < 5) -+#if (PERL_REVISION == 5) && (PERL_VERSION < 5) - # undef dTHR - # ifdef WIN32 - # define dTHR extern int Perl___notused diff --git a/debian/patches/no-makedbz-on-install b/debian/patches/no-makedbz-on-install deleted file mode 100644 index 63b3f65..0000000 --- a/debian/patches/no-makedbz-on-install +++ /dev/null @@ -1,11 +0,0 @@ ---- a/site/Makefile -+++ b/site/Makefile -@@ -116,7 +116,7 @@ config: $(ALL) - ## Don't use parallel rules -- we want this to be viewed carefully. - install: all $(PAUSE) install-config $(RELOAD_AND_GO) - reload-install: all pause install-config reload go --install-config: update $(REST_INSTALLED) $(SPECIAL) -+install-config: update $(REST_INSTALLED) #$(SPECIAL) - - ## Install scripts, not per-host config files. - update: all $(MOST_INSTALLED) diff --git a/debian/patches/nocem-gpg-import b/debian/patches/nocem-gpg-import deleted file mode 100644 index 0c15727..0000000 --- a/debian/patches/nocem-gpg-import +++ /dev/null @@ -1,28 +0,0 @@ ---- a/control/perl-nocem.in -+++ b/control/perl-nocem.in -@@ -521,7 +521,9 @@ Processing NoCeM notices is easy to set - Import the keys of the NoCeM issuers you trust in order to check - the authenticity of their notices. You can do: - -- gpg --no-default-keyring --primary-keyring /pgp/ncmring.gpg --import -+ gpg --no-default-keyring --primary-keyring /pgp/ncmring.gpg \ -+ --no-options --allow-non-selfsigned-uid --no-permission-warning \ -+ --batch --import - - where is the value of the I parameter set in F - and the file containing the key(s) to import. The keyring ---- a/doc/man/perl-nocem.8 -+++ b/doc/man/perl-nocem.8 -@@ -157,8 +157,10 @@ Processing NoCeM notices is easy to set - Import the keys of the NoCeM issuers you trust in order to check - the authenticity of their notices. You can do: - .Sp --.Vb 1 --\& gpg \-\-no\-default\-keyring \-\-primary\-keyring /pgp/ncmring.gpg \-\-import -+.Vb 3 -+\& gpg \-\-no\-default\-keyring \-\-primary\-keyring=/etc/news/pgp/ncmring.gpg \e -+\& \-\-no\-options \-\-allow\-non\-selfsigned\-uid \-\-no\-permission\-warning \e -+\& \-\-batch \-\-import - .Ve - .Sp - where is the value of the \fIpathetc\fR parameter set in \fIinn.conf\fR diff --git a/debian/patches/series b/debian/patches/series deleted file mode 100644 index 9263031..0000000 --- a/debian/patches/series +++ /dev/null @@ -1,20 +0,0 @@ -# backported fixes -fix_ad_flag -fix_body_regexps - -# waiting to be merged upstream - -# debian-specific -nocem-gpg-import -debian-paths - -# packaging-related -configure-hostname -no-makedbz-on-install -u_innreport_misc -u_right_length -u_status_init_ip -u_tls_duplicate_reply -u_xhdr_permissions -u_xover_duplicate_reply -typo_inn_conf_man diff --git a/debian/patches/typo_inn_conf_man b/debian/patches/typo_inn_conf_man deleted file mode 100644 index 39c2a91..0000000 --- a/debian/patches/typo_inn_conf_man +++ /dev/null @@ -1,11 +0,0 @@ ---- a/doc/man/inn.conf.5 -+++ b/doc/man/inn.conf.5 -@@ -480,7 +480,7 @@ this parameter must be set if \fIenableo - .el .IP "\f(CWbuffindexed\fR" 4 - .IX Item "buffindexed" - Stores overview data and index information into buffers, which are --preconfigured files defined in \fIbuffinedexed.conf\fR. \f(CW\*(C`buffindexed\*(C'\fR never -+preconfigured files defined in \fIbuffindexed.conf\fR. \f(CW\*(C`buffindexed\*(C'\fR never - consumes additional disk space beyond that allocated to these buffers. - .ie n .IP """tradindexed""" 4 - .el .IP "\f(CWtradindexed\fR" 4 diff --git a/debian/patches/u_innreport_misc b/debian/patches/u_innreport_misc deleted file mode 100644 index 0b4e7d2..0000000 --- a/debian/patches/u_innreport_misc +++ /dev/null @@ -1,136 +0,0 @@ -Bug-fixes for innreport: - - Test for the existence of 'img_dir' instead of 'html_dir' in innreport; - - Trailing comma after %innfeed_spooled with "Outgoing feeds (innfeed) - by Articles"; - - Column "Total" of "Outgoing feeds (innfeed) by Volume" tries to add - two hashes which evaluates to a constant 0; - - Gracefully handle undefined hash elements in "NNRP readership statistics - (by domain)"; - - Also added two error messages generated by perl-nocem. - -http://inn.eyrie.org/viewcvs/branches/2.4/scripts/innreport.in?r1=8142&r2=8141&pathrev=8142&view=patch -http://inn.eyrie.org/viewcvs/branches/2.4/samples/innreport.conf.in?r1=7945&r2=7944&pathrev=7945&view=patch -http://inn.eyrie.org/viewcvs/branches/2.4/scripts/innreport_inn.pm?r1=7945&r2=7944&pathrev=7945&view=patch - ---- 2.4/scripts/innreport.in 2008/10/05 23:47:25 8141 -+++ 2.4/scripts/innreport.in 2008/10/07 17:08:32 8142 -@@ -212,7 +212,7 @@ - $IMG_pth = $ref{'webpath'} if defined $ref{'webpath'}; - - $IMG_dir = $HTML_dir . "/" . $IMG_pth -- if (defined $output{'default'}{'html_dir'} || -+ if (defined $output{'default'}{'img_dir'} || - defined $ref{'w'} || defined $ref{'webpath'}) - && - (defined $output{'default'}{'html_dir'} || ---- 2.4/samples/innreport.conf.in 2008/08/03 07:30:03 7944 -+++ 2.4/samples/innreport.conf.in 2008/08/03 07:47:10 7945 -@@ -1267,7 +1267,7 @@ - data { - name "Spooled"; - color "#AF00FF"; -- value "%innfeed_spooled,"; -+ value "%innfeed_spooled"; - }; - }; - }; -@@ -1347,12 +1347,6 @@ - color "#FFAF00"; - value "%innfeed_rejected_size"; - }; -- data { -- name "Total"; -- color "#00FF00"; -- value "%innfeed_accepted_size + -- %innfeed_rejected_size"; -- }; - }; - }; - -@@ -2116,8 +2110,8 @@ - name "Rej"; - format_name "%4s"; - format "%4d"; -- value "$nnrpd_post_rej{$key} + -- $nnrpd_post_error{$key}"; -+ value "($nnrpd_post_rej{$key}||0) + -+ ($nnrpd_post_error{$key}||0)"; - total "total(%nnrpd_post_rej) + - total(%nnrpd_post_error)"; - }; -@@ -2179,8 +2173,8 @@ - name "Rej"; - format_name "%4s"; - format "%4d"; -- value "$nnrpd_dom_post_rej{$key} + -- $nnrpd_dom_post_error{$key}"; -+ value "($nnrpd_dom_post_rej{$key}||0) + -+ ($nnrpd_dom_post_error{$key}||0)"; - total "total(%nnrpd_dom_post_rej) + - total(%nnrpd_dom_post_error)"; - }; ---- 2.4/scripts/innreport_inn.pm 2008/08/03 07:30:03 7944 -+++ 2.4/scripts/innreport_inn.pm 2008/08/03 07:47:10 7945 -@@ -440,8 +440,8 @@ - # The exact timers change from various versions of INN, so try to deal - # with this in a general fashion. - if ($left =~ m/^\S+\s+ # ME -- time\ (\d+)\s+ # time -- ((?:\S+\ \d+\(\d+\)\s*)+) # timer values -+ time\s(\d+)\s+ # time -+ ((?:\S+\s\d+\(\d+\)\s*)+) # timer values - $/ox) { - $innd_time_times += $1; - my $timers = $2; -@@ -719,8 +719,8 @@ - # ME time X nnnn X(X) [...] - return 1 if $left =~ m/backlogstats/; - if ($left =~ m/^\S+\s+ # ME -- time\ (\d+)\s+ # time -- ((?:\S+\ \d+\(\d+\)\s*)+) # timer values -+ time\s(\d+)\s+ # time -+ ((?:\S+\s\d+\(\d+\)\s*)+) # timer values - $/ox) { - $innfeed_time_times += $1; - my $timers = $2; -@@ -1459,8 +1459,8 @@ - # The exact timers change from various versions of INN, so try to deal - # with this in a general fashion. - if ($left =~ m/^\S+\s+ # ME -- time\ (\d+)\s+ # time -- ((?:\S+\ \d+\(\d+\)\s*)+) # timer values -+ time\s(\d+)\s+ # time -+ ((?:\S+\s\d+\(\d+\)\s*)+) # timer values - $/ox) { - $nnrpd_time_times += $1; - my $timers = $2; -@@ -1683,13 +1683,28 @@ - $nocem_totalids{$nocem_lastid} += $2; - return 1; - } -- if ($left =~ /bad signature from (.*)/o) { -+ if ($left =~ /Article <[^>]*>: (.*) \(ID [[:xdigit:]]*\) not in keyring/o) { -+ $nocem_badsigs{$1}++; -+ $nocem_goodsigs{$1} = 0 unless ($nocem_goodsigs{$1}); -+ $nocem_totalbad++; -+ $nocem_lastid = $1; -+ return 1; -+ } -+ if ($left =~ /Article <[^>]*>: bad signature from (.*)/o) { - $nocem_badsigs{$1}++; - $nocem_goodsigs{$1} = 0 unless ($nocem_goodsigs{$1}); - $nocem_totalbad++; - $nocem_lastid = $1; - return 1; - } -+ if ($left =~ /Article <[^>]*>: malformed signature/o) { -+ $nocem_badsigs{'N/A'}++; -+ $nocem_goodsigs{'N/A'} = 0 unless ($nocem_goodsigs{'N/A'}); -+ $nocem_totalbad++; -+ $nocem_lastid = 'N/A'; -+ return 1; -+ } -+ - return 1; - } - diff --git a/debian/patches/u_right_length b/debian/patches/u_right_length deleted file mode 100644 index b8cc72e..0000000 --- a/debian/patches/u_right_length +++ /dev/null @@ -1,15 +0,0 @@ -Bug-fix for TLS: return 1 when length is right. - -http://inn.eyrie.org/viewcvs/branches/2.4/nnrpd/tls.c?r1=8058&r2=8057&pathrev=8058&view=patch - ---- 2.4/nnrpd/tls.c 2008/09/26 23:11:47 8057 -+++ 2.4/nnrpd/tls.c 2008/09/26 23:12:49 8058 -@@ -257,7 +257,7 @@ - X509_verify_cert_error_string(err)); - - if (verify_depth >= depth) { -- ok = 0; -+ ok = 1; - verify_error = X509_V_OK; - } else { - ok = 0; diff --git a/debian/patches/u_status_init_ip b/debian/patches/u_status_init_ip deleted file mode 100644 index e91b1e3..0000000 --- a/debian/patches/u_status_init_ip +++ /dev/null @@ -1,26 +0,0 @@ -Fix a bug in the IP address displayed for localhost in innd's status file. -It was not correctly initialized (it is a local connection which does not -use any IP address). - -http://inn.eyrie.org/viewcvs/branches/2.4/innd/status.c?r1=7947&r2=7946&pathrev=7947&view=patch - ---- 2.4/innd/status.c 2008/08/03 07:50:03 7946 -+++ 2.4/innd/status.c 2008/08/03 07:55:20 7947 -@@ -153,9 +153,14 @@ - status = xmalloc(sizeof(STATUS)); - peers++; /* a new peer */ - strlcpy(status->name, TempString, sizeof(status->name)); -- strlcpy(status->ip_addr, -- sprint_sockaddr((struct sockaddr *)&cp->Address), -- sizeof(status->ip_addr)); -+ if (cp->Address.ss_family == 0) { -+ /* Connections from lc.c do not have an IP address. */ -+ memset(&status->ip_addr, 0, sizeof(status->ip_addr)); -+ } else { -+ strlcpy(status->ip_addr, -+ sprint_sockaddr((struct sockaddr *)&cp->Address), -+ sizeof(status->ip_addr)); -+ } - status->can_stream = cp->Streaming; - status->seconds = status->Size = status->DuplicateSize = 0; - status->Ihave = status->Ihave_Duplicate = diff --git a/debian/patches/u_tls_duplicate_reply b/debian/patches/u_tls_duplicate_reply deleted file mode 100644 index 1b6c01e..0000000 --- a/debian/patches/u_tls_duplicate_reply +++ /dev/null @@ -1,15 +0,0 @@ -Do not send 580 when negotiation fails (382 has already been sent). - -http://inn.eyrie.org/viewcvs/branches/2.4/nnrpd/misc.c?r1=8057&r2=8056&pathrev=8057&view=patch - ---- 2.4/nnrpd/misc.c 2008/09/26 23:02:08 8056 -+++ 2.4/nnrpd/misc.c 2008/09/26 23:11:47 8057 -@@ -544,7 +544,7 @@ - result=tls_start_servertls(0, /* read */ - 1); /* write */ - if (result==-1) { -- Reply("%d Starttls failed\r\n", NNTP_STARTTLS_BAD_VAL); -+ /* No reply because we have already sent NNTP_STARTTLS_NEXT_VAL. */ - return; - } - nnrpd_starttls_done = 1; diff --git a/debian/patches/u_xhdr_permissions b/debian/patches/u_xhdr_permissions deleted file mode 100644 index 8e876af..0000000 --- a/debian/patches/u_xhdr_permissions +++ /dev/null @@ -1,49 +0,0 @@ -XHDR and XPAT were not checking the permissions the user has to read -articles when using a message-ID. Now fixed, as well as calls to ARTclose(). - -http://inn.eyrie.org/viewcvs/branches/2.4/nnrpd/article.c?r1=8004&r2=8003&pathrev=8004&view=patch - ---- 2.4/nnrpd/article.c 2008/09/05 19:13:28 8003 -+++ 2.4/nnrpd/article.c 2008/09/06 08:49:55 8004 -@@ -688,6 +688,7 @@ - if (ac > 1) - ARTnumber = tart; - if ((msgid = GetHeader("Message-ID")) == NULL) { -+ ARTclose(); - Reply("%s\r\n", ARTnoartingroup); - return; - } -@@ -745,9 +746,9 @@ - if (!ARTopen(ARTnumber)) - continue; - msgid = GetHeader("Message-ID"); -+ ARTclose(); - } while (msgid == NULL); - -- ARTclose(); - Reply("%d %d %s Article retrieved; request text separately.\r\n", - NNTP_NOTHING_FOLLOWS_VAL, ARTnumber, msgid); - } -@@ -1008,6 +1009,12 @@ - Printf("%d No such article.\r\n", NNTP_DONTHAVEIT_VAL); - break; - } -+ if (!PERMartok()) { -+ ARTclose(); -+ Printf("%s\r\n", NOACCESS); -+ break; -+ } -+ - Printf("%d %s matches follow (ID)\r\n", NNTP_HEAD_FOLLOWS_VAL, - header); - if ((text = GetHeader(header)) != NULL -@@ -1047,8 +1054,8 @@ - SendIOb(buff, strlen(buff)); - SendIOb(p, strlen(p)); - SendIOb("\r\n", 2); -- ARTclose(); - } -+ ARTclose(); - } - SendIOb(".\r\n", 3); - PushIOb(); diff --git a/debian/patches/u_xover_duplicate_reply b/debian/patches/u_xover_duplicate_reply deleted file mode 100644 index 88a53b5..0000000 --- a/debian/patches/u_xover_duplicate_reply +++ /dev/null @@ -1,30 +0,0 @@ -Fix a bug in the replies of XOVER/XHDR/XPAT when the group is empty. -Two initial replies were sent. - -http://inn.eyrie.org/viewcvs/branches/2.4/nnrpd/article.c?r1=8000&r2=7999&pathrev=8000&view=patch - ---- 2.4/nnrpd/article.c 2008/09/03 05:41:27 7999 -+++ 2.4/nnrpd/article.c 2008/09/04 17:06:51 8000 -@@ -854,9 +854,7 @@ - - /* Parse range. */ - if (!CMDgetrange(ac, av, &range, &DidReply)) { -- if (!DidReply) { -- Reply("%d data follows\r\n", NNTP_OVERVIEW_FOLLOWS_VAL); -- Printf(".\r\n"); -+ if (DidReply) { - return; - } - } -@@ -1028,10 +1026,7 @@ - - /* Range specified. */ - if (!CMDgetrange(ac - 1, av + 1, &range, &DidReply)) { -- if (!DidReply) { -- Reply("%d %s no matches follow (range)\r\n", -- NNTP_HEAD_FOLLOWS_VAL, header ? header : "\"\""); -- Printf(".\r\n"); -+ if (DidReply) { - break; - } - } diff --git a/debian/rules b/debian/rules deleted file mode 100755 index 91d2e12..0000000 --- a/debian/rules +++ /dev/null @@ -1,198 +0,0 @@ -#!/usr/bin/make -f -SHELL+= -e - -QUILT_STAMPFN := .stamp-patched -include /usr/share/quilt/quilt.make - -D-std := $(CURDIR)/debian/inn2 -D-lfs := $(CURDIR)/debian/inn2-lfs -D = $(D-$*) -B = $(CURDIR)/build-$* - -############################################################################## -# this code deals with building a second inn2-lfs package from the same -# source, but only on 32 bit architectures -# Ideally new future 32 bit architectures should not bother with inn2-lfs -# and just enable LFS by default. - -DEB_HOST_ARCH ?= $(shell dpkg-architecture -qDEB_HOST_ARCH) -ifeq ($(DEB_HOST_ARCH),$(filter $(DEB_HOST_ARCH),amd64 ia64 ppc64 s390x)) -# 64 bit std package -FLAVORS := std -else ifeq ($(DEB_HOST_ARCH),$(filter $(DEB_HOST_ARCH),armel)) -# 32 bit LFS std package -FLAVORS := std -std_configure_flags = --enable-largefiles -else -# 32 bit std package and 32 bit LFS lfs package -FLAVORS := std lfs -lfs_configure_flags = --enable-largefiles -endif - -std_dh_clean_opts = -pinn2 -pinn2-inews -p inn2-dev -lfs_dh_clean_opts = -pinn2-lfs -std_dh_movefiles_opts = -pinn2 -pinn2-inews -p inn2-dev -lfs_dh_movefiles_opts = -pinn2-lfs -pinn2-lfs-inews -p inn2-lfs-dev - -ifeq ($(FLAVORS),std) -no_package := --no-package=inn2-lfs -endif - -# the upstream source needs to be copied in the flavor-specific build dirs -src_files := $(shell find . -maxdepth 1 \ - -not -name . -and -not -name debian -and -not -name .pc \ - -and -not -name 'build-*' -and -not -name '.stamp-*') - -############################################################################## -DEB_HOST_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_HOST_GNU_TYPE) -DEB_BUILD_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_BUILD_GNU_TYPE) -ifeq ($(DEB_BUILD_GNU_TYPE),$(DEB_HOST_GNU_TYPE)) - configure_flags += --build $(DEB_HOST_GNU_TYPE) -else - configure_flags += --build $(DEB_BUILD_GNU_TYPE) --host $(DEB_HOST_GNU_TYPE) -endif - -clean: unpatch - rm -rf .stamp-* build-* - [ ! -f Makefile.global ] || $(MAKE) distclean - # delete packages which are not in control but are built anyway - rm -rf debian/inn2-lfs-dev/ debian/inn2-lfs-inews/ - # delete the cloned debhelper configuration and logs - find debian -maxdepth 1 -name 'inn2-lfs*' -not -type d -print0 \ - | xargs --no-run-if-empty -0 rm - dh_clean - -configure: $(addprefix .stamp-configure-, $(FLAVORS)) -.stamp-configure-%: $(QUILT_STAMPFN) - dh_testdir - mkdir -p $B - for dir in $(src_files); do cp -ldpR $$dir $B; done - cd $B && \ - _PATH_PERL=/usr/bin/perl \ - ac_cv_path__PATH_AWK=awk \ - ac_cv_path__PATH_EGREP=egrep \ - ac_cv_path__PATH_SED=sed \ - ac_cv_path__PATH_SORT=sort \ - ac_cv_path__PATH_UUX=uux \ - ac_cv_path_PATH_GPGV=/usr/bin/gpgv \ - ac_cv_path_GETFTP=wget \ - ac_cv_search_dbm_open=-ldb \ - LDFLAGS="-Wl,--as-needed $(LDFLAGS)" \ - ./configure \ - --with-perl \ - --enable-ipv6 \ - --prefix=/usr/lib/news \ - --mandir=/usr/share/man \ - --includedir=/usr/include/inn \ - --with-db-dir=/var/lib/news \ - --with-etc-dir=/etc/news \ - --with-filter-dir=/etc/news/filter \ - --with-lib-dir=/usr/lib/news \ - --with-log-dir=/var/log/news \ - --with-run-dir=/var/run/news \ - --with-spool-dir=/var/spool/news \ - --with-tmp-dir=/var/spool/news/incoming/tmp \ - --with-berkeleydb=/usr \ - --with-kerberos=/usr \ - --with-sendmail=/usr/sbin/sendmail \ - $($*_configure_flags) $(configure_flags) - cd $B && \ - mkdir ssl/ ssl/nnrpd/ && \ - cd ssl/ && \ - ln -s ../Makefile.global ../include ../storage ../history . && \ - cd nnrpd/ && ln -s ../../nnrpd/* . - touch $@ - -build: $(addprefix .stamp-build-, $(FLAVORS)) -.stamp-build-%: .stamp-configure-% - dh_testdir - cd $B && $(MAKE) - cd $B/ssl/nnrpd/ && $(MAKE) \ - SSLLIB='-L/usr/lib -lssl -lcrypto -ldl' SSLINC='-DHAVE_SSL=1' - touch $@ - -install1-%: .stamp-build-% - dh_testdir - dh_testroot - dh_clean -k $($*_dh_clean_opts) - - cd $B && $(MAKE) install DESTDIR=$D - sh -e extra/dh_cloneconf inn2 inn2-lfs - - dh_movefiles $($*_dh_movefiles_opts) --sourcedir=$(subst $(CURDIR)/,,$D) - -# move back this one - mv $D-dev/usr/share/man/man3/uwildmat.3 $D/usr/share/man/man3/ - -# remove assorted crap and -# make sure we don't ship active, active.times, newsgroups in place! - cd $D/etc/news/filter && rm -f *.py *.tcl - rm -rf $D/usr/lib/news/bin/simpleftp $D/usr/share/man/man1/simpleftp.1\ - $D/usr/lib/news/doc/ $D/var/lib/news/* \ - $D/usr/include/ - - mv $D/usr/share/man/man1/startinnfeed.1 \ - $D/usr/share/man/man8/startinnfeed.8 - - cp $B/ssl/nnrpd/nnrpd $D/usr/lib/news/bin/nnrpd-ssl - install -m 755 extra/buildinnkeyring extra/ginpaths2 \ - $D/usr/lib/news/bin/ - install -m 755 contrib/showtoken.in $D/usr/lib/news/bin/showtoken - install -m 755 extra/bunbatch $D-inews/usr/lib/news/bin/rnews.libexec/ - - install -m 644 extra/send-uucp.cf extra/sasl.conf $D/etc/news/ - - mkdir $D/var/log/news/path - -install2: $(addprefix install1-, $(FLAVORS)) - dh_link - dh_installchangelogs NEWS - dh_installdocs - dh_installexamples - dh_installinit --noscripts --init-script=inn2 - dh_installcron - dh_installlogcheck - dh_compress - dh_fixperms \ - -Xusr/lib/news/bin/inndstart -Xusr/lib/news/bin/startinnfeed - # some files are not writeable when installed by make install - dh_strip - -install3-%: install2 - chown root:news $D-inews/etc/news/passwd.nntp - chmod 640 $D-inews/etc/news/passwd.nntp - - chmod -x $D/usr/lib/news/bin/control/*.pl - chmod +rw \ - $D/usr/lib/news/bin/inndstart \ - $D/usr/lib/news/bin/startinnfeed - - chown news:uucp $D-inews/usr/lib/news/bin/rnews - chmod 4755 $D-inews/usr/lib/news/bin/rnews - - chown -R news:news $D/var/spool/news/ $D/var/lib/news/ \ - $D/var/run/news/ $D/var/log/news/ - chmod -R g+w $D/var/spool/news/ $D/var/lib/news/ \ - $D/var/run/news/ $D/var/log/news/ - -install4-std: install3-std - -# lfs-specific: rename some files installed by debhelper -install4-lfs: install3-lfs - for file in /etc/logcheck/ignore.d.server/inn2 /etc/logcheck/violations.ignore.d/inn2 /etc/cron.d/inn2; do \ - mv $(D-lfs)$$file-lfs $(D-lfs)$$file; \ - done - -install5: $(addprefix install4-, $(FLAVORS)) - dh_installdeb - dh_md5sums - dh_shlibdeps - dh_gencontrol $(no_package) -- \ - -VPERLAPI=$$(perl -MConfig -e 'print "perlapi-$$Config{version}"') - dh_builddeb $(no_package) - -binary-arch: install5 - -binary: binary-arch - -.PHONY: clean configure build binary-arch binary install% diff --git a/debian/watch b/debian/watch deleted file mode 100644 index 39ffdf8..0000000 --- a/debian/watch +++ /dev/null @@ -1,3 +0,0 @@ -version=3 -opts=dversionmangle=s/r$// \ -ftp://ftp.isc.org/isc/inn/inn-([\d\.]+)\.tar\.gz diff --git a/doc/GPL b/doc/GPL deleted file mode 100644 index 264509e..0000000 --- a/doc/GPL +++ /dev/null @@ -1,347 +0,0 @@ -[ Please note that the only portions of INN covered by this license are - those files explicitly noted as being under the GPL in LICENSE. It is - a requirement of the GPL, however, that a copy of it be distributed - with software licensed under it, and some stand-alone programs that - are distributed with INN are covered under the GPL. ] - - - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc. - 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Library General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) 19yy - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) 19yy name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - , 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Library General -Public License instead of this License. diff --git a/doc/IPv6-info b/doc/IPv6-info deleted file mode 100644 index 4d5c02a..0000000 --- a/doc/IPv6-info +++ /dev/null @@ -1,47 +0,0 @@ -Notes about IPv6 support in INN: - - This is $Revision: 5416 $, dated $Date: 2002-04-14 07:05:36 -0700 (Sun, 14 Apr 2002) $. - - This document contains some notes about the status of IPv6 support in - INN (see also the parts of the code marked FIXME): - - -Things that will break if you compile with --enable-ipv6: - - * innd can only be started via inndstart - * IP_OPTIONS are not cleared for any incoming connections to innd even - over IPv4 - - - -Some comments as of the completion of the original patch: - - Date: Wed, 13 Feb 2002 00:10:59 -0500 (EST) - From: Nathan Lutchansky - To: Jeffrey M. Vinocur - Subject: IPv6 patch notes - - The IPv6 patch is based directly on Marco d'Itri's IPv6 patch of - 2001-03-01 that was posted last year to the inn-workers list. The - patch applied fairly cleanly to a working copy from 2002-02-04, and - the resulting tree was used as the basis for my work. - - Modifications by Marco and myself were made so that if IPv6 support is - not explicitly enabled with the --enable-ipv6 flag to the configure - script, the old networking code will be used. Hopefully, nobody will - notice any problems with the default configuration, although some - changes have been made to data structures even when IPv6 is disabled. - - The original patch added IPv6 support to innd and inndstart, and the - auth_pass program. I have added support to nnrpd, innfeed, and the - ident auth program. There is no IPv6 support for imapfeed and other - auxiliary programs like the radius auth backend. - - Marco's patch made use of several preprocessor defines for - configuration but the defines were hand-coded, so I added the - corresponding tests the the configuration script. I make no - guarantees that the configure script will catch all possible - non-portable behavior; the IPv6 API standardization process has left - quite a wake of incompatible API implementations over the years. - -Nathan - diff --git a/doc/checklist b/doc/checklist deleted file mode 100644 index 144c0ee..0000000 --- a/doc/checklist +++ /dev/null @@ -1,210 +0,0 @@ -Introduction - - $Id: checklist 5912 2002-12-03 05:31:11Z vinocur $ - - This is an installation checklist written by Rebecca Ore, intended to be - the beginning of a different presentation of the information in INSTALL, - since getting started with installing INN can be complex. Further - clarifications, updates, and expansion are welcome. - -Setup - - * Make sure there is a "news" user (and a "news" group) - - * Create a home directory for news (perhaps /usr/local/news/) and make - sure it (and subdirectories) are owned by "news", group "news". - - You want to be careful that things in that directory stay owned by - "news" -- but you can't just "chown -R news.news" after the install, - because you may have binaries that are SUID root. You can do the - build as any user, because "make install" will set the permissions - correctly. After that point, though, you may want to "su news" to - avoid creating any files as root. (For routine maintenance once INN - is working, you can generally be root.) - - * If necessary, add ~news/bin to the news user's path and ~news/man to - the news user's manpath in your shell config files. (You may want - to do this, especially the second part, on your regular account; the - manpages are very useful.) - - You can do this now or later, but you will certainly want the - manpages to help with configuring INN. - - For bash, try: - - PATH=~news/bin:$PATH - export PATH - MANPATH=~news/man:$MANPATH - export MANPATH - - or csh: - - setenv PATH ~news/bin:$PATH - setenv MANPATH ~news/man:$MANPATH - - although if you don't already have MANPATH set, the above may give - an error or override your defaults (making it so you can only read - the news manpages); if "echo $MANPATH" does not give some reasonable - path, you'll need to look up what the default is for your system - (such as /usr/man or /usr/share/man). - -Compile - - * Download the INN tarball and unpack. - - * Work out configure options ("./configure --help" for a list). If - you aren't working out of /usr/local/news, or want to put some files - on a different partition, you can set the directories now (or later - in inn.conf if you change your mind). - - You probably want "--with-perl". If you're not using NetBSD with - cycbuffs or OpenBSD, perhaps "--with-tagged-hash". You might want - to compile in SSL and Berkeley DB, if your system supports them. - - ./configure --with-perl ... - make - - su - make install - - (If you do the last step as root, all of the ownerships and - permissions will be correct.) - -Configure - - * Find INSTALL and open a separate window for it. A printout is - probably a good idea -- it's long but very helpful. Any time the - instructions below ask you to make a decision, you can probably find - help in INSTALL. - - * Now it's time to work on the files in ~news/etc/. Start with - inn.conf; you must fill in the default moderators address, your - fully qualified domain names and path. Fill in all the blanks. - Change the file descriptor limits to something like 500. - - * If using cycbuffs (the CNFS storage method), open cycbuff.conf in - one window and a shell in another to create the cycbuff as described - in INSTALL. As you create them, record in cycbuff.conf the paths - and sizes. Save paths and sizes in a separate text file on another - machine in case you ever blow away the wrong file. - - Name the metacycbuff, then configure storage.conf. - - * In storage.conf, be sure that all sizes of articles can be - accomodated. If you want to throw away large articles, do it - explicitly by using the "trash" storage method. - - * The default options in expire.ctl work fine if you have cycbuffs, if - not, configure to suit. - - * Check over moderators and control.ctl. - - * Run ~news/bin/inncheck and fix anything noted. - - Inncheck gives a rough check on the appropriateness of the - configuration files as you go. (It's the equivalent of "perl -cw - yourfile.pl" for perl scripts.) - - Note that inncheck is very conservative about permissions; there's - no reason most of the config files can't be world-readable if you - prefer that. - - * Import an active file (~news/db/active) and run inncheck again. - Change where noted (there's a gotcha in the ISC's active list 000000 - 000000 (whatever number of zeros) should be 0000000 00000001). - - * Create empty initial db files. Be sure these end up owned by news. - - cd ~news/db - - touch newsgroups - touch active.times - - touch history - ~news/bin/makedbz -i - mv history.n.hash history.hash - mv history.n.index history.index - mv history.n.dir history.dir - - chmod 644 * - - * Create the cron jobs and make the changes to your system's - syslog.conf as noted in INSTALL. Also create the cron job for - nntpsend if you've chosen that over innfeed. - - Create the log files. - - * For the time being, we can see if everything initially works without - worrying about feeds or reader access. - -Run - - * Start inn by running ~news/bin/rc.news *as the news user*. - - Check ~news/log/news.notice to see if everything went well, also use - "ps" to see if innd is running. - - "telnet localhost 119" and you should see either a welcome banner or - a "no permission to talk" message. If not, investigate. - - * "man ctlinnd" now; you'll use "ctlinnd reload" as you complete your - configuration. - -Feeds - - All of this can be done while INN is running. - - * To get your incoming feeds working, edit incoming.conf. When done, - "ctlinnd reload incoming.conf reason" (where "reason" is some text - that will show up in the logs, anything will do). - - * To get your outgoing feeds working, decide whether to use innfeed or - nntpsend. Edit newsfeeds and either innfeed.conf or nntpsend.ctl. - - In newsfeeds, if using innfeed, use the option which doens't require - you to do a separate innfeed configuration unless you know more than - I do. - - Then "ctlinnd reload newsfeeds reason". - - * In readers.conf, remember that auth and access can be separated. - - Begin with auth. Your auth for password users could look like this: - - auth "foreignokay" { - auth: "ckpasswd -d ~news/db/newsusers" - default: "" - } - - There is a perl script in the ckpasswd man page if you want to do - authentications by password and have the appropriate libraries. - Copy it to ~news/bin, name the file something like makepasswd.pl and - change the internal paths to whatever you're using and wherever - you're putting the newsusers database. The standard Apache - "htpasswd" tool also works just fine to create INN password files. - - Follow with the access stanzas. Something for people with - passwords: - - access "generalpeople" { - users: "*" - newsgroups: "*,!junk,!control,!control.*" - } - - And then something like one of the following two, depending on - whether unauthenticated users get any access: - - access "restrictive" { - users: "" - newsgroups: "!*" - } - - access "readonly" { - users: "" - read: "local.*" - post: "!*" - } - - You don't need to reload anything after modifying readers.conf; - every time an nnrpd launches it reads its configuration from disk. - diff --git a/doc/compliance-nntp b/doc/compliance-nntp deleted file mode 100644 index 403e104..0000000 --- a/doc/compliance-nntp +++ /dev/null @@ -1,320 +0,0 @@ -$Id: compliance-nntp 6817 2004-05-18 09:25:55Z rra $ - -The following are outstanding issues regarding INN's compliance with the -NNTP standard. The reference documents used in this analysis are the -current NNTP IETF Working Group draft (draft-ietf-nntpext-base-15.txt at -the time of the last check of this audit) or RFC 2980, not RFC 977 (which -is woefully out of date). - -This file documents only compliance issues with the latest version of the -standard NNTP protocol. It does not cover INN's private extensions or -INN's implementation of widely available extensions not documented in the -NNTP standard. Specifically, it does not cover the extensions listed in -RFC 2980. - ------------------------------- - - Summary: innd doesn't require whitespace between commands and arguments - Standard: draft-ietf-nntpext-base-15.txt, section 4 - Version: 1.0 to CURRENT 2002-12-26 -Reference: innd/nc.c NCproc() and command handlers - Severity: Accepts invalid input - -The standard states: - - Keywords and arguments MUST be each separated by one or more US-ASCII - SPACE or US-ASCII TAB characters. - -This is not checked in NCproc or in the individual command handlers in -innd. Commands followed immediately by their argument will be accepted by -innd. For example: - - stat<9k6vjk.hg0@example.com> - 223 0 @0301543531000000000000079AAE0000006A@ - -Impact: Should one command be a prefix of another, innd could dispatch -the handling of the command to the wrong handler, treating the remainder -of the command verb as an argument. This laxness also encourages sloppy -client code. Internally, the lack of argument parsing in NCproc also -results in code duplication in all of the command handlers. - -Suggested fix: Lift the argument parsing code into a function called from -NCproc, breaking the command line into a vector of command and arguments. -This will work for all commands implemented by innd and will simplify the -implementation of command handlers, as well as fixing this problem. This -is what nnrpd already does. - -Impact of fix: It's possible that some serving code is relying on this -behavior and not sending spaces after commands. Fixing this problem would -break interoperability with that code. - ------------------------------- - - Summary: INN doesn't check argument length - Standard: draft-ietf-nntpext-base-15.txt, section 4 - Version: 1.0 to CURRENT 2002-12-26 -Reference: innd/nc.c and nnrpd/nnrpd.c - Severity: Accepts invalid input - -The standard says: - - Arguments MUST NOT exceed 497 octets. - -This is not checked by either innd or nnrpd, although both do check that -the command itself does not exceed 512 octets. - -Impact: Small. May accept invalid commands in extremely rare edge cases. - -Suggested fix: Probably not worth fixing separately, although if standard -command parsing code is written to handle both innd and nnrpd, it wouldn't -hurt to check this along with everything else. - ------------------------------- - - Summary: Reply codes other than x9x used for private extensions - Standard: draft-ietf-nntpext-base-15.txt, section 4.1 - Version: 1.0 to CURRENT 2002-12-26 -Reference: include/nntp.h - Severity: Violates SHOULD - -The standard says: - - Response codes not specified in this standard MAY be used for any - installation-specific additional commands also not specified. These - SHOULD be chosen to fit the pattern of x9x specified above. - -INN uses quite a few response codes that do not fit this pattern for -various extensions. Some of these will likely later be standardized with -the response codes that INN uses (the streaming commands, the -authentication reply codes, and possibly the STARTTLS reply codes), but -the rest (XGTITLE, MODE CANCEL, and XBATCH) should have used response -codes in the x9x range. - -Impact: Additional ambiguity over the meaning of reply codes, as those -reply codes could later be standardized as the reply codes for other -commands. - -Suggested fix: For XGTITLE and probably XBATCH, there is no way to fix -this now. Changing the reply codes would break all existing -implementations. It may still be possible to change the reply codes for -MODE CANCEL (which should probably be MODE XCANCEL), but it may not be -worth the effort. - ------------------------------- - - Summary: innd may return 480 instead of 500 for unrecognized commands - Standard: draft-ietf-nntpext-base-15.txt, section 4.1.1 - Version: 1.0 to CURRENT 2002-12-26 -Reference: innd/nc.c NCauthinfo() - Severity: Violates MUST - -The standard says: - - If the command is not recognized, or it is an optional command or - extension that is not implemented by the server, the response code 500 - MUST be returned. - -In innd, if the connection is determined to need authentication, all -incoming commands other than MODE are handed off to NCauthinfo() rather -than their normal command handlers. NCauthinfo() responds with a 480 -reply code to anything other than AUTHINFO USER, AUTHINFO PASS, or QUIT. - -Impact: Unlikely to cause problems in practice, but may confuse clients -that don't understand the rarely used innd-level authentication -mechanisms. - -Suggested fix: Restructure the command table so that each command also -has a flag indicating whether it requires authentication for peers that -are required to authenticate. (Some commands, like HELP and MODE READER, -should be allowed without authentication.) Then eliminate the special -casing of the state CSgetauth (it may be better to store whether the peer -has authenticated in the channel rather than in the channel state) and the -special handling in NCauthinfo. This should also simplify the code. - ------------------------------- - - Summary: innd always sends 200 for an accepted connection - Standard: draft-ietf-nntpext-base-15.txt, section 7.1 - Version: 1.0 to CURRENT 2002-12-26 -Reference: innd/nc.c NCsetup() and rc.c RCreader() - Severity: Violates MUST - -The standard says: - - If the server will accept further commands from the client including - POST, the server MUST present a 200 greeting code. If the server will - accept further commands from the client, but it is not authorized to - post articles using the POST command, the server MUST present a 201 - greeting code. - -The implication is that the greeting code from innd (which doesn't -implement POST and therefore is never going to allow it) should always be -201, at least for the case where innd never spawns nnrpd. In the case -where innd spawns nnrpd, it's unclear what the greeting code should be. - -The current implementation nevers send 201 unless one knows for certain -that the connection will never be allowed to issue a POST command, which -means that innd always sends 200. - -It's unknown whether there is any transit news software that would have -difficulties with a 201 greeting. Both innxmit and innfeed handle it -correctly in CURRENT 2001-07-04 and NNTPconnect() handles it correctly in -INN 1.0, so it seems likely that if any such software exists, it's rare. - -Impact: It's almost certain that the current innd behavior isn't hurting -anything. Even a confused client that thought 200 meant that it could -send a POST command would then try and be rejected with no damage done. - -Suggested fix: The purpose of this return code is to give a hint to a -reading client indicating whether it should even attempt POST, since -attempting it may involve a lot of work by the user only to have the post -rejected. It's only relevant to reading connections, not to transit -connections. - -It's known that some clients, upon seeing a 201 response, will never -attempt POST, even if MODE READER then returns 200. Therefore innd, when -handing off connections to nnrpd, must return 200 to not confuse a client -that will later send MODE READER. For connections where innd won't do -that handoff, it makes sense to always send 201 if all transit feeds can -handle that and won't interpret it as unwillingness to accept IHAVE or -streaming feeds. - -RCreader() should therefore be modified to send 201 if noreader is set, -and otherwise send 200. - -Impact of fix: Any feeding software that didn't consider 201 to be a -valid greeting would be unable to feed a fixed innd unless that innd also -allowed reading connections. - ------------------------------- - - Summary: innd doesn't support LIST EXTENSIONS - Standard: draft-ietf-nntpext-base-15.txt, section 8.1 - Version: 1.0 to CURRENT 2002-12-26 -Reference: innd/nc.c NClist() - Severity: Not a violation - -Support for LIST EXTENSIONS is optional, and innd's current behavior -(returning a 500 response) is permitted by the standard, but it means that -innd cannot advertise any of the extensions that it supports. Since this -will eventually include streaming, support should be added. - -Suggested fix: Add support for LIST EXTENSIONS to NClist() as soon as -innd supports a registered extension or as soon as there is documentation -for INN's extensions that specify an extension name (beginning with X). - ------------------------------- - - Summary: nnrpd doesn't return 423 errors when there is no overview info - Standard: draft-ietf-nntpext-base-17.txt, section 10.5.1.2 - Version: 1.4 to CURRENT 2003-05-04 -Reference: nnrpd/article.c CMDxover() - Severity: Violates a MUST - -The standard says: - - If there are no articles in the range specified, a 423 response MUST be - returned. - -nnrpd (from the beginning of the XOVER command) has always returned a 224 -response with an empty multiline response instead. INN doesn't support -OVER yet so this isn't actually a bug in INN, but eventually the XOVER -implementation will also be used for OVER. - -Impact: Less information is communicated to the client about why there -are no overview records returned. An error response indicating there are -no valid articles in that range is possibly more informative. - -Suggested fix: Don't print out the initial 224 message until at least one -overview entry has been found, so that CMDxover() can print a 420 response -instead if no overview records are found. - -Impact of fix: May confuse some clients that don't expect to get 420 -errors back from overview queries. It may be necessary to do something -different for OVER (where clients should expect this behavior since OVER -is a new command) than for XOVER (where clients may be relying on the -existing behavior. - ------------------------------- - - Summary: HDR can return message IDs rather than article numbers - Standard: draft-ietf-nntpext-base-17.txt, section 10.6.1.2 - Version: 1.0 to CURRENT 2003-05-04 -Reference: nnrpd/article.c CMDpat() - Severity: Violates a protocol description - -The standard says: - - The line consists of the article number, a US-ASCII space, and then the - contents of the header (without the header name or the colon and space - that follow it) or metadata item. If the article is specified by - message-id rather than by article range, the article number is given as - "0". - -nnrpd instead returns the message ID as the first word of the line when -HDR is given a message ID argument. - -Impact: A client may not be able to parse the output of HDR correctly, -since the first word is not a number. - -Suggested fix: Change the code to return 0 as the first word instead of -the message ID, per the standard. - -Impact of fix: Clients that are expecting the message ID may be -confused. - ------------------------------- - - Summary: innd improperly caches DNS returns - Standard: draft-ietf-nntpext-base-15.txt, section 14.4 - Version: 1.0 to CURRENT 2002-12-26 -Reference: innd/rc.c RCreadfile() and elsewhere - Severity: Violates a MUST - -The standard says: - - If NNTP clients or servers cache the results of host name lookups in - order to achieve a performance improvement, they MUST observe the TTL - information reported by DNS. - -innd caches DNS lookups when reading incoming.conf and doesn't refresh its -knowledge of DNS except when incoming.conf is reloaded. - -Impact: An explicit reload is required whenever the IP address of any -peer changes, and in the presence of network renumbering innd is -vulnerable to spoofing if DNS is the only authentication mechanism used. - -Suggested fix: This is hard to fix without unacceptable performance -impact. The only good fix is to either fork a separate helper process to -do DNS lookups (since gethostbyname may block for essentially an -arbitrarily long period) or to use the direct resolver library so that one -can get access to a file descriptor and throw it into the select loop. -Either way, this requires keeping a DNS file descriptor in the main select -loop and updating knowledge of DNS periodically, which is a substantial -amount of additional complexity. - ------------------------------- - - Summary: innd doesn't diagnose repeated AUTHINFO USER commands - Standard: RFC 2980, section 3.1.1 - Version: 1.0 to CURRENT 2002-12-26 -Reference: innd/nc.c NCauthinfo() - Severity: Violates a protocol description - -RFC 2980 says: - - The 482 code will also be returned when the AUTHINFO commands are not - entered in the correct sequence (like two AUTHINFO USERs in a row, or - AUTHINFO PASS preceding AUTHINFO USER). - -innd ignores AUTHINFO USER and just always returns a 381 response, however, -since it doesn't care about the username. - -Impact: Probably none. - -Suggested fix: A long-term solution would be to add real authentication -to innd, in which case it would start caring about the authenticated -identity (and perhaps use that identity to map to an incoming.conf entry). -It's unclear if this would be worthwhile. Failing that, innd would need -to keep internal state to know whether AUTHINFO USER had already been -sent. diff --git a/doc/config-design b/doc/config-design deleted file mode 100644 index eda5bf3..0000000 --- a/doc/config-design +++ /dev/null @@ -1,121 +0,0 @@ -$Id: config-design 4805 2001-06-21 10:52:27Z rra $ - -This file is documentation of the design principles that went into INN's -configuration file syntax, and some rationale for why those principles -were chosen. - - 1. All configuration files used by INN should have the same syntax. - This was the root reason why the project was taken on in the first - place; INN developed a proliferation of configuration files, all of - which had a slightly (or greatly) different syntax, forcing the - administrator to learn several different syntaxes and resulting in a - proliferation of parsers, all with their own little quirks. - - 2. Adding a new configuration file or a new set of configuration options - should not require writing a single line of code for syntax parsing. - Code that analyzes the semantics of the configuration will of course - be necessary, but absolutely no additional code to read files, parse - files, build configuration trees, or the like should be required. - Ideally, INN should have a single configuration parser that - everything uses. - - 3. The syntax should look basically like the syntax of readers.conf, - incoming.conf, and innfeed.conf in INN 2.3. After extensive - discussion on the inn-workers mailing list, this seemed to be the - most generally popular syntax of the ones already used in INN, and - inventing a completely new syntax didn't appear likely to have gains - outweighing the effort involved. This syntax seemed sufficiently - general to represent all of the configuration information that INN - needed. - - 4. The parsing layer should *not* attempt to do semantic analysis of the - configuration; it should concern itself solely with syntax (or very - low-level semantics that are standard across all conceivable INN - configuration files). In particular, the parsing layer should not - know what parameters are valid, what groups are permitted, what types - the values for parameters should have, or what default values - parameters have. - - This principle requires some additional explanation, since it is very - tempting to not do things this way. However, the more semantic - information the parser is aware of, the less general the parser is, - and it's very easy to paint oneself into a corner. In particular, - it's *not* a valid assumption that all clients of the parsing code - will want to reduce the configuration to a bunch of structs; this - happens to be true for most clients of inn.conf, for example, but - inndstart doesn't want the code needed to reduce everything to a - struct and set default values to necessarily be executed in a - security-critical context. - - Additionally, making the parser know more semantic information either - complicates (significantly) the parser interface or means that the - parser has to be modified when the semantics change. The latter is - not acceptable, and the parser interface should be as straightforward - as possible (to encourage all parts of INN to use it). - - 5. The result of a parse of the configuration file may be represented as - a tree of dictionaries, where each dictionary corresponds to a group - and each key corresponds to a parameter setting. (Note that this does - not assume that the underlying data structure is a hash table, just - that it has dictionary semantics, namely a collection of key/value - pairs with the keys presumed unique.) - - 6. Parameter values inherit via group nesting. In other words, if a - group is nested inside another group, all parameters defined in the - enclosing group are inherited by the nested group unless they're - explicitly overriden within the nested group. (This point and point - 5 are to some degree just corollaries of point 3.) - - 7. The parsing library must permit writing as well as reading. It must - be possible for a program to read in a configuration file, modify - parameters, add and delete groups, and otherwise change the - configuration, and then write back out to disk a configuration file - that preserves those changes and still remains as faithful to the - original (possibly human-written) configuration file as possible. - (Ideally, this would extend to preserving comments, but that may be - too difficult to do and therefore isn't required.) - - 8. The parser must not limit the configuration arbitrarily. In - particular, unlimited length strings (within available memory) must - be supported for string values, and if allowable line length is - limited, line continuation must be supported everywhere that there's - any reasonable expectation that it might be necessary. One common - configuration parameter is a list of hosts or host wildmats that can - be almost arbitrarily long, and the syntax and parser must support - that. - - 9. The parser should be reasonably efficient, enough so as to not cause - an annoying wait for command-line tools like sm and grephistory to - start. In general, though, efficiency in either time or memory is - not as high of a priority as readable, straightforward code; it's - safe to assume that configuration parsing is only done on startup and - at rare intervals and is not on any critical speed paths. - -10. Error reporting is a must. It must be possible to clearly report - errors in the configuration files, including at minimum the file name - and line number where the error occurred. - -11. The configuration parser should not trust its input, syntax-wise. It - must not segfault, infinitely loop, or otherwise explode on malformed - or broken input. And, as a related point, it's better to be - aggressively picky about syntax than to be lax and attempt to accept - minor violations. The intended configuration syntax is simple and - unambiguous, so it should be unnecessary to accept violations. - -12. It must be possible to do comprehensive semantic checks of a - configuration file, including verifying that all provided parameters - are known ones, all parameter values have the correct type, group - types that are not expected to be repeated are not, and only expected - group types are used. This must *not* be done by the parser, but the - parser must provide sufficient hooks that the client program can do - this if it chooses. - -13. The parser must be re-entrant and thread-safe. - -14. The grammar shouldn't require any lookahead to parse. This is in - order to keep the parser extremely simple and therefore maintainable. - (It's worth noting that this design principle leads to the - requirement that parameter keys end in a colon; the presence of the - colon allows parameter keys to be distinguished from other syntactic - elements allowed in the same scope, like the beginning of a nested - group.) diff --git a/doc/config-semantics b/doc/config-semantics deleted file mode 100644 index 49d601e..0000000 --- a/doc/config-semantics +++ /dev/null @@ -1,79 +0,0 @@ -$Id: config-semantics 4792 2001-06-21 08:59:39Z rra $ - -Groups in a configuration file have a well-defined order, namely the order -in which the groups would be encountered in a depth-first traversal of the -parse tree. - -The supported operations on a configuration file parse tree for reading -are: - - * Search. Find the first group of a given type in a given tree. This is - done via depth-first search. - - * Next. Find the next group of a given type, starting from some group. - This is done via depth-first search. - - * Query. Look up the value of a given parameter in a given group (with - inheritance). Note that the expected type of the parameter value must - be provided by the caller; the parsing library doesn't know the types - of parameters. - - * Prune. Limit one's view of the configuration file to only a given set - of group types and everything underneath them; any other group types - encountered won't be parsed (and therefore everything under them, even - groups of the wanted type, won't be seen). - -Therefore, the *only* significance of nested group structure is parameter -inheritence and pruning. In the absence of pruning, it would always be -possible, by duplicating parameter settings that were inherited and laying -out the groups in depth-first traversal order, to transform any -configuration file into an entirely equivalent one that contains no nested -groups. This isn't true in the presence of pruning, but pruning is -intended to be used primarily for performance (ignoring the parts of the -configuration that don't apply to a given parsing library client). - -The expected way for clients to use the parsing library is to follow one -of these two access patterns: - - * Search for a particular configuration group and then query it for a set - of parameters (either one by one as they're used, or all at once to - collapse the parameters into a struct for faster access later). This - is expected to be the common pattern for finding and looking up - settings for a particular program. There will generally only be a - single group per group type for groups of this sort; it doesn't make - sense to have multiple groups setting general configuration options for - a program and have to iterate through them and merge them in some - fashion. - - * Iterate through all groups of a given type, building a list of them (or - of the data they contain). This is the model used by, for example, - storage classes; each storage class has a set of parameters, and the - storage subsystem needs to know about the full list of classes. - -Note that neither of these operations directly reveal the tree structure; -the tree structure is intended for the convenience of the user in setting -defaults for various parameters so that they don't have to be repeated in -each group, and to allow some top-level pruning. It's not intended to be -semantically significant other than that. - -Here are some suggested general conventions: - - * General options for a particular program should be separated out into a - their own group. For example, a group innwatch in inn.conf to set the - various options only used by innwatch. Note that pruning is inclusive - rather than exclusive, so programs should ideally only need to care - about a short list of groups. - - * Groups used only for grouping and setting default parameters, ones that - won't be searched for explicitly by any program, should use the type - "group". This can be used uniformly in all configuration files so that - whenever a user sees a group of type "group", they know that it's just - syntactic convenience to avoid having to repeat a bunch of parameter - settings and isn't otherwise significant. - - * Groups that are searched for or iterated through shouldn't be nested; - for example, if a configuration file defines a list of access groups, - nesting one access group inside another is discouraged (in favor of - putting both groups inside an enclosing group of type "group" that sets - the parameters they have in common). This is to cut down on user - confusion, since otherwise the nesting appears to be significant. diff --git a/doc/config-syntax b/doc/config-syntax deleted file mode 100644 index 4863d5d..0000000 --- a/doc/config-syntax +++ /dev/null @@ -1,242 +0,0 @@ -$Id: config-syntax 5843 2002-11-19 00:08:18Z rra $ - -This file documents the standardized syntax for INN configuration files. -This is the syntax that the parsing code in libinn will understand and the -syntax towards which all configuration files should move. - -The basic structure of a configuration file is a tree of groups. Each -group has a type and an optional tag, and may contain zero or more -parameter settings, an association of a name with a value. All parameter -names and group types are simple case-sensitive strings composed of -printable ASCII characters and not containing whitespace or any of the -characters "\:;{}[]<>" or the double-quote. A group may contain another -group (and in fact the top level of the file can be thought of as a -top-level group that isn't allowed to contain parameter settings). - -Supported parameter values are booleans, integers, real numbers, strings, -and lists of strings. - -The basic syntax looks like: - - group-type tag { - parameter: value - parameter: [ string string ... ] - # ... - - group-type tag { - # ... - } - } - -Tags are strings, with the same syntax as a string value for a parameter; -they are optional and may be omitted. A tag can be thought of as the name -of a particular group, whereas the says what that group is -intended to specify and there may be many groups with the same type. - -The second parameter example above has as its value a list. The square -brackets are part of the syntax of the configuration file; lists are -enclosed in square brackets and the elements are space-separated. - -As seen above, groups may be nested. - -Multiple occurances of the same parameter in the parameter section of a -group is an error. In practice, the second parameter will take precedent, -but an error will be reported when such a configuration file is parsed. - -Parameter values inherit. In other words, the structure: - - first { - first-parameter: 1 - second { - second-parameter: 1 - third { third-parameter: 1 } - } - - another "tag" { } - } - -is parsed into a tree that looks like: - - +-------+ +--------+ +-------+ - | first |-+-| second |---| third | - +-------+ | +--------+ +-------+ - | - | +---------+ - +-| another | - +---------+ - -where each box is a group. The type of the group is given in the box; -none of these groups have tags except for the only group of type -"another", which has the tag "tag". The group of type "third" has three -parameters set, namely "third-parameter" (set in the group itself), -"second-parameter" (inherited from the group of type "second"), and -"first-parameter" (inherited from "first" by "second" and then from -"second" by "third"). - -The practical meaning of this is that enclosing groups can be used to set -default values for a set of subgroups. For example, consider the -following configuration that defines three peers of a news server and -newsgroups they're allowed to send: - - peer news1.example.com { newsgroups: * } - peer news2.example.com { newsgroups: * } - peer news3.example.com { newsgroups: * } - -This could instead be written as: - - group { - newsgroups: * - - peer news1.example.com { } - peer news2.example.com { } - peer news3.example.com { } - } - -or as: - - peer news1.example.com { - newsgroups: * - - peer news2.example.com { } - peer news3.example.com { } - } - -and for a client program that only cares about the defined list of peers, -these three structures would be entirely equivalent; all questions about -what parameters are defined in the peer groups would have identical -answers either way this configuration was written. - -Note that the second form above is preferred as a matter of style to the -third, since otherwise it's tempting to derive some significance from the -nesting structure of the peer groups. Also note that in the second -example above, the enclosing group *must* have a type other than "peer"; -to see why, consider the program that asks the configuration parser for a -list of all defined peer groups and uses the resulting list to build some -internal data structures. If the enclosing group in the second example -above had been of type peer, there would be four peer groups instead of -three and one of them wouldn't have a tag, probably provoking an error -message. - -Boolean values may be given as yes, true, or on, or as no, false, or off. -Integers must be between -2,147,483,648 and +2,147,483,647 inclusive (the -same as the minimums for a C99 signed long). Floating point numbers must -be between 0 and 1e37 in absolute magnitude (the same as the minimums for -a C99 double) and can safely expect eight digits of precision. - -Strings are optionally enclosed in double quotes, and must be quoted if -they contain any whitespace, double-quote, or any characters in the set -"\:;[]{}<>". Escape sequences in strings (sequences beginning with \) are -parsed the same as they are in C. Strings can be continued on multiple -lines by ending each line in a backslash, and the newline is not -considered part of such a continued string (to embed a literal newline in -a string, use \n). - -Lists of strings are delimited by [] and consist of whitespace-separated -strings, which must follow the same quoting rules as all other strings. -Group tags are also strings and follow the same quoting rules. - -There are two more bits of syntax. Normally, parameters must be separated -by newlines, but for convenience it's possible to put multiple parameters -on the same line separated by semicolons: - - parameter: value; parameter: value - -Finally, the body of a group may be defined in a separate file. To do -this, rather than writing the body of the group enclosed in {}, instead -give the file name in <>: - - group tag - -(The filename is also a string and may be double-quoted if necessary, but -since file names rarely contain any of the excluded characters it's rarely -necessary.) - -Here is the (almost) complete ABNF for the configuration file syntax. -The syntax is per RFC 2234. - -First the basic syntax elements and possible parameter values: - - newline = %d13 / %d10 / %d13.10 - ; Any of CR, LF, or CRLF are interpreted - ; as a newline. - - comment = *WSP "#" *(WSP / VCHAR / %x8A-FF) newline - - WHITE = WSP / newline [comment] - - boolean = "yes" / "on" / "true" / "no" / "off" / "false" - - integer = ["-"] 1*DIGIT - - real-number = ["-"] 1*DIGIT "." 1*DIGIT [ "e" ["-"] 1*DIGIT ] - - non-special = %x21 / %x23-39 / %x3D / %x3F-5A / %x5E-7A - / %x7C / %x7E / %x8A-FF - ; All VCHAR except "\:;<>[]{} - - quoted-string = DQUOTE 1*(WSP / VCHAR / %x8A-FF) DQUOTE - ; DQUOTE within the quoted string must be - ; written as 0x5C.22 (\"), and backslash - ; sequences are interpreted as in C - ; strings. - - string = 1*non-special / quoted-string - - list-body = string *( 1*WHITE string ) - - list = "[" *WHITE [ list-body ] *WHITE "]" - -Now the general structure: - - parameter-name = 1*non-special - - parameter-value = boolean / integer / real-number / string / list - - parameter = parameter-name ":" 1*WSP parameter-value - - parameter-list = parameter [ *WHITE (";" / newline) *WHITE parameter ] - - group-list = group *( *WHITE group ) - - group-body = parameter-list [ *WHITE newline *WHITE group-list ] - / group-list - - group-file = string - - group-contents = "{" *WHITE [ group-body ] *WHITE "}" - / "<" group-file ">" - - group-type = 1*non-special - - group-tag = string - - group-name = group-type [ 1*WHITE group-tag ] - - group = group-name 1*WHITE group-contents - - file = *WHITE *( group *WHITE ) - -One implication of this grammar is that any line outside a quoted string -that begins with "#", optionally preceded by whitespace, is regarded as a -comment and discarded. The line must begin with "#" (and optional -whitespace); comments at the end of lines aren't permitted. "#" has no -special significance in quoted strings, even if it's at the beginning of a -line. Note that comments cannot be continued to the next line in any way; -each comment line must begin with "#". - -It's unclear the best thing to do with high-bit characters (both literal -characters with value > 0x7F in a configuration file and characters with -such values created in quoted strings with \, \x, \u, or \U). In -the long term, INN should move towards assuming UTF-8 everywhere, as this -is the direction that all of the news standards are heading, but in the -interim various non-Unicode character sets are in widespread use and there -must be some way of encoding those values in INN configuration files (so -that things like the default Organization header value can be set -appropriately). - -As a compromise, the configuration parser will pass unaltered any literal -characters with value > 0x7F to the calling application, and \ and -\x escapes will generate eight-bit characters in the strings (and -therefore cannot be used to generate UTF-8 strings containing code points -greater than U+007F). \u and \U, in contrast, will generate characters -encoded in UTF-8. diff --git a/doc/external-auth b/doc/external-auth deleted file mode 100644 index 28fc847..0000000 --- a/doc/external-auth +++ /dev/null @@ -1,111 +0,0 @@ -NNRPD External Authentication Support - - This is $Revision: 7880 $ dated $Date: 2005-03-17 12:42:46 +0100 (Thu, - 17 Mar 2005) $. - - A fundamental part of the readers.conf(5)-based authorization mechanism - is the interface to external authenticator and resolver programs. This - interface is documented below. - - INN ships with a number of such programs (all written in C, although any - language can be used). Code for them can be found in authprogs/ of the - source tree; the authenticators are installed to *pathbin*/auth/passwd, - and the resolvers are installed to *pathbin*/auth/resolv. - -Reading information from nnrpd - - When nnrpd spawns an external auth program, it passes information on - standard input as a sequence of "key: value" lines. Each line ends with - CRLF, and a line consisting of only "." indicates the end of the input. - The order of the fields is not significant. Additional fields not - mentioned below may be included; this should not be cause for alarm. - - (For robustness as well as ease of debugging, it is probably wise to - accept line endings consisting only of LF, and to treat EOF as - indicating the end of the input even if "." has not been received.) - - Code which reads information in the format discussed below and parses it - into convenient structures is available authenticators and resolvers - written in C; see libauth(3) for details. Use of the libauth library - will make these programs substantially easier to write and more robust. - - For authenticators - - When nnrpd calls an authenticator, the lines it passes are - - ClientAuthname: user\r\n - ClientPassword: pass\r\n - - where *user* and *pass* are the username and password provided by the - client (e.g. using AUTHINFO). In addition, nnrpd generally also passes - the fields mentioned as intended for resolvers; it rare instances this - data may be useful for authenticators. - - For resolvers - - When nnrpd calls a resolver, the lines it passes are - - ClientHost: hostname\r\n - ClientIP: IP-address\r\n - ClientPort: port\r\n - LocalIP: IP-address\r\n - LocalPort: port\r\n - .\r\n - - where *hostname* indicates a string representing the hostname if - available, *IP-address* is a numeric IP address (dotted-quad for IPv4, - equivalent for IPv6 if appropriate), and *port* is a numeric port - number. (The *LocalIP* paramter may be useful for determining which - interface was used for the incoming connection.) - - If information is not available, nnrpd will omit the corresponding - fields. In particular, this applies to the unusual situation of nnrpd - not being connected to a socket; TCP-related information is not - available for standard input. - -Returning information to nnrpd - - Exit status and signals - - The external auth program must exit with a status of 0 to indicate - success; any other exit status indicates failure. (The non-zero exit - value will be logged.) - - If the program dies due to catching a signal (for example, a - segmentation fault occurs), this will be logged and treated as a - failure. - - Returning a username and domain - - If the program succeeds, it must return a username string (optionally - with a domain appended) by writing to standard output. The line it - should write is exactly: - - user:username\r\n - - where *username* is the string that nnrpd should use in matching - readers.conf access blocks. - - There should be no extra spaces in lines sent from the hook to nnrpd; - "user:aidan" is read by nnrpd as a different username than "user: - aidan". - -Error messages - - As mentioned above, errors can be indicated by a non-zero exit value, or - termination due to an unhandled signal; both cases are logged by nnrpd. - However, external auth programs may wish to log error messages - separately. - - Although nnrpd will syslog() anything an external auth program writes to - standard error, it is generally better to use the messages.h functions, - such as warn() and die(). - - Please use the ckpasswd.c program as an example for any authenticators - you write, and ident.c as an example for any resolvers. - -HISTORY - - Written by Aidan Cully for InterNetNews. This documentation rewritten - in POD by Jeffrey M. Vinocur . - diff --git a/doc/history b/doc/history deleted file mode 100644 index b5d4cc1..0000000 --- a/doc/history +++ /dev/null @@ -1,258 +0,0 @@ -$Revision: 4165 $ -This file contains a few messages of historical interest. Some of the -information in these messages is out of date (e.g., you don't need any -other software, ihave/sendme is suported, etc); see the README and -installation manual. - -The first is a mail message I sent as soon as I got the idea. - -Six months later I had something to beta, and I posted the second message -to Usenet. My ship date was optimistic. - -The third message is the application that I required all beta sites to -fill out. - -The fourth is a copy of the release notice. - -From: Rich Salz -Date: Sat, 8 Dec 90 15:23:20 EST -Message-Id: <9012082023.AA13441@litchi.bbn.com> -To: newsgurus@ucsd.edu, nntp-managers@ucbarpa.Berkeley.EDU -Subject: Speed idea. - -Suppose inews, nntp, "rnews -U", newsunbatch, etc., all just fed their -articles to a single daemon? - -An idea I started kicking around yesterday. This is intended only for -sites supporting BSD networking. I believe that anyone else who needs -this kind of speed would find Cnews good enough. - -A multi-threaded server that used non-blocking IO to read all incoming -articles on several sockets (don't forker a server, select on the -connection socket will return READOK when a connection request comes in). -All articles are read into memory, then written out to the filesystem -using a single writev call (easy way to splice the path). - -Hash the active file and compile the sys file so as soon as an article was -accepted we can write out the batchfile entries. As one special case, -write entries to another socket for articles that should be fed out via -NNTPLINK or something. - -Put the socket inside a group-access-only directory, so that only trusted -front-ends like inews "rnews -U" etc can connect to it. - -Oh yeah, for things like nntp use sendmsg/recvmesg to hand off the -feeding site to the demon once it's authenticated the incoming call and -recognized it as an "xfer no" site. - -I've a few pages of notes and code fragments to type in. - -No locks of any kind. active file is mmap'd or periodically flushed. -Keep it all in core and blat it out with a single write. - -When you want to expire, or add a group, you send a special message -on a control port, or perhaps a sighup/sigusr1 to force it to resynch. - -Any feedback? - /r$ - -Path: papaya.bbn.com!rsalz -From: rsalz@bbn.com (Rich Salz) -Newsgroups: news.software.nntp,news.admin,comp.org.usenix -Subject: Seeking beta-testers for a new NNTP transfer system -Message-ID: <3632@litchi.bbn.com> -Date: 18 Jun 91 15:47:21 GMT -Followup-To: poster -Organization: Bolt, Beranek and Newman, Inc. -Lines: 72 -Xref: papaya.bbn.com news.software.nntp:1550 news.admin:15565 comp.org.usenix:418 - -InterNetNews, or INN, is a news transport system. The core part of the -package is a single long-running daemon that handles all incoming NNTP -connections. It files the articles and arranges for them to be forwarded -to downstream sites. Because it is long-running, it can be directed to -spawn other long-running processes, telling them exactly when an article -should be sent to a feed. This can replace the "watch the logfile" mode -of nntplink, for example, with a much cleaner mechanism: read the -batchfile on standard input. - -InterNetNews assumes that memory is cheap and fast while disks are slow. -No temporary files are used while incoming articles are being received, -and once processed the entire article is written out using a single -writev(2) call (this includes updating the Path and Xref headers). The -active file is kept in memory (a compile-time option can be set to use -mmap(2)), and the newsfeeds file is parsed once to build a complete matrix -of which sites receive which newsgroups. - -InterNetNews uses many features of standard BSD sockets including -non-blocking I/O and Unix-domain stream and datagram sockets. It is -highly doubtful that the official version will ever provide support for -TLI, DECNET, or other facilities. - -INN is fast. Not many hard numbers are available (that is one requirement -of being a beta-site), but some preliminary tests show it to be at least -twice as fast as the current standard NNTP/C News combination. For -example, Jim Thompson at Sun has had 20 nntpxmits feeding into a 4/490, -and was getting over 14 articles per second, with the CPU 11% utilized. I -was getting 10 articles/second feeding into a DECstations 3100, with the -program (running profiled!) 50% idle and the load average under .7. (It -is a scary thing to see several articles filed with the same timestamp.) - -The sys file format is somewhat different, and has been renamed. The -arcane "foo.all" syntax is gone, replaced with a set of order-dependant -shell patterns. For example, instead of "comp,comp.sys.sun,!comp.sys" you -would write "comp.*,!comp.sys.*,comp.sys.sun"; to not get any groups -related to binaries or pictures, you write "!*pictures*,!*binaries*". - -There are other incompatibilities as well. For example, ihave/sendme -control messages are not supported. Also the philosophy is that that -invalid articles are dropped, rather than filed into "junk." (A log -message is written with the reason, and also sent back to the upstream -feed as part of the NNTP reject reply.) The active file is taken to be -the definitive list of groups that an article wants to recieve, and if -none of an article's newsgroups are mentioned in the active file, then the -article is invalid, logged, and dropped. - -The history and log files are intended to be compatible with those created -by C News. I want to thank Henry and Geoff for their kind permission to -use DBZ and SUBST. You will need to be running C News expire or a B2.11 -expire that has been modified to use DBZ. - -The InterNetNews daemon does not implement all NNTP commands. If sites -within your campus are going to post or read news via NNTP, you will need -the standard NNTP distribution. The daemon will spawn the standard nntpd -if any site not mentioned in its "hosts.nntp" file connects to the TCP -port. InterNetNews includes a replacement for the "mini-inews" that comes -with the standard NNTP distribution. This can be used on any machine that -posts news and connects to an NNTP server somewhere; its use is not -limited to INN. At some point I hope to have a replacement nntpd -optimized for newsreaders, and an NNTP transmission program. These will -remove the need for any external software beyond the C News expire program. - -If you would like to beta-test this version, please FTP the file -pub/usenet/INN.BETA from cronus.bbn.com for directions. It will be a -fairly tightly-screened beta: DO NOT ASK ME FOR COPIES! Once the system -is stable, it will be freely redistributable. I hope to have the official -release by August 7, so that schools can bring the system up before the -semester starts. - /rich $alz --- -Please send comp.sources.unix-related mail to rsalz@uunet.uu.net. -Use a domain-based address or give alternate paths, or you may lose out. - -Thanks for your interest in InterNetNews. I want to run a fairly -tightly-controlled beta test of the software before I make it generally -available. This means that I'm going to screen the sites which will be -able to participate in the test. Please don't be offended or upset by -this whole procedure. I want to make the final package as stable as soon -as possible so that the entire net can benefit (it will be freely -redistributable). I've set up this mechanism because I think it's the -best way for me to get the best test results as quickly as possible. - -I would therefore appreciate your answers to the following questions. -If you think the answers to some of them will be obvious to me (e.g., -"Describe your organization" --> "UUNET" :-) then feel free to leave it -blank. If you have any other feedback or comments, please add them. - -Email your results to - /r$ - -What software (transport, batching, readers, etc.) do you currently run? - -How much experience do you have with Usenet and NNTP? - -Describe your organization. - -How do you plan on testing InterNetNews? Be specific, describing the -machine hardware, any test servers, etc. [The answers to this one -won't be obvious to me -- you gotta write something.] - -What are the rough counts of the upstream and downstream feeds, and how do -they break down by category (UUCP, NNTP, etc.)? - -What special news functions does your server perform (gatewaying, -archiving, etc.)? - -Do you understand that by participating in the beta-test you agree not to -redistribute the software outside of your administrative domain, and that -you promise to upgrade to the official release in a timely manner? - -From: Rich Salz -Message-Id: -Newsgroups: news.software.b,news.protocols.nntp -Subject: Announcing the release of InterNetNews - -I am pleased to announce the official release of InterNetNews. - -InterNetNews, or INN, is a news transport system. The core part of the -package is a single long-running daemon that handles all incoming NNTP -connections. It files the articles and arranges for them to be forwarded -to downstream sites. Because it is long-running, it can be directed to -spawn other long-running processes, telling them exactly when an article -should be sent to a feed. - -INN is a complete Usenet system. It provides article expiration and -archiving, NNTP transport, and UUCP support. Nntplink works fine. - -INN does not include a newsreader. It does provide a version of the NNTP -reference implementation "clientlib" routines so that rrn and other -newsreaders compile with little trouble. The next release of xrn will -include INN support. - -The spool directory is unchanged while the history database is -upwardly-compatible with that of C News and the log file is very similar. -All system configuration files are different. - -INN assumes that memory is cheap and fast while disks are slow. No -temporary files are used while incoming articles are being received, and -once processed the entire article is written out using a single system -call (this includes updating the Path and Xref headers). The active file -is kept in memory, and the newsfeeds file is parsed at start-up to build a -complete matrix of which sites receive which newsgroups. A paper -describing the implementation was presented at the June 1992 Usenix -conference. - -INN uses many features of standard BSD sockets including non-blocking -I/O. It is highly doubtful that the official version will ever provide -support for TLI, DECNET, or other facilities. Among others, INN beta -sites include ATT Unix System V Release 4, Apple A/UX, BSDI BSD/386 0.3.3, -DEC Ultrix 3.x and 4.x, HP-UX s800 8.0, IBM AIX 3.1 and 3.2, Next NeXT-OS -2.1, Pyramid OSx 5.1, SCO Xenix 2.3.4, SGI Irix 4.0, Sequent Dynix 3.0.4 -and 3.0.12, and Sun SunOS 3.5 and 4.x. - -Almost all of the beta-testers have reported faster performance and less -load once they installed INN. Many people find it easy to maintain. - -A number of sites have graciously agreed to provide FTP access to this -release. The machine names and directories are listed below. Within -those directories you will find one or more of the following files: - README Intro and unpacking instructions; - -or- a copy appears at the end of this - README.INN article. - inn1.0.tar.Z The full distribution - inn.usenix.ps.Z The Usenix paper on INN - -The sites providing access are: - cs.utexas.edu /pub/inn - ftp.cs.widener.edu /pub/inn.tar.Z (or wherever). - ftp.germany.eu.net /pub/news/inn - ftp.ira.uka.de pub/network/news - ftp.msen.com /pub/packages/inn - ftp.uu.net /pub/news/nntp/inn - gatekeeper.dec.com /pub/news/inn - grasp1.univ-lyon1.fr /pub/unix/news/inn - munnari.oz.au /pub/news/inn - sparky.Sterling.COM /news/inn - src.doc.ic.ac.uk /computing/usenet/software/transport - stasys.sta.sub.org /pub/src/inn - (Stasys also has anonymous UUCP; contact . - ucsd.edu /INN - usc.edu /pub/inn - -Discussion about INN should be posted to news.software.b and -news.software.nntp. Email should be sent to . Please -do NOT send it to -- it will only just delay your response -since I will have to forward it to UUNET. - -The README follows after the formfeed. - /r$ diff --git a/doc/hook-perl b/doc/hook-perl deleted file mode 100644 index b2e33d8..0000000 --- a/doc/hook-perl +++ /dev/null @@ -1,597 +0,0 @@ -INN Perl Filtering and Authentication Support - - This is $Revision: 7880 $ dated $Date: 2008-06-07 14:46:49 +0200 (Sat, - 07 Jun 2008) $. - - This file documents INN's built-in support for Perl filtering and reader - authentication. The code is based very heavily on work by Christophe - Wolfhugel , and his work was in turn inspired by the - existing TCL support. Please send any bug reports to inn-bugs@isc.org, - not to Christophe, as the code has been modified heavily since he - originally wrote it. - - The Perl filtering support is described in more detail below. - Basically, it allows you to supply a Perl function that is invoked on - every article received by innd from a peer (the innd filter) or by nnrpd - from a reader (the nnrpd filter). This function can decide whether to - accept or reject the article, and can optionally do other, more - complicated processing (such as add history entries, cancel articles, - spool local posts into a holding area, or even modify the headers of - locally submitted posts). The Perl authentication hooks allow you to - replace or supplement the readers.conf mechanism used by nnrpd. - - For Perl filtering support, you need to have Perl version 5.004 or - newer. Earlier versions of Perl will fail with a link error at - compilation time. http://language.perl.com/info/software.html should - have the latest Perl version. - - To enable Perl support, you have to specify --with-perl when you run - configure. See INSTALL for more information. - -The innd Perl Filter - - When innd starts, it first loads the file _PATH_PERL_STARTUP_INND - (defined in include/paths.h, by default startup_innd.pl) and then loads - the file _PATH_PERL_FILTER_INND (also defined in include/paths.h, by - default filter_innd.pl). Both of these files must be located in the - directory specified by pathfilter in inn.conf - (/usr/local/news/bin/filter by default). The default directory for - filter code can be specified at configure time by giving the flag - --with-filter-dir to configure. - - INN doesn't care what Perl functions you define in which files. The - only thing that's different about the two files is when they're loaded. - startup_innd.pl is loaded only once, when innd first starts, and is - never reloaded as long as innd is running. Any modifications to that - file won't be noticed by innd; only stopping and restarting innd can - cause it to be reloaded. - - filter_innd.pl, on the other hand, can be reloaded on command (with - "ctlinnd reload filter.perl 'reason'"). Whenever filter_innd.pl is - loaded, including the first time at innd startup, the Perl function - filter_before_reload() is called before it's reloaded and the function - filter_after_reload() is called after it's reloaded (if the functions - exist). Additionally, any code in either startup_innd.pl or - filter_innd.pl at the top level (in other words, not inside a sub { }) - is automatically executed by Perl when the files are loaded. - - This allows one to do things like write out filter statistics whenever - the filter is reloaded, load a cache into memory, flush cached data to - disk, or other similar operations that should only happen at particular - times or with manual intervention. Remember, any code not inside - functions in startup_innd.pl is executed when that file is loaded, and - it's loaded only once when innd first starts. That makes it the ideal - place to put initialization code that should only run once, or code to - load data that was preserved on disk across a stop and restart of innd - (perhaps using filter_mode() -- see below). - - As mentioned above, "ctlinnd reload filter.perl 'reason'" (or "ctlinnd - reload all 'reason'") will cause filter_innd.pl to be reloaded. If the - function filter_art() is defined after the file has been reloaded, - filtering is turned on. Otherwise, filtering is turned off. (Note that - due to the way Perl stores functions, once you've defined filter_art(), - you can't undefine it just by deleting it from the file and reloading - the filter. You'll need to replace it with an empty sub.) - - The Perl function filter_art() is the heart of a Perl filter. Whenever - an article is received from a peer, via either IHAVE or TAKETHIS, - filter_art() is called if Perl filtering is turned on. It receives no - arguments, and should return a single scalar value. That value should - be the empty string to indicate that INN should accept the article, or - some rejection message to indicate that the article should be rejected. - - filter_art() has access to a global hash named %hdr, which contains all - of the standard headers present in the article and their values. The - standard headers are: - - Also-Control, Approved, Bytes, Cancel-Key, Cancel-Lock, - Content-Base, Content-Disposition, Content-Transfer-Encoding, - Content-Type, Control, Date, Date-Received, Distribution, Expires, - Face, Followup-To, From, In-Reply-To, Injection-Date, Injection-Info, - Keywords, Lines, List-ID, Message-ID, MIME-Version, Newsgroups, - NNTP-Posting-Date, NNTP-Posting-Host, Organization, Originator, - Path, Posted, Posting-Version, Received, References, Relay-Version, - Reply-To, Sender, Subject, Supersedes, User-Agent, - X-Auth, X-Canceled-By, X-Cancelled-By, X-Complaints-To, X-Face, - X-HTTP-UserAgent, X-HTTP-Via, X-Mailer, X-Modbot, X-Modtrace, - X-Newsposter, X-Newsreader, X-No-Archive, X-Original-Message-ID, - X-Original-Trace, X-Originating-IP, X-PGP-Key, X-PGP-Sig, - X-Poster-Trace, X-Postfilter, X-Proxy-User, X-Submissions-To, - X-Trace, X-Usenet-Provider, Xref. - - Note that all the above headers are as they arrived, not modified by - your INN (especially, the Xref: header, if present, is the one of the - remote site which sent you the article, and not yours). - - For example, the Newsgroups: header of the article is accessible inside - the Perl filter as $hdr{'Newsgroups'}. In addition, $hdr{'__BODY__'} - will contain the full body of the article and $hdr{'__LINES__'} will - contain the number of lines in the body of the article. - - The contents of the %hdr hash for a typical article may therefore look - something like this: - - %hdr = (Subject => 'MAKE MONEY FAST!!', - From => 'Joe Spamer ', - Date => '10 Sep 1996 15:32:28 UTC', - Newsgroups => 'alt.test', - Path => 'news.example.com!not-for-mail', - Organization => 'Spammers Anonymous', - Lines => '5', - Distribution => 'usa', - 'Message-ID' => '<6.20232.842369548@example.com>', - __BODY__ => 'Send five dollars to the ISC, c/o ...', - __LINES__ => 5 - ); - - Note that the value of $hdr{Lines} is the contents of the Lines: header - of the article and may bear no resemblence to the actual length of the - article. $hdr{__LINES__} is the line count calculated by INN, and is - guaranteed to be accurate. - - The %hdr hash should not be modified inside filter_art(). Instead, if - any of the contents need to be modified temporarily during filtering - (smashing case, for example), copy them into a seperate variable first - and perform the modifications on the copy. Currently, $hdr{__BODY__} is - the only data that will cause your filter to die if you modify it, but - in the future other keys may also contain live data. Modifying live INN - data in Perl will hopefully only cause a fatal exception in your Perl - code that disables Perl filtering until you fix it, but it's possible - for it to cause article munging or even core dumps in INN. So always, - always make a copy first. - - As mentioned above, if filter_art() returns the empty string (''), the - article is accepted. Note that this must be the empty string, not 0 or - undef. Otherwise, the article is rejected, and whatever scalar - filter_art() returns (typically a string) will be taken as the reason - why the article was rejected. This reason will be returned to the - remote peer as well as logged to the news logs. (innreport, in its - nightly report, will summarize the number of articles rejected by the - Perl filter and include a count of how many articles were rejected with - each reason string.) - - One other type of filtering is also supported. If Perl filtering is - turned on and the Perl function filter_messageid() is defined, that - function will be called for each message ID received from a peer (via - either CHECK or IHAVE). The function receives a single argument, the - message ID, and like filter_art() should return an empty string to - accept the article or an error string to refuse the article. This - function is called before any history lookups and for every article - offered to innd with CHECK or IHAVE (before the actual article is sent). - Accordingly, the message ID is the only information it has about the - article (the %hdr hash will be empty). This code would sit in a - performance-critical hot path in a typical server, and therefore should - be as fast as possible, but it can do things like refuse articles from - certain hosts or cancels for already rejected articles (if they follow - the $alz convention) without having to take the network bandwidth hit of - accepting the entire article first. - - Note that you cannot rely on filter_messageid() being called for every - incoming article; articles sent via TAKETHIS without an earlier CHECK - will never pass through filter_messageid() and will only go through - filter_art(). - - Finally, whenever ctlinnd throttle, ctlinnd pause, or ctlinnd go is run, - the Perl function filter_mode() is called if it exists. It receives no - arguments and returns no value, but it has access to a global hash %mode - that contains three values: - - Mode The current server mode (throttled, paused, or running) - NewMode The new mode the server is going to - reason The reason that was given to ctlinnd - - One possible use for this function is to save filter state across a - restart of innd. There isn't any Perl function which is called when INN - shuts down, but using filter_mode() the Perl filter can dump it's state - to disk whenever INN is throttled. Then, if the news administrator - follows the strongly recommended shutdown procedure of throttling the - server before shutting it down, the filter state will be safely saved to - disk and can be reloaded when innd restarts (possibly by - startup_innd.pl). - - The state of the Perl interpretor in which all of these Perl functions - run is preserved over the lifetime of innd. In other words, it's - permissible for the Perl code to create its own global Perl variables, - data structures, saved state, and the like, and all of that will be - available to filter_art() and filter_messageid() each time they're - called. The only variable INN fiddles with (or pays any attention to at - all) is %hdr, which is cleared after each call to filter_art(). - - Perl filtering can be turned off with "ctlinnd perl n" and back on again - with "ctlinnd perl y". Perl filtering is turned off automatically if - loading of the filter fails or if the filter code returns any sort of a - fatal error (either due to Perl itself or due to a "die" in the Perl - code). - -Supported innd Callbacks - - innd makes seven functions available to any of its embedded Perl code. - Those are: - - INN::addhist(*messageid*, *arrival*, *articledate*, *expire*, *paths*) - Adds *messageid* to the history database. All of the arguments - except the first one are optional; the times default to the current - time and the paths field defaults to the empty string. (For those - unfamiliar with the fields of a history(5) database entry, the - *arrival* is normally the time at which the server accepts the - article, the *articledate* is from the Date header of the article, - the *expire* is from the Expires header of the article, and the - *paths* field is the storage API token. All three times as measured - as a time_t since the epoch.) Returns true on success, false - otherwise. - - INN::article(*messageid*) - Returns the full article (as a simple string) identified by - *messageid*, or undef if it isn't found. Each line will end with a - simple \n, but leading periods may still be doubled if the article - is stored in wire format. - - INN::cancel(*messageid*) - Cancels *messageid*. (This is equivalent to "ctlinnd cancel"; it - cancels the message on the local server, but doesn't post a cancel - message or do anything else that affects anything other than the - local server.) Returns true on success, false otherwise. - - INN::filesfor(*messageid*) - Returns the *paths* field of the history entry for the given - *messageid*. This will be the storage API token for the message. - If *messageid* isn't found in the history database, returns undef. - - INN::havehist(*messageid*) - Looks up *messageid* in the history database and returns true if - it's found, false otherwise. - - INN::head(*messageid*) - Returns the header (as a simple string) of the article identified by - *messageid*, or undef if it isn't found. Each line will end with a - simple \n (in other words, regardless of the format of article - storage, the returned string won't be in wire format). - - INN::newsgroup(*newsgroup*) - Returns the status of *newsgroup* (the last field of the active file - entry for that newsgroup). See active(5) for a description of the - possible values and their meanings (the most common are "y" for an - unmoderated group and "m" for a moderated group). If *newsgroup* - isn't in the active file, returns undef. - - These functions can only be used from inside the innd Perl filter; - they're not available in the nnrpd filter. - -Common Callbacks - - The following additional function is available from inside filters - embedded in innd, and is also available from filters embedded in nnrpd - (see below): - - INN::syslog(level, message) - Logs a message via syslog(2). This is quite a bit more reliable and - portable than trying to use Sys::Syslog from inside the Perl filter. - Only the first character of the level argument matters; the valid - letters are the first letters of ALERT, CRIT, ERR, WARNING, NOTICE, - INFO, and DEBUG (case-insensitive) and specify the priority at which - the message is logged. If a level that doesn't match any of those - levels is given, the default priority level is LOG_NOTICE. The - second argument is the message to log; it will be prefixed by - "filter: " and logged to syslog with facility LOG_NEWS. - -The nnrpd Posting Filter - - Whenever Perl support is needed in nnrpd, it first loads the file - _PATH_PERL_FILTER_NNRPD (defined in include/paths.h, by default - filter_nnrpd.pl). This file must be located in the directory specified - by pathfilter in inn.conf (/usr/local/news/bin/filter by default). The - default directory for filter code can be specified at configure time by - giving the flag --with-filter-dir to configure. - - If filter_nnrpd.pl loads successfully and defines the Perl function - filter_post(), Perl filtering is turned on. Otherwise, it's turned off. - If filter_post() ever returns a fatal error (either from Perl or from a - "die" in the Perl code), Perl filtering is turned off for the life of - that nnrpd process and any further posts made during that session won't - go through the filter. - - While Perl filtering is on, every article received by nnrpd via the POST - command is passed to the filter_post() Perl function before it is passed - to INN (or mailed to the moderator of a moderated newsgroup). If - filter_post() returns an empty string (''), the article is accepted and - normal processing of it continues. Otherwise, the article is rejected - and the string returned by filter_post() is returned to the client as - the error message (with some exceptions; see below). - - filter_post() has access to a global hash %hdr, which contains all of - the headers of the article. (Unlike the innd Perl filter, %hdr for the - nnrpd Perl filter contains *all* of the headers, not just the standard - ones. If any of the headers are duplicated, though, %hdr will contain - only the value of the last occurance of the header. nnrpd will reject - the article before the filter runs if any of the standard headers are - duplicated.) It also has access to the full body of the article in the - variable $body, and if the poster authenticated via AUTHINFO (or if - either Perl authentication or a readers.conf authentication method is - used and produces user information), it has access to the authenticated - username of the poster in the variable $user. - - Unlike the innd Perl filter, the nnrpd Perl filter can modify the %hdr - hash. In fact, if the Perl variable $modify_headers is set to true - after filter_post() returns, the contents of the %hdr hash will be - written back to the article replacing the original headers. - filter_post() can therefore make any modifications it wishes to the - headers and those modifications will be reflected in the article as it's - finally posted. The article body cannot be modified in this way; any - changes to $body will just be ignored. - - Be careful when using the ability to modify headers. filter_post() runs - after all the normal consistency checks on the headers and after server - supplied headers (like Message-ID: and Date:) are filled in. Deleting - required headers or modifying headers that need to follow a strict - format can result in nnrpd trying to post nonsense articles (which will - probably then be rejected by innd). If $modify_headers is set, - *everything* in the %hdr hash is taken to be article headers and added - to the article. - - If filter_post() returns something other than the empty string, this - message is normally returned to the client as an error. There are two - exceptions: If the string returned begins with "DROP", the post will be - silently discarded and success returned to the client. If the string - begins with "SPOOL", success is returned to the client, but the post is - saved in a directory named "spam" under the directory specified by - pathincoming in inn.conf (in a directory named "spam/mod" if the post is - to a moderated group). This is intended to allow manual inspection of - the suspect messages; if they should be posted, they can be manually - moved out of the subdirectory to the directory specified by pathincoming - in inn.conf, where they can be posted by running "rnews -U". If you use - this functionality, make sure those directories exist. - -Changes to Perl Authentication Support for nnrpd - - The old authentication functionality has been combined with the new - readers.conf mechanism by Erik Klavon ; bug reports - should however go to inn-bugs@isc.org, not Erik. - - The remainder of this section is an introduction to the new mechanism - (which uses the perl_auth: and perl_access: readers.conf parameters) - with porting/migration suggestions for people familiar with the old - mechanism (identifiable by the nnrpperlauth: parameter in inn.conf). - - Other people should skip this section. - - The perl_auth parameter allows the use of Perl to authenticate a user. - Scripts (like those from the old mechanism) are listed in readers.conf - using perl_auth in the same manner other authenticators are using auth: - - perl_auth: "/path/to/script/auth1.pl" - - The file given as argument to perl_auth should contain the same - procedures as before. The global hash %attributes remains the same, - except for the removal of the "type" entry which is no longer needed in - this modification and the addition of several new entries (port, - intipaddr, intport) described below. The return array now only contains - either two or three elements, the first of which is the NNTP return - code. The second is an error string which is passed to the client if the - error code indicates that the authentication attempt has failed. This - allows a specific error message to be generated by the perl script in - place of "Authentication failed". An optional third return element if - present will be used to match the connection with the users: parameter - in access groups and will also be the username logged. If this element - is absent, the username supplied by the client during authentication - will be used as was the previous behavior. - - The perl_access parameter (described below) is also new; it allows the - dynamic generation of an access group for an incoming connection using a - Perl script. If a connection matches an auth group which has a - perl_access parameter, all access groups in readers.conf are ignored; - instead the procedure described below is used to generate an access - group. This concept is due to Jeffrey M. Vinocur. - - The new functionality should provide all of the existing capabilities of - the Perl hook, in combination with the flexibility of readers.conf and - the use of other authentication and resolving programs. To use Perl - authentication code that predates the readers.conf mechanism, you would - need to modify the code slightly (see below for the new specification) - and supply a simple readers.conf file. If you don't want to modify your - code, the samples directory has nnrpd_auth_wrapper.pl and - nnrpd_access_wrapper.pl which should allow you to use your old code - without needing to change it. - - However, before trying to use your old Perl code, you may want to - consider replacing it entirely with non-Perl authentication. (With - readers.conf and the regular authenticator and resolver programs, much - of what once required Perl can be done directly.) Even if the - functionality is not available directly, you may wish to write a new - authenticator or resolver (which can be done in whatever language you - prefer to work in). - -Perl Authentication Support for nnrpd - - Support for authentication via Perl is provided in nnrpd by the - inclusion of a perl_auth: parameter in a readers.conf auth group. - perl_auth: works exactly like the auth: parameter in readers.conf, - except that it calls the script given as argument using the Perl hook - rather then treating it as an external program. - - If the processing of readers.conf requires that a perl_auth: statement - be used for authentication, Perl is loaded (if it has yet to be) and the - file given as argument to the perl_auth: parameter is loaded as well. If - a Perl function auth_init() is defined by that file, it is called - immediately after the file is loaded. It takes no arguments and returns - nothing. - - Provided the file loads without errors, auth_init() (if present) runs - without fatal errors, and a Perl function authenticate() is defined, - authenticate() will then be called. authenticate() takes no arguments, - but it has access to a global hash %attributes which contains - information about the connection as follows: $attributes{hostname} will - contain the hostname (or the IP address if it doesn't resolve) of the - client machine, $attributes{ipaddress} will contain its IP address (as a - string), $attributes{port} will contain the client port (as an integer), - $attributes{interface} contains the hostname of the interface the client - connected on, $attributes{intipaddr} contains the IP address (as a - string) of the interface the client connected on, $attributes{intport} - contains the port (as an integer) on the interface the client connected - on, $attributes{username} will contain the provided username and - $attributes{password} the password. - - authenticate() should return a two or three element array. The first - element is the NNTP response code to return to the client, the second - element is an error string which is passed to the client if the response - code indicates that the authentication attempt has failed. An optional - third return element if present will be used to match the connection - with the users: parameter in access groups and will also be the username - logged. If this element is absent, the username supplied by the client - during authentication will be used for matching and logging. - - The NNTP response code should probably be either 281 (authentication - successful) or 502 (authentication unsuccessful). If the code returned - is anything other than 281, nnrpd will print an authentication error - message and drop the connection and exit. - - If authenticate() dies (either due to a Perl error or due to calling - die), or if it returns anything other than the two or three element - array described above, an internal error will be reported to the client, - the exact error will be logged to syslog, and nnrpd will drop the - connection and exit. - -Dynamic Generation of Access Groups - - A Perl script may be used to dynamically generate an access group which - is then used to determine the access rights of the client. This occurs - whenever the perl_access: is specified in an auth group which has - successfully matched the client. Only one perl_access: statement is - allowed in an auth group. This parameter should not be mixed with a - python_access: statement in the same auth group. - - When a perl_access: parameter is encountered, Perl is loaded (if it has - yet to be) and the file given as argument is loaded as well. Provided - the file loads without errors, and a Perl function access() is defined, - access() will then be called. access() takes no arguments, but it has - access to a global hash %attributes which contains information about the - connection as follows: $attributes{hostname} will contain the hostname - (or the IP address if it doesn't resolve) of the client machine, - $attributes{ipaddress} will contain its IP address (as a string), - $attributes{port} will contain the client port (as an integer), - $attributes{interface} contains the hostname of the interface the client - connected on, $attributes{intipaddr} contains the IP address (as a - string) of the interface the client connected on, $attributes{intport} - contains the port (as an integer) on the interface the client connected - on, $attributes{username} will contain the provided username and domain - (in username@domain form). - - access() returns a hash, containing the desired access parameters and - values. Here is an untested example showing how to dynamically generate - a list of newsgroups based on the client's username and domain. - - my %hosts = ( "example.com" => "example.*", "isc.org" => "isc.*" ); - - sub access { - %return_hash = ( - "max_rate" => "10000", - "addnntppostinghost" => "true", - # ... - ); - if( defined $attributes{username} && - $attributes{username} =~ /.*@(.*)/ ) - { - $return_hash{"virtualhost"} = "true"; - $return_hash{"path"} = $1; - $return_hash{"newsgroups"} = $hosts{$1}; - } else { - $return_hash{"read"} = "*"; - $return_hash{"post"} = "local.*" - } - return %return_hash; - } - - Note that both the keys and values are quoted strings. These values are - to be returned to a C program and must be quoted strings. For values - containing one or more spaces, it is not necessary to include extra - quotes inside the string. - - While you may include the users: parameter in a dynamically generated - access group, some care should be taken (unless your pattern is just * - which is equivalent to leaving the parameter out). The group created - with the values returned from the Perl script is the only one considered - when nnrpd attempts to find an access group matching the connection. If - a users: parameter is included and it doesn't match the connection, then - the client will be denied access since there are no other access groups - which could match the connection. - - If access() dies (either due to a Perl error or due to calling die), or - if it returns anything other than a hash as described above, an internal - error will be reported to the client, the exact error will be logged to - syslog, and nnrpd will drop the connection and exit. - -Notes on Writing Embedded Perl - - All Perl evaluation is done inside an implicit eval block, so calling - die in Perl code will not kill the innd or nnrpd process. Neither will - Perl errors (such as syntax errors). However, such errors will have - negative effects (fatal errors in the innd or nnrpd filter will cause - filtering to be disabled, and fatal errors in the nnrpd authentication - code will cause the client connection to be terminated). - - Calling exit directly, however, *will* kill the innd or nnrpd process, - so don't do that. Similarly, you probably don't want to call fork (or - any other function that results in a fork such as system, - IPC::Open3::open3(), or any use of backticks) since there are possibly - unflushed buffers that could get flushed twice, lots of open state that - may not get closed properly, and innumerable other potential problems. - In general, be aware that all Perl code is running inside a large and - complicated C program, and Perl code that impacts the process as a whole - is best avoided. - - You can use print and warn inside Perl code to send output to STDOUT or - STDERR, but you probably shouldn't. Instead, open a log file and print - to it instead (or, in the innd filter, use INN::syslog() to write - messages via syslog like the rest of INN). If you write to STDOUT or - STDERR, where that data will go depends on where the filter is running; - inside innd, it will go to the news log or the errlog, and inside nnrpd - it will probably go nowhere but could go to the client. The nnrpd - filter takes some steps to try to keep output from going across the - network connection to the client (which would probably result in a very - confused client), but best not to take the chance. - - For similar reasons, try to make your Perl code -w clean, since Perl - warnings are written to STDERR. (INN won't run your code under -w, but - better safe than sorry, and some versions of Perl have some mandatory - warnings you can't turn off.) - - You *can* use modules in your Perl code, just like you would in an - ordinary Perl script. You can even use modules that dynamically load C - code. Just make sure that none of the modules you use go off behind - your back to do any of the things above that are best avoided. - - Whenever you make any modifications to the Perl code, and particularly - before starting INN or reloading filter.perl with new code, you should - run perl -wc on the file. This will at least make sure you don't have - any glaring syntax errors. Remember, if there are errors in your code, - filtering will be disabled, which could mean that posts you really - wanted to reject will leak through and authentication of readers may be - totally broken. - - The samples directory has example startup_innd.pl, filter_innd.pl, - filter_nnrpd.pl, and nnrpd_auth.pl files that contain some simplistic - examples. Look them over as a starting point when writing your own. - -Available Packages - - This is an unofficial list of known filtering packages at the time of - publication. This is not an endorsement of these filters by the ISC or - the INN developers, but is included as assistance in locating packages - which make use of this filter mechanism. - - CleanFeed Jeremy Nixon - - A spam filter catching excessive multi-posting and a host of - other things. Uses filter_innd.pl exclusively, requires the MD5 - Perl module. Probably the most popular and widely-used Perl - filter around. - - Usenet II Filter Edward S. Marshall - - Checks for "soundness" according to Usenet II guidelines in the - net.* hierarchy. Designed to use filter_nnrpd.pl. - - News Gizmo Aidan Cully - - A posting filter for helping a site enforce Usenet-II soundness, - and for quotaing the number of messages any user can post to - Usenet daily. diff --git a/doc/hook-python b/doc/hook-python deleted file mode 100644 index f6ef5c0..0000000 --- a/doc/hook-python +++ /dev/null @@ -1,614 +0,0 @@ -INN Python Filtering and Authentication Support - - This file documents INN's built-in optional support for Python article - filtering. It is patterned after the Perl and (now obsolete) TCL hooks - previously added by Bob Heiney and Christophe Wolfhugel. - - For this filter to work successfully, you will need to have at least - Python 1.5.2 installed. You can obtain it from - . - - The innd Python interface and the original Python filtering - documentation were written by Greg Andruk (nee Fluffy) - . The Python authentication and authorization support - for nnrpd as well as the original documentation for it were written by - Ilya Etingof in December 1999. - -Installation - - Once you have built and installed Python, you can cause INN to use it by - adding the --with-python switch to your "configure" command. You will - need to have all the headers and libraries required for embedding Python - into INN; they can be found in Python development packages, which - include header files and static libraries. - - You will then be able to use Python authentication, dynamic access group - generation and dynamic access control support in nnrpd along with - filtering support in innd. - - See the ctlinnd(8) manual page to learn how to enable, disable and - reload Python filters on a running server (especially "ctlinnd mode", - "ctlinnd python y|n" and "ctlinnd reload filter.python 'reason'"). - - Also, see the filter_innd.py, nnrpd_auth.py, nnrpd_access.py and - nnrpd_dynamic.py samples in your filters directory for a demonstration - of how to get all this working. - -Writing an innd Filter - - Introduction - - You need to create a filter_innd.py module in INN's filter directory - (see the *pathfilter* setting in inn.conf). A heavily-commented sample - is provided; you can use it as a template for your own filter. There is - also an INN.py module there which is not actually used by INN; it is - there so you can test your module interactively. - - First, define a class containing the methods you want to provide to - innd. Methods innd will use if present are: - - __init__(*self*) - Not explicitly called by innd, but will run whenever the filter - module is (re)loaded. This is a good place to initialize constants - or pick up where "filter_before_reload" or "filter_close" left off. - - filter_before_reload(*self*) - This will execute any time a "ctlinnd reload all 'reason'" or - "ctlinnd reload filter.python 'reason'" command is issued. You can - use it to save statistics or reports for use after reloading. - - filter_close(*self*) - This will run when a "ctlinnd shutdown 'reason'" command is - received. - - filter_art(*self*, *art*) - *art* is a dictionary containing an article's headers and body. - This method is called every time innd receives an article. The - following can be defined: - - Also-Control, Approved, Bytes, Cancel-Key, Cancel-Lock, - Content-Base, Content-Disposition, Content-Transfer-Encoding, - Content-Type, Control, Date, Date-Received, Distribution, Expires, - Face, Followup-To, From, In-Reply-To, Injection-Date, Injection-Info, - Keywords, Lines, List-ID, Message-ID, MIME-Version, Newsgroups, - NNTP-Posting-Date, NNTP-Posting-Host, Organization, Originator, - Path, Posted, Posting-Version, Received, References, Relay-Version, - Reply-To, Sender, Subject, Supersedes, User-Agent, - X-Auth, X-Canceled-By, X-Cancelled-By, X-Complaints-To, X-Face, - X-HTTP-UserAgent, X-HTTP-Via, X-Mailer, X-Modbot, X-Modtrace, - X-Newsposter, X-Newsreader, X-No-Archive, X-Original-Message-ID, - X-Original-Trace, X-Originating-IP, X-PGP-Key, X-PGP-Sig, - X-Poster-Trace, X-Postfilter, X-Proxy-User, X-Submissions-To, - X-Trace, X-Usenet-Provider, Xref, __BODY__, __LINES__. - - Note that all the above values are as they arrived, not modified by - your INN (especially, the Xref: header, if present, is the one of - the remote site which sent you the article, and not yours). - - These values will be buffer objects holding the contents of the same - named article headers, except for the special "__BODY__" and - "__LINES__" items. Items not present in the article will contain - "None". - - "art('__BODY__')" is a buffer object containing the article's entire - body, and "art('__LINES__')" is an int holding innd's reckoning of - the number of lines in the article. All the other elements will be - buffers with the contents of the same-named article headers. - - The Newsgroups: header of the article is accessible inside the - Python filter as "art['Newsgroups']". - - If you want to accept an article, return "None" or an empty string. - To reject, return a non-empty string. The rejection strings will be - shown to local clients and your peers, so keep that in mind when - phrasing your rejection responses. - - filter_messageid(*self*, *msgid*) - *msgid* is a buffer object containing the ID of an article being - offered by IHAVE or CHECK. Like with "filter_art", the message will - be refused if you return a non-empty string. If you use this - feature, keep it light because it is called at a rather busy place - in innd's main loop. Also, do not rely on this function alone to - reject by ID; you should repeat the tests in "filter_art" to catch - articles sent with TAKETHIS but no CHECK. - - filter_mode(*self*, *oldmode*, *newmode*, *reason*) - When the operator issues a ctlinnd "pause", "throttle", "go", - "shutdown" or "xexec" command, this function can be used to do - something sensible in accordance with the state change. Stamp a log - file, save your state on throttle, etc. *oldmode* and *newmode* - will be strings containing one of the values in ("running", - "throttled", "paused", "shutdown", "unknown"). *oldmode* is the - state innd was in before ctlinnd was run, *newmode* is the state - innd will be in after the command finishes. *reason* is the comment - string provided on the ctlinnd command line. - - How to Use these Methods with innd - - To register your methods with innd, you need to create an instance of - your class, import the built-in INN module, and pass the instance to - "INN.set_filter_hook". For example: - - class Filter: - def filter_art(self, art): - ... - blah blah - ... - - def filter_messageid(self, id): - ... - yadda yadda - ... - - import INN - myfilter = Filter() - INN.set_filter_hook(myfilter) - - When writing and testing your Python filter, don't be afraid to make use - of "try:"/"except:" and the provided "INN.syslog" function. stdout and - stderr will be disabled, so your filter will die silently otherwise. - - Also, remember to try importing your module interactively before loading - it, to ensure there are no obvious errors. One typo can ruin your whole - filter. A dummy INN.py module is provided to facilitate testing outside - the server. To test, change into your filter directory and use a - command like: - - python -ic 'import INN, filter_innd' - - You can define as many or few of the methods listed above as you want in - your filter class (it is fine to define more methods for your own use; - innd will not be using them but your filter can). If you *do* define - the above methods, GET THE PARAMETER COUNTS RIGHT. There are checks in - innd to see whether the methods exist and are callable, but if you - define one and get the parameter counts wrong, innd WILL DIE. You have - been warned. Be careful with your return values, too. The "filter_art" - and "filter_messageid" methods have to return strings, or "None". If - you return something like an int, innd will *not* be happy. - - A Note regarding Buffer Objects - - Buffer objects are cousins of strings, new in Python 1.5.2. Using - buffer objects may take some getting used to, but we can create buffers - much faster and with less memory than strings. - - For most of the operations you will perform in filters (like - "re.search", "string.find", "md5.digest") you can treat buffers just - like strings, but there are a few important differences you should know - about: - - # Make a string and two buffers. - s = "abc" - b = buffer("def") - bs = buffer("abc") - - s == bs # - This is false because the types differ... - buffer(s) == bs # - ...but this is true, the types now agree. - s == str(bs) # - This is also true, but buffer() is faster. - s[:2] == bs[:2] # - True. Buffer slices are strings. - - # While most string methods will take either a buffer or a string, - # string.join (in the string module) insists on using only strings. - import string - string.join([str(b), s], '.') # Returns 'def.abc'. - '.'.join([str(b), s]) # Returns 'def.abc' too. - '.'.join([b, s]) # This raises a TypeError. - - e = s + b # This raises a TypeError, but... - - # ...these two both return the string 'abcdef'. The first one - # is faster -- choose buffer() over str() whenever you can. - e = buffer(s) + b - f = s + str(b) - - g = b + '>' # This is legal, returns the string 'def>'. - - Functions Supplied by the Built-in innd Module - - Besides "INN.set_filter_hook" which is used to register your methods - with innd as it has already been explained above, the following - functions are available from Python scripts: - - addhist(*message-id*) - article(*message-id*) - cancel(*message-id*) - havehist(*message-id*) - hashstring(*string*) - head(*message-id*) - newsgroup(*groupname*) - syslog(*level*, *message*) - - Therefore, not only can innd use Python, but your filter can use some of - innd's features too. Here is some sample Python code to show what you - get with the previously listed functions. - - import INN - - # Python's native syslog module isn't compiled in by default, - # so the INN module provides a replacement. The first parameter - # tells the Unix syslogger what severity to use; you can - # abbreviate down to one letter and it's case insensitive. - # Available levels are (in increasing levels of seriousness) - # Debug, Info, Notice, Warning, Err, Crit, and Alert. (If you - # provide any other string, it will be defaulted to Notice.) The - # second parameter is the message text. The syslog entries will - # go to the same log files innd itself uses, with a 'python:' - # prefix. - syslog('warning', 'I will not buy this record. It is scratched.') - animals = 'eels' - vehicle = 'hovercraft' - syslog('N', 'My %s is full of %s.' % (vehicle, animals)) - - # Let's cancel an article! This only deletes the message on the - # local server; it doesn't send out a control message or anything - # scary like that. Returns 1 if successful, else 0. - if INN.cancel(''): - cancelled = "yup" - else: - cancelled = "nope" - - # Check if a given message is in history. This doesn't - # necessarily mean the article is on your spool; cancelled and - # expired articles hang around in history for a while, and - # rejected articles will be in there if you have enabled - # remembertrash in inn.conf. Returns 1 if found, else 0. - if INN.havehist(''): - comment = "*yawn* I've already seen this article." - else: - comment = 'Mmm, fresh news.' - - # Here we are running a local spam filter, so why eat all those - # cancels? We can add fake entries to history so they'll get - # refused. Returns 1 on success, 0 on failure. - cancelled_id = buffer('') - if INN.addhist("') - artheader = INN.head('') - - # As we can compute a hash digest for a string, we can obtain one - # for artbody. It might be of help to detect spam. - digest = INN.hashstring(artbody) - - # Finally, do you want to see if a given newsgroup is moderated or - # whatever? INN.newsgroup returns the last field of a group's - # entry in active as a string. - froupflag = INN.newsgroup('alt.fan.karl-malden.nose') - if froupflag == '': - moderated = 'no such newsgroup' - elif froupflag == 'y': - moderated = "nope" - elif froupflag == 'm': - moderated = "yep" - else: - moderated = "something else" - -Writing an nnrpd Filter - - Changes to Python Authentication and Access Control Support for nnrpd - - The old authentication and access control functionality has been - combined with the new readers.conf mechanism by Erik Klavon - ; bug reports should however go to , - not Erik. - - The remainder of this section is an introduction to the new mechanism - (which uses the *python_auth*, *python_access*, and *python_dynamic* - readers.conf parameters) with porting/migration suggestions for people - familiar with the old mechanism (identifiable by the now deprecated - *nnrpperlauth* parameter in inn.conf). - - Other people should skip this section. - - The *python_auth* parameter allows the use of Python to authenticate a - user. Authentication scripts (like those from the old mechanism) are - listed in readers.conf using *python_auth* in the same manner other - authenticators are using *auth*: - - python_auth: "nnrpd_auth" - - It uses the script named nnrpd_auth.py (note that ".py" is not present - in the *python_auth* value). - - Scripts should be placed as before in the filter directory (see the - *pathfilter* setting in inn.conf). The new hook method "authen_init" - takes no arguments and its return value is ignored; its purpose is to - provide a means for authentication specific initialization. The hook - method "authen_close" is the more specific analogue to the old "close" - method. These two method hooks are not required, contrary to - "authenticate", the main method. - - The argument dictionary passed to "authenticate" remains the same, - except for the removal of the *type* entry which is no longer needed in - this modification and the addition of several new entries (*port*, - *intipaddr*, *intport*) described below. The return tuple now only - contains either two or three elements, the first of which is the NNTP - response code. The second is an error string which is passed to the - client if the response code indicates that the authentication attempt - has failed. This allows a specific error message to be generated by the - Python script in place of the generic message "Authentication failed". - An optional third return element, if present, will be used to match the - connection with the *user* parameter in access groups and will also be - the username logged. If this element is absent, the username supplied - by the client during authentication will be used, as was the previous - behaviour. - - The *python_access* parameter (described below) is new; it allows the - dynamic generation of an access group of an incoming connection using a - Python script. If a connection matches an auth group which has a - *python_access* parameter, all access groups in readers.conf are - ignored; instead the procedure described below is used to generate an - access group. This concept is due to Jeffrey M. Vinocur and you can add - this line to readers.conf in order to use the nnrpd_access.py Python - script in *pathfilter*: - - python_access: "nnrpd_access" - - In the old implementation, the authorization method allowed for access - control on a per-group basis. That functionality is preserved in the - new implementation by the inclusion of the *python_dynamic* parameter in - readers.conf. The only change is the corresponding method name of - "dynamic" as opposed to "authorize". Additionally, the associated - optional housekeeping methods "dynamic_init" and "dynamic_close" may be - implemented if needed. In order to use nnrpd_dynamic.py in - *pathfilter*, you can add this line to readers.conf: - - python_dynamic: "nnrpd_dynamic" - - This new implementation should provide all of the previous capabilities - of the Python hooks, in combination with the flexibility of readers.conf - and the use of other authentication and resolving programs (including - the Perl hooks!). To use Python code that predates the new mechanism, - you would need to modify the code slightly (see below for the new - specification) and supply a simple readers.conf file. If you do not - want to modify your code, the sample directory has - nnrpd_auth_wrapper.py, nnrpd_access_wrapper.py and - nnrpd_dynamic_wrapper.py which should allow you to use your old code - without needing to change it. - - However, before trying to use your old Python code, you may want to - consider replacing it entirely with non-Python authentication. (With - readers.conf and the regular authenticator and resolver programs, much - of what once required Python can be done directly.) Even if the - functionality is not available directly, you may wish to write a new - authenticator or resolver (which can be done in whatever language you - prefer). - - Python Authentication Support for nnrpd - - Support for authentication via Python is provided in nnrpd by the - inclusion of a *python_auth* parameter in a readers.conf auth group. - *python_auth* works exactly like the *auth* parameter in readers.conf, - except that it calls the script given as argument using the Python hook - rather then treating it as an external program. Multiple, mixed use of - *python_auth* with other *auth* statements including *perl_auth* is - permitted. Each *auth* statement will be tried in the order they appear - in the auth group until either one succeeds or all are exhausted. - - If the processing of readers.conf requires that a *python_auth* - statement be used for authentication, Python is loaded (if it has yet to - be) and the file given as argument to the *python_auth* parameter is - loaded as well (do not include the ".py" extension of this file in the - value of *python_auth*). If a Python object with a method "authen_init" - is hooked in during the loading of that file, then that method is called - immediately after the file is loaded. If no errors have occurred, the - method "authenticate" is called. Depending on the NNTP response code - returned by "authenticate", the authentication hook either succeeds or - fails, after which the processing of the auth group continues as usual. - When the connection with the client is closed, the method "authen_close" - is called if it exists. - - Dynamic Generation of Access Groups - - A Python script may be used to dynamically generate an access group - which is then used to determine the access rights of the client. This - occurs whenever the *python_access* parameter is specified in an auth - group which has successfully matched the client. Only one - *python_access* statement is allowed in an auth group. This parameter - should not be mixed with a *perl_access* statement in the same auth - group. - - When a *python_access* parameter is encountered, Python is loaded (if it - has yet to be) and the file given as argument is loaded as well (do not - include the ".py" extension of this file in the value of - *python_access*). If a Python object with a method "access_init" is - hooked in during the loading of that file, then that method is called - immediately after the file is loaded. If no errors have occurred, the - method "access" is called. The dictionary returned by "access" is used - to generate an access group that is then used to determine the access - rights of the client. When the connection with the client is closed, - the method "access_close" is called, if it exists. - - While you may include the *users* parameter in a dynamically generated - access group, some care should be taken (unless your pattern is just "*" - which is equivalent to leaving the parameter out). The group created - with the values returned from the Python script is the only one - considered when nnrpd attempts to find an access group matching the - connection. If a *users* parameter is included and it does not match - the connection, then the client will be denied access since there are no - other access groups which could match the connection. - - Dynamic Access Control - - If you need to have access control rules applied immediately without - having to restart all the nnrpd processes, you may apply access control - on a per newsgroup basis using the Python dynamic hooks (as opposed to - readers.conf, which does the same on per user basis). These hooks are - activated through the inclusion of the *python_dynamic* parameter in a - readers.conf auth group. Only one *python_dynamic* statement is allowed - in an auth group. - - When a *python_dynamic* parameter is encountered, Python is loaded (if - it has yet to be) and the file given as argument is loaded as well (do - not include the ".py" extension of this file in the value of - *python_dynamic*). If a Python object with a method "dynamic_init" is - hooked in during the loading of that file, then that method is called - immediately after the file is loaded. Every time a reader asks nnrpd to - read or post an article, the Python method "dynamic" is invoked before - proceeding with the requested operation. Based on the value returned by - "dynamic", the operation is either permitted or denied. When the - connection with the client is closed, the method "access_close" is - called if it exists. - - Writing a Python nnrpd Authentication Module - - You need to create a nnrpd_auth.py module in INN's filter directory (see - the *pathfilter* setting in inn.conf) where you should define a class - holding certain methods depending on which hooks you want to use. - - Note that you will have to use different Python scripts for - authentication and access: the values of *python_auth*, *python_access* - and *python_dynamic* have to be distinct for your scripts to work. - - The following methods are known to nnrpd: - - __init__(*self*) - Not explicitly called by nnrpd, but will run whenever the auth - module is loaded. Use this method to initialize any general - variables or open a common database connection. This method may be - omitted. - - authen_init(*self*) - Initialization function specific to authentication. This method may - be omitted. - - authenticate(*self*, *attributes*) - Called when a *python_auth* statement is reached in the processing - of readers.conf. Connection attributes are passed in the - *attributes* dictionary. Returns a response code, an error string, - and an optional string to be used in place of the client-supplied - username (both for logging and for matching the connection with an - access group). - - authen_close(*self*) - This method is invoked on nnrpd termination. You can use it to save - state information or close a database connection. This method may - be omitted. - - access_init(*self*) - Initialization function specific to generation of an access group. - This method may be omitted. - - access(*self*, *attributes*) - Called when a *python_access* statement is reached in the processing - of readers.conf. Connection attributes are passed in the - *attributes* dictionary. Returns a dictionary of values - representing statements to be included in an access group. - - access_close(*self*) - This method is invoked on nnrpd termination. You can use it to save - state information or close a database connection. This method may - be omitted. - - dynamic_init(*self*) - Initialization function specific to dynamic access control. This - method may be omitted. - - dynamic(*self*, *attributes*) - Called when a client requests a newsgroup, an article or attempts to - post. Connection attributes are passed in the *attributes* - dictionary. Returns "None" to grant access, or a non-empty string - (which will be reported back to the client) otherwise. - - dynamic_close(*self*) - This method is invoked on nnrpd termination. You can use it to save - state information or close a database connection. This method may - be omitted. - - The *attributes* Dictionary - - The keys and associated values of the *attributes* dictionary are - described below. - - *type* - "read" or "post" values specify the authentication type; only valid - for the "dynamic" method. - - *hostname* - It is the resolved hostname (or IP address if resolution fails) of - the connected reader. - - *ipaddress* - The IP address of the connected reader. - - *port* - The port of the connected reader. - - *interface* - The hostname of the local endpoint of the NNTP connection. - - *intipaddr* - The IP address of the local endpoint of the NNTP connection. - - *intport* - The port of the local endpoint of the NNTP connection. - - *user* - The username as passed with AUTHINFO command, or "None" if not - applicable. - - *pass* - The password as passed with AUTHINFO command, or "None" if not - applicable. - - *newsgroup* - The name of the newsgroup to which the reader requests read or post - access; only valid for the "dynamic" method. - - All the above values are buffer objects (see the notes above on what - buffer objects are). - - How to Use these Methods with nnrpd - - To register your methods with nnrpd, you need to create an instance of - your class, import the built-in nnrpd module, and pass the instance to - "nnrpd.set_auth_hook". For example: - - class AUTH: - def authen_init(self): - ... - blah blah - ... - - def authenticate(self, attributes): - ... - yadda yadda - ... - - import nnrpd - myauth = AUTH() - nnrpd.set_auth_hook(myauth) - - When writing and testing your Python filter, don't be afraid to make use - of "try:"/"except:" and the provided "nnrpd.syslog" function. stdout - and stderr will be disabled, so your filter will die silently otherwise. - - Also, remember to try importing your module interactively before loading - it, to ensure there are no obvious errors. One typo can ruin your whole - filter. A dummy nnrpd.py module is provided to facilitate testing - outside the server. It is not actually used by nnrpd but provides the - same set of functions as built-in nnrpd module. This stub module may be - used when debugging your own module. To test, change into your filter - directory and use a command like: - - python -ic 'import nnrpd, nnrpd_auth' - - Functions Supplied by the Built-in nnrpd Module - - Besides "nnrpd.set_auth_hook" used to pass a reference to the instance - of authentication and authorization class to nnrpd, the nnrpd built-in - module exports the following function: - - syslog(*level*, *message*) - It is intended to be a replacement for a Python native syslog. It - works like "INN.syslog", seen above. - - $Id: hook-python 7926 2008-06-29 08:27:41Z iulius $ - diff --git a/doc/hook-tcl b/doc/hook-tcl deleted file mode 100644 index 14c4f00..0000000 --- a/doc/hook-tcl +++ /dev/null @@ -1,99 +0,0 @@ -NOTE: The Tcl support described in this file is disabled. The code is -all still there, but you have to define DO_TCL manually while compiling to -enable it. Compiling in Tcl filtering was causing random innd segfaults -even if no Tcl filters were defined, so it's been turned off to prevent -confusion. - -The Tcl code will be removed in the next major release of INN since no one -appears to be using it and the code is unmaintained and has no champion. -If you want to resurrect it, it may be better to start from scratch, since -a lot has changed about INN since the filters were originally written and -the Perl and Python filters have far more capabilities. - - -Note, you need tcl 7.4. Rumour has it that 7.5 won't work. ---------------------------------------------------------------------------- -Subject: TCL-based Filtering for INN 1.5 -Date: Mon, 07 Feb 94 12:36:47 -0800 -From: Bob Heiney - - -Several times in the past few months, a site or two has started posting -the same article over and over again, but with a different message id. -Usually this is caused by broken software (e.g. mail <-> news gateways, -which many have written, but few have written correctly). -Occasionally, however, the reposting is intentional. A recent example -would be the "Global Alert: Jesus Is Coming" message which was posted -to over 2200 newsgroups (each copy with its own message id). - -I expect this to happen more often as the Internet continues its explosive -growth. Although my site (decwrl) usually has enough excess capacity to -weather these problems, many other sites cannot. One problem on -comp.sys.sgi.misc several months ago spewed 40MB of duplicate articles -before the offending sites were fixed, and this overflowed the spool at -many sites. Even for sites with lots of resources, there's still no need -to propagate erroneous or malicious duplicates. - -I wanted a way to protect my site that was highly specific, flexible, and -quick. - -Examination of duplicated articles showed that although the message ids -were different, it was usually easy for a news admin to come up with a -few rules based on the headers of the article that could be used to -differentiate the duplicates from other articles. (E.g. from -John.Doe@foo.com to comp.sys.sgi.misc with 'foobar' in the subject".) -I concluded that modifying innd to let me say "kill things that look -like _this_" would solve my problem. - -I also wanted to allow enough flexibilty in the design that I could -later work on automatic detection and elimination of excessive -duplicates (using a body checksum instead of headers). - -Since I needed a fairly powerful language to do all this, and since the -world doesn't need yet another special language, my solution was to add TCL -support to INN. I then modified "ARTpost" to call a TCL procedure which -could then accept or reject the article. The TCL code has access to an -associative array called "Headers", which contains all of the articles -headers. The TCL code may also call a 32-bit article-body checksum -procedure (this is to aid in future automatic detection of duplicates). - -Here's what a sample TCL filter procedure looks like: - -proc filter_news {} { - global o Headers - set sum [checksum_article] - puts $o "$Headers(Message-ID) $sum" - set newsgroups [split $Headers(Newsgroups) ,] - foreach i $newsgroups { - if {$i=="alt.test" && [string match "*heiney@pa.dec.com*" $Headers(From)]} { - return "dont like alt.test from heiney" - } - } - return "accept" -} - -The above TCL code does a few things. First it computes a 32-bit -checksum and writes it and the message ID to a file. It then rejects -articles from me to alt.test. - -The work I've done is totally integrated into the INN build and runtime -environments. For example, to turn filtering off, you'd just type - - ctlinnd filter n - -To reload the TCL code that does the filtering, you just say - - ctlinnd reload filter.tcl 'your comment here' - -(You may specify TCL callbacks to be executed right before and/or right -after reloading, in case your filter is doing fancy stuff.) See the -ctlinnd man page for more info. - -Filtering capability that's this powerful can be used for many -purposes, some benign and useful (excessive duplicate detections, -on-the-fly statistics), others abusive. I would ask that news admins -think carefully about any filtering they do. - -/Bob - - diff --git a/doc/man/Makefile b/doc/man/Makefile deleted file mode 100644 index 3e1a758..0000000 --- a/doc/man/Makefile +++ /dev/null @@ -1,66 +0,0 @@ -## $Id: Makefile 7458 2005-12-12 00:25:05Z eagle $ - -include ../../Makefile.global - -top = ../.. - -## Edit these if you need to. -MANFLAGS = -c $(OWNER) -m 0444 -B .OLD - -SEC1 = convdate.1 fastrm.1 getlist.1 grephistory.1 inews.1 innconfval.1 \ - innfeed.1 innmail.1 nntpget.1 pgpverify.1 pullnews.1 rnews.1 \ - shlock.1 shrinkfile.1 simpleftp.1 sm.1 startinnfeed.1 - -SEC3 = clientlib.3 dbz.3 inndcomm.3 libauth.3 libinn.3 libinnhist.3 \ - libstorage.3 list.3 parsedate.3 qio.3 tst.3 uwildmat.3 - -SEC5 = active.5 active.times.5 buffindexed.conf.5 control.ctl.5 \ - cycbuff.conf.5 distrib.pats.5 expire.ctl.5 history.5 incoming.conf.5 \ - inn.conf.5 innfeed.conf.5 innwatch.ctl.5 moderators.5 motd.news.5 \ - newsfeeds.5 nnrpd.track.5 newslog.5 nntpsend.ctl.5 ovdb.5 \ - overview.fmt.5 passwd.nntp.5 radius.conf.5 readers.conf.5 sasl.conf.5 \ - storage.conf.5 subscriptions.5 - -SEC8 = actsync.8 actsyncd.8 archive.8 auth_smb.8 batcher.8 buffchan.8 \ - ckpasswd.8 cnfsheadconf.8 cnfsstat.8 controlchan.8 ctlinnd.8 \ - cvtbatch.8 domain.8 expire.8 expireover.8 expirerm.8 filechan.8 \ - ident.8 inncheck.8 innd.8 inndf.8 inndstart.8 innreport.8 innstat.8 \ - innupgrade.8 innwatch.8 innxbatch.8 innxmit.8 mailpost.8 makedbz.8 \ - makehistory.8 mod-active.8 news.daily.8 news2mail.8 ninpaths.8 \ - nnrpd.8 nntpsend.8 ovdb_init.8 ovdb_monitor.8 ovdb_server.8 \ - ovdb_stat.8 overchan.8 perl-nocem.8 prunehistory.8 radius.8 \ - rc.news.8 scanlogs.8 send-nntp.8 send-uucp.8 sendinpaths.8 \ - tally.control.8 tdx-util.8 writelog.8 - -COPY = $(SHELL) ./putman.sh $(MANPAGESTYLE) "$(MANFLAGS)" - -all: -clobber clean distclean: -tags ctags: -profiled: - -install: install-man1 install-man3 install-man5 install-man8 - -install-man1: - for M in $(SEC1) ; do \ - $(COPY) $$M $D$(MAN1)/$$M ; \ - done - -install-man3: - for M in $(SEC3) ; do \ - $(COPY) $$M $D$(MAN3)/$$M ; \ - done - -install-man5: - for M in $(SEC5) ; do \ - $(COPY) $$M $D$(MAN5)/$$M ; \ - done - -# auth_krb5 is conditionally compiled, so handle it specially. -install-man8: - for M in $(SEC8) ; do \ - $(COPY) $$M $D$(MAN8)/$$M ; \ - done - if [ x"$(KRB5_AUTH)" != x ] ; then \ - $(COPY) auth_krb5.8 $D$(MAN8)/auth_krb5.8 ; \ - fi diff --git a/doc/man/active.5 b/doc/man/active.5 deleted file mode 100644 index 97a0d62..0000000 --- a/doc/man/active.5 +++ /dev/null @@ -1,221 +0,0 @@ -.\" Automatically generated by Pod::Man v1.37, Pod::Parser v1.32 -.\" -.\" Standard preamble: -.\" ======================================================================== -.de Sh \" Subsection heading -.br -.if t .Sp -.ne 5 -.PP -\fB\\$1\fR -.PP -.. -.de Sp \" Vertical space (when we can't use .PP) -.if t .sp .5v -.if n .sp -.. -.de Vb \" Begin verbatim text -.ft CW -.nf -.ne \\$1 -.. -.de Ve \" End verbatim text -.ft R -.fi -.. -.\" Set up some character translations and predefined strings. \*(-- will -.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left -.\" double quote, and \*(R" will give a right double quote. \*(C+ will -.\" give a nicer C++. Capital omega is used to do unbreakable dashes and -.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, -.\" nothing in troff, for use with C<>. -.tr \(*W- -.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' -.ie n \{\ -. ds -- \(*W- -. ds PI pi -. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch -. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch -. ds L" "" -. ds R" "" -. ds C` "" -. ds C' "" -'br\} -.el\{\ -. ds -- \|\(em\| -. ds PI \(*p -. ds L" `` -. ds R" '' -'br\} -.\" -.\" If the F register is turned on, we'll generate index entries on stderr for -.\" titles (.TH), headers (.SH), subsections (.Sh), items (.Ip), and index -.\" entries marked with X<> in POD. Of course, you'll have to process the -.\" output yourself in some meaningful fashion. -.if \nF \{\ -. de IX -. tm Index:\\$1\t\\n%\t"\\$2" -.. -. nr % 0 -. rr F -.\} -.\" -.\" For nroff, turn off justification. Always turn off hyphenation; it makes -.\" way too many mistakes in technical documents. -.hy 0 -.if n .na -.\" -.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). -.\" Fear. Run. Save yourself. No user-serviceable parts. -. \" fudge factors for nroff and troff -.if n \{\ -. ds #H 0 -. ds #V .8m -. ds #F .3m -. ds #[ \f1 -. ds #] \fP -.\} -.if t \{\ -. ds #H ((1u-(\\\\n(.fu%2u))*.13m) -. ds #V .6m -. ds #F 0 -. ds #[ \& -. ds #] \& -.\} -. \" simple accents for nroff and troff -.if n \{\ -. ds ' \& -. ds ` \& -. ds ^ \& -. ds , \& -. ds ~ ~ -. ds / -.\} -.if t \{\ -. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" -. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' -. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' -. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' -. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' -. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' -.\} -. \" troff and (daisy-wheel) nroff accents -.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' -.ds 8 \h'\*(#H'\(*b\h'-\*(#H' -.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] -.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' -.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' -.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] -.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] -.ds ae a\h'-(\w'a'u*4/10)'e -.ds Ae A\h'-(\w'A'u*4/10)'E -. \" corrections for vroff -.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' -.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' -. \" for low resolution devices (crt and lpr) -.if \n(.H>23 .if \n(.V>19 \ -\{\ -. ds : e -. ds 8 ss -. ds o a -. ds d- d\h'-1'\(ga -. ds D- D\h'-1'\(hy -. ds th \o'bp' -. ds Th \o'LP' -. ds ae ae -. ds Ae AE -.\} -.rm #[ #] #H #V #F C -.\" ======================================================================== -.\" -.IX Title "ACTIVE 5" -.TH ACTIVE 5 "2008-04-06" "INN 2.4.5" "InterNetNews Documentation" -.SH "NAME" -active \- List of newsgroups carried by the server -.SH "DESCRIPTION" -.IX Header "DESCRIPTION" -The file \fIpathdb\fR/active lists the newsgroups carried by \s-1INN\s0. This file -is generally maintained using \fIctlinnd\fR\|(8) to create and remove groups, or -by letting \fIcontrolchan\fR\|(8) do so on the basis of received control messages. -This file should not be edited directly without throttling \fBinnd\fR, and -must be reloaded using \fBctlinnd\fR before \fBinnd\fR is unthrottled. Editing -it directly even with those precautions may make it inconsistent with the -overview database and won't update \fIactive.times\fR, so \fBctlinnd\fR should -be used to make modifications whenever possible. -.PP -Each newsgroup should be listed only once. Each line specifies one group. -The order of groups does not matter. Within each newsgroup, received -articles for that group are assigned monotonically increasing numbers as -unique names. If an article is posted to newsgroups not mentioned in this -file, those newsgroups are ignored. -.PP -If none of the newsgroups listed in the Newsgroups header of an article -are present in this file, the article is either rejected (if \fIwanttrash\fR -is false in \fIinn.conf\fR), or is filed into the newsgroup \f(CW\*(C`junk\*(C'\fR and only -propagated to sites that receive the \f(CW\*(C`junk\*(C'\fR newsgroup (if \fIwanttrash\fR is -true). -.PP -Each line of this file consists of four fields separated by a space: -.PP -.Vb 1 -\& -.Ve -.PP -The first field is the name of the newsgroup. The newsgroup \f(CW\*(C`junk\*(C'\fR is -special, as mentioned above. The newsgroup \f(CW\*(C`control\*(C'\fR and any newsgroups -beginning with \f(CW\*(C`control.\*(C'\fR are also special; control messages are filed -into a control.* newsgroup named after the type of control message if that -group exists, and otherwise are filed into the newsgroup \f(CW\*(C`control\*(C'\fR -(without regard to what newsgroups are listed in the Newsgroups header). -If \fImergetogroups\fR is set to true in \fIinn.conf\fR, newsgroups that begin -with \f(CW\*(C`to.\*(C'\fR are also treated specially; see \fIinnd\fR\|(8). -.PP -The second field is the highest article number that has been used in that -newsgroup. The third field is the lowest article number in the group; -this number is not guaranteed to be accurate, and should only be taken to -be a hint. It is normally updated nightly as part of the expire process; -see \fInews.daily\fR\|(8) and look for \f(CW\*(C`lowmark\*(C'\fR or \f(CW\*(C`renumber\*(C'\fR for more details. -Note that because of article cancellations, there may be gaps in the -numbering sequence. If the lowest article number is greater then the -highest article number, then there are no articles in the newsgroup. In -order to make it possible to update an entry in-place without rewriting -the entire file, the second and third fields are padded out with leading -zeros to make them a fixed width. -.PP -The fourth field contains one of the following flags: -.PP -.Vb 6 -\& y Local postings are allowed. -\& m The group is moderated and all postings must be approved. -\& n No local postings are allowed, only articles from peers. -\& j Articles are filed in the junk group instead. -\& x No local postings and ignored for articles from peers. -\& =foo.bar Articles are filed in the group foo.bar instead. -.Ve -.PP -If a newsgroup has the \f(CW\*(C`j\*(C'\fR flag, no articles will be filed in that -newsgroup, and local postings to that group will be rejected. If an -article for that newsgroup is received from a remote site, and it is not -crossposted to some other valid group, it will be filed into the \f(CW\*(C`junk\*(C'\fR -newsgroup instead. This is different than simply not listing the group, -since the article will still be accepted and can be propagated to other -sites, and the \f(CW\*(C`junk\*(C'\fR group can be made available to readers if wished. -.PP -If the field begins with an equal sign, the newsgroup is an alias. -Articles cannot be posted to that newsgroup, but they can be received from -other sites. Any articles received from peers for that newsgroup are -treated as if they were actually posted to the group named after the equal -sign. Note that the Newsgroups header of the articles are not modified. -(Alias groups are typically used during a transition and are typically -created manually with \fIctlinnd\fR\|(8).) An alias should not point to another -alias. -.SH "HISTORY" -.IX Header "HISTORY" -Written by Rich \f(CW$alz\fR for InterNetNews. Converted to -\&\s-1POD\s0 by Russ Allbery . -.PP -$Id: active.5 7880 2008-06-16 20:37:13Z iulius $ -.SH "SEE ALSO" -.IX Header "SEE ALSO" -\&\fIactive.times\fR\|(5), \fIcontrolchan\fR\|(8), \fIctlinnd\fR\|(8), \fIinn.conf\fR\|(5), \fIinnd\fR\|(8), -\&\fInews.daily\fR\|(8) diff --git a/doc/man/active.times.5 b/doc/man/active.times.5 deleted file mode 100644 index 2b95ac5..0000000 --- a/doc/man/active.times.5 +++ /dev/null @@ -1,163 +0,0 @@ -.\" Automatically generated by Pod::Man v1.37, Pod::Parser v1.32 -.\" -.\" Standard preamble: -.\" ======================================================================== -.de Sh \" Subsection heading -.br -.if t .Sp -.ne 5 -.PP -\fB\\$1\fR -.PP -.. -.de Sp \" Vertical space (when we can't use .PP) -.if t .sp .5v -.if n .sp -.. -.de Vb \" Begin verbatim text -.ft CW -.nf -.ne \\$1 -.. -.de Ve \" End verbatim text -.ft R -.fi -.. -.\" Set up some character translations and predefined strings. \*(-- will -.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left -.\" double quote, and \*(R" will give a right double quote. \*(C+ will -.\" give a nicer C++. Capital omega is used to do unbreakable dashes and -.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, -.\" nothing in troff, for use with C<>. -.tr \(*W- -.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' -.ie n \{\ -. ds -- \(*W- -. ds PI pi -. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch -. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch -. ds L" "" -. ds R" "" -. ds C` "" -. ds C' "" -'br\} -.el\{\ -. ds -- \|\(em\| -. ds PI \(*p -. ds L" `` -. ds R" '' -'br\} -.\" -.\" If the F register is turned on, we'll generate index entries on stderr for -.\" titles (.TH), headers (.SH), subsections (.Sh), items (.Ip), and index -.\" entries marked with X<> in POD. Of course, you'll have to process the -.\" output yourself in some meaningful fashion. -.if \nF \{\ -. de IX -. tm Index:\\$1\t\\n%\t"\\$2" -.. -. nr % 0 -. rr F -.\} -.\" -.\" For nroff, turn off justification. Always turn off hyphenation; it makes -.\" way too many mistakes in technical documents. -.hy 0 -.if n .na -.\" -.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). -.\" Fear. Run. Save yourself. No user-serviceable parts. -. \" fudge factors for nroff and troff -.if n \{\ -. ds #H 0 -. ds #V .8m -. ds #F .3m -. ds #[ \f1 -. ds #] \fP -.\} -.if t \{\ -. ds #H ((1u-(\\\\n(.fu%2u))*.13m) -. ds #V .6m -. ds #F 0 -. ds #[ \& -. ds #] \& -.\} -. \" simple accents for nroff and troff -.if n \{\ -. ds ' \& -. ds ` \& -. ds ^ \& -. ds , \& -. ds ~ ~ -. ds / -.\} -.if t \{\ -. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" -. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' -. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' -. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' -. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' -. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' -.\} -. \" troff and (daisy-wheel) nroff accents -.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' -.ds 8 \h'\*(#H'\(*b\h'-\*(#H' -.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] -.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' -.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' -.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] -.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] -.ds ae a\h'-(\w'a'u*4/10)'e -.ds Ae A\h'-(\w'A'u*4/10)'E -. \" corrections for vroff -.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' -.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' -. \" for low resolution devices (crt and lpr) -.if \n(.H>23 .if \n(.V>19 \ -\{\ -. ds : e -. ds 8 ss -. ds o a -. ds d- d\h'-1'\(ga -. ds D- D\h'-1'\(hy -. ds th \o'bp' -. ds Th \o'LP' -. ds ae ae -. ds Ae AE -.\} -.rm #[ #] #H #V #F C -.\" ======================================================================== -.\" -.IX Title "ACTIVE.TIMES 5" -.TH ACTIVE.TIMES 5 "2008-04-06" "INN 2.4.5" "InterNetNews Documentation" -.SH "NAME" -active.times \- List of local creation times of newsgroups -.SH "DESCRIPTION" -.IX Header "DESCRIPTION" -The file \fIpathdb\fR/active.times provides a chronological record of when -newsgruops were created on the local server. This file is normally -updated by \fBinnd\fR whenever a newgroup control message is processed or a -\&\f(CW\*(C`ctlinnd newgroup\*(C'\fR command is issued, and is used by \fBnnrpd\fR to answer -\&\s-1NEWGROUPS\s0 requests. -.PP -Each line consists of three fields: -.PP -.Vb 1 -\&