uqwk-2.21/scripts/getsoup100644 35070 36 5516 6670766661 13433 0ustar jsuser#!/bin/sh # $Id: getsoup,v 1.1 1999/03/08 15:28:40 js Exp $ UQWKARGS="-B0 -m +L" # What to do? Set variables to enable. #UQ_DO_MAIL=1 UQ_DO_NEWS=1 export UQ_DO_MAIL UQ_DO_NEWS # NNTPAUTH="yes please!" # When reading mail from the system mailbox, locking # will have to be done somehow. If your Unix system # does not have lockfile, but does have /usr/ucb/mail, # use UQ_LOCKING="ucbmail". See below. UQ_LOCKING="lockfile" # # No user servicable parts below (I hope) # prg=`basename $0` if [ -z "$UQ_DO_MAIL" -a -z "$UQ_DO_NEWS" ] then echo "$prg: nothing to do" >&2 exit fi UQ_HOME_DIR=$HOME/.uqwk UQ_NRC_FILE=$HOME/.newsrc export UQ_HOME_DIR UQ_NRC_FILE # Do things in a nice, cozy subdirectory if [ ! -d $UQ_HOME_DIR ] then echo "$prg: $UQ_HOME_DIR does not exist, creating it" mkdir -p $UQ_HOME_DIR if [ ! -d $UQ_HOME_DIR ] then echo "$prg: failed to create $UQ_HOME_DIR" >&2 echo "$prg: bailing out" >&2 exit 1 fi fi cd $UQ_HOME_DIR soupfile=soup.zip if [ -f $soupfile ] ; then echo "Hmmm, $soupfile already exists." rm -i $soupfile if [ -f $soupfile ] ; then exit 1 fi fi if [ -n "$UQ_DO_NEWS" ] then UQWKARGS="$UQWKARGS +n" # Get auth stuff (nntp auth mode only) if [ -n "$NNTPAUTH" ] then while [ -z "$UQ_AUTH_PASS" ] do echo "Authentication for server $NNTPSERVER;" echo "Username: $USER, password: \\c" stty -echo read UQ_AUTH_PASS; echo stty echo done # Pass these through environment UQ_AUTH_USER=$USER; export UQ_AUTH_USER UQ_AUTH_PASS fi fi if [ -n "$UQ_DO_MAIL" ] then UQWKARGS="$UQWKARGS +m" # Read mail from the system mail box? if [ -z "$UQ_MAIL_FILE" ] then # uqwk does not do mailbox locking. Locking options: # - procmail's nifty "lockfile" utility # - /usr/ucb/mail ("ucbmail") UQ_MAIL_FILE=/tmp/$prg.$USER.mbx.$$; export UQ_MAIL_FILE case $UQ_LOCKING in "lockfile") lockfile -l666 -ml; trap "lockfile -mu" 1 2 3 13 15 mv $MAIL $UQ_MAIL_FILE lockfile -mu; trap "" 1 2 3 13 15 ;; "ucbmail") ( echo 's1-$' $UQ_MAIL_FILE ; echo q ) | /usr/ucb/mail >/dev/null ;; *) echo "$prg: no, or unknown, locking method" >&2 echo "$prg: bailing out" >&2 exit 1 ;; esac fi fi # # Now we know how to call uqwk, proper args 'n' all # uqwk $UQWKARGS; err=$? if [ $err -ne 0 ] then echo "$prg: fatal error in uqwk" >&2 echo "$prg: proceed with caution" >&2 fi # Create the SOUP packet # if [ "`echo *.MSG`" = "*.MSG" ] then echo "Sorry, nothing to get." rm -f AREAS exit fi zip -m $soupfile AREAS *.MSG mv $soupfile $HOME echo "Done, you can upload now." uqwk-2.21/scripts/putsoup100644 35070 36 650 6670766661 13436 0ustar jsuser#!/bin/sh # $Id: putsoup,v 1.1 1999/03/08 15:28:40 js Exp $ prg=`basename $0` rf=reply.zip; cd $UQ_HOME_DIR if [ ! -f $rf ]; then echo "$prg: no reply packet found" >&2 exit 1 fi unzip -ju $rf 2>/dev/null if uqwk -m -n +L -RREPLIES then echo "$prg: fatal uqwk error, proceed with caution" >&2 fi echo "Done. If all went well, $rf can safely be deleted." rm -i $rf uqwk-2.21/scripts/unix2mac100644 35070 36 1451 6670766661 13465 0ustar jsuser#!/bin/sh # $Id: unix2mac,v 1.1 1999/03/08 15:28:41 js Exp $ prog=`basename $0` tmp=/tmp/$prog.$$ trap 'rm -f $tmp' 0 1 case $# in 0) ;; 1) if cp $1 $tmp 2> /dev/null; then :; else echo "$prog: could not open $1"; exit 1; fi exec < $tmp > $1 ;; 2) if cp $1 $tmp 2> /dev/null; then :; else echo "$prog: could not open $1"; exit 1; fi exec < $tmp > $2 ;; *) echo "Usage: $prog [infile] [outfile]" exit 1 ;; esac case $prog in mac2unix) tr '\015' '\012' ;; unix2mac) tr '\012' '\015' ;; dos2unix) sed -e 's/ $//g' ;; unix2dos) sed -e 's/$/ /g' ;; dos2mac) sed -e 's/ $//g' | tr '\012' '\015' ;; mac2dos) tr '\015' '\012' | sed -e 's/$/ /g' ;; dos2dos|mac2mac|unix2unix) ;; *) echo 'I can only convert between Mac, Unix and DOS. What else?' exit 1 ;; esac uqwk-2.21/README.Typhoon100600 35070 36 1715 6762163025 12622 0ustar jsuser $Id: README.Typhoon,v 1.1 1999/08/29 07:49:41 js Exp $ There is a known problem with the Typhoon news server, at least in versions < 1.2.1. Version 1.2.2 is claimed to fix it. The problem is that Typhoon reports existing groups as nonexistent; i.e. in an NNTP transacton, the following would typically happen: $ telnet typhoon.news.server nntp 200 typhoon.news.server Typhoon v.1.2.1 ready (posting ok). GROUP news.groups 411 No such group news.groups This is reported to be happen only under certain circumstances, in particular when a server is "chained" to a particular news server. If this bug bites you, please inform your news server's administrator. Updates to Typhoon that are claimed to fix this bug can be found at: When possible, I (Jeroen Scheerder ) would like to hear the details of the configuration that's causing the problem; i.e. the Typhoon version number, and whether chaining is indeed on. uqwk-2.21/FAQ100600 35070 36 17112 6705130414 10644 0ustar jsuser$Id: FAQ,v 1.3 1999/04/14 15:15:09 js Exp $ Frequently-Asked Questions about uqwk: ________________________________________________________________________ > uqwk creates files called control.dat, messages.dat, and *.ndx. How > do I make a QWK packet from those files? First, you really shouldn't use QWK mode -- see below. Trust me, you won't want to. Then again, if you really must for some reason: a QWK packet is just a ZIP archive of these files. So a command like "zip bbs.qwk control.dat messages.dat *.ndx" will create the QWK packet. If you don't have zip on your Unix system, contact your system administrator, or download those files and ZIP them on your PC. ________________________________________________________________________ > My site gets news from a news server. Can uqwk run in such an > environment? Yes. Compile the NNTP version of uqwk: see README. ________________________________________________________________________ > uqwk doesn't appear to do anything? The default behavior is just that. To get uqwk to collect your news, you have to explicitly ask it with the +n switch, and to get it to collect your mail, you have to set the "+m" switch. See the man page for details. ________________________________________________________________________ > I tell uqwk to collect my news, but all I get is a bunch of empty > *.ndx files. What's wrong? You may need the NNTP version of uqwk. See the README on how to compile the NNTP version. If that fails, your site may be running non-standard news software. Contact your news administrator for help. ________________________________________________________________________ > Our site's mail is not in /var/spool/mail. Can anything be done? > Our site's news is not in /var/spool/news. Can anything be done? > Our site's active file is not in /usr/lib/news. Can anything be done? You can define your site dependencies by creating a config file containing the site dependencies. Copy config-generic.h to config-.h, edit config-.h to your liking, and make sure Makefile contains "CONFIG=mysite". Furthermore, uqwk has runtime switches to control all these things and many more. See the man page for details. ________________________________________________________________________ > When I use uqwk to post a follow-up, it gets posted to the wrong > newsgroup. What can I do? Be sure you have the latest version (2.0 at this writing). Also, see the BUGS section in the man page. ________________________________________________________________________ > Is there any way to have uqwk create the packet files somewhere > besides my home directory? Yes. Use the -H switch to specify where you want the files to be created. Since uqwk will also look in this directory for the .newsrc file, you'll probably also have to use the -N switch to tell uqwk where to find your .newsrc. ________________________________________________________________________ > How do I get uqwk to process a QWK reply packet? Hrmpf. Once again, don't do that. Really; see below why not. Anyway, if you must: a QWK reply packet, usually named something.REP, is simply a ZIP archive of something.MSG. Unzip the archive, and feed something.MSG to uqwk thusly: uqwk -m -n -Rsomething.MSG ________________________________________________________________________ > How do I get uqwk to process an HDPF (SOUP) reply packet? Unzip the reply packet. Be sure to use the -U switch of unzip or else the file names will be mapped to lower case and uqwk won't find them. Then feed the REPLIES file to uqwk thusly: uqwk -m -n +L -RREPLIES ________________________________________________________________________ > How do I get uqwk to process a ZipNews reply packet? Unzip the reply packet. Then tell uqwk which *directory* the reply files are in. For example, if they are in your current directory, invoke uqwk thusly: uqwk -m -n +z -R. ________________________________________________________________________ > I have the registered ZipNews reader, but uqwk refuses to process > reply packets. Why? Be sure to specify "packer : uqwk" in your ZipNews Reader configuration file. ________________________________________________________________________ > Where can I get the latest version of uqwk? See . ________________________________________________________________________ > Where can I FTP reader programs? You might want to check , and its FAQ. A few candidates (remember, avoid QWK readers like the plague): MacSOUP (Mac OS): Yarn (DOS, OS/2): Helldiver Packet Viewer (DOS): ZipNews reader (DOS): Usenet Offline Reader (WINDOS): Note that these links may be outdated; an archie- or websearch might be worthwile. ________________________________________________________________________ > How can I get uqwk to work with my Waffle (Unix version) mailbox? Try changing the ^A's in the mailbox file to newlines: tr '\001' '\012' tmp-mailbox uqwk +m -ftmp-mailbox ________________________________________________________________________ > I've made score files, but with no noticable effects. Now what? Check to see if scoring support was compiled in: uqwk -p uqwk should identify itself as a scoring version. Also, verify that the score files are located in the proper directory. If all is as it should be, and it still doesn't work, try something *very* simple. For example, put a line "-666 Newsgroups: ," in your "global" file. Maek sure the "global" file is in the proper location (usually in the subdir ".uqwk" of your home directory). No run uqwk in "read only" mode (so you won't lose stuff): uqwk +r +n uqwk should start reporting "+(global scoring)", and for all your subscribed groups it will report "mm kept, nn killed". If not, check the man page carefully. ________________________________________________________________________ > I've configured uqwk to use the QWK format, but it keeps nagging me, > telling me I shouldn't. Why? The QWK format imposes certain restrictions on messages that are irreconcilable with basic Usenet (and even mail, but less urgently there) requirements. Consequently, when using QWK, articles get severely damaged, and you'll be causing damage to the newsgroups you post to -- and you'll be aggravating a lot of people. So, just don't do that; getting another newsreader that can handle SOUP packets is by far preferrable to messing up things with QWK-damaged contributions. Either that, or put on your best asbestos suit. You'll need it to cope with the flames you're bound to provoke. ________________________________________________________________________ > I get error and warning messages when I try to process reply packets. > What's all this, then? uqwk can be set up to do basic sanity checking on articles before they are posted to Usenet; if they will be posted to Usenet, they should be valid Usenet articles. Much problems have been caused (and are still being caused) by software (and people inadvertently messing up things they shouldn't be able to). This can have all kinds of unwanted effects; uqwk is helping you to prevent these bad things from happening. If you really insist on posting messages that violate the requirements for Usenet messages, you can. you can tell uqwk to post failing messages anyway. The man page explains how to acomplish this. ________________________________________________________________________ uqwk-2.21/HISTORY100600 35070 36 24335 7366072516 11417 0ustar jsuser$Id: HISTORY,v 1.13 2001/10/25 20:22:19 js Exp $ uqwk 2.21 (js, 10/25/2001) - Rewrote a little part of the signal handling/error returning code uqwk 2.20 (js, 10/24/2001) - More bugfixed, most related to maildir and signal handling, as proposed by Jos en Bekker. uqwk 2.19 (js, 10/23/2001) - Fixed a bug when SUBSCRIBEing to a group, an offline command; with no connection to the server, this would still result in attempts to communicate with it. Thanks, Jos den Bekker! uqwk 2.18 (js, 10/05/2001) - Fixed a bug where uqwk closed an already closed file handle, causing SIGSEGV's on some platforms, thanks to Konstantin Isakov and Peter Karlsson. uqwk 2.17 (js, 04/19/2001) - Fixed a one-off error in a mail reading error message, thanks to Jos den Bekker. uqwk 2.16 (js, 06/21/2000) - Fixed a bug that broke compilation without NNTP support, as noted by Peter Karlsson. Thanks, Peter! uqwk 2.15 (js, 01/03/2000) - Applied Doug Kaufman's patches. Thanks, Doug! uqwk 2.14 (js, 10/19/1999) - Included Helmut Karlowski's modifications to ignore errors on opening articles. Thanks, Helmut! - Brought the manual page up to date. uqwk 2.13 (js, 09/11/1999) - Fixed an NNTP command that accidentally carried a newline too much (causing existing groups to be reported as nonexistent in the worst case). Thanks to Jeff Schroeder. uqwk 2.12 (js, 07/15/1999) - Fixed a nasty bug in SLNP (SOUP) mail reply handling in which article length was determined incorrectly uqwk 2.11 (js, 05/20/1999) - Several small changes to make uqwk compiler cleaner than ever (thanks mainly to George Schwarz) uqwk 2.10 (js, 05/14/1999) - Put under `configure' control - Made to compile cleanly (even when being pedantic) uqwk 2.09 (js, 05/12/1998) - More code cleanup - Preempted nonexisting MSG files from addition to the AREAS file (SOUP mode) (thanks to George Schwarz for pointing this out and testing) uqwk 2.08 (js, 03/07/1998) - Finished(?) maildir support; thanks to Jos den Bekker for code revision, contribution and testing. uqwk 2.07 (js, 03/04/1998) - Rudimentary maildir support - Preparations for full maildir support - Some cleanup uqwk 2.06 (js, 06/02/1998) - Removed obsolete (unused) code from misc.c uqwk 2.05 (js, 05/25/1998) - Tiny modification (due to a change in GNKSAlib's API) uqwk 2.04 (js, 03/26/1998) - fixes a summary mode bug (news.c) that somehow crept in along the way (thanks to Doug Kaufman for the report and the fix). uqwk 2.03 (js, 02/16/1998) - fixed an (ancient, yet unnoticed all this time...) bug in appending messages (both mail and news) to QWK "messages.dat" files. uqwk 2.02 (js, 02/09/1998) - fixed a tiny bug in init.c/close.c: when processing replies only, NNTP connections were opened/closed unnecessarily (NNTP uqwk only) uqwk 2.01 (js, 01/06/1998) - added basic status reporting when fetching mail uqwk 2.0 (js, 12/16/1997 -- final version) - updated to reflect MANKSA name (and interface) change (MANKSA is now (again) GNKSA, the Good Net-Keeping Seal of Approval) - extensive acceptance testing in real life situations, no problems found -- so it went final. Finally. uqwk 2.0fc4 (js, 11/12/1997 -- fourth final candidate version) - rnews batches (== SOUP newsgroup files) contain `indexes' which are _almost_ the article byte length -- almost, because line termination counts as a single byte, even if represented by multiple. When news articles -- they shouldn't, but sometimes do somehow -- contain \r\n line termination, uqwk used a wrong index (the file size of the article instead of the size with the number of \r's subtracted). uqwk now makes excruciatingly sure that articles are written to the SOUP files in Unix format, with '\n' line termination, and correct article indexing in them. - a few other (minor) fixes in news.c's error handling uqwk 2.0fc2 (js, 10/22/1997 -- second final candidate version) - changed (enhanced) control over message validation (-Vn switch) - worked around a few bugs occurring in a particular Unix version better left unmentioned. uqwk 2.0fc1 (js, 10/21/1997 -- first final candidate version) - A few (very minor) cleanups in reply.c - Rethought some of the GNKSA validation decisions (and adapted the man page accordingly) uqwk 2.0b7 (js, 10/13/1997 -- seventh beta version) - Updated calls to gnksalib routines uqwk 2.0b6 (js, 10/07/1997 -- sixth beta version) - Fixed (usually spurious) extra `group' (directly after FindActive() in DoGroup in NNTP mode - Fixed one more instance of a conference being created before testing whether the group actually exists - Reorganized/cleaned up a bit in news.c uqwk 2.0b5 (js, 10/06/1997 -- fifth beta version) - SOUP mode: a .MSG file was created, even for non-existing groups -- fixed - fixed a fclose() on a possibly null filehandle (crashing bug) - Updated the man page, and the getsoup script, for decent mailbox locking strategies, and some information about it uqwk 2.0b4 (js, 10/06/1997 -- fourth beta version) - Small robustness patch, and enhanced user feedback in the offline command handling functions (once again, thanks Jos den Bekker) uqwk 2.0b3 (js, 10/03/1997 -- third beta version) - More fixes in the mail handling part (again, thanks to Jos den Bekker) uqwk 2.0b2 (js, 10/01/1997 -- second beta version) - Fixes in offline.c's OffLine function (reported and fixed by Jos den Bekker uqwk 2.0b1 (js, 09/30/1997 -- first beta version) - Calls sendmail directly when mailing, in _all_ cases (sometimes, "mail" was used, sometimes sendmail) - Fixed a few bugs w.r.t. returning errorcodes - Added `-I/path/to/inews' switch and global variables containing the inews path as well as a full inews call (/path/to/inews -h); removed `INEWS_WRAPPER' compile option. Added UQ_INEWS_PATH environment variable - Added (basic) message validation support (GNKSA, using gnksalib) - Added `+V', `-V' switches (and `UQ_VALIDATE' environment var) to enable/disable message validation - Added a warning message against using QWK mode (Usenet message headers get maimed when using the QWK format) - Updated the man page Note: at present, `gnksalib' is preliminary, and under development. uqwk1.8++ (js, 08/26/97 -- intermediate version): - NNTP version does not fetch entire active file, but uses the GROUP command to obtain group article counts (big performance win) - Fixed scoring bugs (group score rules lingered on...) - Fixed bugs in NNTP buffer lengtht - Fixed bugs writing .newsrc files - Added errorchecking, -handling en -returning throughout the program (on I/O errors) - Added `-i' to sendmail invocation, to make it dot-transparent - Added NNTP authentication code - Integrated Jim Tittsler's scoring code - More sanity checks added: !(zip_mode && slnp_mode) - Changed SERVER #define (indicating NNTP mode) to NNTP - Changed nntp-code to be harmles (empty) if compiled without NNTP defined - Integrated Makefile.nntp into Makefile, and ditched Makefile - Added "install" and "install.man" options to Makefile - Got rid of uqwk.cat, renamed uqwk.man to uqwk.1 - Changed behaviour regarding "irrelevant" options, and added `-v' and `-?' (identical to `-p'). - Updated documentation uqwk1.8: - Fixed fclose() of non-open file in close.c which caused core dumps. - Properly define sum_flag in uqwk.h to keep compilers happy. - Support for a desired newsgroup table, used to specify the order of newsgroup processing instead of the .newsrc. (-D) - Don't write ZipNews mail file if no mail. - ^Z's stripped in ZipNews mode to keep ZNR happy. - Command language works in ZipNews mode (really!). - Various changes and cleanup suggested by nick@kralizec.zeta.org.au (Nick) - Various changes and cleanup suggested by raarts@hacktic.nl (Ron Arts) (Thanks guys!) - Unsubscribed groups not listed by GROUPS offline command. - Sanity checking on options: sum_mode | sel_mode -> do_news sum_mode -> !zip_mode && !slnp_mode sum_mode -> !do_mail - artnum problem in NNTP code fixed, caused core dumps. - CR's causing off-by-one error in offline processing, fixed. - MODE READER sent to NNTP server to keep INN happy. - Quote "to" address in sendmail popen()'s, so addresses like "seb3@gte.com (steve belczyk)" work now. - Use "sendmail -t" in SOUP mode -- Bcc: works now. - Verbose messages in ZipNews and SOUP mode. - Use "SOUP" in documentation. - Option to write every group to control.dat. (+e) - Selection mode fooled by CR's. Fixed. - Email conference number wrong in selection mode. Fixed. - Don't write control file if just replying. uqwk1.7: - Command language works for ZipNews and Helldiver - CATCHUP offline command - Write ZipNews mail - Block limit works in ZipNews and HDPF modes - Option to suppress crossposting (+x) - Ignore empty groups - Blue wave kludge (+W) - Process .newsrc frontwards - Expert QWK mode (+X) - ZipNews replies - Handle Cc: lines in HDPF and ZipNews modes - Offline subject selection (-U and -E) - Fix NNTP null file descriptor bug - FAQ list uqwk 1.6: - Added Helldiver (SLNP) support - Added ZipNews news-reading support - Fixed a bug in date parsing - Support "holes" in the .newsrc - Include door.id file uqwk 1.5: - In ReadNewsrc, assign a conference number of -1 to unsubscribed newsgroups. - Somehow handle bogus groups that don't appear in the active file. Maybe they should be treated as unsubscribed groups. - Better From: field parsing - Start processing articles at the active low if it's greater than the newsrc hi. - Fix the nagging bug in LastInt(). - stderr in line 60 of init.c. - Make followups work with NNTP's mini-inews. - Get rid of prototypes in news.c. - New SHELL offline command. uqwk 1.4: - News articles can be obtained from a news server using NNTP (thanks to Ken Whedbee). - Long email addresses can be specified in a "To:" line in the body of replies. - The newsrc file can be interpreted as a Waffle "join" file. - A newsgroup name translation table is supported. uqwk 1.3: - Fix a big problem which caused articles to be posted to the wrong newsgroup. uqwk 1.2: - Fix a pretty nasty bug reading some .newsrc files. uqwk 1.1: - A new switch, "-l" to limit the length of newsgroup names. - Core dumps on unsubscribed, unread newsgroups fixed. - Control.dat now created in proper directory. - Some other small changes and code clean-up. uqwk 1.0: - Original release uqwk-2.21/INSTALL100600 35070 36 3447 6707126376 11347 0ustar jsuser $Id: INSTALL,v 1.6 1999/04/20 16:36:14 js Exp $ INSTALLING UQWK 0. Get the uqwk distribution somewhere, and extract the archive wherever you like it to be. Example: $ cd /usr/local/src $ lynx -dump http://www.xs4all.nl/%7Ejs/warez/uqwk.tar.gz | gtar zxf - 1. Go to the uqwk distribution directory. Example: $ cd $HOME/src/uqwk20 2. Use `configure' to prepare for compilation. Use configure's `--help' option to check for available options. Example 0 -- getting help from configure: $ ./configure --help Example 1 -- using default install locations and options: $ ./configure Example 2 -- nstalling in $HOME, specifying site config file, replacing broken system regex stuff, and disabling scoring: $ ./configure --with-prefix=$HOME --with-regex=../gnu-regex-0.12 \ --with-config=config-mysite.h --disable-scores After running configure a Makefile will be set up, ready to run. CAVEAT: The supported additional/replacing libs (regex, gnksa, ...) may not have been made into a library. In that case, you can either - add the objects (i.e. regexpath/regex.o) to the Makefile line for the `uqwk' target - create the library, for example: cd regexpath ar cq libregex.a regex.o ranlib libregex.a # Not needed on most Unices 3. Make (compile) the software. Example: $ make If this doesn't work you may have to twiddle with the Makefile, or, heaven forbid, the actual source code. Take good notice of error and warning messages; the C compiler is your friend. :-) 4. Install the software. Example: $ make install 5. There is no step [5]. Fooled you! uqwk-2.21/README100600 35070 36 5732 7034062147 11162 0ustar jsuser $Id: README,v 1.3 2000/01/03 08:56:55 js Exp $ UQWK Copyright 1993-1994, steve belczyk Modifications 1996, 1997, 1998, 1999, 2000 jeroen scheerder uqwk is a program which collects all a user's unread mail or news and formats it into a packet for offline reading. QWK, Simple Offline Usenet Packet (SOUP), and ZipNews packet formats are supported. See the manual page for sommand line options, environment variables and examples. Uqwk also accepts reply packets, so replies can be mailed or posted, depending whether the message is marked private (email) or public (news). Uqwk also supports a small offline command language, so the contents of the user's .newsrc file can be viewed and manipulated offline. 0. Install uqwk if not installed already; see the INSTALL file. 1. Now you can try it. Login as a normal user who has some mail. First, tell uqwk to print its options: issue uqwk -p Check that the output reflects your choices in the makefile. Next, issue: uqwk +r +m (The "+r" stops uqwk from clearing the user's mail spool file.) This should create a number of *.MSG files in your home directory, along with a file named AREAS. These are the files the offline SOUP reader will need. (Some readers expect these files to have been archived using an archiver like zip, lharc, or arj. You may need to obtain Unix versions of these archivers.) 2a. If you will not be using uqwk in QWK mode (hurray!), you need not even bother reading [2b]; advance to [3]. 2b. If you are using uqwk to create QWK packets (please *don't*, really, since the QWK format does not allow storing Usenet messages correctly): QWK packets contain the name, location, etc., of the BBS from which messages are being downloaded. If you plan to use the QWK format (please, please, please don't!), you should configure this information. The best way is probably to use environment variables. If you are using a Bourne shell, you should add something like this to /etc/profile or .profile: UQ_BBS_NAME="My Super BBS" UQ_BBS_CITY="Somewhere, PA" UQ_BBS_PHONE="+1 215 555 1212" UQ_BBS_SYSOP="Joe Shmoe" UQ_BBS_ID="0,MYBBS" export UQ_BBS_NAME UQ_BBS_CITY UQ_BBS_PHONE export UQ_BBS_SYSOP UQ_BBS_ID If you use a C type shell, try something like this in your .cshrc or .login: setenv UQ_BBS_NAME "My Super BBS" setenv UQ_BBS_CITY "Somewhere, PA" setenv UQ_BBS_PHONE "+1 215 555 1212" setenv UQ_BBS_SYSOP "Joe Shmoe" setenv UQ_BBS_ID "0,MYBBS" In both cases, the last entry, the "BBS ID", is the most important. It always consists of an integer, a comma, and a string less than nine characters, with no intervening spaces. The string will be used to identify reply packets. 3. Now would be a good time for reading the man page ("man uqwk") and the Frequently Asked Questions list ("more FAQ"). uqwk-2.21/close.c100600 35070 36 12233 7366072516 11576 0ustar jsuser/* * $Id: close.c,v 1.7 2001/10/25 20:22:20 js Exp $ */ #include #include #include #include #include "uqwk.h" #ifdef NNTP #include "nntp.h" extern void close_server(); #endif /* * Wrap things up */ int _CloseStuff() { #ifdef NNTP /* JS -- server might have been connected to implicitly! */ close_server(); #endif if (msg_fd != NULL) fclose (msg_fd); /* Write QWK CONTROL.DAT file (or SLNP AREAS file) */ if (!zip_mode && !sum_mode && (do_mail || do_news) && WriteControl() < 0) return -1; /* Close summary file */ if (sum_mode) fclose (sum_fd); /* Update .newsrc */ if (do_news && (!read_only) && WriteNewsrc() < 0) return(-2); if ( (blk_cnt >= max_blks) && (max_blks > 0) ) { fprintf (stderr, "%s: block count exceeded; some articles not packed\n", progname); } /* Remove reply packet */ if ( (!read_only) && (strcmp (rep_file, DEF_REP_FILE))) unlink (rep_file); return 0; } int CloseStuff() { static int closed = 0; static int ret = 0; if (!closed++) { ret = _CloseStuff(); if(ret < 0) fprintf (stderr, "%s: error closing up\n", progname); } return ret; } int WriteControl() /* * Create the CONTROL.DAT file (or AREAS if SLNP) */ { struct conf_ent *cp; struct tm *t; char ctl_fname[PATH_LEN]; time_t clock; int n; if(!conf_list) return 0; strcpy (ctl_fname, home_dir); strcat (ctl_fname, "/"); if (slnp_mode) strcat (ctl_fname, "AREAS"); else strcat (ctl_fname, "control.dat"); if (NULL == (ctl_fd = fopen (ctl_fname, "w"))) { fprintf (stderr, "%s: can't open %s\n", progname, ctl_fname); return -1; /* Return failure error code to caller */ } /* SLNP AREAS file is different */ if (slnp_mode) return WriteAreas(); if(fprintf(ctl_fd, "%s\r\n%s\r\n%s\r\n%s\r\n%s\r\n", bbs_name, bbs_city, bbs_phone, bbs_sysop, bbs_id) < 0 && ferror(ctl_fd)) { fprintf(stderr,"%s: can't write to %s\n", progname, ctl_fname); return -1; } /* Date */ clock = time (NULL); t = gmtime (&clock); if(fprintf(ctl_fd, "%02d-%02d-%04d,%02d:%02d:%02d\r\n", t->tm_mon+1, t->tm_mday, t->tm_year+1900, t->tm_hour, t->tm_min, t->tm_sec) < 0 && ferror(ctl_fd)) { fprintf(stderr,"%s: can't write to %s\n", progname, ctl_fname); return -1; } if(fprintf (ctl_fd, "%s\r\n \r\n0\r\n", user_name) < 0 && ferror(ctl_fd)) { fprintf(stderr,"%s: can't write to %s\n", progname, ctl_fname); return -1; } /* Count conferences with articles */ n = 0; cp = conf_list; while (cp != NULL) { if (every_mode || (cp->count > 0)) n++; cp = cp->next; } if(fprintf (ctl_fd, "%d\r\n%d\r\n", msg_cnt, n-1) < 0 && ferror(ctl_fd)) { fprintf(stderr,"%s: can't write to %s\n", progname, ctl_fname); return -1; } /* List of conferences */ cp = conf_list; while (cp != NULL) { if (every_mode || (cp->count > 0)) { strcpy (buf, cp->name); /* Translate the name if desired */ if (trn_list != NULL) TransName (buf); /* Truncate the group name if desired */ if ( (grp_len > 0) && (grp_len < BUF_LEN) ) buf[grp_len] = 0; if(fprintf(ctl_fd, "%d\r\n%s\r\n", cp->number, buf) < 0 && ferror(ctl_fd)) { fprintf(stderr,"%s: can't write to %s\n", progname, ctl_fname); return -1; } } cp = cp->next; } if(fprintf (ctl_fd, "WELCOME.DAT\r\nNEWS.DAT\r\nLOGOFF.DAT\r\n\032") < 0 && ferror(ctl_fd)) { fprintf(stderr,"%s: can't write to %s\n", progname, ctl_fname); return -1; } fclose (ctl_fd); return 0; } int WriteAreas() /* * Write the SLNP AREAS file */ { struct conf_ent *cp; int ret = 0; /* Loop through conference list */ cp = conf_list; while (cp != NULL) { /* Don't add empty conferences */ if(cp->count) { if (strcmp (cp->name, MAIL_CONF_NAME)) { if (cp->count > 0) ret = fprintf (ctl_fd, "%07d\011%s\011un\n", cp->number, cp->name); } else { ret = fprintf (ctl_fd, "%07d\011%s\011bn\n", cp->number, cp->name); } } cp = cp->next; } fclose (ctl_fd); return ret==EOF?ret:0; } int WriteNewsrc() /* * Rewrite the updated .newsrc file */ { struct nrc_ent *np; int err = 0; if (read_only) return (0); if (NULL == (nrc_fd = fopen (nrc_file, "w"))) { fprintf (stderr, "%s: can't write %s\n", progname, nrc_file); exit(-1); /* Return failure error code to caller */ } for (np=nrc_list; np!=NULL; np=np->next) { /* Write this one */ if (waf_mode) { if(np->subscribed) { if(fprintf(nrc_fd, "%s %d\r\n", np->name, np->sub->hi) < 0 && ferror(nrc_fd)) err++; } } else { /* Not waffle mode */ if(np->subscribed) { if(fprintf(nrc_fd, "%s: ", np->name) < 0 && ferror(nrc_fd)) err++; } else { if(fprintf(nrc_fd, "%s! ", np->name) < 0 && ferror(nrc_fd)) err++; } if(!err) WriteSub (nrc_fd, np->sub); } if(err) { fprintf(stderr, "%s: can't write to %s\n", progname, nrc_file); exit(-1); } } fclose (nrc_fd); return 1; } void TransName (n) char *n; /* * Translate newsgroup name */ { struct trn_ent *tp; tp = trn_list; while (tp != NULL) { if (!strcmp (n, tp->old)) { /* Found a match */ strcpy (n, tp->new); return; } tp = tp->next; } } uqwk-2.21/config-generic.h100600 35070 36 1176 7034062147 13330 0ustar jsuser/* * $Id: config-generic.h,v 1.5 2000/01/03 08:56:56 js Exp $ * * Generic uqwk config */ #define CONFIGNAME "generic" #define DEF_BBS_NAME "The BBS That Shall Not Be Named" #define DEF_BBS_CITY "Nowhere, Utopia" #define DEF_BBS_PHONE "555-1212" #define DEF_BBS_SYSOP "Joe A. Sysop" #define DEF_BBS_ID "0,TBSNBN-BBS" #ifndef NNTP #define DEF_ACT_FILE "/usr/lib/news/active" #define DEF_NEWS_DIR "/var/spool/news" #endif #define DEF_MAIL_DIR "/var/spool/mail" #define SENDMAIL "/usr/lib/sendmail -i" #define INEWS_PATH "/usr/local/bin/inews" #define NNTP_HOST_FILE "/usr/local/news/lib/nntp_server" /* news server file */ uqwk-2.21/config-xs4all.h100600 35070 36 1266 7034062147 13123 0ustar jsuser/* * $Id: config-xs4all.h,v 1.4 2000/01/03 08:56:56 js Exp $ * * This is an uqwk configuration file for the XS4ALL ISP */ #define CONFIGNAME "XS4ALL" #define DEF_BBS_NAME "XS4ALL" #define DEF_BBS_CITY "Amsterdam, NL" #define DEF_BBS_PHONE "+31 30 3987654" #define DEF_BBS_SYSOP "xs4all helpdesk " #define DEF_BBS_ID "0,XS4ALL" #ifndef NNTP #define DEF_ACT_FILE "/usr/local/news/lib/active" #define DEF_NEWS_DIR "/usr/local/news/spool" #endif #define DEF_MAIL_DIR "/var/spool/mail" #define SENDMAIL "/usr/sbin/sendmail -i" #define INEWS_PATH "/usr/contrib/lib/news/inews" #define NNTP_HOST_FILE "/usr/local/news/lib/nntp_server" /* news server file */ uqwk-2.21/init.c100600 35070 36 7030 6705116353 11405 0ustar jsuser/* * $Id: init.c,v 1.3 1999/04/14 13:44:49 js Exp $ */ #include #include #include "uqwk.h" #define QWK_MAGIC "Produced by Qmail...Copyright (c) 1987 by Sparkware. All rights Reserved" #ifdef NNTP #include "nntp.h" extern void connect_nntp(); #endif /* * Initialize stuff */ void InitStuff() { char msg_fname[PATH_LEN]; /* Mail, conference, etc. lists */ mail_list = NULL; conf_list = NULL; last_conf = NULL; act_list = NULL; nrc_list = NULL; trn_list = NULL; ng_list = NULL; /* Message and conference counts */ msg_cnt = 0; conf_cnt = 0; /* Kludge around fclose() bug in close.c */ msg_fd = NULL; /* Open MESSAGES.DAT */ if (!slnp_mode && !zip_mode && !sum_mode) { strcpy (msg_fname, home_dir); strcat (msg_fname, "/"); strcat (msg_fname, "messages.dat"); if (NULL == (msg_fd = fopen (msg_fname, "w"))) { fprintf (stderr, "%s: can't open %s\n", progname, msg_fname); exit(-1); /* Return failure errorcode to caller */ } /* Write magic string to MESSAGES.DAT */ if( (fprintf(msg_fd, "%-128s", QWK_MAGIC) < 0) /* != 128? */ && ferror(msg_fd) ) { fprintf(stderr,"%s: write error!\n",progname); exit(-1); } blk_cnt = 2; } /* Open summary file */ if (sum_mode) { if (NULL == (sum_fd = fopen (sum_file, "w"))) { fprintf (stderr, "%s: can't open %s\n", progname, sum_file); exit(-1); /* Return failure errorcode to caller */ } } /* Read the ng trans table if specified */ if (strcmp (trn_file, DEF_TRN_FILE)) ReadTrans(); /* Read the desired newsgroups file if specified */ if (strcmp (ng_file, DEF_NG_FILE)) ReadNG(); #ifdef NNTP /* JS -- no need to open a connection if replying only! if (strcmp (rep_file, DEF_REP_FILE) || do_news) connect_nntp(); */ if (do_news) connect_nntp(); #endif } int ReadTrans() /* * Read the newsgroup name translation table */ { FILE *trn_fd; struct trn_ent *tp; char n1[PATH_LEN], n2[PATH_LEN]; /* Open the file */ if (NULL == (trn_fd = fopen (trn_file, "r"))) { fprintf (stderr, "%s: can't open %s, tran table not used\n", progname, trn_file); exit(-1); /* Return failure errorcode to caller */ } /* Read through the file */ while (2 == fscanf (trn_fd, "%s %s", n1, n2)) { /* Get space for new list entry */ if (NULL == (tp = (struct trn_ent *) malloc (sizeof (struct trn_ent)))) { OutOfMemory(); } if (NULL == (tp->old = (char *) malloc (strlen(n1)+1))) { OutOfMemory(); } if (NULL == (tp->new = (char *) malloc (strlen(n2)+1))) { OutOfMemory(); } /* Fill in new entry */ strcpy (tp->old, n1); strcpy (tp->new, n2); /* Add to list */ tp->next = trn_list; trn_list = tp; } fclose (trn_fd); return (0); } int ReadNG() /* * Read the desired newsgroups file */ { FILE *ng_fd; struct ng_ent *np, *last_np = NULL; char n[PATH_LEN]; /* Open the file */ if (NULL == (ng_fd = fopen (ng_file, "r"))) { fprintf (stderr, "%s: can't open %s, ng file not used\n", progname, ng_file); exit(-1); /* Return failure errorcode to caller */ } /* Read through the file */ while (1 == fscanf (ng_fd, "%s", n)) { /* Get space for new list entry */ if (NULL == (np = (struct ng_ent *) malloc (sizeof (struct ng_ent)))) { OutOfMemory(); } if (NULL == (np->name = (char *) malloc (strlen(n)+1))) { OutOfMemory(); } /* Fill in new entry */ strcpy (np->name, n); /* Add to list */ if (ng_list == NULL) { /* First one */ ng_list = np; } else { /* Add to end */ last_np->next = np; } np->next = NULL; last_np = np; } fclose (ng_fd); return (0); } uqwk-2.21/mail.c100600 35070 36 35124 7365523746 11424 0ustar jsuser/* * $Id: mail.c,v 1.10 2001/10/24 11:37:10 js Exp $ */ #include #include "uqwk.h" #include #include #include #include /* * All sorts of stuff to do mail processing */ FILE *mail_fd; /* For mail spool */ struct mail_ent *last_mp; /* Points to last mail list entry */ /* * A few useful routines */ int fileexists(const char *fname) { struct stat fbuf; return (stat(fname,&fbuf)!=EOF && !(fbuf.st_mode&S_IFDIR)); } time_t filetime(const char *fname) { struct stat fbuf; return stat(fname,&fbuf)!=EOF ? fbuf.st_ctime : -1L; } long filesize(const char *s) { struct stat st; return (stat((char*)s,&st)!=EOF) ? st.st_size : -1L; } long openfilesize(FILE *fp) { struct stat st; return (fstat(fileno(fp),&st)!=EOF) ? st.st_size : -1L; } int isdir(const char *s) { struct stat st; return (stat((char*)s,&st)!=EOF && !(st.st_mode & S_IFDIR)); } #define strend(x) ((x) + strlen(x)) /* * Some stuff for maildir-handling */ int ismaildir(char *dirname) { char subdirname[255]; char *subdir_names[] = {"/cur","/new","/tmp",NULL}, **p; char *endp; if(!isdir(dirname)) return 0; strcpy(subdirname, dirname); endp = subdirname+strlen(subdirname); for (p=subdir_names; *p; p++) { strcpy(endp, *p); if(isdir(subdirname) <= 0) return 0; } return 1; } /* * Process mail into QWK packet */ int DoMail() { if(!fileexists(mail_file)) return 1; /* if(ismaildir(mail_file)) */ if(isdir(mail_file)) return DoMaildirMail(); else return DoClassicMail(); } /* * Maildir handling HOW A MESSAGE IS READ A mail reader operates as follows. It looks through the new directory for new messages. Say there is a new message, new/unique. The reader may freely display the contents of new/unique, delete new/unique, or rename new/unique as cur/unique:info. See http://pobox.com/~djb/proto/maildir.html for the meaning of info. The reader is also expected to look through the tmp directory and to clean up any old files found there. A file in tmp may be safely removed if it has not been accessed in 36 hours. It is a good idea for readers to skip all filenames in new and cur starting with a dot. Other than this, readers should not attempt to parse filenames. */ typedef struct flist { char *fnam; struct flist *tail; } filelist; filelist *AddMaildirfile(l, s) filelist *l; char *s; { filelist *new; /* Get space for new entry */ if (NULL== (new = (filelist *) malloc(sizeof(filelist)))) { fprintf (stderr, "%s: out of memory\n", progname); exit(-1); } new->fnam = (char *) strdup(s); new->tail = l; return new; } static void free_filelist(register filelist *f) { register filelist *ptr; while(f) { ptr=f->tail; if (f->fnam) free(f->fnam); free(f); f=ptr; } } int DoMaildirMail() { struct conf_ent *cp; struct mail_ent me; DIR *dirp; struct dirent *d; char *endp; char tmp[PATH_LEN]; filelist *mfs = NULL, *l; /* get name of directory */ strcpy(tmp, mail_file); endp = strend(tmp); if (endp > tmp && endp[-1] == '/') *--endp = '\0'; /* Do new directory */ strcpy(endp, "/new/"); if ((dirp = opendir(tmp))) { /* open directory */ while ((d = readdir (dirp))) { /* empty the directory */ if (d->d_name[0] != '.') { /* skip ., .., and .files */ strcpy(endp+5, d->d_name); mfs = AddMaildirfile(mfs, tmp); } } closedir (dirp); /* flush directory */ } /* Do cur directory */ strcpy(endp, "/cur/"); if ((dirp = opendir(tmp))) { /* open directory */ while ((d = readdir (dirp))) { /* empty the directory */ if (d->d_name[0] != '.') { /* skip ., .., and .files */ strcpy(endp+5, d->d_name); mfs = AddMaildirfile(mfs, tmp); } } closedir (dirp); /* flush directory */ } if (!mfs) { fprintf (stdout, "no mail for %s\n", user_name); return(0); } /* Define the mail "conference" */ cp = NewConference (MAIL_CONF_NAME, conf_cnt); /* Open ZipNews mail file */ if (zip_mode && (mail_list != NULL)) OpenZipMail(); printf ("maildir mailbox (%s)", mail_file); /* Walk through all the messages */ /* handle list of messages */ me.next = NULL; for(l = mfs; l; l = l->tail) { long ln; char *uidl, *s; char xheaders[128] = {0}; char status[16] = {0}; char xstatus[16] = {0}; if (!l->fnam) continue; ln = filesize(l->fnam); uidl = (char *) strrchr(l->fnam, '/'); if(uidl && !strncmp(uidl-3, "cur", 3)) strcat(status, "O"); uidl++; s = (char *) strchr(uidl, ':'); if(s != NULL) { *s++ = 0; /* Add (X-)Status codes */ if(strchr(s, 'S')) strcat(status, "R"); if(strchr(s, 'R')) { strcat(status, "r"); strcat(xstatus, "A"); } if(strchr(s, 'F')) strcat(xstatus, "F"); if(strchr(s, 'T')) strcat(xstatus, "D"); } sprintf(xheaders, "X-UIDL: %s\n", uidl?uidl:"unknown"); if(s != NULL) *(s-1) = ':'; if(*status) { strcat(xheaders, "Status: "); strcat(xheaders, status); strcat(xheaders, "\n"); } if(*xstatus) { strcat(xheaders, "X-Status: "); strcat(xheaders, xstatus); strcat(xheaders, "\n"); } if(ln > 0) { FILE *fd; /* Open the message file */ if (NULL == (fd = fopen(l->fnam, "r"))) { fprintf (stderr, "could not open %s\n", l->fnam); exit(1); } cp->count++; me.begin = 0; me.end = ln; AddMessage(fd, &me, xheaders); if(fclose(fd)==EOF) { fprintf(stderr, "error closing file %s\n", l->fnam); exit(1); } } } printf(" %d message%s\n", cp->count, cp->count==1?"":"s"); if (!slnp_mode && !zip_mode) fclose (ndx_fd); if (slnp_mode) { fclose (msg_fd); msg_fd = NULL; } if (zip_mode && (mail_list != NULL)) fclose (mai_fd); /* in read only mode we're done now */ if (read_only) { free_filelist(mfs); return 1; } /* Now empty the mail box */ for(l = mfs; l; l = l->tail) { if (l->fnam) unlink(l->fnam); } /* purge old junk from tmp */ strcpy(endp, "/tmp/"); if ((dirp = opendir(tmp))) { /* open directory */ while ((d = readdir (dirp))) { if ((d->d_name[0] != '.')) { /* skip ., .., and .files */ strcpy(endp+5, d->d_name); if (filetime(tmp) < (time(NULL)-(36L*60*60)) && access(tmp,W_OK)==0) { unlink(tmp); } } } closedir (dirp); /* flush directory */ } free_filelist(mfs); return 1; } int DoClassicMail () { struct mail_ent *mailp; struct conf_ent *cp; /* No mail in summary mode */ if (sum_mode) return (0); /* Open the mail spool */ if (NULL == (mail_fd = fopen(mail_file, "r"))) { fprintf (stdout, "no mail in %s for %s\n", mail_file, user_name); return(0); } /* Construct the mail linked list */ MakeMailList (); if (!mail_list) { fprintf (stdout, "no mail in %s for %s\n", mail_file, user_name); fclose(mail_fd); return(0); } /* Define the mail "conference" */ cp = NewConference (MAIL_CONF_NAME, conf_cnt); /* Open ZipNews mail file */ if (zip_mode && (mail_list != NULL)) OpenZipMail(); printf ("classic mailbox (%s)", mail_file); /* Walk through all the messages */ mailp = mail_list; while (mailp != NULL) { cp->count++; AddMessage(mail_fd, mailp, NULL); mailp = mailp->next; } fclose (mail_fd); printf(" %d message%s\n", cp->count, cp->count==1?"":"s"); if (!slnp_mode && !zip_mode) fclose (ndx_fd); if (slnp_mode) { fclose (msg_fd); msg_fd = NULL; } if (zip_mode && (mail_list != NULL)) fclose (mai_fd); /* Now empty the mail box */ if (!read_only) { if (NULL == (mail_fd = fopen (mail_file, "w"))) { fprintf (stderr, "%s: can't write %s\n", progname, mail_file); return(-1); } else { fclose (mail_fd); } } return(1); } /* * Construct linked list of pointers to individual messages in * the mail spool. */ void MakeMailList() { long offset; last_mp = NULL; /* Read through, looking for "From" lines */ offset = ftell (mail_fd); while (NULL != Fgets (buf, BUF_LEN, mail_fd)) { if (!strncmp (buf, "From ", 5)) { DoFromLine (offset); } offset = ftell (mail_fd); } if (last_mp != NULL) last_mp->end = offset; } void DoFromLine (offset) long offset; { struct mail_ent *mp; /* Get space for new mail list entry */ if (NULL==(mp=(struct mail_ent *) malloc(sizeof(struct mail_ent)))) { fprintf (stderr, "%s: out of memory\n", progname); exit(-1); } /* Fill in offset */ mp->begin = offset; if (last_mp == NULL) { /* This is first message */ mail_list = mp; } else { /* Add to end of list */ last_mp->next = mp; last_mp->end = offset; } mp->next = NULL; last_mp = mp; } void AddMessage(fd, mp, xhdrs) FILE *fd; struct mail_ent *mp; char *xhdrs; { if (slnp_mode) SLNPMessage(fd, mp, xhdrs); else if (zip_mode) ZipMessage(fd, mp, xhdrs); else QwkMessage(fd, mp, xhdrs); } /* * Convert a message to SLNP format */ void SLNPMessage (fd, mp, xhdrs) FILE *fd; struct mail_ent *mp; char *xhdrs; { long bytes, c, b; /* Compute message size */ b = bytes = mp->end - mp->begin; /* If there are xtra heades to be added, add those to the byte count */ if(xhdrs) b += strlen(xhdrs); /* Write byte count line */ for (c=3; c>=0; c--) { buf[c] = b % 256; b = b / 256; } if(fwrite(buf, 4, 1, msg_fd) != 1) { fprintf(stderr,"%s: write error!\n",progname); exit(-1); } /* Seek to start of message */ fseek (fd, mp->begin, 0); if(xhdrs && *xhdrs) { char s[1024] = ""; int err=0; while(fgets(s, sizeof(s), fd) && ftell(fd) < mp->end) { bytes -= strlen(s); if(s[0]=='\n' || (s[0]=='\r' && s[1]=='\n')) { if(fputs(xhdrs,msg_fd)==EOF || fputs(s, msg_fd)==EOF) err++; break; } if(fputs(s, msg_fd)==EOF) { err++; break; } } if(err) { fprintf(stderr, "%s: write error!\n", progname); exit(-1); } } /* Copy rest of bytes */ while (bytes--) { if((c = getc(fd)) == EOF) { fprintf(stderr,"%s: read error (%ld bytes unread)\n", progname, bytes+1); exit(-1); } if(putc((0xff & c), msg_fd) == EOF) { fprintf(stderr,"%s: write error!\n",progname); exit(-1); } } } /* * Convert a message to QWK format * We're ignoring any xhdrs -- QWK is too badly broken anyway */ void QwkMessage(fd, mp, xhdrs) FILE * fd; struct mail_ent *mp; char *xhdrs; { struct qwk_hdr hdr; char c[PATH_LEN], *eof, ndx[5]; int out_bytes, n, i; /* Write the ndx file entry */ inttoms (blk_cnt, (unsigned char *) ndx); ndx[4] = conf_cnt; if(fwrite (ndx, 5, 1, ndx_fd) != 1) { fprintf(stderr,"%s: write error!\n",progname); exit(-1); } Spaces ((char *)&hdr, 128); /* Fill in the header fields we can do now */ hdr.status = QWK_PRIVATE; PadNum (msg_cnt, hdr.number, 7); Spaces (hdr.password, 12); Spaces (hdr.refer, 8); hdr.flag = (char) QWK_ACT_FLAG; IntNum (conf_cnt, hdr.conference); IntNum (msg_cnt+1, hdr.msg_num); hdr.tag = ' '; msg_cnt++; /* Seek to start of message */ fseek (fd, mp->begin, 0); /* Read the From line */ Fgets (buf, BUF_LEN, fd); /* The second field of the From line is used as a first guess for who sent the message */ sscanf (&buf[5], "%s", c); PadString (c, hdr.from, 25); /* Now read through header lines, looking for ones we need */ eof = Fgets (buf, BUF_LEN, fd); while ( (0 != strlen(buf)) && (eof != NULL) ) { if (!strncmp (buf, "Date: ", 6)) { ParseDate (&buf[6], &hdr); } else if (!strncmp (buf, "To: ", 4)) { PadString (&buf[4], hdr.to, 25); } else if (!strncmp (buf, "Subject: ", 9)) { PadString (&buf[9], hdr.subject, 25); } else if (!strncmp (buf, "From: ", 6)) { PadString (ParseFrom(&buf[6]), hdr.from, 25); } eof = Fgets (buf, BUF_LEN, fd); } mp->text = ftell(fd); /* Fill in block count */ if (inc_hdrs) { PadNum (2+(mp->end-mp->begin)/128, hdr.blocks, 6); blk_cnt += (1+(mp->end - mp->begin)/128); } else { PadNum (2+(mp->end-mp->text)/128, hdr.blocks, 6); blk_cnt += (1+(mp->end - mp->text)/128); } /* Write out the message header */ if( fwrite(&hdr, 128, 1, msg_fd) != 1) { fprintf(stderr,"%s: write error!\n",progname); exit(-1); } blk_cnt++; /* Now write the message text */ if (inc_hdrs) fseek(fd, mp->begin, 0); out_bytes = 0; eof = Fgets (buf, BUF_LEN, fd); do { n = strlen (buf); /* MMDF puts funny things in messages -- change to spaces */ for (i=0; iend - mp->begin; /* Write separator */ for (c=0; c<20; c++) if( putc(1, mai_fd) == EOF) { fprintf(stderr,"%s: write error!\n",progname); exit(-1); } if( (fprintf (mai_fd, "\r\n") < 0) && ferror(mai_fd) ) { fprintf(stderr,"%s: write error!\n",progname); exit(-1); } /* Seek to start of message */ fseek (fd, mp->begin, 0); if(xhdrs && *xhdrs) { char s[1024] = ""; int err=0; while(fgets(s, sizeof(s), fd) && ftell(fd) < mp->end) { bytes -= strlen(s); if(s[0]=='\n' || (s[0]=='\r' && s[1]=='\n')) { if(fputs(xhdrs,msg_fd)==EOF || fputs(s, msg_fd)==EOF) err++; break; } if(fputs(s, msg_fd)==EOF) { err++; break; } } if(err) { fprintf(stderr, "%s: write error!\n", progname); exit(-1); } } /* Copy bytes */ while (bytes--) { if( (c = getc(fd)) == EOF) { fprintf(stderr,"%s: read error (%d bytes unread)\n", progname, bytes); exit(-1); } /* ZipNews doesn't like ^Z's */ if (c == 26) c = 32; /* Map LF to CRLF */ if ( c==10 && putc(13, mai_fd) == EOF) { fprintf(stderr,"%s: write error!\n",progname); exit(-1); } if( putc((0xff & c), mai_fd) == EOF) { fprintf(stderr,"%s: write error!\n",progname); exit(-1); } } } uqwk-2.21/misc.c100600 35070 36 15227 6742615311 11423 0ustar jsuser/* * $Id: misc.c,v 1.5 1999/07/13 10:53:39 js Exp $ */ #include #include #include "uqwk.h" /* * Miscellaneous uqwk routines */ char f[PATH_LEN]; /* Static area for ParseFrom() */ struct conf_ent *NewConference (name, num) char *name; int num; { struct conf_ent *tmp_cp; char *c; /* Get space for new conference */ if (NULL == (tmp_cp = (struct conf_ent *) malloc (sizeof (struct conf_ent)))) { fprintf (stderr, "%s: out of memory\n", progname); exit(-1); } /* Get space for name */ if (NULL == (c = (char *) malloc (1+strlen(name)))) { fprintf (stderr, "%s: out of memory\n", progname); exit(-1); } /* Fill in conference name */ tmp_cp->name = c; strcpy (tmp_cp->name, name); /* Fill in conference number */ tmp_cp->number = num; /* Article count */ tmp_cp->count = 0; /* Add to end of conference list */ if (last_conf == NULL) { /* This is first conference */ conf_list = tmp_cp; } else { last_conf->next = tmp_cp; } tmp_cp->next = NULL; last_conf = tmp_cp; if (slnp_mode) { /* Open SLNP message file */ sprintf (msg_fn, "%s/%07d.MSG", home_dir, num); if (NULL == (msg_fd = fopen (msg_fn, "w"))) { fprintf (stderr, "%s: can't open %s\n", progname, msg_fn); exit (-1); } } else if (!zip_mode && !sum_mode) { /* Else open new QWK index file */ if (!bw_kludge && !strcmp (name, MAIL_CONF_NAME)) { strcpy (ndx_fn, home_dir); strcat (ndx_fn, "/"); strcat (ndx_fn, "personal.ndx"); } else { sprintf (ndx_fn, "%s/%03d.ndx", home_dir, num); } if (NULL == (ndx_fd = fopen (ndx_fn, "w"))) { fprintf (stderr, "%s: can't open %s\n", progname, ndx_fn); exit (-1); } } /* Maintain conf_cnt: should always be one greater than highest newsgroup conference number encountered */ if (strcmp (name, MAIL_CONF_NAME)) { if (num >= conf_cnt) conf_cnt = num + 1; } /* Remember no summaries for this newsgroup yet */ if (sum_mode) sum_flag = 0; return (tmp_cp); } /* * Take a null-terminated string s and copy it, space-padded or * truncated if necessary, into field c of n characters */ void PadString (char *s, char *c, int n) { int len; len = strlen (s); if (len >= n) { strncpy (c, s, n); } else { strcpy (c, s); Spaces (&c[len], n-len); } } /* * Fill field of n characters with spaces */ void Spaces (char *c, int n) { sprintf(c,"%*s", n, ""); } /* * Format an integer i and place it, space filled, in * field c of n characters */ void PadNum (int i, char *c, int n) { sprintf (buf, "%d", i); PadString (buf, c, n); } void IntNum (i, c) int i; char c[2]; /* * Put binary integer i into two bytes */ { c[0] = i % 256; c[1] = (i / 256) % 256; } char *Fgets (c, n, fd) char *c; int n; FILE *fd; /* * Same as fgets, but changes trailing linefeed to a null */ { int i; char *bufptr = c; size_t bufsiz = n; /* * This bit of code reallocs dynamically -- it will fail * if it is tries to reallocate non-reallocatable memory */ if (NULL == fgets (c, n, fd)) return (NULL); i = strlen (c); if ( i == n-1 ) { /* n-1 bytes read! more? */ i = n; while (i == n) { if((c = (char *)realloc(c, bufsiz + n )) == NULL) OutOfMemory(); bufptr = c + bufsiz - 1; bufsiz += n; fgets (bufptr, n+1, fd); i = strlen (c); } } i = strlen (c); if ( (i > 0) && (c[i-1]=='\n') ) c[i-1] = 0; if ( (i > 1) && (c[i-2]=='\r') ) c[i-2] = 0; return (c); } /* * Convert an integer into the Microsoft Basic floating format. * This is the dumbest thing in the whole QWK standard. Why in * the world store block offsets as floating point numbers? * Stupid! */ void inttoms (int i, unsigned char c[4]) { int m, e; if (i == 0) { c[0] = c[1] = c[2] = 0; c[3] = 0x80; return; } e = 152; m = 0x7fffff & i; while (!(0x800000 & m)) { m <<= 1; e--; } c[0] = 0xff & m; c[1] = 0xff & (m >> 8); c[2] = 0x7f & (m >> 16); c[3] = 0xff & e; } int buftoint(unsigned char c[4]) { int count = 0, i; if(do_debug) { fprintf(stdout,"DBG: buf [%d,%d,%d,%d]\n", c[0], c[1], c[2], c[3]); } for(i=0; i< 4; i++) { count = (count << 8) + c[i]; if(do_debug) fprintf(stdout,"DBG: count/%d is %d\n", i, count); } if(do_debug) { fprintf(stdout,"DBG: msg size is %d\n", count); } return(count); } void ParseDate (c, hp) char *c; struct qwk_hdr *hp; { char s[PATH_LEN]; int day, mon, year, hour, minute; char month[4]; /* Skip white space */ while ( (*c == ' ') || (*c == 9) ) c++; /* Dates come in two flavors: with the weekday, and without. we simply look for the comma which follows the weekday */ if (c[3] == ',') { sscanf (&c[4], "%d %s %d %d:%d", &day, month, &year, &hour, &minute); } else { sscanf (c, "%d %s %d %d:%d", &day, month, &year, &hour, &minute); } /* Convert alphabetic month name to integer */ mon = 0; if (!strncmp (month, "Jan", 3)) mon = 1; if (!strncmp (month, "Feb", 3)) mon = 2; if (!strncmp (month, "Mar", 3)) mon = 3; if (!strncmp (month, "Apr", 3)) mon = 4; if (!strncmp (month, "May", 3)) mon = 5; if (!strncmp (month, "Jun", 3)) mon = 6; if (!strncmp (month, "Jul", 3)) mon = 7; if (!strncmp (month, "Aug", 3)) mon = 8; if (!strncmp (month, "Sep", 3)) mon = 9; if (!strncmp (month, "Oct", 3)) mon = 10; if (!strncmp (month, "Nov", 3)) mon = 11; if (!strncmp (month, "Dec", 3)) mon = 12; /* Convert date */ sprintf (s, "%02d-%02d-%02d", mon, day, year%100); PadString (s, hp->date, 8); /* Time */ sprintf (s, "%02d:%02d", hour, minute); PadString (s, hp->time, 5); } char *ParseFrom (c) char *c; /* * Extract the email address from a From: line */ { int type, n, i, where = 0; /* * Addresses come in three flavors: * * 1: seb3@gte.com * 2: seb3@gte.com (steve belczyk) * 3: steve belczyk */ /* Assume type 1 */ type = 1; /* Look through address */ n = strlen (c); for (i=0; i') c[i] = 0; /* If we find an open-angle-bracket, assume type 3 */ if (c[i] == '<') { type = 3; where = i+1; } } /* Now extract the address */ if (type == 1) { /* This works for type 2 addresses too */ sscanf (c, "%s", f); } else { /* type == 3 */ /* Check we don't fly off the end of c. This should never happen, but I've been wrong before. */ if (where > n) { strcpy (f, "unknown"); } else { /* Get address */ sscanf (&c[where], "%s", f); } } /* Done! */ return (&f[0]); } uqwk-2.21/news.c100600 35070 36 72311 7366072516 11450 0ustar jsuser/* * $Id: news.c,v 1.12 2001/10/25 10:23:35 js Exp $ */ #include /* fill the gaps of stupid SunOS stdio */ #ifndef SEEK_SET #define SEEK_SET 0 #define SEEK_CUR 1 #define SEEK_END 2 #endif #include #include #include #include "uqwk.h" #define MAXFILENAME 128 #ifdef NNTP #include "nntp.h" /* extern FILE *getactive_nntp(); */ extern FILE *nntpopen(); extern int nntp_get(); #endif #ifdef SCORES extern int read_score_file(char *); extern int free_group_score(); extern int Kill(FILE *); #endif /* * All sorts of stuff to do news processing */ int DoNews () /* * Collect unread news into a packet */ { #if defined(NNTP_FULL_ACTIVE) char active_name[MAXFILENAME]; #endif struct nrc_ent *np; struct ng_ent *ngp; int ret; #ifdef SCORES int has_score = 0; #endif /* Open ZipNews files */ if (zip_mode) { if ((ret=OpenZipFiles())<=0) { fprintf(stderr,"%s: can't open zipfiles\n", progname); return(ret); } } /* Read .newsrc file */ if ((ret=ReadNewsrc()) < 0) { fprintf(stderr,"%s: can't read newsrc file\n", progname); return(ret); } #if !defined(NNTP) || defined(NNTP_FULL_ACTIVE) /* And active file */ if ((ret=ReadActive()) < 0) { fprintf(stderr,"%s: can't read active file\n", progname); return(ret); } #endif /* Handle selection mode */ if (sel_mode) { if((ret=DoSelect())!=1) return(ret); #if defined(NNTP_FULL_ACTIVE) sprintf(active_name,"/tmp/rrnact.%d",getpid()); unlink(active_name); #endif /* ZipNews "join" file */ if (zip_mode) { if((ret=WriteJoin())!=1) return(ret); fclose (nws_fd); fclose (idx_fd); } return (0); } #ifdef SCORES if (do_kills) { if(read_score_file (GLOBAL_SCORE_FILE)) printf("(global scoring)\n"); else printf("(no global scoring)\n"); } #endif /* Use .newsrc or desire newsgroup file? */ if (ng_list == NULL) { /* * No desired ng file, use newsrc */ np = nrc_list; while (np != NULL) { /* Check if too many blocks already */ if ( (blk_cnt >= max_blks) && (max_blks > 0) ) { #ifdef NNTP_FULL_ACTIVE sprintf(active_name,"/tmp/rrnact.%d",getpid()); unlink(active_name); #endif /* ZipNews "join" file */ if (zip_mode) { if((ret=WriteJoin())!=1) return(ret); fclose (nws_fd); fclose (idx_fd); } return (0); } if (np->subscribed) { #ifdef SCORES if (do_kills) { group_kill_thresh = kill_thresh; has_score = read_score_file (np->name); } #endif /* Do this group */ ret=DoGroup(np); #ifdef SCORES if (do_kills && has_score) free_group_score(); #endif switch(ret) { case -1: fprintf(stderr,"%s: can't entirely do group %s\n", progname, np->name); return(0); break; case 0: break; case 1: break; default: fprintf(stderr,"%s: can't do group %s\n", progname, np->name); return(ret); break; } } np = np->next; } #ifdef NNTP_FULL_ACTIVE sprintf(active_name,"/tmp/rrnact.%d",getpid()); unlink(active_name); #endif /* ZipNews "join" file */ if (zip_mode) { if((ret=WriteJoin())!=1) return(ret); fclose (nws_fd); fclose (idx_fd); } } else { /* * Read desired ng file for groups */ for (ngp=ng_list; ngp!=NULL; ngp=ngp->next) { /* Check if too many blocks already */ if ( (blk_cnt >= max_blks) && (max_blks > 0) ) { #ifdef NNTP_FULL_ACTIVE sprintf(active_name,"/tmp/rrnact.%d",getpid()); unlink(active_name); #endif /* ZipNews "join" file */ if (zip_mode) { if((ret=WriteJoin())!=1) return(ret); fclose (nws_fd); fclose (idx_fd); } return (0); } /* Find .newsrc entry, book if none */ for (np=nrc_list; np!=NULL; np=np->next) { if (!strcmp (ngp->name, np->name)) break; } if (np == NULL) { fprintf (stderr, "%s: %s not in .newsrc\n", progname, ngp->name); } else { #ifdef SCORES if (do_kills) read_score_file (np->name); #endif /* Do this group */ ret=DoGroup(np); #ifdef SCORES if (do_kills) free_group_score(); #endif switch(ret !=1) { case -1: fprintf(stderr,"%s: can't entirely do group %s\n", progname, np->name); return(0); break; case 0: break; case 1: break; default: fprintf(stderr,"%s: can't do group %s\n", progname, np->name); return(ret); break; } } } #ifdef NNTP_FULL_ACTIVE sprintf(active_name,"/tmp/rrnact.%d",getpid()); unlink(active_name); #endif /* ZipNews "join" file */ if (zip_mode) { if((ret=WriteJoin())!=1) return(ret); fclose (nws_fd); fclose (idx_fd); } } return (1); } int ReadNewsrc() /* * Read the .newsrc file */ { char group_name[PATH_LEN]; struct nrc_ent *np, *lnp; int i, n, c; char *buf; /* lnp points to last entry */ lnp = NULL; /* Don't bother if we've alread read it */ if (nrc_list != NULL) return (1); /* Allocate a buffer for reading */ if((buf = (char *) malloc(BUF_LEN)) == NULL) OutOfMemory(); /* Open it */ if (NULL == (nrc_fd = fopen (nrc_file, "r"))) { fprintf (stderr, "%s: can't open %s\n", progname, nrc_file); return(-1); } /* Read through */ while (NULL != Fgets (buf, BUF_LEN, nrc_fd)) { /* Allocate a new nrc entry */ np = (struct nrc_ent *) malloc (sizeof (struct nrc_ent)); if (np == NULL) OutOfMemory(); if (waf_mode) { /* Waffle is easy */ sscanf (buf, "%s %d", group_name, &n); np->subscribed = 1; /* Allocate sub entry */ if (NULL == (np->sub = (struct sub_ent *) malloc (sizeof (struct sub_ent)))) OutOfMemory(); np->sub->lo = 0; np->sub->hi = n; np->sub->next = NULL; } else { /* Regular Unix-style .newsrc */ /* Assume not subscribed */ np->subscribed = 0; /* Avoid bus error on missing ! or : */ np->sub = 0; /* Parse group name */ n = strlen (buf); for (i=0; isubscribed = 1; buf[i] = ' '; /* Parse subscription list */ np->sub = SubList (&buf[i+1]); } if (buf[i] == '!') { np->subscribed = 0; buf[i] = ' '; /* Parse subscription list */ np->sub = SubList (&buf[i+1]); } } sscanf (buf, "%s", group_name); } n = strlen (group_name); np->name = (char *) malloc (n+1); if (np->name == NULL) OutOfMemory(); strcpy (np->name, group_name); np->next = NULL; /* Add to nrc list */ if (lnp == NULL) { /* First one */ nrc_list = np; } else { /* Add to end */ lnp->next = np; } lnp = np; } /* Walk through the nrc list, assign conference numbers */ np = nrc_list; c = 0; while (np != NULL) { if (np->subscribed) { np->conf = c; c++; } else { np->conf = (-1); } np = np->next; } free(buf); fclose (nrc_fd); return (1); } int ReadActive() /* * Read active file */ { struct act_ent *ap; char group_name[PATH_LEN]; /* Don't bother if it's already here */ if (act_list != NULL) return (1); #if !defined(NNTP) /* Open the active file */ if (NULL == (act_fd = fopen (act_file, "r"))) { fprintf (stderr, "%s: can't open %s\n", progname, act_file); return(-1); } #else /* Retrieve active file from news server */ if (NULL == (act_fd = (FILE *)getactive_nntp())) { fprintf (stderr, "%s: can't get active file\n", progname); return (-1); } #endif /* Read through the full active file */ while (NULL != Fgets (buf, BUF_LEN, act_fd)) { /* Get new act entry */ ap = (struct act_ent *) malloc (sizeof (struct act_ent)); if (ap == NULL) OutOfMemory(); /* Parse name, message numbers */ sscanf (buf, "%s %d %d", group_name, &ap->hi, &ap->lo); ap->name = (char *) malloc (1+strlen(group_name)); if (ap->name == NULL) OutOfMemory(); strcpy (ap->name, group_name); /* Add to list */ ap->next = act_list; act_list = ap; } fclose (act_fd); return (1); } struct act_ent *FindActive (c) char *c; /* * Look for group's active entry given group name */ { struct act_ent *ap; #ifdef NNTP int dummy; #endif #if defined(NNTP) && !defined(NNTP_FULL_ACTIVE) /* Ask server about group */ sprintf(buf,"GROUP %s", c); put_server(buf); nntp_get(buf, sizeof(buf)); if (*buf != CHAR_OK) { /* and then see if that's ok */ if(atoi(buf) == ERR_NOGROUP) { fprintf(stderr, "%s: %s does not exist (server said: %s)\n", progname, c, buf); } else { fprintf(stderr, "%s: `GROUP %s' server response: %s\n", progname, c, buf); } } else { /* Get new act entry */ ap = (struct act_ent *) malloc (sizeof (struct act_ent)); if (ap == NULL) OutOfMemory(); /* Parse name, message numbers; `buf' contains a server response */ sscanf (buf, "%d %d %d %d", &dummy, &dummy, &ap->lo, &ap->hi); if((ap->name = (char *) malloc (1+strlen(c))) == NULL) OutOfMemory();; strcpy (ap->name, c); /* Add to list */ /* No need to -- better not to cache, and always do a fresh GROUP ap->next = act_list; act_list = ap; */ return(ap); } #else /* Not in NNTP mode, or in NNTP_FULL_ACTIVE mode */ ap = act_list; while (NULL != ap) { if (!strcmp (c, ap->name)) return (ap); ap = ap->next; } #endif return (NULL); } int DoGroup (np) struct nrc_ent *np; /* * Process given group */ { struct act_ent *ap; char news_path[PATH_LEN]; int i, n; struct conf_ent *cp; #ifdef SCORES int nArticles = 0; int nKills = 0; #endif printf ("%s", np->name); #ifdef SCORES fflush(stdout); #endif /* Lookup group in active file */ ap = FindActive (np->name); /* If the group doesn't exist (that is, doesn't appear in the active file), do nothing else */ if (ap == NULL) { printf (": no such group\n"); return 0; } /* Make a new conference with this name */ cp = NewConference (np->name, np->conf); /* Remember no ZipNews index entry yet */ if (zip_mode) zip_flag = 0; #ifdef NNTP #ifdef NNTP_FULL_ACTIVE /* select group name from news server */ group_nntp(np->name); #endif #else /* Construct path name for articles in this group */ strcpy (news_path, news_dir); strcat (news_path, "/"); strcat (news_path, np->name); strcat (news_path, "/"); n = strlen (news_path); for (i=0; isub = FixSub (np->sub, ap->lo, ap->hi); /* Look through unread articles */ for (i=ap->lo; i<=ap->hi; i++) { /* Check max block count */ if ( (blk_cnt >= max_blks) && (max_blks > 0) ) { if (!slnp_mode && !zip_mode && !sum_mode) NdxClose (ndx_fd); if (slnp_mode) MsgClose (msg_fd); #ifdef SCORES if (do_kills) printf(" %d articles obtained, %d killed", nArticles, nKills); #endif printf("\n"); return (-1); } /* Process this article */ if (!IsRead (i, np->sub)) { /* Mark as read */ np->sub = MarkRead (i, np->sub); /* Process the article */ #ifdef SCORES n=DoArticle(news_path, i, np, cp); switch(n){ case 1: ++nArticles; break; case -1: ++nKills; break; case 0: continue; default: return(n); } #else /* ndef SCORES */ if((n=DoArticle(news_path, i, np, cp))!=1) return(n); #endif /* SCORES */ } } if (!slnp_mode && !zip_mode && !sum_mode) NdxClose (ndx_fd); if (slnp_mode) MsgClose (msg_fd); #ifdef SCORES if (do_kills) printf(" %d articles obtained, %d killed", nArticles, nKills); #endif /* SCORES */ printf("\n"); return (1); } int DoArticle (news_path, artnum, np, cp) char *news_path; int artnum; struct nrc_ent *np; struct conf_ent *cp; { struct qwk_hdr hdr; struct stat stat_buf; long txt_offset, end_offset; int n, out_bytes; char ndx[5], *eof; FILE *art_fd; char art_file[PATH_LEN]; #ifdef NNTP /* retrieve article from news server */ art_fd = nntpopen(artnum, GET_ARTICLE); if (art_fd == NULL){ #ifdef DEBUG char *s = ignore_0fd?"(ignored)":"(stop)"; fprintf( stderr, "%s: couldn't nntpopen article#%d %s\n", progname, artnum, s ); #endif return ignore_0fd ? 1 : 0; } /* Construct article's file name */ sprintf(art_file,"/tmp/rrn%ld.%ld", (long) artnum, (long) getpid()); #else /* Construct article's file name */ sprintf (art_file, "%s%d", news_path, artnum); /* Forget it if we can't open the article */ if (NULL == (art_fd = fopen (art_file, "r"))) { #ifdef DEBUG fprintf(stderr,"%s: couldn't read article#%d\n", progname, artnum); #endif return 0; } #endif /* stat() the article to get file size */ if (0 != stat (art_file, &stat_buf)) { fclose (art_fd); #ifdef DEBUG fprintf(stderr,"%s: couldn't stat article %d\n", progname, artnum); #endif #ifdef NNTP unlink (art_file); #endif return 0; } end_offset = stat_buf.st_size; /* Skip empty articles */ if (end_offset == 0) { fclose (art_fd); #ifdef NNTP unlink (art_file); #endif #ifdef DEBUG fprintf(stderr,"%s: empty article\n", progname); #endif return (0); } #ifdef SCORES if (do_kills) { if (Kill(art_fd) < group_kill_thresh) { fclose (art_fd); #ifdef NNTP unlink (art_file); #endif return (-1); } else { fseek (art_fd, 0L, SEEK_SET); } } #endif /* We now assume the article is for real, so we can bump this conference's article count */ cp->count++; /* Check the Xref line if desired */ if (xrf_mode) DoXref (art_fd, end_offset); /* Do SLNP stuff */ if (slnp_mode) { if((n=SLNPArticle(art_fd, end_offset))!=1) return(n); fclose (art_fd); #ifdef NNTP unlink(art_file); #endif return (1); } /* Do ZipNews stuff */ if (zip_mode) { n=ZipArticle(art_fd, end_offset, np); fclose (art_fd); #ifdef NNTP unlink(art_file); #endif return (n); } /* Do summary stuff */ if (sum_mode) { SumArticle (art_fd, artnum, end_offset, np); fclose (art_fd); #ifdef NNTP unlink(art_file); #endif return (1); } /* Write the index file entry */ inttoms (blk_cnt, (unsigned char *)ndx); ndx[4] = np->conf; if(fwrite(ndx, 5, 1, ndx_fd)!=1) return(-2); Spaces ((char *)&hdr, 128); /* Fill in some header fields */ hdr.status = QWK_PUBLIC; PadNum (msg_cnt, hdr.number, 7); Spaces (hdr.password, 12); Spaces (hdr.refer, 8); hdr.flag = (char) QWK_ACT_FLAG; IntNum (np->conf, hdr.conference); IntNum (msg_cnt+1, hdr.msg_num); hdr.tag = ' '; PadString ("ALL", hdr.to, 25); msg_cnt++; /* Process header lines */ eof = Fgets (buf, BUF_LEN, art_fd); while ( (0 != strlen(buf)) && (eof != NULL) ) { if (!strncmp (buf, "Date: ", 6)) { ParseDate (&buf[6], &hdr); } else if (!strncmp (buf, "Subject: ", 9)) { PadString (&buf[9], hdr.subject, 25); } else if (!strncmp (buf, "From: ", 6)) { PadString (ParseFrom(&buf[6]), hdr.from, 25); } eof = Fgets (buf, BUF_LEN, art_fd); } txt_offset = ftell (art_fd); /* Compute block count */ if (inc_hdrs) { PadNum (2+end_offset/128, hdr.blocks, 6); blk_cnt += 1+end_offset/128; } else { PadNum (2+(end_offset-txt_offset)/128, hdr.blocks, 6); blk_cnt += 1+(end_offset-txt_offset)/128; } /* Write the message header */ if((out_bytes =fwrite(&hdr, 128, 1, msg_fd)) != 1 ) { return(-2); } blk_cnt++; /* Now write the article's text */ if (inc_hdrs) fseek (art_fd, 0, 0); out_bytes = 0; while (NULL != Fgets (buf, BUF_LEN, art_fd)) { n = strlen (buf); if(fwrite(buf, 1, n, msg_fd)!=n) { return(-2); } out_bytes += n; if (n < BUF_LEN-1) { if(putc(QWK_EOL, msg_fd) == EOF) { return(-2); } out_bytes++; } } /* Pad block as necessary */ n = out_bytes % 128; for (;n<128;n++) putc (' ', msg_fd); fclose (art_fd); #ifdef NNTP unlink(art_file); #endif return (1); } int SLNPArticle (art_fd, bytes) FILE *art_fd; int bytes; /* * Convert an article to SLNP format */ { #if 0 int c; /* Write "rnews" line */ if(fprintf(msg_fd, "#! rnews %d\n", bytes) < 0) return -1; /* Maintain block count */ blk_cnt += (bytes + 64) / 128; /* Copy bytes */ while (bytes--) { if( (c = getc (art_fd))==EOF) return(0); if( putc((0xff & c), msg_fd)==EOF) return(-1); } return 1; #endif int c, index = bytes; char *buf; if((buf = (char *)malloc(bytes)) == NULL ) { fprintf(stderr, "could not allocate %i bytes for article\n", bytes); return -1; } if(fread(buf, 1, bytes, art_fd) != bytes) { fprintf(stderr, "could not fread() %i bytes from article\n", bytes); free(buf); return -1; } /* Determine proper index (may have to correct for \r\n lines) */ for (c = 0; c < bytes-1; c++) if(buf[c] == '\r' && buf[c+1] == '\n') /* linetermination counts for (and will be) a single byte! */ index--; /* Write "rnews" line */ if(fprintf(msg_fd, "#! rnews %d\n", index) < 0) { free(buf); return -1; } /* Copy bytes; be sure to enforce '\n' line termination */ for (c = 0; c < bytes; c++) if(buf[c] != '\r' || (c >= bytes-1) || buf[c+1] != '\n') /* don't write the \r, whenever encountering \r\n */ if( putc((0xff & buf[c]), msg_fd) == EOF) { free(buf); return -1; } free(buf); /* Maintain block count */ blk_cnt += (bytes + 64) / 128; return 1; } int ZipArticle (art_fd, bytes, np) FILE *art_fd; int bytes; struct nrc_ent *np; /* * Convert article to ZipNews format */ { int c; long offset; /* Write separator */ for (c=0; c<20; c++) if(putc(1, nws_fd)==EOF) return(-1); if((fprintf(nws_fd, "\r\n") < 0) && ferror(nws_fd)) return(-1); /* Write index file entry for this group if there isn't already one */ if (!zip_flag) { offset = ftell (nws_fd); if( (fprintf(idx_fd, "N %08ld %s\r\n", offset, np->name) < 0) && ferror(idx_fd) ) return(-1); zip_flag = 1; } /* Maintain block count */ blk_cnt += (bytes + 64) / 128; /* Copy bytes */ while (bytes--) { if( (c = getc(art_fd))==EOF) return(-1); /* ZipNews doesn't like ^Z's */ if (c == 26) c = 32; /* Map LF to CRLF */ if( c==10 && putc(13, nws_fd)==EOF) return -1; if( putc((0xff & c), nws_fd)==EOF) return -1; } return 1; } void OutOfMemory() { fprintf (stderr, "%s: out of memory\n", progname); exit(-1); } struct sub_ent *SubList (c) char *c; /* * Parse a newsrc subscription line, make into subscription list */ { struct sub_ent *sp, *sub_list; int lo, hi; char *range; /* Initialize subscription list */ sub_list = NULL; /* Loop through line entries */ range = strtok (c, ","); while (range != NULL) { /* Get space for new list entry */ if (NULL == (sp = (struct sub_ent *) malloc (sizeof (struct sub_ent)))) OutOfMemory(); /* Determine if it's a range or single entry */ if (2 == sscanf (range, "%d-%d", &lo, &hi)) { sp->lo = lo; sp->hi = hi; /* Reverse them in case they're backwards */ if (hi < lo) { sp->lo = hi; sp->hi = lo; } } else { /* Not a range */ sp->lo = atoi (range); sp->hi = sp->lo; } /* Check if range overlaps last one */ if ( (sub_list != NULL) && (sp->lo <= (sub_list->hi + 1))) { /* Combine ranges */ if (sp->lo < sub_list->lo) sub_list->lo = sp->lo; if (sp->hi > sub_list->hi) sub_list->hi = sp->hi; /* Free old one */ free (sp); } else { /* No overlap, maintain pointers */ sp->next = sub_list; sub_list = sp; } range = strtok (NULL, ","); } return (sub_list); } int IsRead (num, sp) int num; struct sub_ent *sp; /* * Determine if an article has been read */ { /* Remember the list is from hi number to lo number */ /* Look through the list */ while (sp != NULL) { if (num > sp->hi) return (0); if ( (num >= sp->lo) && (num <= sp->hi) ) return (1); sp = sp->next; } return (0); } struct sub_ent *MarkRead (num, sp_head) int num; struct sub_ent *sp_head; /* * Mark article as read * * Remember, the list is stored from highest numbers to lowest numbers. */ { struct sub_ent *sp, *tsp, *lsp; sp = sp_head; /* If num is much higher than highest list, or the list is empty, we need new entry */ if ( (sp == NULL) || (num > (sp->hi + 1))) { if (NULL == (tsp = (struct sub_ent *) malloc (sizeof (struct sub_ent)))) OutOfMemory(); tsp->lo = tsp->hi = num; tsp->next = sp; return (tsp); } /* lsp remembers last entry in case we need to add a new entry */ lsp = NULL; /* Find appropriate entry for this number */ while (sp != NULL) { /* Have to squeeze one in before this one? */ if (num > (sp->hi + 1)) { if (NULL == (tsp = (struct sub_ent *) malloc (sizeof (struct sub_ent)))) OutOfMemory(); tsp->lo = tsp->hi = num; tsp->next = sp; lsp->next = tsp; return (sp_head); } /* One greater than entry's hi? */ if (num == (sp->hi + 1)) { sp->hi = num; return (sp_head); } /* In middle of range, do nothing */ if ( (num >= sp->lo) && (num <= sp->hi) ) return (sp_head); /* One too lo, must check if we merge with next entry */ if (num == (sp->lo - 1)) { if (NULL == sp->next) { /* No next entry to merge with */ sp->lo = num; return (sp_head); } /* Check for merge */ if (num == (sp->next->hi + 1)) { tsp = sp->next; sp->lo = tsp->lo; sp->next = tsp->next; free (tsp); return (sp_head); } else { /* No merge */ sp->lo = num; return (sp_head); } } lsp = sp; sp = sp->next; } /* We flew off the end and need a new entry */ if (NULL == (tsp = (struct sub_ent *) malloc (sizeof (struct sub_ent)))) OutOfMemory(); tsp->lo = tsp->hi = num; tsp->next = NULL; lsp->next = tsp; return (sp_head); } void WriteSub (fd, sp) FILE *fd; struct sub_ent *sp; /* * Write the subscription list */ { /* Do this recursively to reverse the order */ ws (fd, sp, sp); fprintf (fd, "\n"); } void ws (fd, sp, sp_head) FILE *fd; struct sub_ent *sp, *sp_head; { if (sp == NULL) return; /* Do the rest of them */ ws (fd, sp->next, sp_head); /* Do this one */ if (sp->lo == sp->hi) { fprintf (fd, "%d", sp->lo); fflush (fd); } else { fprintf (fd, "%d-%d", sp->lo, sp->hi); fflush (fd); } if (sp != sp_head) fprintf (fd, ","); } struct sub_ent *FixSub (sp, lo, hi) struct sub_ent *sp; int lo, hi; /* * Sanity fixes to the subscription list */ { struct sub_ent *tsp1, *tsp2, *tsp3; /* If the list is empty, make one new entry marking everything up to the lowest available article as read */ if (sp == NULL) { if (NULL == (tsp1 = (struct sub_ent *) malloc (sizeof (struct sub_ent)))) OutOfMemory(); tsp1->lo = 1; tsp1->hi = (lo > 1) ? (lo-1) : 1; tsp1->next = NULL; return (tsp1); } /* If the highest read article is greater than the highest available article, assume the group has been reset */ if (sp->hi > hi) { /* Mark everything as unread */ sp->lo = 1; sp->hi = (lo > 1) ? (lo-1) : 1; /* Free the rest */ tsp1 = sp->next; while (tsp1 != NULL) { tsp2 = tsp1->next; free (tsp1); tsp1 = tsp2; } sp->next = NULL; return (sp); } /* Now walk through the list and eliminate ranges lower than the lowest available article */ tsp1 = sp; while (tsp1 != NULL) { /* If lowest read article of this range is smaller than the lowest available article, all the rest of the ranges are unnecessary */ if (tsp1->lo < lo) { /* Make this range from 1 to lo */ tsp1->lo = 1; if (tsp1->hi < lo) tsp1->hi = lo - 1; /* Free the rest */ tsp2 = tsp1->next; while (tsp2 != NULL) { tsp3 = tsp2->next; free (tsp2); tsp2 = tsp3; } tsp1->next = NULL; return (sp); } tsp1 = tsp1->next; } return (sp); /* Probably shouldn't get here */ } int OpenZipFiles () /* * Open files for a ZipNews news packet */ { char fn[PATH_LEN]; /* Open .nws file */ sprintf (fn, "%s/%s.nws", home_dir, user_name); if (NULL == (nws_fd = fopen (fn, "w"))) { fprintf (stderr, "%s: can't open %s\n", progname, fn); return(-1); } /* Open .idx file */ sprintf (fn, "%s/%s.idx", home_dir, user_name); if (NULL == (idx_fd = fopen (fn, "w"))) { fprintf (stderr, "%s: can't open %s\n", progname, fn); fclose (nws_fd); return(-1); } return (1); } int WriteJoin () /* * Write the ZipNews join file */ { FILE *fd; char fn[PATH_LEN]; struct nrc_ent *np; /* Open join file */ sprintf (fn, "%s/%s.jn", home_dir, user_name); if (NULL == (fd = fopen (fn, "w"))) { fprintf (stderr, "%s: can't open %s\n", progname, fn); return -1; } /* Walk through the newsrc */ np = nrc_list; while (np != NULL) { if (np->subscribed) { if (np->sub == NULL) { if((fprintf(fd, "%s 0\r\n", np->name) < 0) && ferror(fd) ) return -1; } else { if((fprintf (fd, "%s %d\r\n", np->name, np->sub->hi) < 0) && ferror(fd) ) return -1; } } np = np->next; } fclose (fd); return 1; } void NdxClose (fd) FILE *fd; /* * Close ndx file, remove if empty */ { long offset; /* See how big it is */ offset = ftell (fd); /* Close it */ fclose (fd); /* Remove it if it's empty */ if (offset == 0) unlink (ndx_fn); } void MsgClose (fd) FILE *fd; /* * Close msg file, remove if empty */ { long offset; /* See how big it is */ offset = ftell (fd); /* Close it */ fclose (fd); /* Remove it if it's empty */ if (offset == 0) unlink (msg_fn); } int DoXref (fd, bytes) FILE *fd; long bytes; /* * Look for Xref line. */ { long offset; int n; char *rc; /* Remember file position */ offset = ftell (fd); /* Look through header */ rc = Fgets (buf, BUF_LEN, fd); n = strlen (buf); while ( (rc != NULL) && (bytes > 0) && (n > 0) ) { /* Xref: line? */ if (!strncmp (buf, "Xref: ", 6)) { /* Found one, process it */ Xref (buf); /* Restore position, return */ fseek (fd, offset, 0); return 1; } /* Get next line */ bytes -= n; rc = Fgets (buf, BUF_LEN, fd); if (rc != NULL) n = strlen (buf); } /* Reposition file */ fseek (fd, offset, 0); return 0; } int Xref (s) char *s; /* * Process an Xref line. */ { char *c, *p, name[PATH_LEN]; int num; struct nrc_ent *np; /* Skip the first two fields (Xref: and host) */ c = strtok (s, " \t"); if (c == NULL) return 0; c = strtok (NULL, " \t"); if (c == NULL) return 0; /* Look through the rest of the fields */ c = strtok (NULL, " \t"); while (c != NULL) { /* Change : to space */ for (p=c; *p; p++) if (*p == ':') *p = ' '; /* Parse xref entry */ if (2 == sscanf (c, "%s %d", name, &num)) { /* Find nrc entry for this group */ for (np=nrc_list; np!=NULL; np=np->next) { /* Match? */ if (!strcmp (np->name, name)) { /* Mark as read */ np->sub = MarkRead (num, np->sub); break; } } } /* Next xref entry */ c = strtok (NULL, " \t"); } return 0; } int SumArticle (fd, artnum, bytes, np) FILE *fd; long bytes; struct nrc_ent *np; int artnum; /* * Summarize article */ { char subject[PATH_LEN]; /* Get subject line */ if (!GetHdr (fd, subject, bytes, "Subject: ")) return (0); /* Write group name if this is first article for group */ if (sum_flag == 0) { sum_flag = 1; if((fprintf (sum_fd, "\r\n*** %s\r\n", np->name) < 0) && ferror(fd) ) return -1; } /* Write article number, subject line */ if((fprintf(sum_fd, "%d:%s\r\n", artnum, subject) < 0) && ferror(fd)) return -1; return 0; } int DoSelect () /* * Select articles from a summary file */ { char group[PATH_LEN], news_path[PATH_LEN]; #ifndef NNTP char *p; #endif int artnum; struct act_ent *ap; struct nrc_ent *np = NULL, *tnp; struct conf_ent *cp = NULL; /* Open selection file */ if (NULL == (sel_fd = fopen (sel_file, "r"))) { fprintf (stderr, "%s: can't open %s\n", progname, sel_file); return -1; } /* Show no group yet */ group[0] = 0; /* Read through lines */ while (NULL != Fgets (buf, BUF_LEN, sel_fd)) { /* Check if too many blocks already */ if ( (blk_cnt >= max_blks) && (max_blks > 0) ) break; /* Ignore empty lines */ if (0 == strlen (buf)) continue; /* First character determines type of line */ switch (buf[0]) { case '*': /* New group */ /* Close old index files if any */ if (group[0] != 0) { if (!slnp_mode && !zip_mode && !sum_mode) NdxClose (ndx_fd); if (slnp_mode) MsgClose (msg_fd); } /* New newsgroup */ if (1 != sscanf (buf, "%*s %s", group)) { group[0] = 0; break; } /* Find it in newsrc, bail if not there */ np = NULL; for (tnp=nrc_list; tnp!=NULL; tnp=tnp->next) { if (!strcmp (tnp->name, group)) np = tnp; } if (np == NULL) { group[0] = 0; break; } printf ("%s: %s\n", progname, group); /* Look up in active file */ ap = FindActive (group); /* Do nothing if not in active file */ if (ap == NULL) { /* Show no valid group */ group[0] = 0; break; } /* Make new conference */ cp = NewConference (group, np->conf); /* No ZipNews index yet */ if (zip_mode) zip_flag = 0; #ifdef NNTP #ifdef NTP_FULL_ACTIVE /* Select group from NNTP server */ group_nntp (group); #endif #else /* Make news path */ sprintf (news_path, "%s/%s/", news_dir, group); for (p=(&news_path[0]); *p; p++) if (*p == '.') *p = '/'; #endif /* Fix up the subscription list */ np->sub = FixSub (np->sub, ap->lo, ap->hi); break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': /* Wants article; skip if no group */ if (group[0] != 0) { /* Get article number */ sscanf (buf, "%d", &artnum); /* Process it */ if( DoArticle(news_path, artnum, np, cp)==-2) return -2; /* Mark as read */ np->sub = MarkRead (artnum, np->sub); } break; default: break; } } fclose (sel_fd); return (1); } uqwk-2.21/nntp.h100644 35070 36 7635 6671050507 11451 0ustar jsuser/* * $Id: nntp.h,v 1.3 1999/03/08 22:37:34 js Exp $ */ /* * This header file comes from NNTP 1.5.10 * It has been modified slightly to work with uqwk. * It is used to read news articles from a remote * news server. * * -- Ken Whedbee 3/31/93 * */ /* * Response codes for NNTP server * * @(#)Header: nntp.h,v 1.8 90/07/05 02:08:31 sob Exp $ * * First digit: * * 1xx Informative message * 2xx Command ok * 3xx Command ok so far, continue * 4xx Command was correct, but couldn't be performed * for some specified reason. * 5xx Command unimplemented, incorrect, or a * program error has occurred. * * Second digit: * * x0x Connection, setup, miscellaneous * x1x Newsgroup selection * x2x Article selection * x3x Distribution * x4x Posting */ #define CHAR_INF '1' #define CHAR_OK '2' #define CHAR_CONT '3' #define CHAR_ERR '4' #define CHAR_FATAL '5' #define INF_HELP 100 /* Help text on way */ #define INF_AUTH 180 /* Authorization capabilities */ #define INF_DEBUG 199 /* Debug output */ #define OK_CANPOST 200 /* Hello; you can post */ #define OK_NOPOST 201 /* Hello; you can't post */ #define OK_SLAVE 202 /* Slave status noted */ #define OK_GOODBYE 205 /* Closing connection */ #define OK_GROUP 211 /* Group selected */ #define OK_GROUPS 215 /* Newsgroups follow */ #define OK_ARTICLE 220 /* Article (head & body) follows */ #define OK_HEAD 221 /* Head follows */ #define OK_BODY 222 /* Body follows */ #define OK_NOTEXT 223 /* No text sent -- stat, next, last */ #define OK_NEWNEWS 230 /* New articles by message-id follow */ #define OK_NEWGROUPS 231 /* New newsgroups follow */ #define OK_XFERED 235 /* Article transferred successfully */ #define OK_POSTED 240 /* Article posted successfully */ #define OK_AUTHSYS 280 /* Authorization system ok */ #define OK_AUTH 281 /* Authorization (user/pass) ok */ #define CONT_XFER 335 /* Continue to send article */ #define CONT_POST 340 /* Continue to post article */ #define NEED_AUTHINFO 380 /* authorization is required */ #define NEED_AUTHDATA 381 /* authorization data required */ #define ERR_GOODBYE 400 /* Have to hang up for some reason */ #define ERR_NOGROUP 411 /* No such newsgroup */ #define ERR_NCING 412 /* Not currently in newsgroup */ #define ERR_NOCRNT 420 /* No current article selected */ #define ERR_NONEXT 421 /* No next article in this group */ #define ERR_NOPREV 422 /* No previous article in this group */ #define ERR_NOARTIG 423 /* No such article in this group */ #define ERR_NOART 430 /* No such article at all */ #define ERR_GOTIT 435 /* Already got that article, don't send */ #define ERR_XFERFAIL 436 /* Transfer failed */ #define ERR_XFERRJCT 437 /* Article rejected, don't resend */ #define ERR_NOPOST 440 /* Posting not allowed */ #define ERR_POSTFAIL 441 /* Posting failed */ #define ERR_NOAUTH 480 /* authorization required for command */ #define ERR_AUTHSYS 481 /* Authorization system invalid */ #define ERR_AUTHREJ 482 /* Authorization data rejected */ #define ERR_COMMAND 500 /* Command not recognized */ #define ERR_CMDSYN 501 /* Command syntax error */ #define ERR_ACCESS 502 /* Access to server denied */ #define ERR_FAULT 503 /* Program fault, command not performed */ #define ERR_AUTHBAD 580 /* Authorization Failed */ /* RFC 977 defines this; don't change it. */ /* #define NNTP_STRLEN 512 */ /* but, unfortunately, some cross-posted articles cause INN to offer */ /* longer lines; furthermore, 1036bis prescribes `at least 1000 octets' */ #define NNTP_STRLEN 2048 /* MUST be in increasing order of completeness! */ #define GET_STATUS 1 /* test for existence only */ #define GET_HEADER 2 /* if only header items are desired */ #define GET_ARTICLE 3 /* retreive full article */ /* J$ some prototypes */ #include #include #include #include #include int handle_server_response(int response, char *nntpserver); int get_tcp_socket(char *machine); int get_server(char *string, int size); uqwk-2.21/nntpclient.c100600 35070 36 14263 7365523746 12661 0ustar jsuser/* * $Id: nntpclient.c,v 1.8 2001/10/24 11:37:10 js Exp $ */ /* * * This software is Copyright 1991 by Stan Barber. * * Permission is hereby granted to copy, reproduce, redistribute or otherwise * use this software as long as: there is no monetary profit gained * specifically from the use or reproduction of this software, it is not * sold, rented, traded or otherwise marketed, and this copyright notice is * included prominently in any copy made. * * The author make no claims as to the fitness or correctness of this software * for any use whatsoever, and it is provided as is. Any use of this software *is at the user's own risk. */ /* * The functions in this file come from rn-1.4.4 * They have been modified to work with uqwk. * They are used to read news articles from a remote * news server. * * -- Ken Whedbee 3/31/93 * * Even more (teensy) modifications have been made while working on uqwk. * -- J$, 3/8/1999 * */ #include #include "nntp.h" #if defined(NNTP) || defined (NNTPAUTH) #include "uqwk.h" #define Nullfp Null(FILE *) #define MAXFILENAME 128 char ser_line[NNTP_STRLEN]; int openart; extern char *getserverbyfile (); extern int server_init (); extern void put_server (); extern int get_server (); extern void close_server (); void connect_nntp(); FILE *getactive_nntp(); void group_nntp(); FILE *nntpopen(); int nntp_get(); void connect_nntp() { char *server; int response; /* open connection to server if appropriate */ server = getserverbyfile(NNTP_HOST_FILE); if (server == NULL) { fprintf(stderr, "Can't get the name of the news server from %s\n", NNTP_HOST_FILE); fprintf(stderr, "Either fix this file, or put NNTPSERVER in your environment.\n"); exit(1); } response = server_init(server); if (response < 0) { fprintf(stderr, "Couldn't connect to %s news server, try again later.\n", server); exit(1); } if (handle_server_response(response, server) < 0) exit(1); /* This is for INN */ put_server ("mode reader"); nntp_get (ser_line, sizeof(ser_line)); #ifdef NNTPAUTH if(do_auth) { char s[256]; sprintf(s, "authinfo user %s", auth_user); put_server(s); nntp_get (ser_line, sizeof(ser_line)); sprintf(s, "authinfo pass %s", auth_pass); put_server(s); nntp_get (ser_line, sizeof(ser_line)); if (*ser_line != CHAR_OK) { /* and then see if that's ok */ fprintf(stderr, "NNTP authentication failed:\n\t%s\n", ser_line); exit(1); } } #endif } /* open active file, etc. */ FILE *getactive_nntp() { char active_name[MAXFILENAME]; register FILE *actfp; /* open the active file */ put_server("LIST"); /* tell server we want the active file */ nntp_get(ser_line, sizeof(ser_line)); if (*ser_line != CHAR_OK) { /* and then see if that's ok */ fprintf(stderr, "Can't get active file from server:\n\t%s\n", ser_line); exit(1); } /* make a temporary name */ sprintf(active_name,"/tmp/rrnact.%d",(int)getpid()); actfp = fopen(active_name, "w+"); /* and get ready */ if (actfp == (FILE *)NULL) { fprintf(stderr,"Cant open %s\n",active_name), fflush(stdout); exit(1); } while (1) { if (nntp_get(ser_line, sizeof(ser_line)) < 0) { fprintf(stderr,"Can't get active file from server\n"); exit(1); } if (ser_line[0] == '.') /* while there's another line */ break; /* get it and write it to */ fputs(ser_line, actfp); putc('\n', actfp); } if (ferror(actfp)) { fprintf(stderr,"Error writing to active file %s.\n", active_name), fflush(stdout); exit(1); } if (fseek(actfp,0L,0) == -1) { /* just get to the beginning */ fprintf(stderr,"Error seeking in active file.\n"), fflush(stdout); exit(1); } return actfp;/* return active file ptr */ } void group_nntp(ngname) /* select newsgroup to read from */ char *ngname; { sprintf(ser_line, "GROUP %s", ngname); put_server(ser_line); if (nntp_get(ser_line, sizeof(ser_line)) < 0) { fprintf(stderr, "\nrrn: Unexpected close of server socket.\n"); /* Update .newsrc, &c. */ exit(1); } if (*ser_line != CHAR_OK) { if (atoi(ser_line) != ERR_NOGROUP){ fprintf(stderr, "\nrrn: server response to GROUP %s:\n%s\n", ngname, ser_line); /* Update .newsrc, &c. */ exit(1); } } } /** ** example usage: ** ** artfp = nntpopen(artnum,GET_ARTICLE); ** **/ FILE *nntpopen(artnum,function) int artnum; int function; { char artname[MAXFILENAME]; /* filename of current article */ FILE *artfp; if (artnum < 1) return (FILE *)NULL; sprintf(artname,"/tmp/rrn%ld.%ld", (long) artnum, (long) getpid()); artfp = fopen(artname, "w+"); /* create the temporary article */ if (artfp == (FILE *)NULL) { unlink(artname); return (FILE *)NULL; } switch (function){ case GET_STATUS: function = GET_HEADER; /* fall through */ case GET_HEADER: sprintf(ser_line, "HEAD %ld", (long)artnum); break; case GET_ARTICLE: sprintf(ser_line, "ARTICLE %ld", (long)artnum); break; } put_server(ser_line); /* ask the server for the article */ if (nntp_get(ser_line, sizeof(ser_line)) < 0) { fprintf(stderr, "\nrrn: Unexpected close of server socket.\n"); exit(1); } if (*ser_line == CHAR_FATAL) { /* Fatal error */ fprintf(stderr,"\nrrn: %s\n",ser_line); exit(1); } if (*ser_line != CHAR_OK) { /* and get it's reaction */ fclose(artfp); artfp = (FILE *)NULL; unlink(artname); return (FILE *)NULL; } for (;;) { if (nntp_get(ser_line, sizeof(ser_line)) < 0) { fprintf(stderr, "\nrrn: Unexpected close of server socket.\n"); exit(1); } if (ser_line[0] == '.' && ser_line[1] == '\0') { break; } fputs((ser_line[0] == '.' ? ser_line + 1 : ser_line), artfp); putc('\n', artfp); } if (function == GET_HEADER) putc('\n', artfp); /* req'd blank line after header */ fseek(artfp, 0L, 0); /* Then get back to the start */ openart = artnum; /* printf("got article %ld\n",(long) artnum); */ return artfp; /* and return either fp or NULL */ } int nntp_get(buf, len) char *buf; int len; { int n; n = get_server(buf, len); return n; } #endif /* defined(NNTP) || defined (NNTPAUTH) */ uqwk-2.21/nntplib.c100600 35070 36 34350 7365523746 12150 0ustar jsuser/* * $Id: nntplib.c,v 1.8 2001/10/24 11:37:10 js Exp $ */ #if defined(NNTP) || defined (NNTPAUTH) /* #ifndef lint static char *rcsid = "@(#)$Header: /home/js/CVS-Repository/Source-Code/uqwk20/nntplib.c,v 1.8 2001/10/24 11:37:10 js Exp $"; #endif */ /* * This software is Copyright 1991 by Stan Barber. * * Permission is hereby granted to copy, reproduce, redistribute or otherwise * use this software as long as: there is no monetary profit gained * specifically from the use or reproduction or this software, it is not * sold, rented, traded or otherwise marketed, and this copyright notice is * included prominently in any copy made. * * The author make no claims as to the fitness or correctness of this software * for any use whatsoever, and it is provided as is. Any use of this software * is at the user's own risk. * */ /* * NNTP client routines. */ /* * The functions in this file come from NNTP 1.5.10 * They have been modified slightly to work with uqwk. * They are used to read news articles from a remote * news server. * * -- Ken Whedbee 3/31/93 * */ #include #include #include #include #ifdef TLI #include #include #include #include #ifdef WIN_TCP #include #else #include #endif # define IPPORT_NNTP ((unsigned short) 119) # include /* All TLI implementations may not have this */ #else /* !TLI */ #include #include #ifndef EXCELAN # include #endif /* !EXCELAN */ #endif /* !TLI */ #ifdef USG # define index strchr # define bcopy(a,b,c) memcpy(b,a,c) # define bzero(a,b) memset(a,'\0',b) #endif /* USG */ #ifdef EXCELAN # define IPPORT_NNTP ((unsigned short) 119) #if __STDC__ int connect(); unsigned short htons(); unsigned long rhost(); int rresvport(); int socket(); #endif #endif #ifdef DECNET #include #include #endif /* DECNET */ #include "nntp.h" void connect_nntp(); FILE *ser_rd_fp = NULL; FILE *ser_wr_fp = NULL; /* * getserverbyfile Get the name of a server from a named file. * Handle white space and comments. * Use NNTPSERVER environment variable if set. * * Parameters: "file" is the name of the file to read. * * Returns: Pointer to static data area containing the * first non-ws/comment line in the file. * NULL on error (or lack of entry in file). * * Side effects: None. */ char * getserverbyfile(file) char *file; { register FILE *fp; register char *cp; static char buf[256]; char *index(); char *getenv(); /* char *strcpy(); */ if ((cp = getenv("NNTPSERVER"))) { (void) strcpy(buf, cp); return (buf); } if (file == NULL) return (NULL); fp = fopen(file, "r"); if (fp == NULL) return (NULL); while (fgets(buf, sizeof (buf), fp) != NULL) { if (*buf == '\n' || *buf == '#') continue; cp = index(buf, '\n'); if (cp) *cp = '\0'; (void) fclose(fp); return (buf); } (void) fclose(fp); return (NULL); /* No entry */ } /* * server_init Get a connection to the remote news server. * * Parameters: "machine" is the machine to connect to. * * Returns: -1 on error * server's initial response code on success. * * Side effects: Connects to server. * "ser_rd_fp" and "ser_wr_fp" are fp's * for reading and writing to server. */ int server_init(machine) char *machine; { int sockt_rd, sockt_wr; char line[256]; char *index(); #ifdef DECNET char *cp; cp = index(machine, ':'); if (cp && cp[1] == ':') { *cp = '\0'; sockt_rd = get_dnet_socket(machine); } else sockt_rd = get_tcp_socket(machine); #else sockt_rd = get_tcp_socket(machine); #endif if (sockt_rd < 0) return (-1); /* * Now we'll make file pointers (i.e., buffered I/O) out of * the socket file descriptor. Note that we can't just * open a fp for reading and writing -- we have to open * up two separate fp's, one for reading, one for writing. */ if ((ser_rd_fp = fdopen(sockt_rd, "r")) == NULL) { perror("server_init: fdopen #1"); return (-1); } sockt_wr = dup(sockt_rd); #ifdef TLI if (t_sync(sockt_rd) < 0){ /* Sync up new fd with TLI */ t_error("server_init: t_sync"); ser_rd_fp = NULL; /* from above */ return (-1); } #endif if ((ser_wr_fp = fdopen(sockt_wr, "w")) == NULL) { perror("server_init: fdopen #2"); ser_rd_fp = NULL; /* from above */ return (-1); } /* Now get the server's signon message */ (void) get_server(line, sizeof(line)); return (atoi(line)); } /* * get_tcp_socket -- get us a socket connected to the news server. * * Parameters: "machine" is the machine the server is running on. * * Returns: Socket connected to the news server if * all is ok, else -1 on error. * * Side effects: Connects to server. * * Errors: Printed via perror. */ int get_tcp_socket(machine) char *machine; /* remote host */ { int s = 0; struct sockaddr_in sin; #ifdef TLI char*t_alloc(); struct t_call *callptr; /* * Create a TCP transport endpoint. */ if ((s = t_open("/dev/tcp", O_RDWR, (struct t_info*) 0)) < 0){ t_error("t_open: can't t_open /dev/tcp"); return(-1); } if(t_bind(s, (struct t_bind *)0, (struct t_bind *)0) < 0){ t_error("t_bind"); t_close(s); return(-1); } bzero((char *) &sin, sizeof(sin)); sin.sin_family = AF_INET; sin.sin_port = htons(IPPORT_NNTP); if (!isdigit(*machine) || (long)(sin.sin_addr.s_addr = inet_addr(machine)) == -1){ struct hostent *gethostbyname(), *hp; if((hp = gethostbyname(machine)) == NULL){ fprintf(stderr,"gethostbyname: %s: host unknown\n", machine); t_close(s); return(-1); } bcopy(hp->h_addr, (char *) &sin.sin_addr, hp->h_length); } /* * Allocate a t_call structure and initialize it. * Let t_alloc() initialize the addr structure of the t_call structure. */ if ((callptr = (struct t_call *) t_alloc(s,T_CALL,T_ADDR)) == NULL){ t_error("t_alloc"); t_close(s); return(-1); } callptr->addr.maxlen = sizeof(sin); callptr->addr.len = sizeof(sin); callptr->addr.buf = (char *) &sin; callptr->opt.len = 0; /* no options */ callptr->udata.len = 0; /* no user data with connect */ /* * Connect to the server. */ if (t_connect(s, callptr, (struct t_call *) 0) < 0) { t_error("t_connect"); t_close(s); return(-1); } /* * Now replace the timod module with the tirdwr module so that * standard read() and write() system calls can be used on the * descriptor. */ if (ioctl(s, I_POP, (char *) 0) < 0){ perror("I_POP(timod)"); t_close(s); return(-1); } if (ioctl(s, I_PUSH, "tirdwr") < 0){ perror("I_PUSH(tirdwr)"); t_close(s); return(-1); } #else /* !TLI */ #ifndef EXCELAN struct servent *getservbyname(), *sp; struct hostent *gethostbyname(), *hp; #ifdef h_addr int x = 0; register char **cp; static char *alist[1]; #endif /* h_addr */ static struct hostent def; static struct in_addr defaddr; static char namebuf[ 256 ]; if ((sp = getservbyname("nntp", "tcp")) == NULL) { fprintf(stderr, "nntp/tcp: Unknown service.\n"); return (-1); } /* If not a raw ip address, try nameserver */ if (!isdigit((int) *machine) || (long)(defaddr.s_addr = inet_addr(machine)) == -1) hp = gethostbyname(machine); else { /* Raw ip address, fake */ (void) strcpy(namebuf, machine); def.h_name = namebuf; #ifdef h_addr def.h_addr_list = alist; #endif def.h_addr = (char *)&defaddr; def.h_length = sizeof(struct in_addr); def.h_addrtype = AF_INET; def.h_aliases = 0; hp = &def; } if (hp == NULL) { fprintf(stderr, "%s: Unknown host.\n", machine); return (-1); } bzero((char *) &sin, sizeof(sin)); sin.sin_family = hp->h_addrtype; sin.sin_port = sp->s_port; #else /* EXCELAN */ bzero((char *) &sin, sizeof(sin)); sin.sin_family = AF_INET; #endif /* EXCELAN */ /* * The following is kinda gross. The name server under 4.3 * returns a list of addresses, each of which should be tried * in turn if the previous one fails. However, 4.2 hostent * structure doesn't have this list of addresses. * Under 4.3, h_addr is a #define to h_addr_list[0]. * We use this to figure out whether to include the NS specific * code... */ #ifdef h_addr /* get a socket and initiate connection -- use multiple addresses */ for (cp = hp->h_addr_list; cp && *cp; cp++) { s = socket(hp->h_addrtype, SOCK_STREAM, 0); if (s < 0) { perror("socket"); return (-1); } bcopy(*cp, (char *)&sin.sin_addr, hp->h_length); if (x < 0) fprintf(stderr, "trying %s\n", (char *)inet_ntoa(sin.sin_addr)); x = connect(s, (struct sockaddr *)&sin, sizeof (sin)); if (x == 0) break; fprintf(stderr, "connection to %s: ", (char *)inet_ntoa(sin.sin_addr)); perror(""); (void) close(s); } if (x < 0) { fprintf(stderr, "giving up...\n"); return (-1); } #else /* no name server */ #ifdef EXCELAN if ((s = socket(SOCK_STREAM,(struct sockproto *)NULL,&sin,SO_KEEPALIVE)) < 0) { /* Get the socket */ perror("socket"); return (-1); } bzero((char *) &sin, sizeof(sin)); sin.sin_family = AF_INET; sin.sin_port = htons(IPPORT_NNTP); /* set up addr for the connect */ if ((sin.sin_addr.s_addr = rhost(&machine)) == -1) { fprintf(stderr, "%s: Unknown host.\n", machine); return (-1); } /* And then connect */ if (connect(s, (struct sockaddr *)&sin) < 0) { perror("connect"); (void) close(s); return (-1); } #else /* not EXCELAN */ if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) { perror("socket"); return (-1); } /* And then connect */ bcopy(hp->h_addr, (char *) &sin.sin_addr, hp->h_length); if (connect(s, (struct sockaddr *) &sin, sizeof(sin)) < 0) { perror("connect"); (void) close(s); return (-1); } #endif /* !EXCELAN */ #endif /* !h_addr */ #endif /* !TLI */ return (s); } #ifdef DECNET /* * get_dnet_socket -- get us a socket connected to the news server. * * Parameters: "machine" is the machine the server is running on. * * Returns: Socket connected to the news server if * all is ok, else -1 on error. * * Side effects: Connects to server. * * Errors: Printed via nerror. */ get_dnet_socket(machine) char *machine; { int s, area, node; struct sockaddr_dn sdn; struct nodeent *getnodebyname(), *np; bzero((char *) &sdn, sizeof(sdn)); switch (s = sscanf( machine, "%d%*[.]%d", &area, &node )) { case 1: node = area; area = 0; case 2: node += area*1024; sdn.sdn_add.a_len = 2; sdn.sdn_family = AF_DECnet; sdn.sdn_add.a_addr[0] = node % 256; sdn.sdn_add.a_addr[1] = node / 256; break; default: if ((np = getnodebyname(machine)) == NULL) { fprintf(stderr, "%s: Unknown host.\n", machine); return (-1); } else { bcopy(np->n_addr, (char *) sdn.sdn_add.a_addr, np->n_length); sdn.sdn_add.a_len = np->n_length; sdn.sdn_family = np->n_addrtype; } break; } sdn.sdn_objnum = 0; sdn.sdn_flags = 0; sdn.sdn_objnamel = strlen("NNTP"); bcopy("NNTP", &sdn.sdn_objname[0], sdn.sdn_objnamel); if ((s = socket(AF_DECnet, SOCK_STREAM, 0)) < 0) { nerror("socket"); return (-1); } /* And then connect */ if (connect(s, (struct sockaddr *) &sdn, sizeof(sdn)) < 0) { nerror("connect"); close(s); return (-1); } return (s); } #endif /* * handle_server_response * * Print some informative messages based on the server's initial * response code. This is here so inews, rn, etc. can share * the code. * * Parameters: "response" is the response code which the * server sent us, presumably from "server_init", * above. * "nntpserver" is the news server we got the * response code from. * * Returns: -1 if the error is fatal (and we should exit). * 0 otherwise. * * Side effects: None. */ int handle_server_response(response, nntpserver) int response; char *nntpserver; { switch (response) { case OK_NOPOST: /* fall through */ printf( "NOTE: This machine does not have permission to post articles.\n"); printf( " Please don't waste your time trying.\n\n"); case OK_CANPOST: return (0); break; case ERR_ACCESS: printf( "This machine did not get permission to use the news server `%s'.\n", nntpserver); return (-1); break; default: printf("Unexpected response code from %s news server: %d\n", nntpserver, response); return (-1); break; } /*NOTREACHED*/ } /* * put_server -- send a line of text to the server, terminating it * with CR and LF, as per ARPA standard. * * Parameters: "string" is the string to be sent to the * server. * * Returns: Nothing. * * Side effects: Talks to the server. * * Note: This routine flushes the buffer each time * it is called. For large transmissions * (i.e., posting news) don't use it. Instead, * do the fprintf's yourself, and then a final * fflush. */ void put_server(string) char *string; { if (!ser_wr_fp) { connect_nntp(); if (!ser_wr_fp) { fprintf(stderr,"cannot put string `%s' to server: stream is NULL\n",string); return; } } #ifdef DEBUG fprintf(stderr, ">>> %s\n", string); #endif fprintf(ser_wr_fp, "%s\r\n", string); (void) fflush(ser_wr_fp); } /* * get_server -- get a line of text from the server. Strips * CR's and LF's. * * Parameters: "string" has the buffer space for the * line received. * "size" is the size of the buffer. * * Returns: -1 on error, 0 otherwise. * * Side effects: Talks to server, changes contents of "string". */ int get_server(string, size) char *string; int size; { register char *cp; char *index(); if (!ser_rd_fp) { fprintf(stderr,"cannot get string `%s' from server: stream is NULL\n",string); return(-1); } if (fgets(string, size, ser_rd_fp) == NULL) return (-1); if ((cp = index(string, '\r')) != NULL) *cp = '\0'; else if ((cp = index(string, '\n')) != NULL) *cp = '\0'; #ifdef DEBUG fprintf(stderr, "<<< %s\n", string); #endif return (0); } /* * close_server -- close the connection to the server, after sending * the "quit" command. * * Parameters: None. * * Returns: Nothing. * * Side effects: Closes the connection with the server. * You can't use "put_server" or "get_server" * after this routine is called. */ void close_server() { char ser_line[256]; if (ser_wr_fp == NULL || ser_rd_fp == NULL) return; put_server("QUIT"); (void) get_server(ser_line, sizeof(ser_line)); (void) fclose(ser_wr_fp); (void) fclose(ser_rd_fp); } #endif /* defined(NNTP) || defined (NNTPAUTH) */ uqwk-2.21/offline.c100600 35070 36 21300 7124107770 12077 0ustar jsuser/* * $Id: offline.c,v 1.4 2000/06/21 09:49:46 js Exp $ */ #include #include #include "uqwk.h" /* * Process offline commands */ int QWKOffLine (bytes, fd) int bytes; FILE *fd; /* * Process offline commands. Message is open on fd. We * must be careful to leave the file pointer ready for the * next message. */ { FILE *pfd; char c, cmd[PATH_LEN]; int ret = 0; /* Open mail pipe to send results back to user */ /* sprintf (buf, "%s -s 'Results of your request' %s", MAILER_PATH, user_name); */ sprintf (buf, "%s %s", SENDMAIL, user_name); if (NULL == (pfd = popen (buf, "w"))) { fprintf (stderr, "%s: can't popen() mail\n", progname); while (bytes--) fread (&c, 1, 1, fd); return -1; } fprintf (pfd, "Subject: Results of your request\n\nHere are the results of your mail to UQWK:\n"); /* Get lines, process them */ while (GetLine (&bytes, fd)) { /* Echo command */ fprintf (pfd, "\nCommand: %s\n", buf); /* Extract command */ if (1 != sscanf (buf, "%s", cmd)) { fprintf (pfd, "Malformed command.\n"); fprintf (stderr, "%s: Malformed offline command: \"%s\"\n", progname, buf); } else { fprintf (stdout, "%s: performing offline command: \"%s\"\n", progname, buf); /* Look up command */ if ( !strcasecmp (cmd, "HELP") ) { Help(pfd); } else if ( !strcasecmp (cmd, "SUBSCRIBE") ) { if((ret = Subscribe(pfd)) == -1) break; } else if ( !strcasecmp (cmd, "UNSUBSCRIBE") ) { if((ret = Unsubscribe(pfd)) == -1) break; } else if ( !strcasecmp (cmd, "GROUPS") ) { if((ret = Groups(pfd)) == -1) break; } else if ( !strcasecmp (cmd, "ALLGROUPS") ) { Allgroups(pfd); } else if ( !strcasecmp (cmd, "SHELL") ) { if((ret = Shell(pfd)) == -1) break; } else if ( !strcasecmp (cmd, "CATCHUP") ) { if((ret = Catchup(pfd)) == -1) break; } else { fprintf (pfd, "No such command. "); fprintf (pfd, "Send HELP for help.\n"); } } } fprintf (pfd, "\nEnd of commands.\n"); pclose (pfd); return ret; } int GetLine (bytes, fd) int *bytes; FILE *fd; /* * Get a line from fd, put it in buf, check for end of message */ { int i; unsigned char eol; i = 0; eol = QWK_EOL; if (slnp_mode || zip_mode) eol = '\n'; /* Read bytes until EOL or end of message */ while (*bytes) { fread (&buf[i], 1, 1, fd); (*bytes)--; /* Lose CR's from ZipNews */ if (buf[i] == '\r') buf[i] = 0; if ( (buf[i] == eol) || (i == BUF_LEN-1) ) { buf[i] = 0; return (1); } i++; } /* If we got here, we ran out of bytes */ return (0); } void Help (pfd) FILE *pfd; { fprintf (pfd, "\nAvailable commands:\n\n"); fprintf (pfd, "HELP - This message.\n"); fprintf (pfd, "SUBSCRIBE newsgroup - Subscribe to named newsgroup.\n"); fprintf (pfd, "UNSUBSCRIBE newsgroup - Unsubscribe from newsgroup.\n"); fprintf (pfd, "UNSUBSCRIBE ALL - Unsubscribe from all newsgroups.\n"); fprintf (pfd, "GROUPS - List all subscribed newsgroups.\n"); fprintf (pfd, "ALLGROUPS - List all available newsgroups.\n"); fprintf (pfd, "CATCHUP newsgroup - Mark all articles as read.\n"); fprintf (pfd, "SHELL command - Execute shell command\n\n"); } int Subscribe (pfd) FILE *pfd; { struct act_ent *ap; struct nrc_ent *np; char group[PATH_LEN]; /* Extract group name */ if (1 != sscanf (buf, "%*s %s", group)) { fprintf (pfd, "Usage: SUBSCRIBE newsgroup\n"); return (0); } #if !defined(NNTP) || defined(NNTP_FULL_ACTIVE) /* We will need active file and .newsrc */ if ((ReadActive() < 0) || (ReadNewsrc() < 0)) { #else if (ReadNewsrc() < 0) { #endif fprintf (pfd, "Sorry, couldn't read system files.\n"); return (-1); } /* Already subscribed? */ np = nrc_list; while (np != NULL) { if (!strcmp (group, np->name)) { if (np->subscribed) { fprintf (pfd, "Already subscribed to %s.\n", group); return (0); } else { np->subscribed = 1; fprintf (pfd, "Okay, re-subscribed to %s.\n", group); WriteNewsrc(); return (0); } } np = np->next; } /* Find group in active file */ if (NULL == (ap = FindActive (group))) { fprintf (pfd, "No such newsgroup: %s\n", group); return (0); } /* Okay already, add to .newsrc */ np = (struct nrc_ent *) malloc (sizeof (struct nrc_ent)); if (np == NULL) OutOfMemory(); np->name = (char *) malloc (1+strlen(group)); if (np->name == NULL) OutOfMemory(); strcpy (np->name, group); np->subscribed = 1; /* Make subscription list - everything is read */ if (NULL == (np->sub = (struct sub_ent *) malloc (sizeof (struct sub_ent)))) OutOfMemory(); np->sub->lo = 1; np->sub->hi = ap->hi; np->sub->next = NULL; np->next = nrc_list; nrc_list = np; WriteNewsrc(); fprintf (pfd, "Okay, you are now subscribed to %s.\n", group); return (1); } int Unsubscribe (pfd) FILE *pfd; { struct nrc_ent *np; char group[PATH_LEN]; /* Parse group name */ if (1 != sscanf (buf, "%*s %s", group)) { fprintf (pfd, "Usage: UNSUBSCRIBE newsgroup\n"); return 0; } /* Check for ALL */ if ( (!strcmp (group, "ALL")) || (!strcmp (group, "all")) ) { nrc_list = NULL; WriteNewsrc(); fprintf (pfd, "Okay, you are now unsubscribed from all newsgroups.\n"); return 0; } /* We need the .newsrc file */ if (ReadNewsrc() < 0) { fprintf (pfd, "Sorry, couldn't read .newsrc\n"); return -1; } /* Look for group in newsrc */ np = nrc_list; while (np != NULL) { if (!strcmp (group, np->name)) break; np = np->next; } if (np == NULL) { fprintf (pfd, "You are not currently subscribed to %s.\n", group); return 0; } np->subscribed = 0; WriteNewsrc(); fprintf (pfd, "Okay, you are unsubscribed from %s.\n", group); return 1; } int Groups (pfd) FILE *pfd; { struct nrc_ent *np; if (ReadNewsrc() < 0) { fprintf (pfd, "Sorry, couldn't read .newsrc\n"); return (-1); } fprintf (pfd, "Newsgroups to which you are subscribed:\n\n"); np = nrc_list; while (np != NULL) { if (np->subscribed) fprintf (pfd, " %s\n", np->name); np = np->next; } return (1); } int Allgroups (pfd) FILE *pfd; { struct act_ent *ap; if (ReadActive() < 0) { fprintf (pfd, "Sorry, no newsgroups are available.\n"); return (0); } fprintf (pfd, "List of available newsgroups:\n\n"); ap = act_list; while (ap != NULL) { fprintf (pfd, " %s (%d articles)\n", ap->name, ap->hi - ap->lo); ap = ap->next; } return (1); } int Catchup (pfd) FILE *pfd; { struct act_ent *ap; struct nrc_ent *np; struct sub_ent *sp, *tsp; char group[PATH_LEN]; /* Extract group name */ if (1 != sscanf (buf, "%*s %s", group)) { fprintf (pfd, "Usage: CATCHUP newsgroup\n"); return (0); } #if !defined(NNTP) || defined(NNTP_FULL_ACTIVE) /* We will need active file and .newsrc */ if ((ReadActive() < 0) || (ReadNewsrc() < 0)) { #else if (ReadNewsrc() < 0) { #endif fprintf (pfd, "Sorry, couldn't read system files.\n"); return (-1); } /* Not subscribed? */ np = nrc_list; while (np != NULL) { if (!strcmp (group, np->name)) { if (np->subscribed) { break; } else { fprintf (pfd, "You are not subscribed to %s.\n", group); return (0); } } np = np->next; } if (np == NULL) { fprintf (pfd, "You are not subscribed to %s.\n", group); return (0); } /* Find group in active file */ if (NULL == (ap = FindActive (group))) { fprintf (pfd, "No such newsgroup: %s\n", group); return (0); } /* Free subscription list */ sp = np->sub; while (sp != NULL) { tsp = sp->next; free (sp); sp = tsp; } /* Okay already, add to .newsrc */ np = (struct nrc_ent *) malloc (sizeof (struct nrc_ent)); if (np == NULL) OutOfMemory(); np->name = (char *) malloc (1+strlen(group)); if (np->name == NULL) OutOfMemory(); strcpy (np->name, group); np->subscribed = 1; /* Make subscription list - everything is read */ if (NULL == (np->sub = (struct sub_ent *) malloc (sizeof (struct sub_ent)))) OutOfMemory(); np->sub->lo = 1; np->sub->hi = ap->hi; np->sub->next = NULL; np->next = nrc_list; nrc_list = np; WriteNewsrc(); fprintf (pfd, "Okay, you are now caught up in %s.\n", group); return (1); } int Shell (pfd) FILE *pfd; { int c; FILE *cfd; if (strlen(buf) < 7) { fprintf (pfd, "Usage: SHELL command\n"); return (0); } if (NULL == (cfd = popen (&buf[6], "r"))) { fprintf (pfd, "Can't open pipe for command\n"); return (-1); } while (EOF != (c = getc (cfd))) { if(putc( (0xff & c), pfd) == EOF) return(-1); } if(putc ('\n', pfd) == EOF) return(-1); pclose (cfd); return (1); } int OffLine (fd, bytes) FILE *fd; int bytes; /* * Offline command */ { /* Skip header */ while( (fgets (buf, BUF_LEN, fd) != NULL) && (bytes > 0)) { bytes -= strlen(buf); if(buf[0] == '\n' || (buf[0] == '\r' && buf[1] == '\n')) break; } /* Hand off to the QWK Offline function */ return(QWKOffLine (bytes, fd)); } uqwk-2.21/options.c100600 35070 36 31133 7003030364 12143 0ustar jsuser/* * $Id: options.c,v 1.6 1999/10/19 08:48:42 js Exp $ */ #include #include #include #include #include "uqwk.h" /* * Determine runtime options */ void DefaultOptions() /* * Set up default options */ { struct passwd *pw; /* Do user-specific stuff*/ if (NULL == (pw = getpwuid(getuid()))) { fprintf (stderr, "%s: warning: you don't exist\n", progname); strcpy (user_name, DEF_USER_NAME); strcpy (home_dir, DEF_HOME_DIR); } else { strcpy (user_name, pw->pw_name); strcpy (home_dir, pw->pw_dir); } /* Dinky misc options */ do_debug = DEF_DO_DEBUG; do_mail = DEF_DO_MAIL; do_news = DEF_DO_NEWS; #ifdef SCORES do_kills = DEF_DO_KILLS; kill_thresh = 0; #endif ignore_0fd = DEF_IGNORE0FD; inc_hdrs = DEF_INC_HDRS; prt_opts = DEF_PRT_OPTS; read_only = DEF_READ_ONLY; max_blks = DEF_MAX_BLKS; grp_len = DEF_GRP_LEN; waf_mode = DEF_WAF_MODE; slnp_mode = DEF_SLNP_MODE; zip_mode = DEF_ZIP_MODE; xrf_mode = DEF_XRF_MODE; bw_kludge = DEF_BW_KLUDGE; xprt_mode = DEF_XPRT_MODE; sum_mode = DEF_SUM_MODE; sel_mode = DEF_SEL_MODE; every_mode = DEF_EVERY_MODE; #ifdef NNTPAUTH strcpy (auth_user, DEF_AUTH_USER); strcpy (auth_pass, DEF_AUTH_PASS); #endif strcpy (mail_dir, DEF_MAIL_DIR); strcpy (mail_file, DEF_MAIL_FILE); strcpy (nrc_file, DEF_NRC_FILE); #ifndef NNTP strcpy (act_file, DEF_ACT_FILE); strcpy (news_dir, DEF_NEWS_DIR); #endif strcpy (bbs_name, DEF_BBS_NAME); strcpy (bbs_city, DEF_BBS_CITY); strcpy (bbs_phone, DEF_BBS_PHONE); strcpy (bbs_sysop, DEF_BBS_SYSOP); strcpy (bbs_id, DEF_BBS_ID); strcpy (rep_file, DEF_REP_FILE); strcpy (trn_file, DEF_TRN_FILE); strcpy (host_name, DEF_HOST_NAME); strcpy (sum_file, DEF_SUM_FILE); strcpy (sel_file, DEF_SEL_FILE); strcpy (ng_file, DEF_NG_FILE); strcpy (inews_path, INEWS_PATH); #ifdef SCORES strcpy (kill_dir, home_dir); strcat (kill_dir, "/"); strcat (kill_dir, DEF_KILL_DIR); /* strcpy (kill_dir, DEF_KILL_DIR); */ #endif #ifdef GNKSA gnksa_level = GNKSA_VERBOSE|GNKSA_HONOUR; #endif } void EnvOptions() /* * Override options from environment variables */ { char *c; if (NULL != (c = getenv ("UQ_DO_DEBUG"))) do_debug = atoi (c); if (NULL != (c = getenv ("UQ_DO_MAIL"))) do_mail = atoi (c); if (NULL != (c = getenv ("UQ_DO_NEWS"))) do_news = atoi (c); #ifdef SCORES if (NULL != (c = getenv ("UQ_DO_KILLS"))) do_kills = atoi (c); if (NULL != (c = getenv ("UQ_KILL_THRESHOLD"))) kill_thresh = atoi (c); #endif if (NULL != (c = getenv ("UQ_IGNORE0FD"))) ignore_0fd = atoi (c); if (NULL != (c = getenv ("UQ_INC_HDRS"))) inc_hdrs = atoi (c); if (NULL != (c = getenv ("UQ_PRT_OPTS"))) prt_opts = atoi (c); if (NULL != (c = getenv ("UQ_READ_ONLY"))) read_only = atoi (c); if (NULL != (c = getenv ("UQ_MAX_BLKS"))) max_blks = atoi (c); if (NULL != (c = getenv ("UQ_GRP_LEN"))) grp_len = atoi (c); if (NULL != (c = getenv ("UQ_WAF_MODE"))) waf_mode = atoi (c); if (NULL != (c = getenv ("UQ_ZIP_MODE"))) zip_mode = atoi (c); if(zip_mode) slnp_mode = 0; if (NULL != (c = getenv ("UQ_SOUP_MODE"))) slnp_mode = atoi (c); if(slnp_mode) zip_mode = 0; if (NULL != (c = getenv ("UQ_XRF_MODE"))) xrf_mode = atoi (c); if (NULL != (c = getenv ("UQ_BW_KLUDGE"))) bw_kludge = atoi (c); if (NULL != (c = getenv ("UQ_XPRT_MODE"))) xprt_mode = atoi (c); if (NULL != (c = getenv ("UQ_EVERY_MODE"))) every_mode = atoi (c); if (NULL != (c = getenv ("UQ_HOME_DIR"))) strcpy (home_dir, c); #ifdef NNTPAUTH if (NULL != (c = getenv ("UQ_AUTH_USER"))) strcpy (auth_user, c); if (NULL != (c = getenv ("UQ_AUTH_PASS"))) strcpy (auth_pass, c); #endif if (NULL != (c = getenv ("UQ_MAIL_DIR"))) strcpy (mail_dir, c); else if (NULL != (c = getenv ("MAIL"))) strcpy (mail_file, c); if (NULL != (c = getenv ("UQ_MAIL_FILE"))) strcpy (mail_file, c); if (NULL != (c = getenv ("UQ_USER_NAME"))) strcpy (user_name, c); if (NULL != (c = getenv ("UQ_INEWS_PATH"))) strcpy (inews_path, c); #ifdef SCORES if (NULL != (c = getenv ("UQ_KILL_DIR"))) strcpy (kill_dir, c); #endif #ifdef GNKSA if (NULL != (c = getenv ("UQ_VALIDATE"))) gnksa_level = atoi (c); #endif if (NULL != (c = getenv ("UQ_BBS_NAME"))) strcpy (bbs_name, c); if (NULL != (c = getenv ("UQ_BBS_CITY"))) strcpy (bbs_city, c); if (NULL != (c = getenv ("UQ_BBS_PHONE"))) strcpy (bbs_phone, c); if (NULL != (c = getenv ("UQ_BBS_SYSOP"))) strcpy (bbs_sysop, c); if (NULL != (c = getenv ("UQ_BBS_ID"))) strcpy (bbs_id, c); #ifndef NNTP if (NULL != (c = getenv ("UQ_ACT_FILE"))) strcpy (act_file, c); if (NULL != (c = getenv ("UQ_NEWS_DIR"))) strcpy (news_dir, c); #endif if (NULL != (c = getenv ("UQ_NRC_FILE"))) strcpy (nrc_file, c); if (NULL != (c = getenv ("UQ_REP_FILE"))) strcpy (rep_file, c); if (NULL != (c = getenv ("UQ_TRN_FILE"))) strcpy (trn_file, c); if (NULL != (c = getenv ("UQ_HOST_NAME"))) strcpy (host_name, c); if (NULL != (c = getenv ("UQ_NG_FILE"))) strcpy (ng_file, c); if (NULL != (c = getenv ("UQ_SUM_FILE"))) { strcpy (sum_file, c); sum_mode = 1; } if (NULL != (c = getenv ("UQ_SEL_FILE"))) { strcpy (sel_file, c); sel_mode = 1; } } void CommandOptions (argc, argv) int argc; char *argv[]; /* * Override options from command line */ { int i; for (i=1; i #include #include #include #include #include "uqwk.h" #ifdef GNKSA #include #endif /* * Process a reply packet */ int DoReply () { int n, rep_cnt, ret; char bbs[PATH_LEN]; /* Check for ZipNews reply */ if (zip_mode) return DoZipReplies(); rep_cnt = 0; /* Open the packet */ if (NULL == (rep_fd = fopen (rep_file, "r"))) { fprintf (stderr, "%s: can't open %s\n", progname, rep_file); return(-1); } /* Handle SLNP reply */ if (slnp_mode) { if((ret=SLNPReply())) return ret; fclose (rep_fd); return 0; } /* Get the first block, the BBS ID */ if (1 != fread (buf, 128, 1, rep_fd)) { fprintf (stderr, "%s: reply packet read error\n", progname); fclose (rep_fd); return -1; } /* Extract bbs id and check */ sscanf (bbs_id, "%*d,%s", bbs); n = strlen (bbs); buf[n] = 0; if (strcmp (bbs, buf)) { fprintf (stderr, "%s: reply BBS ID mismatch: %s != %s\n", progname, buf, bbs); fclose (rep_fd); return 0; } /* Read the .newsrc file; we will need the list of conferences */ if((ret=ReadNewsrc()<=0)) return(ret); /* Read the next message header and process it */ while (1 == fread (&rep_hdr, 128, 1, rep_fd)) { if((ret=SendReply()) <= 0) return(ret); rep_cnt++; } fclose (rep_fd); printf ("%s: sent %d replies\n", progname, rep_cnt); return 1; } /* * Pipe a reply to the mailer or inews */ int SendReply () { FILE *pfd; unsigned char c; char to[PATH_LEN], subject[PATH_LEN], group[PATH_LEN]; int i, n, blocks, bytes, conf; struct nrc_ent *np; /* Extract recipient */ strncpy (buf, rep_hdr.to, 25); buf[25] = 0; sscanf (buf, "%s", to); /* Extract conference number */ strncpy (buf, rep_hdr.number, 7); buf[7] = 0; sscanf (buf, "%d", &conf); /* Extract subject */ strncpy (buf, rep_hdr.subject, 25); buf[25] = 0; strcpy (subject, buf); /* Get rid of single quotes in subject */ n = strlen (subject); for (i=0; iconf == conf) break; np = np->next; } /* Get newsgroup name */ if (np == NULL) { /* Bet this generates lots of email for "ALL" */ rep_hdr.status = QWK_PRIVATE; } else { strcpy (group, np->name); } /* Extract block count */ strncpy (buf, rep_hdr.blocks, 6); buf[6] = 0; sscanf (buf, "%d", &blocks); blocks -= 1; bytes = 128 * blocks; /* Check for off-line command message */ if ( (!strcmp (to, "uqwk")) || (!strcmp (to, "UQWK")) ) return(QWKOffLine (bytes, rep_fd)); /* Check for a configuration message intended for some other QWK "door" */ if ( (!strcasecmp (to, "MARKMAIL")) || (!strcasecmp (to, "QMAIL")) || (!strcasecmp (to, "ROSEMAIL")) || (!strcasecmp (to, "KMAIL")) || (!strcasecmp (to, "MAINMAIL")) || (!strcasecmp (to, "CMPMAIL")) || (!strcasecmp (to, "ULTRABBS")) || (!strcasecmp (to, "BGQWK")) || (!strcasecmp (to, "CAM-MAIL")) || (!strcasecmp (to, "TRIMAIL")) || (!strcasecmp (to, "QSO")) ) { /* Send warning to user */ if((n=SendWarning(to)) <= 0) return(n); /* Skip the rest of the message */ while (bytes--) fread (&c, 1, 1, rep_fd); return (0); } /* Check for a "To: " line in the body of the message */ CheckTo (to, bytes); /* Open pipe to proper program */ pfd = NULL; /* * QWK is beyond hope -- don't even bother basic GNKSA-checking :-( */ if ( (rep_hdr.status == QWK_PUBLIC) || (rep_hdr.status == QWK_PUBLIC2) ) { /* Public message, open pipe to inews */ if (xprt_mode) { sprintf (buf, "%s", posting_agent); } else { #ifdef NNTP sprintf (buf, "%s", inews_path); #else sprintf (buf, "%s -t '%s' -n '%s'", inews_path, subject, group); #endif } printf ("%s: Posting to %s\n", progname, group); if (NULL == (pfd = popen (buf, "w"))) { fprintf (stderr, "%s: can't popen() %s\n", progname, inews_path); return(-1); } #ifdef NNTP if (!xprt_mode && (pfd != NULL) ) { fprintf (pfd, "Newsgroups: %s\nSubject: %s\n\n", group, subject); } #endif } else if ( (rep_hdr.status == QWK_PRIVATE) || (rep_hdr.status == QWK_PRIVATE2) ) { /* Open pipe to mail */ if (xprt_mode) { sprintf (buf, "%s", XPRT_MAILER); } else { sprintf (buf, "%s '%s'", SENDMAIL, to); } printf ("%s: Mailing to %s\n", progname, to); if (NULL == (pfd = popen (buf, "w"))) { fprintf (stderr, "%s: can't popen() %s\n", progname, buf); return(-1); } fprintf(pfd,"Subject: %s\n", subject); } /* Read and send all bytes of message */ for (i=0; i= 0) && (c != QWK_EOL) && (c != 9) && (c != ' ') ) { to[i++] = c; fread (&c, 1, 1, rep_fd); bytes--; } to[i] = 0; /* Done! */ fseek (rep_fd, offset, 0); return (1); } /* * Process an SLNP reply packet */ int SLNPReply () { char fname[PATH_LEN], kind[PATH_LEN], type[PATH_LEN]; int rval=0; /* Look through lines in REPLIES file */ while (Fgets (buf, BUF_LEN, rep_fd)) { if (3 != sscanf (buf, "%s %s %s", fname, kind, type)) { fprintf (stderr, "%s: malformed REPLIES line\n", progname); return (-1); } /* Look for mail or news */ if (strcmp(kind,"mail") && strcmp(kind,"news")) { fprintf (stderr, "%s: bad reply kind: %s\n", progname, kind); } /* Check reply type */ else if ( (type[0] != 'u') && (type[0] != 'b') && (type[0] != 'B') ) { fprintf (stderr, "%s: reply type %c not supported\n", progname, type[0]); } else { /* Make file name */ strcat (fname, ".MSG"); /* Process it */ switch (type[0]) { case 'u': if( !strcmp(kind, "mail")) rval=SLuMail(fname); if( !strcmp(kind, "news")) rval|=SLuNews(fname); break; case 'b': case 'B': if( !strcmp(kind, "mail")) rval=SLbMail(fname); if( !strcmp(kind, "news")) rval|=SLbNews(fname); break; } /* Delete it */ if (!read_only) unlink (fname); } } return(rval); } /* * Process a SLNP mail reply file, usenet type */ int SLuMail(char *fn) { FILE *fd; int bytes, ret = 0; char *to, cmd[PATH_LEN]; long offset; /* Get space for To: */ if (NULL == (to = (char *) malloc (BUF_LEN))) OutOfMemory(); /* Open the reply file */ if (NULL == (fd = fopen (fn, "r"))) { fprintf (stderr, "%s: can't open %s\n", progname, fn); free (to); return(-1); } /* Read through it */ while (NULL != Fgets (buf, BUF_LEN, fd)) { if (strncmp (buf, "#! rnews ", 9)) { fprintf (stderr, "%s: malformed reply file\n", progname); fclose (fd); free (to); return (-1); } /* Get byte count */ sscanf (&buf[8], "%d", &bytes); /* Remember file position */ offset = ftell (fd); /* Look for To: */ GetHdr (fd, to, bytes, "To: "); /* Check for offline command */ if (!strcasecmp (to, "UQWK")) { if((ret = OffLine (fd, bytes)) == -1) break; continue; } /* Construct delivery line */ sprintf (cmd, "%s", SLNP_MAILER); printf ("%s: Mailing to %s\n", progname, to); /* Pipe message to delivery agent */ ret = SLPipe(fd, bytes, cmd); } free (to); fclose (fd); return (ret); } int SLuNews (fn) char *fn; /* * Process a SLNP news reply file, usenet type */ { FILE *fd; int bytes, rval = 0; char *grp; /* Get space for newsgroup name */ if (NULL == (grp = (char *) malloc (BUF_LEN))) { OutOfMemory(); return (-1); } #ifdef GNKSA if(gnksa_level && GnksaErrors(GnksaCheckFile(fn, fn, gnksa_level&GNKSA_VERBOSE, FROMOPTIONAL))) { AppendBadArticle(fn); if(gnksa_level & GNKSA_HONOUR) { fprintf (stderr, "%s: cannot post invalid message\n", progname); return(-1); } else fprintf (stderr, "%s: warning: attempting to post invalid message\n", progname); } #endif /* Open the reply file */ if (NULL == (fd = fopen (fn, "r"))) { fprintf (stderr, "%s: can't open %s\n", progname, fn); return(-1); } /* Read through it */ while (NULL != Fgets (buf, BUF_LEN, fd)) { if (strncmp (buf, "#! rnews ", 9)) { fprintf (stderr, "%s: mailformed reply file\n", progname); fclose (fd); return(-1); } /* Get byte count */ sscanf (&buf[8], "%d", &bytes); if (GetHdr (fd, grp, bytes, "Newsgroups: ")) { printf ("%s: Posting article to %s\n", progname, grp); } /* Pipe message to delivery agent */ rval = SLPipe(fd, bytes, posting_agent); } free (grp); fclose (fd); return (rval); } /* * Process a SLNP mail reply file, binary type */ int SLbMail(char *fn) { FILE *fd; int bytes, ret = 0; char *to, cmd[PATH_LEN]; long offset; /* Get space for To: */ if (NULL == (to = (char *) malloc (BUF_LEN))) return (-1); /* Open the reply file */ if (NULL == (fd = fopen (fn, "r"))) { fprintf (stderr, "%s: can't open %s\n", progname, fn); free (to); return(-1); } /* Read through it */ while (0 != fread (buf, 4, 1, fd)) { /* Get byte count */ bytes = buftoint((unsigned char *) buf); /* Remember file position */ offset = ftell (fd); /* Find the To: line */ GetHdr (fd, to, bytes, "To: "); /* Check for offline command */ if (!strcmp (to, "uqwk") || !strcmp (to, "UQWK")) { if((ret=OffLine(fd, bytes)) == -1) break; continue; } /* Construct delivery line */ sprintf (cmd, "%s", SLNP_MAILER); printf ("%s: Mailing to %s\n", progname, to); /* Pipe message to delivery agent */ ret = SLPipe(fd, bytes, cmd); } free (to); fclose (fd); return (ret); } /* * Process a SLNP news reply file, binary type */ int SLbNews (char *fn) { FILE *fd; int bytes, rval=0; char *grp; /* Get space for newsgroup name */ if (NULL == (grp = (char *) malloc (BUF_LEN))) { OutOfMemory(); return (-1); } #ifdef GNKSA if(gnksa_level && GnksaErrors(GnksaCheckFile(fn, fn, gnksa_level&GNKSA_VERBOSE, FROMOPTIONAL))) { AppendBadArticle(fn); if(gnksa_level & GNKSA_HONOUR) { fprintf (stderr, "%s: cannot post invalid message\n", progname); return(-1); } else fprintf (stderr, "%s: warning: attempting to post invalid message\n", progname); } #endif /* Open the reply file */ if (NULL == (fd = fopen (fn, "r"))) { fprintf (stderr, "%s: can't open %s\n", progname, fn); return(-1); } /* Read through it */ while (0 != fread (buf, 4, 1, fd)) { /* Get byte count */ bytes = buftoint((unsigned char *) buf); if (GetHdr (fd, grp, bytes, "Newsgroups: ")) { printf ("%s: Posting article to %s\n", progname, grp); } /* Pipe message to delivery agent */ rval = SLPipe(fd, bytes, posting_agent); } free (grp); fclose (fd); return (rval); } int SLPipe (fd, bytes, agent) FILE *fd; int bytes; char *agent; /* * Pipe a SLNP reply to the specified delivery agent */ { FILE *pfd; int c; /* Open pipe to agent */ if (NULL == (pfd = popen (agent, "w"))) { fprintf (stderr, "%s: can't open reply pipe (%s)\n", progname, agent); while (bytes--) getc (fd); return(-1); } /* Send message to pipe */ while (bytes--) { if( (c = getc(fd) & 0xff) == EOF) { fprintf(stderr,"%s: unable to read %d bytes\n", progname, bytes); return -1; } if( putc(c, pfd) == EOF) { fprintf(stderr, "%s: write error\n", progname); return -1; } } return(pclose(pfd)); } int GetHdr (fd, cc, bytes, hdr) FILE *fd; char *cc, *hdr; int bytes; /* * Find given header line */ { int offset, n, cnt; char *rc; cnt = strlen (hdr); /* Remember file position */ offset = ftell (fd); /* Look through header */ rc = Fgets (buf, BUF_LEN, fd); n = strlen (buf); while ( (rc != NULL) && (bytes > 0) && (n > 0) ) { /* Right line? */ if (!strncmp (buf, hdr, cnt)) { strcpy (cc, &buf[cnt]); fseek (fd, offset, 0); return (1); } /* Get next line */ bytes -= n; rc = Fgets (buf, BUF_LEN, fd); if (rc != NULL) n = strlen (buf); } /* Reposition file */ fseek (fd, offset, 0); return (0); } int DoZipReplies () /* * Process replies in a Zip packet */ { int n; char fn[PATH_LEN]; if ((n=ZipId()) <=0) return(n); /* Loop through possible mail files. This is a little kludgy, but readdir() seems to have problems on some systems, including Esix, which is the system I use. */ for (n=0; n<100; n++) { /* Construct file name */ sprintf (fn, "%s/%s.m%02d", rep_file, user_name, n); /* Process it */ if((n=ZipMail(fn)) <= 0) return(n); } /* Loop through possible news files */ for (n=0; n<100; n++) { /* Construct file name */ sprintf (fn, "%s/%s.n%02d", rep_file, user_name, n); /* Process it */ if((n=ZipNews(fn)) <= 0) return(n); } return (1); } char ZZZ[PATH_LEN]; int ZipId () { char fn[PATH_LEN],zzz[PATH_LEN],zzZ[256],*zZz,ZzZ[PATH_LEN], ZZz[PATH_LEN];FILE *zz;int zZ,zZZ=0,Zzz,z=0; sprintf (fn, "%s/%s.id", rep_file, user_name); if (NULL == (zz = fopen (fn, "r"))) { fprintf (stderr, "%s: can't open %s\n", progname, fn); return(-1); } strcpy(zzz,"Vrth#glfp#YjsMftp-#Kllqbz-");Zzz=strlen(zzz); for(zZz=(&zzz[0]);*zZz;zZz++)*zZz^=3;zZz=(&zzz[0]);zZ=getc(zz); while(zZ!=EOF){zzZ[z]=zZ^*(zZz+zZZ)^(*zZz*zZZ);*(zZz+zZZ)+= (zZZ<(Zzz+1))?*(zZz+zZZ+1):*zZz;if(!*(zZz+zZZ))(*(zZz+zZZ))++; if(++zZZ>=Zzz)zZZ=0;z++;zZ=getc(zz);}zzZ[z]=0;for(z=0;z<9;z++) zzZ[z]^=3;fclose(zz);if(strncmp(zzZ,"YMQ(VRTH#",9))return(0); zZz=(&zzZ[0]);z=0;zZz=strtok(zZz+9,"\n");zZz=strtok(NULL,"\n"); strcpy(ZZz,zZz);zZz=strtok(NULL,"\n");strcpy(ZzZ,zZz);strcat (ZzZ,"\100");strcat(ZzZ,host_name);for(zZz=(&ZzZ[0]);*zZz;zZz++) *zZz^=3;for(zZz=(&ZZz[0]);*zZz;zZz++)if((*zZz>='A')&&(*zZz<='Z')) *zZz=tolower(*zZz);z=0;while(ZZz[z]){if(z==0)ZZz[z]=toupper(ZZz[z]); if((ZZz[z]==' ')||(ZZz[z]=='-')||(ZZz[z]==0x27))ZZz[z+1]=toupper (ZZz[z+1]);z++;}for(zZz=(&ZZz[0]);*zZz;zZz++)*zZz^=3;sprintf(ZZZ, "Eqln9#%s#+%s*",ZzZ,ZZz);for(zZz=(&ZZZ[0]);*zZz;zZz++)*zZz^=3; return (1); } int ZipMail (fn) char *fn; /* * Process ZipNews mail reply */ { FILE *fd, *pfd; struct stat stat_buf; int c, have_cc, rval = 0; char *to, *cc, *addr; /* Get space for To: and Cc: */ if (NULL == (to = (char *) malloc (BUF_LEN))) return (0); if (NULL == (cc = (char *) malloc (BUF_LEN))) return (0); /* Try to stat() it */ if (0 != stat (fn, &stat_buf)) return (0); /* Try to open it */ if (NULL == (fd = fopen (fn, "r"))) return(-1); /* Get To: and Cc: */ GetHdr (fd, to, stat_buf.st_size, "To: "); have_cc = GetHdr (fd, cc, stat_buf.st_size, "Cc: "); /* Check for offline command */ if (!strcasecmp (to, "UQWK")) { int ret = OffLine(fd, stat_buf.st_size); free (cc); free (to); fclose (fd); if (!read_only) unlink (fn); return (ret); } /* Make mailer command line */ sprintf (buf, "%s '%s'", ZIP_MAILER, to); printf ("%s: Mailing to %s\n", progname, to); /* Open pipe to mailer */ if (NULL == (pfd = popen (buf, "w"))) { fprintf (stderr, "%s: can't popen() mailer\n", progname); free (cc); free (to); fclose (fd); return (-1); } if( (fprintf (pfd, "%s\n", ZZZ) < 0) && ferror(pfd)) return(-1); /* Send bytes of message */ while (EOF != (c = getc (fd))) { if (c != '\r') putc ((0xff & c), pfd); } /* Done */ rval = pclose (pfd); /* Now do Cc: addresses */ if (have_cc) { addr = strtok (cc, ", \t"); while (addr != NULL) { /* Rewind file */ fseek (fd, 0, 0); /* Make mailer command line */ sprintf (buf, "%s '%s'", ZIP_MAILER, addr); printf ("%s: Cc'ing to %s\n", progname, addr); /* Open pipe to mailer */ if (NULL == (pfd = popen (buf, "w"))) { fprintf (stderr, "%s: can't popen() mailer\n", progname); fclose (fd); return(-1); } if( (fprintf (pfd, "%s\n", ZZZ) < 0) && ferror(pfd)) return(-1); /* Send bytes of message */ while (EOF != (c = getc (fd))) { if (c != '\r') putc ((0xff & c), pfd); } /* Done */ rval |= pclose (pfd); addr = strtok (NULL, ", \t"); } } free (cc); free (to); fclose (fd); if (!read_only) unlink (fn); return (rval); } int ZipNews (fn) char *fn; /* * Process ZipNews news reply */ { FILE *fd, *pfd; struct stat stat_buf; int c, rval = 0; /* Try to stat() it */ if (0 != stat (fn, &stat_buf)) return (0); #ifdef GNKSA if(gnksa_level && GnksaErrors(GnksaCheckFile(fn, fn, gnksa_level&GNKSA_VERBOSE, FROMOPTIONAL))) { AppendBadArticle(fn); if(gnksa_level & GNKSA_HONOUR) { fprintf (stderr, "%s: cannot post invalid message\n", progname); return(-1); } else fprintf (stderr, "%s: warning: attempting to post invalid message\n", progname); } #endif /* Try to open it */ if (NULL == (fd = fopen (fn, "r"))) return(-1); printf ("%s: Posting article...\n", progname); /* Open pipe to inews */ if (NULL == (pfd = popen (posting_agent, "w"))) { fprintf (stderr, "%s: can't popen() inews\n", progname); fclose (fd); return(-1); } if( (fprintf (pfd, "%s\n", ZZZ) < 0) && ferror(pfd)) return(-1); /* Send bytes of message */ while (EOF != (c = getc (fd))) { if (c != '\r') putc ((0xff & c), pfd); } /* Done */ rval = pclose (pfd); fclose (fd); if (!read_only) unlink (fn); return (rval); } #ifdef GNKSA void AppendBadArticle(char *fn) { char *buf, out_file[PATH_LEN]; FILE *fd; size_t size; sprintf(out_file, "%s/dead.articles", home_dir); if((fd = fopen(out_file, "a")) == NULL) fprintf(stderr, "could not open %s for appending\n", out_file); if((buf = SlurpFile(fn, &size)) == NULL) { fprintf(stderr, "could not get bad article %s\n", fn); fclose(fd); return; } if(fwrite(buf, 1, size, fd) != size) fprintf(stderr, "failed to write %i bytes to %s\n", size, fn); fclose(fd); free(buf); fprintf(stderr, "%s: bad article appended to %s\n", progname, out_file); } #endif uqwk-2.21/score.c100600 35070 36 11207 6705130415 11571 0ustar jsuser/* * $Id: score.c,v 1.4 1999/04/14 15:15:11 js Exp $ */ #ifdef SCORES #include #include #include /* POSIX regular expressions */ #include "uqwk.h" /* * Score file processing * function for scanning article header for matches * utilities for reading/freeing score files * * 960413 Jim Tittsler <7j1ajh@amsat.org> */ struct scorest { struct scorest *next; regex_t rexp; #ifdef DEBUG char re_text[BUF_LEN]; #endif int score; }; struct scorest *kill_list = NULL; struct scorest *group_kill_list = NULL; char *sws ( char *p ) { char c; while((c = *p)) { if ((c == ' ') || (c == '\t')) ++p; else break; } return p; } char *snf ( char *p ) { char c; while((c = *p)) { if ((c != ' ') && (c != '\t')) ++p; else break; } return sws(p); } int read_score_file ( const char *score_filename ) { FILE *score_fd; char score_pathname[PATH_LEN]; char score_regex[BUF_LEN]; char *p,*s; struct scorest *score_entry; struct scorest **score_link; int global = 0; strcpy (score_pathname, kill_dir); strcat (score_pathname, "/"); strcat (score_pathname, score_filename); global = !strcasecmp (score_filename, GLOBAL_SCORE_FILE); if(global) { score_link = &kill_list; } else { score_link = &group_kill_list; } #ifdef DEBUG fprintf(stderr,"Looking for score file: %s\n", score_pathname); #endif if ((score_fd = fopen(score_pathname, "r")) == NULL) { printf(" "); return 0; /* no score file */ } printf("+"); #ifdef DEBUG fprintf(stderr,"Loading %d score file \"%s\"\n", global?"global":"group", score_filename); #endif while (Fgets (buf, BUF_LEN, score_fd) != NULL) { p = sws (buf); if ( (*p == '#') || (*p == '\0') || (*p == ';') ) continue; if (!strncasecmp(p, "killthr", 7)) { p = snf(p); if (global) { kill_thresh = atoi (p); #ifdef DEBUG fprintf(stderr,"Global kill threshold: %d\n", kill_thresh); #endif } else { group_kill_thresh = atoi (p); #ifdef DEBUG fprintf(stderr,"Group kill threshold: %d\n", group_kill_thresh); #endif } continue; } if ( (score_entry = (struct scorest *)malloc( sizeof (struct scorest) ) ) == NULL) { fprintf (stderr, "unable to allocate space for building score file\n"); return (0); } score_entry->next = NULL; score_entry->score = atoi(p); p = snf (p); if (strncasecmp(p, "pattern", 7) == 0) p = snf (p); s = score_regex; while (*p) { if (*p == ' ') break; *s++ = *p++; } *s = '\0'; p = sws (p); if (strncasecmp(score_regex, "Header", 6) == 0) *score_regex = '\0'; else if (strncasecmp(score_regex, "Body", 4) == 0) { fprintf (stderr, "Body scoring not supported\n"); free (score_entry); return 0; } strcat(score_regex, ".*"); strcat(score_regex, p); strcat(score_regex, ".*"); #ifdef DEBUG strcpy(score_entry->re_text, score_regex); fprintf(stderr,"score: %d where:%s: expression:%s:\n", score_entry->score, score_regex, p); fprintf(stderr,"compiling regular expresion\n"); #endif if ( regcomp(&score_entry->rexp, score_regex, REG_ICASE | REG_NOSUB) ) { fprintf(stderr, "bad regular expression\n"); free(score_entry); return 0; } else { #ifdef DEBUG fprintf(stderr,"compiled okay, linking into score list\n"); #endif *score_link = score_entry; score_link = &score_entry->next; } #ifdef DEBUG fprintf(stderr,"next score entry\n"); #endif } fclose (score_fd); #ifdef DEBUG for (sp = kill_list; sp ; sp = sp->next) fprintf(stderr, "(%d) %d\t%s [global]\n", (unsigned long)sp, sp->score, sp->re_text); for (sp = group_kill_list; sp ; sp = sp->next) fprintf(stderr, "(%d) %d\t%s [%s]\n", (unsigned long)sp, sp->score, sp->re_text, score_filename); #endif return 1; } int free_group_score(void) { struct scorest *sp, *np; #ifdef DEBUG fprintf(stderr,"freeing group score...\n"); #endif for (sp = group_kill_list ; sp ; sp = np) { #ifdef DEBUG fprintf(stderr, "\t(%ld) %d\t%s\n", (unsigned long)sp, sp->score, sp->re_text); #endif np = sp->next; regfree(&sp->rexp); free(sp); } group_kill_list = NULL; return (0); } int Kill (FILE *art_fd) { struct scorest *sp; int score = 0; /* scan through header lines, looking for regex matches */ while (Fgets (buf, BUF_LEN, art_fd) != NULL) { if (strlen(buf) == 0) break; #ifdef DEBUG fprintf(stderr,"header line: %s\n", buf); #endif for (sp = kill_list; sp ; sp = sp->next) { if (regexec(&(sp->rexp), buf, 0, NULL, 0) == 0) { score += sp->score; } } for (sp = group_kill_list; sp ; sp = sp->next) { if (regexec(&(sp->rexp), buf, 0, NULL, 0) == 0) { score += sp->score; } } } #ifdef DEBUG fprintf(stderr,"article score: %d\n", score); #endif return score; } #endif /* SCORES */ uqwk-2.21/uqwk.1100600 35070 36 66330 7003030365 11365 0ustar jsuser.TH UQWK 1 "$Author: js $ $Date: 1999/10/19 08:48:42 $" .IX uqwk .IX qwk .SH NAME .B uqwk - Collect news & mail messages for offline reading .SH SYNOPSIS .B uqwk .RB [a-plethora-of-options] .SH DESCRIPTION .B uqwk is a program which collects all a user's unread news and/or mail, and formats it into a packet for offline reading, saving telephone and connect charges. Simple Offline Usenet Packet (SOUP), ZipNews, and the deprecated QWK packet formats are supported. Mail can be read from classic Unix mbox format mail files, MMDF mail files, or maildir mailboxes. News is either read directly from a locally available file system, or obtained using NNTP. .PP .B uqwk also accepts reply packets, so replies can be mailed or posted, depending whether the message is marked private (email) or public (news). .PP .B uqwk also supports a small offline command language, so the contents of the user's .newsrc file can be viewed and manipulated offline. .SH "GENERAL OPTIONS Note that many varieties of uqwk can be built: not all options are applicable to (and available) in every one. Specifically, the NNTP-related options are only available in uqwk builds using NNTP, the options related to reading news directly from disk only to non-NNTP builds. Furthermore, the options concerning scoring and NNTP authentication are only present if support for scoring, resp. NNTP authentication, was compiled in. .TP .B -p Print options. .B uqwk will show its version number and the options that were compiled in, will examine all appropriate environment variables and command line options, print the values of all run-time options, then exit. This is useful to see what .B uqwk thinks it is going to do before you actually run it (and what setup it is offering). .TP .B -v identical to "-p". .TP .B -? same as "-v". .TP .B +r Read only. Normally, .B uqwk will empty the user's mail spool file and update the user's .newsrc file to reflect the fact that mail and news have been read. If this switch is specified, .B uqwk will not touch these files. This is useful for testing. .TP .B -r Do not execute in read-only mode. This is the default. .TP .B +m Do mail. .B uqwk will process all mail in the user's mail spool file and convert it into an offline packet. .TP .B -m Don't do mail. This is the default. .TP .B +n Do news. Using the user's .newsrc file and the news system's active file, .B uqwk will collect all unread news articles in all subscribed newsgroups into the packet. This can generate a large number of messages and large packet files. .TP .B -n Don't do news. This is the default. .TP .B +L Operate in SOUP (also known as HDPF or SLNP) mode. The files comprising a Simple Offline Usenet Packet (SOUP), specifically, AREAS and *.MSG, will be created instead of a QWK packet. The reply file, if any, will be interpreted as an SOUP "replies" file instead of a QWK reply packet. This is the default. .TP .B -L Do not operate in SOUP mode. If (and only if) neither SOUP nor ZipNews mode is selected, .B uqwk will operate in QWK mode. .TP .B +z Operate in ZipNews mode. The files comprising a ZipNews news packet, specifically, "user.JN", "user.NWS", and "user.IDX", will be created instead of a QWK packet. .TP .B -z Do not operate in ZipNews mode. If (and only if) neither SOUP nor ZipNews mode is selected, .B uqwk will operate in QWK mode. This is the default. .TP .B -I\fIposting_agent\fR Specifies the program used when posting messages (usually /usr/lib/news/inews). .B uqwk adds a `-h' flag when calling it, except in plain (non-expert) QWK mode. .TP .B +V\fIn\fR The value of \fIn\fR determines whether articles are validated before posting, whether this checking is verbose, and whether the result is respected or ignored: +V Equivalent to `+V3' (default) +V0 No article validation +V1 Verbose article validation, ignoring the outcome +V2 Silent article validation, failing articles are not posted +V3 Verbose article validation, articles containing fatal errors are not posted Whenever checking is performed, bad articles are appended to the file `dead.articles' in the .B uqwk home directory. This option is only available when .B uqwk was compiled with the `GNKSA' option, in which case the default value is `3'. .TP .B -V Equivalent to `+V0', as defined above. .TP .B +x Honor Xref header lines in news articles. When this switch is in effect, .B uqwk will only pack a crossposted article in the first newsgroup in which it is encountered. This can reduce the size of the packet but may introduce unexpected behaviour on the part of the offline reader. This is the default. .TP .B -x Do not honor Xref lines. .TP .B +F Ignore error on nonexisting news messages; proceed instead of aborting. This is the default. .TP .B -F Signal an error and abort on missing news messages. .TP .B -M\fImailspool\fR Look in the directory \fIfImailspool\fR for the mailbox file (or maildir mailbox). The default is /var/spool/mail. .TP .B -f\fImailfile\fR Look for mail in the file \fImailfile\fR. The default is a file (or maildir mailbox) with the same name as the user's login name in \fIfImailspool\fR; however, the MAIL environment variable is used when set. This switch overrides the .B -M switch. .TP .B -a\fIactivefile\fR Use \fIactivefile\fR for the list of all available newsgroups and article numbers. The default is /usr/local/news/lib/active. This option is not available if .B uqwk obtains articles from a news server using NNTP. .TP .B -S\fInewsdir\fR Look for news articles in the directory \fInewsdir\fR. The default is /var/spool/news. This option is not available if .B uqwk obtains articles from a news server using NNTP. .TP .B -N\fInewsrcfile\fR Use \fInewsrcfile\fR for the list of all newsgroups to which the user is subscribed and the list of article numbers which have been read. The default is $HOME/.newsrc. .TP .B -u\fIusername\fR By default .B uqwk uses the getpwuid() system call to determine the proper user name to use. This switch overrides the results of that call. .TP .B -H\fIhomedir\fR By default, .B uqwk uses the getpwuid() system call to determine the user's home directory. The home directory is where the files comprising the offline packet will be created. It is also where .B uqwk looks for the .newsrc file. This switch may be used to override the results of the getpwuid() call. .TP .B -B\fImaxblocks\fR Stop processing news articles if the size of the offline packet exceeds \fImaxblocks\fR 128-byte blocks. This is useful since large amounts of unread news can create large packets. Use a \fImaxblocks\fR value of zero to suppress this check. The default is 4096 blocks (half a megabyte). .TP .B -D\fIngfile\fR Process newsgroups in the order specified in \fIngfile\fR. \fIngfile\fR is expected to contain one newsgroup name per line. .TP .B -U\fIsumfile\fR Operate in "summary" mode. Instead of packing articles, .B uqwk creates a summary file, \fIsumfile\fR, which consists of the newsgroup name, article number, and subject line of each unread article. All summarized articles are marked as read. .TP .B -E\fIselfile\fR Operate in "selection" mode. Instead of using the .newsrc file to determine which articles to pack, .B uqwk reads \fIselfile\fR, a file in the same format as the summary file. (The actual subjects are optional in \fIselfile\fR.) The idea is that a summary may be created by using -U, downloaded, edited or processed by additional software to select desired articles, uploaded, and fed to the -E switch for offline article selection. .TP .B -R\fIreplyfile\fR Process \fIreplyfile\fR as a reply packet. Messages and articles created by the offline reader must be uploaded as a reply packet and then processed by this switch to be mailed or posted. If operating in SOUP mode, this file should be the REPLIES file. .B uqwk will remove \fIreplyfile\fR when it has been processed unless it is running in read-only mode. If operating in ZipNews mode, this switch should specify the .B directory in which the ZipNews reply files reside. No default reply file is set. .TP .B -d\fIhostname\fR Use the specified \fIhostname\fR when processing ZipNews reply packets. This should be the fully-qualified domain name of the Unix host. The default is "nowhere". .SH "QWK MODE OPTIONS" .TP .B +h Include headers. Since the QWK specification places limits on the sizes of certain header fields such as To:, From:, and Subject:, .B uqwk can include all message and article headers in the body of the message so all fields are visible. This is the default. (This switch only applies to the QWK packet format.) .TP .B -h Do not include headers in messages. (QWK only.) .TP .B -l\fIlen\fR Truncate the names of newsgroups to \fIlen\fR characters. Some offline readers cannot handle long newsgroup names. Newsgroup names are truncated after having been translated. The default is 15 characters. Specify a value of zero for unlimited newsgroup name lengths. (QWK only.) .TP .B +e Include an entry for every subscribed newsgroup in the CONTROL.DAT file. (QWK only). .TP .B -e Do not include an entry in CONTROL.DAT for empty newsgroups. This is the default. (QWK only.) .TP .B +W Activate the Blue Wave kludge. The Blue Wave QWK reader does not like the personal.ndx file that .B uqwk creates by default. If this switch is specified .B uqwk will create a regular ???.ndx file that Blue Wave likes. (QWK only.) .TP .B -W Do not activate the Blue Wave kludge. This is the default. .TP .B +X Operate in expert QWK mode. The QWK header is ignored and all header lines are taken from the body of the message. In the hands of an expert, this permits the creation of RFC822 compliant mail messages and RFC1036 compliant news articles using QWK readers, which is difficult or impossible otherwise in many cases. This is intended for people who really know what they're doing. (QWK only.) .TP .B -X Do not operate in expert QWK mode. This is the default. .TP .B -t\fItablefile\fR Translate newsgroup names as specified in \fItablefile\fR. Each line in \fItablefile\fR is expected to have two fields separated by white space: The old name of the newsgroup and the name to which it will be translated. (QWK only.) .TP .B -b\fIbbsname\fR Specify the BBS Name to be entered into the QWK packet. The default is "unknown BBS". (QWK only.) .TP .B -c\fIcity\fR Specify the BBS City to be entered into the QWK packet. The default is "Anytown, USA". (QWK only.) .TP .B -P\fIphone\fR Specify the BBS Phone Number to be entered into the QWK packet. The default is "555-1212". (QWK only.) .TP .B -s\fIsysop\fR Specify the BBS Sysop Name to be entered into the QWK packet. The default is "Joe Sysop". (QWK only.) .TP .B -i\fIbbsid\fR Specify the BBS ID to be entered into the QWK packet. The BBS ID is important since it will be checked against the BBS ID string in any incoming reply packets. If the two do not match, the reply packet will not be processed. The BBS ID consists of an integer, a comma, and a string of less than nine characters, with no spaces. The default is "0,SOMEBBS". (QWK only.) .SH "SCORING OPTIONS" .TP .B +k Perform kill/score processing. The global score file will be read (if it exists), as well as the score file for the current group, and each article will becored'. See the "USING SCORE FILES" section below. This is the default. .TP .B -k Do not perform kill/score processing. .TP .B -T\fIn\fR Set global threshold to signed integer \fIn\fR. The default is 0. .TP .B -K\fIkilldir\fR Look for score files in \fIkilldir\fR. The default is $HOME/.uqwk. .SH "NNTP AUTHENTICATION OPTIONS" .TP .B +A\fIusername\fR:\fIpassword\fR Perform NNTP authentication, specifying the username and password to use for that purpose. (NNTP only) .TP .B -A Don't do NNTP authentication. This is the default. (NNTP only) .SH ENVIRONMENT Most of the run-time options can also be controlled by environment variables. If an option is specified by both an environment variable and a command-line option, the command-line option is honored. .PP Note that, as with options, not all variables are meaningful in al possible incarnations of the program. .TP .B UQ_DO_MAIL Determines whether or not to process mail. Should be set to `1' (do mail) or `0' (don't do mail). .TP .B UQ_DO_NEWS Determines whether or not to process news. Should be set to `1' (do news) or `0' (don't do news). .TP .B UQ_INC_HDRS Determines whether or not to include headers in messages. Should be set to `1' (include headers) or `0' (don't include headers). .TP .B UQ_EVERY_MODE Determines whether or not to include an entry in CONTROL.DAT for empty newsgroups. Should be set to `1' (include empty groups) or `0' (don't include empty groups). .TP .B UQ_PRT_OPTS Determines whether or not to just print the values of run-time options and stop. Should be set to `1' (print options) or `0' (don't print options). .TP .B UQ_READ_ONLY Determines whether or not to run in read-only mode. Should be set to `1' (read-only) or `0' (not read-only). .TP .B UQ_WAF_MODE Determines whether the .newsrc file should be interpreted as a Waffle "join" file. Should be set to `0' (normal) or `1' (Waffle mode). .TP .B UQ_SOUP_MODE Determines whether or not to run in SOUP mode. Should be set to `0' (don't run in SOUP mode) or `1' (run in SOUP mode). .TP .B UQ_ZIP_MODE Determines whether or not to run in ZipNews mode. Should be set to `0' (don't run in ZipNews mode) or `1' (run in ZipNews mode). .TP .B UQ_INEWS_PATH Specifies the posting agent (usually inews) to be used. .B uqwk calls it with a `-h' command line switch, except in non-expert QWK mode. .TP .B UQ_VALIDATE Determines the level of message validation. Applicable only with GNKSA support compiled in. See the `+V' switch for details. .TP .B UQ_XRF_MODE Determines whether or not to honor Xref lines. Should be set to `0' (do not honor Xref lines) or `1' (honor Xref lines). .B UQ_IGNORE0FD Determines whether or not to ignore nonexisting news messages; `0' to abort, `1' to ignore. .TP .B UQ_BW_KLUDGE Determines whether or not to activate the Blue Wave kludge. Should be set to `0' (do not activate the Blue Wave kludge) or `1' (activate the Blue Wave kludge). .TP .B UQ_XPRT_MODE Determines whether or not to operate in QWK expert mode. Should be set to `0' (do not run in expert mode) or `1' (run in expert mode). .TP .B UQ_MAIL_DIR Specifies the directory where the mailbox file (or maildir type mailbox) resides. .TP .B UQ_MAIL_FILE Specifies the mailbox file (or maildir mailbox). .TP .B UQ_ACT_FILE Specifies the name of the news system's active file. .TP .TP .B UQ_NEWS_DIR Specifies the directory where the news spool resides. .B UQ_USER_NAME Specifies the username of the person running .B uqwk. .TP .B UQ_HOME_DIR Specifies the home directory, where the packet files will be created, and where .B uqwk expects to find the .newsrc file. .TP .B UQ_BBS_NAME Specifies the BBS name to be entered into the QWK packet. .TP .B UQ_BBS_CITY Specifies the BBS city to be entered into the QWK packet. .TP .B UQ_BBS_PHONE Specifies the BBS phone number to be entered into the QWK packet. .TP .B UQ_BBS_SYSOP Specifies the BBS sysop name to be entered into the QWK packet. .TP .B UQ_BBS_ID Specifies the BBS ID to be entered into the QWK packet. .TP .B UQ_NRC_FILE Specifies the name of the user's .newsrc file. .TP .B UQ_NG_FILE Specifies the name of the desired newsgroups file. .TP .B UQ_MAX_BLKS Specifies the maximum size of the offline packet in 128-byte blocks. .TP .B UQ_TRN_FILE Specifies the name of the newsgroup name translation table. .TP .B UQ_GRP_LEN Specifies the maximum length of newsgroup names. .TP .B UQ_REP_FILE Specifies the name of the reply packet, if any. .TP .B UQ_HOST_NAME Specifies the host name for ZipNews replies. .TP .B UQ_SUM_FILE Specifies the name of the summary file, if any. Also causes .B uqwk to execute in summary mode. .TP .B UQ_SEL_FILE Specifies the name of the selection file, if any. Also causes .B uqwk to execute in selection mode. .TP .B UQ_DO_KILLS Determines whether or not to perform kill/score processing. Should be set to `1' (do scoring) or `0' (don't do scoring). .TP .B UQ_KILL_THRESHOLD Specifies the global threshold. Should be set to a signed integer. .TP .B UQ_KILL_DIR Specifies the directory where the score files are. .TP .B UQ_AUTH_USER Specifies the username to use for NNTP authentication. If, and only if, both a username and a password are set, NNTP authentication will be attempted. .TP .B UQ_AUTH_PASS Specifies the password to use for NNTP authentication. If, and only if, both a username and a password are set, NNTP authentication will be attempted. .SH "USING SCORE FILES" If support for scoring was compiled in, .B uqwk can "score articles" while collecting news, so that articles whose "score" is below a certain threshold can be excluded from the packet. The rules according to which articles are scored are specified by the user in so-called score files. .PP The format of these score files is based on the score files used by some offline readers (notably YARN). Each newsgroup can have a score file; its name is the name of the group. There is also a global score file, that applies to all groups, which is called "global". .PP Getting started .PP If you find some class of articles you wish to exclude from a particular newsgroup, use any text editor to create a file named after it. Each line of such a file contains a score, a place to look for a keyword or regular expression, and the keyword. .PP For example, to exclude all crossposted articles from talk.bizarre, create a file called "talk.bizarre" in the directory $HOME/.uqwk, with the following line in it: .PP -10 Newsgroups: , .PP The effect of this line in this file would be that all articles in talk.bizarre which' "Newsgroups: " header contains a `,' would get -10 added to their initial score of 0. With a threshold of 0, that means that unless other lines add enought to compensate, these articles will not be included. .PP Score file format .PP Each score file carries the name of the group it applies to, and consists of a series of score lines. Blank lines and lines beginning with `#' are ignored. Lines can have any of the following formats: .TP .B killthreshold \fIn\fR specifies an integer score \fIn\fR that articles must meet or exceed in order to be included in the packet. This line is optional, if not present the global kill threshold is used. (which defaults to 0 if not set). .TP .B \fIscore\fR \fIheader\fR \fIpattern\fR constitutes an actual scoring line; \fIscore\fR is added to an article's score if the remainder of the line matches. To match, the specified \fIpattern\fR must match with the articles's indicated \fIheader\fR. The specified pattern is always interpreted as a regular expression; for reasons of compatibility patterns can be preceded with the word "pattern". .PP The global score file is processed first. Its patterns are applied to all articles. Score lines are processed in sequence. An article that scores below the kill threshold will not be included. .PP Example alt.usenet.offline-reader score file .PP # only include articles explicitly selected killthreshold 1 .PP # select messages about FurriNews +2 Subject: FurriNews # select messages about uqwk +2 Subject: uqwk .PP # eliminate messages about crapware -666 Subject: microsoft -666 Subject: netscape .PP Limitations, additional notes .PP It should be noted that only headers are scanned for computing scores. Furthermore, all scanning is done using POSIX regex functions -- even when a simple substring search could have sufficed. .SH "COMMAND LANGUAGE" If, while processing a reply packet, .B uqwk encounters a message to the username "UQWK", the body of the message will be interpreted as a small command language, used to display newsgroup names and subscribe or unsubscribe to newsgroups. The results of the execution of the commands will be mailed back to the originating user. .PP This is what the command language looks like: .TP .B HELP List all the available commands. .TP .B SUBSCRIBE newsgroup Subscribe to the named newsgroup. .TP .B UNSUBSCRIBE newsgroup Unsubscribe from the named newsgroup. UNSUBSCRIBE ALL may be used to unsubscribe from all newsgroups. UNSUBSCRIBE ALL is also the only way to create a new .newsrc if it does not already exist. .TP .B CATCHUP newsgroup Mark all articles in the named newsgroup as read. .TP .B GROUPS List all newsgroups to which the user is currently subscribed. .TP .B ALLGROUPS List all the available newsgroups and the number of articles in each one. .TP .B SHELL command Execute the specified shell command. Anything written to standard output will be mailed back to the originating user. .SH NOTES In QWK mode, it is possible to send mail to long email addresses by including, as the first thing in the body of the message, a line of the form: .PP To: user@site.com .PP (The space after the colon is important.) .SH BUGS .PP The handling of MMDF mail files is kludgy and should be fixed. .PP In QWK mode, if the .newsrc file is modified significantly between the time a packet is created and the time replies to that packet are processed, it is possible that articles may be posted to the wrong newsgroup. If you use .B uqwk along with a conventional online newsreader, it may be wise to maintain a separate .newsrc file strictly for .B uqwk. .PP .B uqwk does not do mail locking. New mail messages that arrive while packing mail can therefore be lost. If this worries you (it should), there are a few ways of preventing message loss. One approach (see the `getsoup' script, listed below, for an example) is to move your messages to a temporary file, and let .B uqwk collect the messages from that file instead of directly from the system mailbox. Since messages might get appended at any time, locking must be applied even while the mailbox is being moved. Another approach is to explicitly lock the mailbox before, and unlock it after, running .B uqwk -- i.e. like this: .PP lockfile -l666 -ml; trap "lockfile -mu" 1 2 3 13 15 uqwk +m lockfile -mu; trap "" 1 2 3 13 15 .PP A third approach to run .B uqwk in read-only mode and clean up your mailbox afterwards; in which case one can but hope one really knows what one's doing. .PP .B uqwk does not support the ZipNews offline commands. To perform offline configuration using .B uqwk, send mail to the username "UQWK" in the format described in the COMMAND LANGUAGE section above. .SH "SAMPLE SCRIPTS" It may be convenient for users to employ simple shell scripts for preparing packets using uqwk, and for handling reply packets. A few examples might prove instructive. .PP .B getsoup - collect mail and news into a SOUP packet .PP #!/bin/sh UQWKARGS="-B0 -m +L" # What to do? Set variables to enable. #UQ_DO_MAIL=1 UQ_DO_NEWS=1 export UQ_DO_MAIL UQ_DO_NEWS # NNTPAUTH="yes please!" # When reading mail from the system mailbox, locking # will have to be done somehow. If your Unix system # does not have lockfile, but does have /usr/ucb/mail, # use UQ_LOCKING="ucbmail". See below. UQ_LOCKING="lockfile" # # No user servicable parts below (I hope) # prg=`basename $0` if [ -z "$UQ_DO_MAIL" -a -z "$UQ_DO_NEWS" ] then echo "$prg: nothing to do" >&2 exit fi UQ_HOME_DIR=$HOME/.uqwk UQ_NRC_FILE=$HOME/.newsrc export UQ_HOME_DIR UQ_NRC_FILE # Do things in a nice, cozy subdirectory if [ ! -d $UQ_HOME_DIR ] then echo "$prg: $UQ_HOME_DIR does not exist, creating it" mkdir -p $UQ_HOME_DIR if [ ! -d $UQ_HOME_DIR ] then echo "$prg: failed to create $UQ_HOME_DIR" >&2 echo "$prg: bailing out" >&2 exit 1 fi fi cd $UQ_HOME_DIR soupfile=soup.zip if [ -f $soupfile ] ; then echo "Hmmm, $soupfile already exists." rm -i $soupfile if [ -f $soupfile ] ; then exit 1 fi fi if [ -n "$UQ_DO_NEWS" ] then UQWKARGS="$UQWKARGS +n" # Get auth stuff (nntp auth mode only) if [ -n "$NNTPAUTH" ] then while [ -z "$UQ_AUTH_PASS" ] do echo "Authentication for server $NNTPSERVER;" echo "Username: $USER, password: \\c" stty -echo read UQ_AUTH_PASS; echo stty echo done # Pass these through environment UQ_AUTH_USER=$USER; export UQ_AUTH_USER UQ_AUTH_PASS fi fi if [ -n "$UQ_DO_MAIL" ] then UQWKARGS="$UQWKARGS +m" # Read mail from the system mail box? if [ -z "$UQ_MAIL_FILE" ] then # uqwk does not do mailbox locking. Locking options: # - procmail's nifty "lockfile" utility # - /usr/ucb/mail ("ucbmail") UQ_MAIL_FILE=/tmp/$prg.$USER.mbx.$$; export UQ_MAIL_FILE case $UQ_LOCKING in "lockfile") lockfile -l666 -ml; trap "lockfile -mu" 1 2 3 13 15 mv $MAIL $UQ_MAIL_FILE lockfile -mu; trap "" 1 2 3 13 15 ;; "ucbmail") ( echo 's1-$' $UQ_MAIL_FILE ; echo q ) | /usr/ucb/mail >/dev/null ;; *) echo "$prg: no, or unknown, locking method" >&2 echo "$prg: bailing out" >&2 exit 1 ;; esac fi fi # # Now we know how to call uqwk, proper args 'n' all # uqwk $UQWKARGS; err=$? if [ $err -ne 0 ] then echo "$prg: fatal error in uqwk" >&2 echo "$prg: proceed with caution" >&2 fi # Create the SOUP packet # if [ "`echo *.MSG`" = "*.MSG" ] then echo "Sorry, nothing to get." rm -f AREAS exit fi zip -m $soupfile AREAS *.MSG mv $soupfile $HOME echo "Done, you can upload now." .PP .B putsoup - process a SOUP reply packet .PP #!/bin/sh prg=`basename $0` rf=reply.zip; cd $UQ_HOME_DIR if [ ! -f $rf ]; then echo "$prg: no reply packet found" >&2 exit 1 fi unzip -ju $rf 2>/dev/null if uqwk -m -n +L -RREPLIES then echo "$prg: fatal uqwk error, proceed with caution" >&2 fi echo "Done. If all went well, $rf can safely be deleted." rm -i $rf .SH "SEE ALSO" .PD .BR inews(8), .BR lockfile(1), .BR mail(1), .BR procmail(1) .SH ACKNOWLEDGEMENTS .PP .B uqwk was inspired by a conversation with Harry Lockwood . .PP QWK format was designed by Mark "Sparky" Herring . The creator of SOUP is Rhys Weatherley . The creator of ZipNews is Jack Kilday . .PP Thanks to Patrick Y. Lee for the QWK documentation. Many thanks also to the beta-testers: Karl J. Vesterling and Brian J. Coan . .PP Many thanks to Ken Whedbee for the NNTP modifications. .PP Many other people, too numerous to list here, contributed bug fixes and suggestions for improvement. .SH AUTHOR Steve Belczyk, steve1@genesis.nred.ma.us, seb3@gte.com. .PP Copyright (C) 1993-1994 by steve belczyk. Permission to use, copy, modify and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation. This software is provided "as is" without expressed or implied warranty. .SH "MODIFIED BY" Jeroen Scheerder, js@cwi.nl, js@xs4all.nl, js@phil.ruu.nl. .SH "MORE ACKNOWLEDGEMENTS" .PP Jim Tittsler <7j1ajh@amsat.org> came up with decent scoring code. Jos den Bekker provided valuable suggestions and bugfixes, most notably regarding error handling. uqwk-2.21/uqwk.c100600 35070 36 2074 7366072516 11442 0ustar jsuser/* * $Id: uqwk.c,v 1.6 2001/10/25 20:22:20 js Exp $ */ #include #include #define ALLOCATE #include "uqwk.h" void install_signals(void); /* * Make really sure we close up properly... */ void do_exit(void) { CloseStuff(); } /* * Try to make QWK packets from a mail and/or news spool */ int main (argc, argv) int argc; char *argv[]; { progname = argv[0]; /* Set up defaults */ DefaultOptions(); /* Look for environment variable overrides */ EnvOptions(); /* Look for command line overrides */ CommandOptions (argc, argv); /* Initialize files, etc. */ InitStuff(); atexit(do_exit); /* Do reply packet? */ if (strcmp (rep_file, DEF_REP_FILE) && DoReply() < 0) { fprintf (stderr, "%s: error sending replies\n", progname); return(-1); } install_signals(); /* Do news? */ if (do_news && DoNews() < 0) { fprintf (stderr, "%s: error getting news\n", progname); return(-1); } /* Mail? */ if (do_mail && DoMail() < 0) { fprintf (stderr, "%s: error getting mail\n", progname); return(-1); } return CloseStuff(); } uqwk-2.21/uqwk-version.h100600 35070 36 133 7366072516 13104 0ustar jsuser/* * $Id: uqwk-version.h,v 1.13 2001/10/25 20:22:20 js Exp $ */ #define VERSION "2.21" uqwk-2.21/contrib/olmenu+sonr/olmenu/olmenu100700 35070 36 47047 6770666030 16774 0ustar jsuser#!/bin/sh ######################################################################## # OLMenu - A menu-driven offline reader system for UQWK # # # # Version 1.16sh 11/06/95 # # # # Copyright (C) 1995 by Ken Gresham # # Permission to use, copy, modify and distribute this software # # and its documentation for any purpose and without fee is hereby # # granted, provided that the above copyright notice appear in all # # copies and that both that copyright notice and this permission # # notice appear in supporting documentation. This software is # # provided "as is" without expressed or implied warranty. # # # ######################################################################## # Begin User Configuration Area # ######################################################################## # ## SYSTEM VARIABLES - Modify as needed for your system ## # Some variables are set within uqwk's system setup # # Home directory HomeDir=$HOME # Working directory for UQWK UQ_HOME_DIR=$HomeDir; export UQ_HOME_DIR WorkDir=/tmp/$LOGNAME # Name of .newsrc file UQ_NRC_FILE=$HomeDir/.newsrc; export UQ_NRC_FILE # Name of active news file UQ_ACT_FILE=/usr/local/news/active; export UQ_ACT_FILE # ## PATH to OLMenu help files. Change as required. # Uncomment next line for system-wide installation. # OLMenuPath='/usr/lib/offline' # Uncomment next line for individual installation in $HOME directory OLMenuPath=$HOME # ## COMMANDS that might need to be globally changed. # # Zip utility ZIP="zip -j -k -m -T " # Unzip utility UNZIP="unzip -j -o " # Browser for help file BROWSER=hytelnet; export BROWSER # Can use page or more as text browser # ## QWK CONFIGURATION # Data for the .inf file that QWK readers create. These values may # already be set up in uqwk. Run uqwk -p to check the runtime settings. # The values below are an example only! Change the values before # uncommenting the lines! # # Host name, used as BBSID for QWK packets #HOST=MARLIN FN_HOST=`echo $HOST | tr "[A-Z]" "[a-z]"` # Fully qualified domain name #UQ_HOST_NAME=ssnet.com; export UQ_HOST_NAME #UQ_BBS_NAME="unknown BBS" #UQ_BBS_CITY="Anytown, USA" #UQ_BBS_PHONE="555-1212" #UQ_BBS_SYSOP="Joe Sysop" # Most important, identifies reply packet. Consists of an integer, a # comma, and up to nine characters, with no spaces. #UQ_BBS_ID="0,$HOST" #export UQ_BBS_NAME UQ_BBS_CITY UQ_BBS_PHONE #export UQ_BBS_SYSOP UQ_BBS_ID # Length of newsgroup names in characters. 0=no limit. UQ_GRP_LEN=0; export UQ_GRP_LEN # ## PACKET FILENAMES - may be changed in Configuration menu # # SOUP Reply filename SOUPReply="reply.zip" # SOUP Message filename SOUPOut="new.zip" # QWK Reply filename QWKReply="$FN_HOST.rep" # QWK Message filename QWKOut="$FN_HOST.qwk" # ZipNews Reply filename ZNReply="$FN_HOST.pst" # ZipNews outgoing filename ZNOut="$FN_HOST.zns" # ##################################################################### # End User Configuration Area # ##################################################################### # Assign default constants and variables (some may be configured in OLMenu): DoUpload=NO DoDownload=YES Protocol=Zmodem DoMail=YES ShowMail=YES DoNews=NO ShowNews=NO MarkAsRead=NO DeletePrompt=NO UQ_MAX_BLKS=4000; export UQ_MAX_BLKS Packet=SOUP # Begin Function Declarations ReadEnv() { # Get the saved configuration from the last session if [ -f $HOME/.olmenurc1 ] then . $HOME/.olmenurc1 fi # If $WorkDir doesn't exist, create it. if [ ! -d $WorkDir ] then mkdir $WorkDir fi if [ $DoDownload = NO ] then ShowMail="---" ShowNews="---" else ShowMail=$DoMail ShowNews=$DoNews fi SetUQWK } WriteEnv() { # Write new configuration values to .olmenurc1 file echo "DoUpload=$DoUpload" > $HOME/.olmenurc1 echo "DoDownload=$DoDownload" >> $HOME/.olmenurc1 echo "Protocol=$Protocol" >> $HOME/.olmenurc1 echo "SOUPReply=\"$SOUPReply\"" >> $HOME/.olmenurc1 echo "SOUPOut=\"$SOUPOut\"" >> $HOME/.olmenurc1 echo "QWKReply=\"$QWKReply\"" >> $HOME/.olmenurc1 echo "QWKOut=\"$QWKOut\"" >> $HOME/.olmenurc1 echo "ZNReply=\"$ZNReply\"" >> $HOME/.olmenurc1 echo "ZNOut=\"$ZNOut\"" >> $HOME/.olmenurc1 echo "DoMail=$DoMail" >> $HOME/.olmenurc1 echo "DoNews=$DoNews" >> $HOME/.olmenurc1 echo "MarkAsRead=$MarkAsRead" >> $HOME/.olmenurc1 echo "DeletePrompt=$DeletePrompt" >> $HOME/.olmenurc1 echo "UQ_MAX_BLKS=$UQ_MAX_BLKS" >> $HOME/.olmenurc1 echo "Packet=$Packet" >> $HOME/.olmenurc1 } OldFiles() { # List and optionally remove message-related files # from the $HOME directory and $WorkDir subdirectory if [ -f $HomeDir/$ReplyFile ] then Header echo echo -n " Old $ReplyFile found - (P)rocess or (R)emove? " GetSelection case $reply in [Pp]*) case $Packet in SOUP) $UNZIP -U $HomeDir/$ReplyFile ;; *) $UNZIP $HomeDir/$ReplyFile ;; esac Reply;; *) rm $HomeDir/$ReplyFile echo echo " $ReplyFile removed";; esac sleep 1 fi if [ -f $HomeDir/$OutFile ] then Header echo echo -n " Old $OutFile found - (D)ownload or (R)emove? " GetSelection case $reply in [Dd]*) Download echo " press enter to continue" read keypress;; *) rm $HomeDir/$OutFile echo " $OutFile removed" sleep 1;; esac fi clear if [ -f $WorkDir/* ] then Header echo echo " You have the following files in $WorkDir:" echo ls $WorkDir/* echo echo -n " Would you like to remove them? (y/n) " GetChar case $reply in [Yy]*) rm -f $WorkDir/* echo echo " Files have been removed." ;; *) echo echo " Files have not been removed" ;; esac sleep 1 fi } CleanFiles() { if [ -d $WorkDir ] then rm -fr $WorkDir fi } Header() { # Syntax: Header # Clear the screen and write a header. clear echo " OLMenu 1.17 - Offline Reader System" echo echo "__________________enter h for help in any menu________________________" } MainMenu() { # Main menu template Header echo echo " Session Settings" echo echo " U) Upload Reply Packet: $DoUpload" echo " D) Download New Packet: $DoDownload" echo " ($Packet packet via $Protocol)" echo echo " M) Read Mail: $ShowMail" echo " N) Read News: $ShowNews" echo echo " R) Mark Messages as Read: $MarkAsRead" echo echo " C) Configure Offline Reader System" echo " E) Execute with Session Settings" echo " Q) Quit" echo echo -n " Select [UDMNRCEQ]: " GetSelection case $reply in [Uu]*) if [ $DoUpload = YES ] then DoUpload=NO else DoUpload=YES fi ;; [Dd]*) if [ $DoDownload = YES ] then DoDownload=NO ShowMail="---" ShowNews="---" else DoDownload=YES ShowMail=$DoMail ShowNews=$DoNews fi ;; [Mm]*) if [ $DoDownload = YES ] then if [ $DoMail = YES ] then DoMail=NO ShowMail=NO else DoMail=YES ShowMail=YES fi else ShowMail="---" fi ;; [Nn]*) if [ $DoDownload = YES ] then if [ $DoNews = YES ] then DoNews=NO ShowNews=NO else DoNews=YES ShowNews=YES fi else ShowNews="---" fi ;; [Rr]*) if [ $MarkAsRead = YES ] then MarkAsRead=NO else MarkAsRead=YES fi ;; [Cc]*) ConfigMenu ;; [Ee]*) RunUQWK;; [Qq]*) clear WriteEnv CleanFiles exit ;; [Hh]*) clear; $BROWSER ${OLMenuPath}/olmenu.howto ;; *) BadSelection $reply ;; esac } ConfigMenu() { # Get a selection from the Configuration Menu while : do # Configuration menu template Header echo echo " Configure Offline Reader System" echo echo " P) Packet type is: $Packet" echo " S) SOUP Reply Packet Name is: $SOUPReply" echo " O) SOUP Out Packet Name is: $SOUPOut" echo " Q) QWK/BlueWave Reply Packet Name is: $QWKReply" echo " W) QWK/BlueWave Out Packet Name is: $QWKOut" echo " Z) ZipNews Reply Packet Name is: $ZNReply" echo " N) ZipNews Out Packet Name is: $ZNOut" echo " T) File Transfer Protocol is: $Protocol" echo " A) Prompt before deleting d/l packet: $DeletePrompt" echo " C) Change Out Packet Size: $UQ_MAX_BLKS blocks" echo " X) Return to Main Menu" echo echo -n " Select [PSOQWZNTACX]: " GetSelection case $reply in [Pp]*) SetPacket ;; [Ss]*) GetSRname ;; [Oo]*) GetSOname ;; [Qq]*) GetQRname ;; [Ww]*) GetQOname ;; [Zz]*) GetZRname ;; [Nn]*) GetZOname ;; [Tt]*) PSelect ;; [Aa]*) GetDeletePrompt ;; [Cc]*) ChgBlkSize ;; [Xx]*) SetUQWK return ;; [Hh]*) clear; $BROWSER ${OLMenuPath}/olmenu.howto ;; *) BadSelection $reply ;; esac done } GetChar() { stty raw reply=`dd if=/dev/tty bs=1 count=1 2>/dev/null` stty -raw echo "" } GetSelection() { # Input a selection from the menus. If GetChar doesn't work for some # reason, comment it out and uncomment the line following. GetChar is # a "hotkey" routine - "read reply" requires to be pressed after # the entry. GetChar # read reply } BadSelection() { # usage: BadSelection $var # Notify user of incorrect entry echo " $1 is not valid - try again" sleep 1 } SetPacket() { case $Packet in SOUP) Packet=QWK;; ZipNews) Packet=SOUP;; BlueWave) Packet=ZipNews;; QWK) Packet=BlueWave;; *) Packet=SOUP;; esac } GetSRname() { Header echo echo " Reply Packet Name is $SOUPReply" echo echo " Enter a new name and press or" echo " press for no change" echo echo -n " Enter Reply Packet name: " read NewName case $NewName in [a-zA-Z0-9]*) SOUPReply=$NewName esac } GetSOname() { Header echo echo " Out Packet Name is $SOUPOut" echo echo " Enter a new name and press or" echo " press for no change" echo echo -n " Enter Out Packet name: " read NewName case $NewName in [a-zA-Z0-9]*) SOUPOut=$NewName esac } GetQRname() { Header echo echo " Reply Packet Name is $QWKReply" echo echo " Enter a new name and press or" echo " press for no change" echo echo -n " Enter Reply Packet name: " read NewName case $NewName in [a-zA-Z0-9]*) QWKReply=$NewName esac } GetQOname() { Header echo echo " Out Packet Name is $QWKOut" echo echo " Enter a new name and press or" echo " press for no change" echo echo -n " Enter Out Packet name: " read NewName case $NewName in [a-zA-Z0-9]*) QWKOut=$NewName esac } GetZRname() { Header echo echo " Reply Packet Name is $ZNReply" echo echo " Enter a new name and press or" echo " press for no change" echo echo -n " Enter Reply Packet name: " read NewName case $NewName in [a-zA-Z0-9]*) ZNReply=$NewName esac } GetZOname() { Header echo echo " Out Packet Name is $ZNOut" echo echo " Enter a new name and press or" echo " press for no change" echo echo -n " Enter Out Packet name: " read NewName case $NewName in [a-zA-Z0-9]*) ZNOut=$NewName esac } GetDeletePrompt() { # Choose whether to automatically delete $OutFile after a download # with X, Y, or Zmodem. Header echo echo " OLMenu can automatically delete $OutFile" echo " after a download with X, Y, or Zmodem," echo " or prompt you to (S)ave or (D)elete $OutFile" echo " (OLMenu always prompts after an ftp transfer)" echo echo " Do you want to be prompted to delete $OutFile" echo -n " after downloading? (y/n) " GetChar case $reply in y|Y) DeletePrompt=YES;; *) DeletePrompt=NO;; esac } PSelect() { # Display menu and select file transfer protocol Header echo echo " The current file transfer protocol is $Protocol" echo echo " Select a file transfer protocol," echo " or press for no change" echo echo " X) Xmodem" echo " Y) Ymodem" echo " Z) Zmodem" echo " F) ftp" echo echo -n " Select [XYZF]: " GetSelection case $reply in [Xx]*) Protocol=Xmodem ;; [Yy]*) Protocol=Ymodem ;; [Zz]*) Protocol=Zmodem ;; [Ff]*) Protocol=ftp ;; [Hh]*) $BROWSER ${OLMenuPath}/olmenu.howto ;; esac } ChgBlkSize() { Header echo echo " Default New Packet size is 4000 blocks" echo " (approximately 500k before zipping)" echo echo " Current New Packet size is $UQ_MAX_BLKS blocks" echo echo " Enter a new size in blocks," echo " (0 for unlimited size) then " echo " or for no change" echo echo -n " Size = " read NewBlockSize case $NewBlockSize in [0-9]*) UQ_MAX_BLKS=$NewBlockSize export UQ_MAX_BLKS ;; [!0-9]*) BadSelection $NewBlockSize ;; esac } Upload() { # Upload a file using the selected protocol # Modify the commands for the protocols if necessary if [ $DoUpload = YES ] then Header case $Protocol in Xmodem) echo echo " Upload $ReplyFile now..." echo xmodem -rb $ReplyFile;; Ymodem) echo echo " Upload $Replyfile now..." echo rb $ReplyFile;; Zmodem) echo echo " Upload $ReplyFile now..." echo rz;; ftp) GetFTP;; esac fi } Download() { # Download a file using the selected protocol # Modify the commands for the protocols if necessary Header case $Protocol in Xmodem) xmodem -sb $HomeDir/$OutFile;; Ymodem) sb $HomeDir/$OutFile;; Zmodem) sz -w 8192 $HomeDir/$OutFile;; ftp) PutFTP;; esac } SetUQWK() { # Set the $OPTS variables control UQWK if [ $MarkAsRead = NO ] then UQ_READ_ONLY=1 else UQ_READ_ONLY=0 fi if [ $ShowMail = YES ] then UQ_DO_MAIL=1 else UQ_DO_MAIL=0 fi if [ $ShowNews = YES ] then UQ_DO_NEWS=1 else UQ_DO_NEWS=0 fi UQ_HOME_DIR=$WorkDir export UQ_READ_ONLY UQ_DO_MAIL UQ_DO_NEWS UQ_HOME_DIR case $Packet in SOUP) ReplyFile=$SOUPReply OutFile=$SOUPOut;; QWK) ReplyFile=$QWKReply OutFile=$QWKOut;; BlueWave) ReplyFile=$QWKReply OutFile=$QWKOut;; ZipNews) ReplyFile=$ZNReply OutFile=$ZNOut;; esac } Reply() { case $Packet in SOUP) uqwk -m -n +L -RREPLIES ;; QWK) uqwk -m -n -L -R${FN_HOST}.msg ;; BlueWave) uqwk -m -n -L -R${FN_HOST}.msg ;; ZipNews) uqwk -m -n +z -R$HomeDir ;; esac sleep 3 rm $HomeDir/$ReplyFile } Send() { case $Packet in SOUP) uqwk +L $ZIP $HomeDir/$SOUPOut \ $WorkDir/AREAS \ $WorkDir/*.MSG sleep 2 Download Save;; QWK) uqwk -L $ZIP $HomeDir/$QWKOut \ $WorkDir/control.dat \ $WorkDir/messages.dat \ $WorkDir/*.ndx sleep 2 Download Save;; BlueWave) uqwk -x +W +h -L $ZIP $HomeDir/$QWKOut \ $WorkDir/control.dat \ $WorkDir/messages.dat \ $WorkDir/*.ndx sleep 2 Download Save;; ZipNews) uqwk +z $ZIP $HomeDir/$ZNOut \ $WorkDir/$LOGNAME.idx \ $WorkDir/$LOGNAME.jn \ $WorkDir/$LOGNAME.mai \ $WorkDir/$LOGNAME.nws sleep 2 Download Save;; esac } Save() { case $Protocol in ftp) echo echo -n " [S]ave or [D]elete $OutFile? " GetChar case $reply in D|d) rm $HomeDir/$OutFile echo echo " $OutFile has been deleted..." sleep 1 ;; *) echo echo " $OutFile has been saved..." sleep 1 ;; esac;; *) if [ $DeletePrompt = NO ] then rm $HomeDir/$OutFile else echo echo -n " [S]ave or [D]elete $OutFile? " GetChar case $reply in D|d) rm $HomeDir/$OutFile echo echo " $OutFile has been deleted..." sleep 1 ;; *) echo echo " $OutFile has been saved..." sleep 1 ;; esac fi ;; esac } RunUQWK() { # Run the UQWK program using configuration from .olmenurc1 # and selections made in this program SetUQWK if [ $DoUpload = YES ] then Upload if [ -f $HomeDir/$ReplyFile ] then Header case $Packet in SOUP) $UNZIP -U $HomeDir/$ReplyFile ;; *) $UNZIP $HomeDir/$ReplyFile ;; esac if [ $? = 0 ] then Reply fi fi fi if [ $DoDownload = YES ] then Header Send fi sleep 1 } GetFTP() { # Get a file with a telnet session and ftp while : do echo echo " OLMenu is ready to receive $ReplyFile" echo echo " Switch to your ftp session" echo " and upload $ReplyFile now" echo echo " When the transfer is complete," echo " switch back to this session and" echo " press enter to continue." read keypress if [ -f $HomeDir/$ReplyFile ] then return else Header echo echo echo " $ReplyFile not found..." echo echo " [U]pload now" echo " [A]bort upload" echo echo -n " Select: [UA] " GetSelection case $reply in [Aa]) return;; esac fi done } PutFTP() { # Send a file with a telnet session and ftp echo echo " Switch to your ftp session" echo " and download $OutFile NOW." echo echo " When the transfer is complete," echo " switch back to this session and" } # Begin main program # Get the environment variables from .olmenurc1 ReadEnv OldFiles # Main program loop while : do MainMenu done #end of main while/do uqwk-2.21/contrib/olmenu+sonr/olmenu/olmenu.howto100600 35070 36 6271 6770666030 20104 0ustar jsuserOLMenu - Menu-based Offline Reader System Starting the Offline Reader System The Offline Reader System may be started from the shell prompt by entering "olmenu", or may be installed on a menu system: --------------- Configuring the Offline Reader System From the main screen, you may choose how Reply and New packets, mail and news articles are handled by entering one of the letter selections in the menu. Entering selections U, D, M, N, or R will toggle the setting. You may choose: U) Upload Reply Packet: NO D) Download New Packet: YES M) Read Mail: YES N) Read News: NO R) Mark new messages as read? YES C) Configure Offline Reader System E) Execute with session settings Q) Quit Entering C will present the configuration menu: P) Packet type is: S) SOUP Reply Packet Name is: O) SOUP Out Packet Name is: Q) QWK/BlueWave Reply Packet Name is: W) QWK/BlueWave Out Packet Name is: Z) ZipNews Reply Packet Name is: N) ZipNews Out Packet Name is: D) Working Directory is: T) File Transfer Protocol is: A) Prompt before deleting d/l packet: C) Change Out Packet Size: X) Return to Main Menu Selection P toggles among the packet format types. Selections S, O, Q, W, Z, and N allow you to change the packet names. Selection O renames the working directory used by the reader system. Selection T will present a menu with file transfer protocols: X) Xmodem Y) Ymodem Z) Zmodem F) ftp Selection A gives you the option of having the download (d/l) packet deleted automatically after downloading, or of being prompted to (S)ave or (D)elete the d/l packet. The default is NO (that is, to NOT be prompted). If ftp is the transfer protocol, you are always prompted. Selection C allows you to change the size of the New (download) Packet. The default value is 4000 blocks of 128 bytes each, which is roughly 500kb before zipping. You may change this to a larger value, or to 0 (zero), which allows UQWK to pack everything selected regardless of size. Use caution when resetting this value! --------------- Execute the Offline Reader System using the current configuration and session settings by entering E from the Main Menu. Entering Q will terminate the Offline Reader System and return you either to the menu system or the shell prompt. The configuration is saved upon exit and loaded when OLMenu is invoked. --------------- Running in a telnet session When running in a telnet session to your shell account, an ftp session will be used to transfer the reply file and/or the new message file, created by OLMenu and uqwk, between Connect Atlanta and your local terminal. When instructed, you will switch to your ftp session and transfer the file requested, then switch back to the telnet session to continue with the Offline Reader System. --------------- Special thanks to Cindy McKinnon who originated the offline reader project and the staff at Access America/Connect Atlanta (tm) who made possible this work. Thanks to Dirk A. Loedding (judge@america.net), Jude Dashiell (jude@omni.voicenet.com) and others for many valuable suggestions and comments. Suggestions for future versions and bug reports will be appreciated, and should be e-mailed to kgresham@america.net. uqwk-2.21/contrib/olmenu+sonr/olmenu/olmenu.setup100600 35070 36 4263 6770666031 20104 0ustar jsuser OLMenu - Offline Reader System for uqwk version 1.15 System operation and setup notes - 7/19/95 OLMenu is a shell script and related files written for the Unix operating system that utilizes uqwk (written by Steve Belczyk ) to handle e-mail and usenet news articles in upload and download packets. SOUP, QWK, BlueWave and Zipnews formats are supported. The name OLMenu in the program file and all documentation refers to the Offline Reader System in general, and to the olmenu script in particular. External program requirements include: uqwk hytelnet or another text browser # for help pages OLMenu is being developed and used on a system using AT&T System V Release 4.2 Unix, and will run in ksh (Korn shell) or in sh (Bourne shell). The distribution file, olmenu.zip, contains the following files: olmenu Main program file olmenu.howto Program help file olmenu.setup System operation and setup notes (this file) Setup Procedures ---------------- * Individual installation All files in olmenu.zip may be placed in your $HOME directory. The script, olmenu, is configured for individual installation. * System installation Unzip olmenu.zip in a convenient directory. The olmenu script should be located in or linked to /usr/rbin/ (or wherever restricted executables may be located). The olmenu.howto (help) file location is defined by the OLMenuPath variable on line 39 in the olmenu script. * All installations Edit the olmenu script in the User Configuration Area as required, ESPECIALLY in the QWK Configuration area! Values that may need to be changed are commented. A personal installation that will use SOUP format only should need no editing. ----------------- OLMenu is still evolving. Comments, criticisms, suggestions for improvement/enhancement will be appreciated. Let me know how it benefits you! I want OLMenu to be a valuable part of your Offline Reader System, so don't hesitate to contact me for support. I'm available for questions from sysadmins and individual users alike. Ken Gresham kgresham@america.net uqwk-2.21/contrib/olmenu+sonr/README100600 35070 36 2344 6770666021 15101 0ustar jsuser OLMenu - A menu-driven offline reader system for uqwk Thanks for using OLMenu! OLMenu will simplify the use of uqwk for handling mail and news by allowing individual and system users to configure and execute uqwk from an easy-to-use menu. If you are installing OLMenu for personal use, unzip the olmenu.zip file in your $HOME directory. Enter "olmenu" without the quotes to start OLMenu. Read olmenu.howto for information about running OLMenu (may be accessed while running olmenu by entering h from any menu). If you are installing OLMenu on a system for multiple users, unzip the olmenu.zip file in a convenient location, then read olmenu.setup for instructions on setting up OLMenu on a system. Also included in the package is SONR - Simple Offline News/mail Reader. SONR is a simplified menu-based script for SOUP format packets only which is fast and efficient if no configuration capabilities are required by the users. See the readme.sonr file in sonr101.zip for more details. The latest versions of OLMenu and SONR are always available via anonymous ftp from: america.net in the /pub/users/kgresham/ directory. Questions, suggestions and bug reports may be sent to: kgresham@america.net Thanks, and enjoy OLMenu! Ken Gresham uqwk-2.21/contrib/olmenu+sonr/olmenu.html100600 35070 36 14137 6770666021 16431 0ustar jsuser OLMenu Home Page

OLMenu and sonr
Internet freeware by Ken Gresham

OLMenu and sonr are menu-based front ends for uqwk, a "packet generator" installed on your service provider's shell account server. Uqwk packages e-mail and/or Usenet news in SOUP (Simple Offline Usenet Protocol) or QWK (BBS-style) packets that are downloaded and read by Offline Reader software on your computer.

Both programs are Unix shell scripts that install on the host (service provider's) machine. They can be installed either system-wide or in an individual shell account.

OLMenu automates packet generation and handling:

  • Gather mail and news articles with uqwk, zip uqwk's output, and download a single file.
  • Upload, unzip and send mail and news replies and posts from your Offline Reader.
  • Create and maintain a configuration file with your preferences of packet filenames, file transfer protocols, and uqwk parameters (such as packet size, whether to process mail and/or news, etc.) that you'd otherwise have to enter as runtime parameters to uqwk.
  • Supports SOUP, QWK and ZipNews packet formats; x-, y-, z-modem and ftp file transfers.
A configuration file is saved by OLMenu in the user's account after each run. This enables the user to download e-mail and/or new articles with as little as ONE keystroke once OLMenu is configured through easy menu selections. Uploads require only that the user start the upload when prompted.

Sonr is a simpler version of OLMenu supporting only SOUP format, without saving a configuration file. A "quiet" version of sonr is ideal for use with screen reader software, or wherever menu displays are not required or desired. Sonr is included in the OLMenu package, and available separately.

Get your copy of OLMenu or sonr today!

Click here to get OLMenu

Click here to get sonr

Can't find uqwk on your service provider?

Click here to get uqwk 1.8 by Steve Belczyk (source code)

Or try uqwk 2.13, an enhanced version of uqwk

Click here to get uqwk 2.13 (source code)

There are several precompiled versions of uqwk 2.05 available if you can't compile the source code. I've had good results, but use with care. It's a good idea to run the command "uqwk -p" (or "./uqwk -p") after installing to check the operation and verify the configuration of uqwk. This will display uqwk's parameters without processing anything. Check with your service provider if you don't know which version of Unix runs on their system.

SGI IRIX 5.3 and IRIX 6.2
SunOS 4.1.4
Solaris 2.6 (SunOS 5.6)
Linux 2.0.0 (i80x86 only)

Need more help getting your offline reader setup?

Kevin Martin's "How-to Hands-on" Offline Reader page is a very complete introduction to the world of Offline Readers. You'll find all the information you need to get started. There are also links to offline reader software, mailing lists, and Usenet newsgroups related to offline readers.

Go to the Hands On page now!


Go to Ken Gresham's Home Page

Various parts of this site have been visited

times since 7/3/97

Stat Track - Free Stats for your WebSite!

Updated 12/31/98

uqwk-2.21/contrib/olmenu+sonr/sonr/readme.sonr100600 35070 36 3160 6770666031 17340 0ustar jsuser sonr - Simple Offline News/mail Reader Sonr is a Unix shell script that automates the operation of uqwk by providing a simple menu-based interface. It requires a minimum of imput from the user to upload and send SOUP format reply packets, and to package and download mail, news articles, or both in a SOUP format packet. Sonr.quiet is a version of sonr that prints to the screen only a minimum number of messages, indicating the sending and packaging of mail and news articles. It is intended primarily for use with speech interpretive software or comm scripts that benefit from or don't require menu's appearing on the screen. The commands are identical to the standard sonr, and it is recommended that the standard version be installed first to become familiar with the commands. Sonr is an alternative to OLMenu for those who do not require OLMenu's configurable features. Sonr101.zip should be unzipped either in a user's $HOME directory, or in a directory in the executable path. The file sonr is the only one required. A few items may be configured in the User Configuration Area of the script if desired, but this should not be required for either a system or individual installation. Copyright 1995 by Ken Gresham (kgresham@america.net) Permission is hereby granted to use, copy, modify and distribute this software and it's documentation for any purpose and without fee provided that the above copyright notice appears in all copies and that the above copyright notice and this permission notice appear in all supporting documentation. This software is provided "as is" and without expressed or implied warranty. uqwk-2.21/contrib/olmenu+sonr/sonr/sonr100700 35070 36 11556 6770666031 16135 0ustar jsuser#!/bin/ksh # # Simple Offline News/Mail Reader - version 1.02 10/07/95 # # Using SOUP format, upload and send mail and news article replies; # package and download new mail and news articles using menu-based # system with uqwk. # # Copyright 1995 by Ken Gresham (kgresham@america.net) # Permission is hereby granted to use, copy, modify and distribute this # software and it's documentation for any purpose and without fee provided # that the above copyright notice appears in all copies and that the above # copyright notice and this permission notice appear in all supporting # documentation. This software is provided "as is" and without expressed # or implied warranty. # # -------------------------- # User Configuration Section # -------------------------- # Reply packet name (name must end in .zip) ReplyFile="reply.zip" # New message packet name NewFile="new.zip" # Size of download packet in blocks (4000 blocks = ~500kb unzipped, or # set to 0 for unlimited size [be careful!!]) BlockSize=4000 # Home directory HomeDir=$HOME # Temporary working directory TempWork="$HOME/Tempdir" # SOUP Options SOUPOPTS=" -r +L -H$TempWork -B$BlockSize -N$HOME/.newsrc " # --------------------------------- # End of User Configuration Section # --------------------------------- Header() { clear echo echo "__________________Simple Offline News/mail Reader___________________" echo } # Get a character from the terminal GetChar() { stty raw reply=`dd if=/dev/tty bs=1 count=1 2>/dev/null` stty -raw echo "" } Transfer() { while : do Header echo "" echo "" echo " Select a transfer protocol" echo "" echo " X) Xmodem" echo " Y) Ymodem" echo " Z) Zmodem" echo " F) ftp" GetChar case $reply in [XxYyZzFf]*) Protocol=$reply export Protocol return;; esac done } Upload() { case $Protocol in X|x) xmodem -rb $HomeDir/$ReplyFile;; Y|y) rb $HomeDir/$ReplyFile;; Z|z) rz;; F|f) Header echo "" echo "" echo "" echo " Transfer $ReplyFile via ftp now..." echo " then press enter in this screen" echo " to continue..." GetChar;; esac } Download() { case $Protocol in X|x) xmodem -sb $HomeDir/$NewFile > dljunk 2>&1 rm dljunk;; Y|y) sb $HomeDir/$NewFile > dljunk 2>&1 rm dljunk;; Z|z) sz -w 8192 $HomeDir/$NewFile > dljunk 2>&1 rm dljunk;; F|f) Header echo "" echo "" echo "" echo " Transfer $NewFile via ftp now..." echo " then press enter in this screen" echo " to continue..." GetChar;; esac } Send() { unzip -Uj $HomeDir/$ReplyFile clear echo "Sending messages..." echo uqwk -m -n +L -RREPLIES sleep 1 } RmFiles() { # Look for temporary files and directory - remove if found if [ -d $TempWork ] then rm -fr $TempWork fi # Remove old reply file if found if [ -f $HomeDir/$ReplyFile ] then rm $HomeDir/$ReplyFile fi # Remove old message file if found if [ -f $HomeDir/$NewFile ] then rm $HomeDir/$NewFile fi } # Main Program # # Create temporary working directory if needed if [ ! -d $TempWork ] then mkdir $TempWork fi # Get file transfer protocol Transfer # Clean up old files from aborted session # Prompt to send old reply file if found, then remove if [ -f $HomeDir/$ReplyFile ] then Header echo "\n\n" echo " Old $ReplyFile found - [S]end or [R]emove?" GetChar case $reply in S|s) Send;; *) rm $HomeDir/$ReplyFile;; esac fi # Prompt to download old message file if found, then remove if [ -f $HomeDir/$NewFile ] then Header echo "\n\n" echo " Old $NewFile found - [D]ownload or [R]emove?" GetChar case $reply in D|d) Download;; *) rm $HomeDir/$NewFile;; esac fi # Main menu while : do Header echo "" echo "" echo " 1) Upload reply packet ($ReplyFile)" echo " 2) Download new mail" echo " 3) Download newsgroup articles" echo " 4) Download mail and newsgroup articles" echo "" echo " Q) Quit" GetChar Selection=$reply case $Selection in 1) Upload Send;; 2) clear; echo "Packaging messages..."; echo "" uqwk +m -n $SOUPOPTS zip -jkmT $HomeDir/$NewFile $TempWork/AREAS $TempWork/*.MSG sleep 1 Download;; 3) clear; echo "Packaging messages..."; echo uqwk -m +n $SOUPOPTS zip -jkmT $HomeDir/$NewFile $TempWork/AREAS $TempWork/*.MSG sleep 1 Download;; 4) clear; echo "Packaging messages..."; echo uqwk +m +n $SOUPOPTS zip -jkmT $HomeDir/$NewFile $TempWork/AREAS $TempWork/*.MSG sleep 1 Download;; Q|q) clear # Clear out temporary files RmFiles exit;; *) ;; esac done uqwk-2.21/contrib/olmenu+sonr/sonr/sonr.quiet100700 35070 36 7202 6770666031 17234 0ustar jsuser#!/bin/ksh # # Simple Offline News/Mail Reader - version 1.01 09/19/95 # Modified for "quiet mode". Menu's will not appear. # Command entry is unchanged. May enhance operation of speech # software and "hands off" operation with comm program scripts. # Ftp file transfer is not supported in this version. Error handling # such as prompting to handle old upload and download files has # been removed. Announcements that indicate messages being sent or # packaged for download have been retained to indicate operation. # # Using SOUP format, upload and send mail and news article replies; # package and download new mail and news articles using menu-based # system with uqwk. # # Copyright 1995 by Ken Gresham (kgresham@america.net) # Permission is hereby granted to use, copy, modify and distribute this # software and it's documentation for any purpose and without fee provided # that the above copyright notice appears in all copies and that the above # copyright notice and this permission notice appear in all supporting # documentation. This software is provided "as is" and without expressed # or implied warranty. # # -------------------------- # User Configuration Section # -------------------------- # Reply packet name (name must end in .zip) ReplyFile="reply.zip" # New message packet name NewFile="new.zip" # Size of download packet in blocks (4000 blocks = ~500kb unzipped, or # set to 0 for unlimited size [be careful!!]) BlockSize=4000 # Home directory HomeDir=$HOME # Temporary working directory TempWork="$HOME/Tempdir" # SOUP Options SOUPOPTS=" -r +L -H$TempWork -B$BlockSize -N$HOME/.newsrc " # --------------------------------- # End of User Configuration Section # --------------------------------- # Get a character from the terminal GetChar() { stty raw reply=`dd if=/dev/tty bs=1 count=1 2>/dev/null` stty -raw echo "" } Transfer() { while : do GetChar case $reply in [XxYyZzFf]*) Protocol=$reply export Protocol return;; esac done } Upload() { case $Protocol in X|x) xmodem -rb $HomeDir/$ReplyFile > junk 2>&1;; Y|y) rb $HomeDir/$ReplyFile > junk 2>&1;; Z|z) rz > junk 2>&1;; esac rm junk } Download() { case $Protocol in X|x) xmodem -sb $HomeDir/$NewFile > dljunk 2>&1 rm dljunk;; Y|y) sb $HomeDir/$NewFile > dljunk 2>&1 rm dljunk;; Z|z) sz -w 8192 $HomeDir/$NewFile > dljunk 2>&1 rm dljunk;; esac } Send() { unzip -Ujq $HomeDir/$ReplyFile > junk 2>&1 clear echo "Sending messages..." echo uqwk -m -n +L -RREPLIES > junk 2>&1 rm junk } RmFiles() { # Look for temporary files and directory - remove if found if [ -d $TempWork ] then rm -fr $TempWork fi # Remove old reply file if found if [ -f $HomeDir/$ReplyFile ] then rm $HomeDir/$ReplyFile fi # Remove old message file if found if [ -f $HomeDir/$NewFile ] then rm $HomeDir/$NewFile fi } # Main Program # # Create temporary working directory if needed if [ ! -d $TempWork ] then mkdir $TempWork fi # Get file transfer protocol Transfer # Main menu while : do GetChar Selection=$reply case $Selection in 1) Upload Send;; 2) clear; echo "Packaging messages..." uqwk +m -n $SOUPOPTS > junk 2>&1 rm junk zip -jkmTq $HomeDir/$NewFile $TempWork/AREAS $TempWork/*.MSG Download;; 3) clear; echo "Packaging messages..." uqwk -m +n $SOUPOPTS > junk 2>&1 rm junk zip -jkmTq $HomeDir/$NewFile $TempWork/AREAS $TempWork/*.MSG Download;; 4) clear; echo "Packaging messages..." uqwk +m +n $SOUPOPTS > junk 2>&1 rm junk zip -jkmTq $HomeDir/$NewFile $TempWork/AREAS $TempWork/*.MSG Download;; Q|q) clear # Clear out temporary files RmFiles exit;; *) ;; esac done uqwk-2.21/Makefile.in100600 35070 36 5362 7366072516 12357 0ustar jsuser# $Id: Makefile.in,v 1.15 2001/10/25 20:22:19 js Exp $ # # Makefile.in for uqwk js, 4/14/1999 # # Options (driven by configure): # # SCORES Compile with scoring code (very useful) # NNTP Compile to use nntp to get news articles # rather than read them directly from spool # NNTPAUTH Compile with nntp authentication code # (defines NNTP implicitly) # NNTP_FULL_ACTIVE (for historic reasons only; not recommended) # Use full active file from NNTP server (rather than # just fetching info about subscribed groups only) # (defines NNTP implicitly) # GNKSA Use the GNKSA toolkit for validating/correcting # Usenet messages (be sure to set a proper include # path in CFLAGS (-I/gnksa/lib/dir), and to include # the gnksa.o file in LDFLAGS (/gnksa/lib/dir/gnksa.o) # SITECFG For site dependencies, make a copy of config-generic.h # to config-.h, and modify definitions # as appropriate. # CC = @CC@ CFLAGS = @CFLAGS@ @SCORECFLAGS@ @NNTPAUTHCFLAGS@ @NNTPCFLAGS@ @GNKSACFLAGS@ @RECFLAGS@\ -DHAVE_CONFIG=\"@SITECFG@\" LDFLAGS = @GNKSALDLAGS@ @RELDFLAGS@ @SOCKLIBS@ prefix = @prefix@ exec_prefix = @exec_prefix@ bindir = @bindir@ mandir = @mandir@ BINFILES = uqwk LIBFILES = INCLUDEFILES = MANFILES = uqwk.1 all: ${BINFILES} uqwk: uqwk.o options.o init.o mail.o misc.o close.o news.o reply.o offline.o nntpclient.o nntplib.o score.o signal.o $(CC) -o uqwk uqwk.o options.o init.o mail.o misc.o close.o news.o reply.o offline.o nntpclient.o nntplib.o score.o signal.o $(LDFLAGS) precompiled: ${BINFILES} ${MANFILES} @(pkg=`basename \`pwd\``-`uname -rs|sed -e 's/ /-/g' -e 's/\//_/'`; tar cvf $$pkg.tar README HISTORY ${BINFILES} ${MANFILES}; gzip -9 $$pkg.tar) install: install.man ${BINFILES} mkdir -p ${bindir} cp ${BINFILES} ${bindir} for prg in ${BINFILES}; do chmod 755 ${bindir}/$${prg}; done install.man: ${MANFILES} mkdir -p ${mandir}/man1 cp ${MANFILES} ${mandir}/man1 for doc in ${MANFILES}; do chmod 644 ${mandir}/man1/$${doc}; done uqwk.o: uqwk.c uqwk.h options.o: options.c uqwk.h uqwk-version.h init.o: init.c uqwk.h mail.o: mail.c uqwk.h misc.o: misc.c uqwk.h close.o: close.c uqwk.h news.o: news.c uqwk.h reply.o: reply.c uqwk.h offline.o: offline.c uqwk.h nntpclient.o: nntpclient.c nntp.h nntplib.o: nntplib.c nntp.h score.o: score.c uqwk.h clean: rm -f *.o ${BINFILES} distclean: clean rm -f config.cache config.log config.status # This one's for Larry love: @echo "not war" dist: distclean ( dir=`basename \`pwd\`` ; cd .. ; \ files=`find $$dir -type f -print | \ grep -v 'Makefile$$' | \ grep -v CVS` ; \ tar cf $$dir.tar $$files ; \ rm -f $$dir.tar.gz ; \ gzip -9 $$dir.tar ) uue: dist @(dir=`basename \`pwd\`` ; cd .. ; \ uuencode $$dir.tar.gz $$dir.tar.gz > $$dir.uue ) uqwk-2.21/configure100700 35070 36 143673 6707076531 12266 0ustar jsuser#! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated automatically using autoconf version 2.13 # Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc. # # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. # Defaults: ac_help= ac_default_prefix=/usr/local # Any additions from configure.in: ac_help="$ac_help --with-config=FILE site configuration to use [config-generic.h]" ac_help="$ac_help --with-gnksa=DIR enable gnksalib support" ac_help="$ac_help --with-regex=DIR regex lib to be used instead of broken vendor lib" ac_help="$ac_help --disable-scores disable article scoring support" ac_help="$ac_help --disable-nntpauth disable nntp authentication support" ac_help="$ac_help --disable-nntp disable nntp support" # Initialize some variables set by options. # The variables have the same names as the options, with # dashes changed to underlines. build=NONE cache_file=./config.cache exec_prefix=NONE host=NONE no_create= nonopt=NONE no_recursion= prefix=NONE program_prefix=NONE program_suffix=NONE program_transform_name=s,x,x, silent= site= srcdir= target=NONE verbose= x_includes=NONE x_libraries=NONE bindir='${exec_prefix}/bin' sbindir='${exec_prefix}/sbin' libexecdir='${exec_prefix}/libexec' datadir='${prefix}/share' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' libdir='${exec_prefix}/lib' includedir='${prefix}/include' oldincludedir='/usr/include' infodir='${prefix}/info' mandir='${prefix}/man' # Initialize some other variables. subdirs= MFLAGS= MAKEFLAGS= SHELL=${CONFIG_SHELL-/bin/sh} # Maximum number of lines to put in a shell here document. ac_max_here_lines=12 ac_prev= for ac_option do # If the previous option needs an argument, assign it. if test -n "$ac_prev"; then eval "$ac_prev=\$ac_option" ac_prev= continue fi case "$ac_option" in -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;; *) ac_optarg= ;; esac # Accept the important Cygnus configure options, so we can diagnose typos. case "$ac_option" in -bindir | --bindir | --bindi | --bind | --bin | --bi) ac_prev=bindir ;; -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) bindir="$ac_optarg" ;; -build | --build | --buil | --bui | --bu) ac_prev=build ;; -build=* | --build=* | --buil=* | --bui=* | --bu=*) build="$ac_optarg" ;; -cache-file | --cache-file | --cache-fil | --cache-fi \ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) ac_prev=cache_file ;; -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) cache_file="$ac_optarg" ;; -datadir | --datadir | --datadi | --datad | --data | --dat | --da) ac_prev=datadir ;; -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \ | --da=*) datadir="$ac_optarg" ;; -disable-* | --disable-*) ac_feature=`echo $ac_option|sed -e 's/-*disable-//'` # Reject names that are not valid shell variable names. if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } fi ac_feature=`echo $ac_feature| sed 's/-/_/g'` eval "enable_${ac_feature}=no" ;; -enable-* | --enable-*) ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'` # Reject names that are not valid shell variable names. if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; } fi ac_feature=`echo $ac_feature| sed 's/-/_/g'` case "$ac_option" in *=*) ;; *) ac_optarg=yes ;; esac eval "enable_${ac_feature}='$ac_optarg'" ;; -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ | --exec | --exe | --ex) ac_prev=exec_prefix ;; -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ | --exec=* | --exe=* | --ex=*) exec_prefix="$ac_optarg" ;; -gas | --gas | --ga | --g) # Obsolete; use --with-gas. with_gas=yes ;; -help | --help | --hel | --he) # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat << EOF Usage: configure [options] [host] Options: [defaults in brackets after descriptions] Configuration: --cache-file=FILE cache test results in FILE --help print this message --no-create do not create output files --quiet, --silent do not print \`checking...' messages --version print the version of autoconf that created configure Directory and file names: --prefix=PREFIX install architecture-independent files in PREFIX [$ac_default_prefix] --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX [same as prefix] --bindir=DIR user executables in DIR [EPREFIX/bin] --sbindir=DIR system admin executables in DIR [EPREFIX/sbin] --libexecdir=DIR program executables in DIR [EPREFIX/libexec] --datadir=DIR read-only architecture-independent data in DIR [PREFIX/share] --sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data in DIR [PREFIX/com] --localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var] --libdir=DIR object code libraries in DIR [EPREFIX/lib] --includedir=DIR C header files in DIR [PREFIX/include] --oldincludedir=DIR C header files for non-gcc in DIR [/usr/include] --infodir=DIR info documentation in DIR [PREFIX/info] --mandir=DIR man documentation in DIR [PREFIX/man] --srcdir=DIR find the sources in DIR [configure dir or ..] --program-prefix=PREFIX prepend PREFIX to installed program names --program-suffix=SUFFIX append SUFFIX to installed program names --program-transform-name=PROGRAM run sed PROGRAM on installed program names EOF cat << EOF Host type: --build=BUILD configure for building on BUILD [BUILD=HOST] --host=HOST configure for HOST [guessed] --target=TARGET configure for TARGET [TARGET=HOST] Features and packages: --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) --x-includes=DIR X include files are in DIR --x-libraries=DIR X library files are in DIR EOF if test -n "$ac_help"; then echo "--enable and --with options recognized:$ac_help" fi exit 0 ;; -host | --host | --hos | --ho) ac_prev=host ;; -host=* | --host=* | --hos=* | --ho=*) host="$ac_optarg" ;; -includedir | --includedir | --includedi | --included | --include \ | --includ | --inclu | --incl | --inc) ac_prev=includedir ;; -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ | --includ=* | --inclu=* | --incl=* | --inc=*) includedir="$ac_optarg" ;; -infodir | --infodir | --infodi | --infod | --info | --inf) ac_prev=infodir ;; -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) infodir="$ac_optarg" ;; -libdir | --libdir | --libdi | --libd) ac_prev=libdir ;; -libdir=* | --libdir=* | --libdi=* | --libd=*) libdir="$ac_optarg" ;; -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ | --libexe | --libex | --libe) ac_prev=libexecdir ;; -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ | --libexe=* | --libex=* | --libe=*) libexecdir="$ac_optarg" ;; -localstatedir | --localstatedir | --localstatedi | --localstated \ | --localstate | --localstat | --localsta | --localst \ | --locals | --local | --loca | --loc | --lo) ac_prev=localstatedir ;; -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ | --localstate=* | --localstat=* | --localsta=* | --localst=* \ | --locals=* | --local=* | --loca=* | --loc=* | --lo=*) localstatedir="$ac_optarg" ;; -mandir | --mandir | --mandi | --mand | --man | --ma | --m) ac_prev=mandir ;; -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) mandir="$ac_optarg" ;; -nfp | --nfp | --nf) # Obsolete; use --without-fp. with_fp=no ;; -no-create | --no-create | --no-creat | --no-crea | --no-cre \ | --no-cr | --no-c) no_create=yes ;; -no-recursion | --no-recursion | --no-recursio | --no-recursi \ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) no_recursion=yes ;; -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ | --oldin | --oldi | --old | --ol | --o) ac_prev=oldincludedir ;; -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) oldincludedir="$ac_optarg" ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ac_prev=prefix ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) prefix="$ac_optarg" ;; -program-prefix | --program-prefix | --program-prefi | --program-pref \ | --program-pre | --program-pr | --program-p) ac_prev=program_prefix ;; -program-prefix=* | --program-prefix=* | --program-prefi=* \ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) program_prefix="$ac_optarg" ;; -program-suffix | --program-suffix | --program-suffi | --program-suff \ | --program-suf | --program-su | --program-s) ac_prev=program_suffix ;; -program-suffix=* | --program-suffix=* | --program-suffi=* \ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) program_suffix="$ac_optarg" ;; -program-transform-name | --program-transform-name \ | --program-transform-nam | --program-transform-na \ | --program-transform-n | --program-transform- \ | --program-transform | --program-transfor \ | --program-transfo | --program-transf \ | --program-trans | --program-tran \ | --progr-tra | --program-tr | --program-t) ac_prev=program_transform_name ;; -program-transform-name=* | --program-transform-name=* \ | --program-transform-nam=* | --program-transform-na=* \ | --program-transform-n=* | --program-transform-=* \ | --program-transform=* | --program-transfor=* \ | --program-transfo=* | --program-transf=* \ | --program-trans=* | --program-tran=* \ | --progr-tra=* | --program-tr=* | --program-t=*) program_transform_name="$ac_optarg" ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ | --sbi=* | --sb=*) sbindir="$ac_optarg" ;; -sharedstatedir | --sharedstatedir | --sharedstatedi \ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ | --sharedst | --shareds | --shared | --share | --shar \ | --sha | --sh) ac_prev=sharedstatedir ;; -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ | --sha=* | --sh=*) sharedstatedir="$ac_optarg" ;; -site | --site | --sit) ac_prev=site ;; -site=* | --site=* | --sit=*) site="$ac_optarg" ;; -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ac_prev=srcdir ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) srcdir="$ac_optarg" ;; -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ | --syscon | --sysco | --sysc | --sys | --sy) ac_prev=sysconfdir ;; -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) sysconfdir="$ac_optarg" ;; -target | --target | --targe | --targ | --tar | --ta | --t) ac_prev=target ;; -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) target="$ac_optarg" ;; -v | -verbose | --verbose | --verbos | --verbo | --verb) verbose=yes ;; -version | --version | --versio | --versi | --vers) echo "configure generated by autoconf version 2.13" exit 0 ;; -with-* | --with-*) ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'` # Reject names that are not valid shell variable names. if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } fi ac_package=`echo $ac_package| sed 's/-/_/g'` case "$ac_option" in *=*) ;; *) ac_optarg=yes ;; esac eval "with_${ac_package}='$ac_optarg'" ;; -without-* | --without-*) ac_package=`echo $ac_option|sed -e 's/-*without-//'` # Reject names that are not valid shell variable names. if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; } fi ac_package=`echo $ac_package| sed 's/-/_/g'` eval "with_${ac_package}=no" ;; --x) # Obsolete; use --with-x. with_x=yes ;; -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ | --x-incl | --x-inc | --x-in | --x-i) ac_prev=x_includes ;; -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) x_includes="$ac_optarg" ;; -x-libraries | --x-libraries | --x-librarie | --x-librari \ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) ac_prev=x_libraries ;; -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) x_libraries="$ac_optarg" ;; -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; } ;; *) if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then echo "configure: warning: $ac_option: invalid host type" 1>&2 fi if test "x$nonopt" != xNONE; then { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; } fi nonopt="$ac_option" ;; esac done if test -n "$ac_prev"; then { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; } fi trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 # File descriptor usage: # 0 standard input # 1 file creation # 2 errors and warnings # 3 some systems may open it to /dev/tty # 4 used on the Kubota Titan # 6 checking for... messages and results # 5 compiler messages saved in config.log if test "$silent" = yes; then exec 6>/dev/null else exec 6>&1 fi exec 5>./config.log echo "\ This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. " 1>&5 # Strip out --no-create and --no-recursion so they do not pile up. # Also quote any args containing shell metacharacters. ac_configure_args= for ac_arg do case "$ac_arg" in -no-create | --no-create | --no-creat | --no-crea | --no-cre \ | --no-cr | --no-c) ;; -no-recursion | --no-recursion | --no-recursio | --no-recursi \ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;; *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*) ac_configure_args="$ac_configure_args '$ac_arg'" ;; *) ac_configure_args="$ac_configure_args $ac_arg" ;; esac done # NLS nuisances. # Only set these to C if already set. These must not be set unconditionally # because not all systems understand e.g. LANG=C (notably SCO). # Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'! # Non-C LC_CTYPE values break the ctype check. if test "${LANG+set}" = set; then LANG=C; export LANG; fi if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi # confdefs.h avoids OS command line length limits that DEFS can exceed. rm -rf conftest* confdefs.h # AIX cpp loses on an empty file, so make sure it contains at least a newline. echo > confdefs.h # A filename unique to this package, relative to the directory that # configure is in, which we can look for to find out if srcdir is correct. ac_unique_file= # Find the source files, if location was not specified. if test -z "$srcdir"; then ac_srcdir_defaulted=yes # Try the directory containing this script, then its parent. ac_prog=$0 ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'` test "x$ac_confdir" = "x$ac_prog" && ac_confdir=. srcdir=$ac_confdir if test ! -r $srcdir/$ac_unique_file; then srcdir=.. fi else ac_srcdir_defaulted=no fi if test ! -r $srcdir/$ac_unique_file; then if test "$ac_srcdir_defaulted" = yes; then { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; } else { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; } fi fi srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'` # Prefer explicitly selected file to automatically selected ones. if test -z "$CONFIG_SITE"; then if test "x$prefix" != xNONE; then CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site" else CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" fi fi for ac_site_file in $CONFIG_SITE; do if test -r "$ac_site_file"; then echo "loading site script $ac_site_file" . "$ac_site_file" fi done if test -r "$cache_file"; then echo "loading cache $cache_file" . $cache_file else echo "creating cache $cache_file" > $cache_file fi ac_ext=c # CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. ac_cpp='$CPP $CPPFLAGS' ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' cross_compiling=$ac_cv_prog_cc_cross ac_exeext= ac_objext=o if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu. if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then ac_n= ac_c=' ' ac_t=' ' else ac_n=-n ac_c= ac_t= fi else ac_n= ac_c='\c' ac_t= fi if test -z "${CFLAGS}" ; then OLDCFLAGS="no" fi # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 echo "configure:547: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" ac_dummy="$PATH" for ac_dir in $ac_dummy; do test -z "$ac_dir" && ac_dir=. if test -f $ac_dir/$ac_word; then ac_cv_prog_CC="gcc" break fi done IFS="$ac_save_ifs" fi fi CC="$ac_cv_prog_CC" if test -n "$CC"; then echo "$ac_t""$CC" 1>&6 else echo "$ac_t""no" 1>&6 fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 echo "configure:577: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" ac_prog_rejected=no ac_dummy="$PATH" for ac_dir in $ac_dummy; do test -z "$ac_dir" && ac_dir=. if test -f $ac_dir/$ac_word; then if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" break fi done IFS="$ac_save_ifs" if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# -gt 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift set dummy "$ac_dir/$ac_word" "$@" shift ac_cv_prog_CC="$@" fi fi fi fi CC="$ac_cv_prog_CC" if test -n "$CC"; then echo "$ac_t""$CC" 1>&6 else echo "$ac_t""no" 1>&6 fi if test -z "$CC"; then case "`uname -s`" in *win32* | *WIN32*) # Extract the first word of "cl", so it can be a program name with args. set dummy cl; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 echo "configure:628: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":" ac_dummy="$PATH" for ac_dir in $ac_dummy; do test -z "$ac_dir" && ac_dir=. if test -f $ac_dir/$ac_word; then ac_cv_prog_CC="cl" break fi done IFS="$ac_save_ifs" fi fi CC="$ac_cv_prog_CC" if test -n "$CC"; then echo "$ac_t""$CC" 1>&6 else echo "$ac_t""no" 1>&6 fi ;; esac fi test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; } fi echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6 echo "configure:660: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5 ac_ext=c # CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. ac_cpp='$CPP $CPPFLAGS' ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' cross_compiling=$ac_cv_prog_cc_cross cat > conftest.$ac_ext << EOF #line 671 "configure" #include "confdefs.h" main(){return(0);} EOF if { (eval echo configure:676: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then ac_cv_prog_cc_works=yes # If we can't run a trivial program, we are probably using a cross compiler. if (./conftest; exit) 2>/dev/null; then ac_cv_prog_cc_cross=no else ac_cv_prog_cc_cross=yes fi else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 ac_cv_prog_cc_works=no fi rm -fr conftest* ac_ext=c # CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. ac_cpp='$CPP $CPPFLAGS' ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' cross_compiling=$ac_cv_prog_cc_cross echo "$ac_t""$ac_cv_prog_cc_works" 1>&6 if test $ac_cv_prog_cc_works = no; then { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; } fi echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6 echo "configure:702: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5 echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6 cross_compiling=$ac_cv_prog_cc_cross echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6 echo "configure:707: checking whether we are using GNU C" >&5 if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.c <&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then ac_cv_prog_gcc=yes else ac_cv_prog_gcc=no fi fi echo "$ac_t""$ac_cv_prog_gcc" 1>&6 if test $ac_cv_prog_gcc = yes; then GCC=yes else GCC= fi ac_test_CFLAGS="${CFLAGS+set}" ac_save_CFLAGS="$CFLAGS" CFLAGS= echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6 echo "configure:735: checking whether ${CC-cc} accepts -g" >&5 if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else echo 'void f(){}' > conftest.c if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then ac_cv_prog_cc_g=yes else ac_cv_prog_cc_g=no fi rm -f conftest* fi echo "$ac_t""$ac_cv_prog_cc_g" 1>&6 if test "$ac_test_CFLAGS" = set; then CFLAGS="$ac_save_CFLAGS" elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6 echo "configure:767: checking whether ${MAKE-make} sets \${MAKE}" >&5 set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftestmake <<\EOF all: @echo 'ac_maketemp="${MAKE}"' EOF # GNU make sometimes prints "make[1]: Entering...", which would confuse us. eval `${MAKE-make} -f conftestmake 2>/dev/null | grep temp=` if test -n "$ac_maketemp"; then eval ac_cv_prog_make_${ac_make}_set=yes else eval ac_cv_prog_make_${ac_make}_set=no fi rm -f conftestmake fi if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then echo "$ac_t""yes" 1>&6 SET_MAKE= else echo "$ac_t""no" 1>&6 SET_MAKE="MAKE=${MAKE-make}" fi SHELL=/bin/sh if test "${OLDCFLAGS}" = "no"; then if test ${GCC} = "yes" ; then CFLAGS="-O4 -Wall" else CFLAGS="-O2" fi fi NOSOCKLIBS=$LIBS SOCKET_FOUND=no SOCKLIBS= echo $ac_n "checking for socket in -lsocket""... $ac_c" 1>&6 echo "configure:812: checking for socket in -lsocket" >&5 ac_lib_var=`echo socket'_'socket | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_save_LIBS="$LIBS" LIBS="-lsocket $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=no" fi rm -f conftest* LIBS="$ac_save_LIBS" fi if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then echo "$ac_t""yes" 1>&6 SOCKET_FOUND=yes;SOCKLIBS="-lsocket" else echo "$ac_t""no" 1>&6 fi if test ${SOCKET_FOUND} = no; then echo $ac_n "checking for socket in -lbsd""... $ac_c" 1>&6 echo "configure:853: checking for socket in -lbsd" >&5 ac_lib_var=`echo bsd'_'socket | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_save_LIBS="$LIBS" LIBS="-lbsd $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=no" fi rm -f conftest* LIBS="$ac_save_LIBS" fi if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then echo "$ac_t""yes" 1>&6 SOCKET_FOUND=yes;SOCKLIBS="-lbsd";DEFS="$DEFS -D_BSD=43" else echo "$ac_t""no" 1>&6 fi if test ${SOCKET_FOUND} = no; then echo $ac_n "checking for socket in -lsun""... $ac_c" 1>&6 echo "configure:894: checking for socket in -lsun" >&5 ac_lib_var=`echo sun'_'socket | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_save_LIBS="$LIBS" LIBS="-lsun $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=no" fi rm -f conftest* LIBS="$ac_save_LIBS" fi if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then echo "$ac_t""yes" 1>&6 SOCKET_FOUND=yes;SOCKLIBS="-lsun" else echo "$ac_t""no" 1>&6 fi fi fi GHN_FOUND=no echo $ac_n "checking for gethostname in -lnsl""... $ac_c" 1>&6 echo "configure:937: checking for gethostname in -lnsl" >&5 ac_lib_var=`echo nsl'_'gethostname | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_save_LIBS="$LIBS" LIBS="-lnsl $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=no" fi rm -f conftest* LIBS="$ac_save_LIBS" fi if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then echo "$ac_t""yes" 1>&6 GHN_FOUND=yes;SOCKLIBS="$SOCKLIBS -lnsl" else echo "$ac_t""no" 1>&6 fi if test ${GHN_FOUND} = no; then echo $ac_n "checking for gethostname in -lnsl""... $ac_c" 1>&6 echo "configure:978: checking for gethostname in -lnsl" >&5 ac_lib_var=`echo nsl'_'gethostname | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_save_LIBS="$LIBS" LIBS="-lnsl $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=no" fi rm -f conftest* LIBS="$ac_save_LIBS" fi if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then echo "$ac_t""yes" 1>&6 GHN_FOUND=yes;SOCKLIBS="$SOCKLIBS -lsun" else echo "$ac_t""no" 1>&6 fi fi echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6 echo "configure:1022: checking how to run the C preprocessor" >&5 # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= fi if test -z "$CPP"; then if eval "test \"`echo '$''{'ac_cv_prog_CPP'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else # This must be in double quotes, not single quotes, because CPP may get # substituted into the Makefile and "${CC-cc}" will confuse make. CPP="${CC-cc} -E" # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. cat > conftest.$ac_ext < Syntax Error EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" { (eval echo configure:1043: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then : else echo "$ac_err" >&5 echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* CPP="${CC-cc} -E -traditional-cpp" cat > conftest.$ac_ext < Syntax Error EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" { (eval echo configure:1060: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then : else echo "$ac_err" >&5 echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* CPP="${CC-cc} -nologo -E" cat > conftest.$ac_ext < Syntax Error EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" { (eval echo configure:1077: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then : else echo "$ac_err" >&5 echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* CPP=/lib/cpp fi rm -f conftest* fi rm -f conftest* fi rm -f conftest* ac_cv_prog_CPP="$CPP" fi CPP="$ac_cv_prog_CPP" else ac_cv_prog_CPP="$CPP" fi echo "$ac_t""$CPP" 1>&6 echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6 echo "configure:1102: checking for ANSI C header files" >&5 if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include #include #include EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" { (eval echo configure:1115: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* ac_cv_header_stdc=yes else echo "$ac_err" >&5 echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* ac_cv_header_stdc=no fi rm -f conftest* if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat > conftest.$ac_ext < EOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | egrep "memchr" >/dev/null 2>&1; then : else rm -rf conftest* ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. cat > conftest.$ac_ext < EOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | egrep "free" >/dev/null 2>&1; then : else rm -rf conftest* ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. if test "$cross_compiling" = yes; then : else cat > conftest.$ac_ext < #define ISLOWER(c) ('a' <= (c) && (c) <= 'z') #define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) #define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) int main () { int i; for (i = 0; i < 256; i++) if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2); exit (0); } EOF if { (eval echo configure:1182: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then : else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -fr conftest* ac_cv_header_stdc=no fi rm -fr conftest* fi fi fi echo "$ac_t""$ac_cv_header_stdc" 1>&6 if test $ac_cv_header_stdc = yes; then cat >> confdefs.h <<\EOF #define STDC_HEADERS 1 EOF fi echo $ac_n "checking for working const""... $ac_c" 1>&6 echo "configure:1207: checking for working const" >&5 if eval "test \"`echo '$''{'ac_cv_c_const'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <j = 5; } { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */ const int foo = 10; } ; return 0; } EOF if { (eval echo configure:1261: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_c_const=yes else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* ac_cv_c_const=no fi rm -f conftest* fi echo "$ac_t""$ac_cv_c_const" 1>&6 if test $ac_cv_c_const = no; then cat >> confdefs.h <<\EOF #define const EOF fi echo $ac_n "checking for size_t""... $ac_c" 1>&6 echo "configure:1282: checking for size_t" >&5 if eval "test \"`echo '$''{'ac_cv_type_size_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #if STDC_HEADERS #include #include #endif EOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | egrep "(^|[^a-zA-Z_0-9])size_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then rm -rf conftest* ac_cv_type_size_t=yes else rm -rf conftest* ac_cv_type_size_t=no fi rm -f conftest* fi echo "$ac_t""$ac_cv_type_size_t" 1>&6 if test $ac_cv_type_size_t = no; then cat >> confdefs.h <<\EOF #define size_t unsigned EOF fi for ac_func in strdup do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 echo "configure:1318: checking for $ac_func" >&5 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < /* Override any gcc2 internal prototype to avoid an error. */ /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ char $ac_func(); int main() { /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined (__stub_$ac_func) || defined (__stub___$ac_func) choke me #else $ac_func(); #endif ; return 0; } EOF if { (eval echo configure:1346: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else echo "configure: failed program was:" >&5 cat conftest.$ac_ext >&5 rm -rf conftest* eval "ac_cv_func_$ac_func=no" fi rm -f conftest* fi if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then echo "$ac_t""yes" 1>&6 ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` cat >> confdefs.h <&6 fi done SITECFG="config-generic.h" # Check whether --with-config or --without-config was given. if test "${with_config+set}" = set; then withval="$with_config" SITECFG=${withval} fi # Check whether --with-gnksa or --without-gnksa was given. if test "${with_gnksa+set}" = set; then withval="$with_gnksa" GNKSACFLAGS="-DGNKSA -I${withval}";GNKSALDLAGS="-L${withval} -lgnksa" fi # Check whether --with-regex or --without-regex was given. if test "${with_regex+set}" = set; then withval="$with_regex" RECFLAGS="-I${withval}";RELDFLAGS="-L${withval} -lregex" fi SCORECFLAGS="-DSCORES" # Check whether --enable-scores or --disable-scores was given. if test "${enable_scores+set}" = set; then enableval="$enable_scores" test ${enableval} = "no" && SCORECFLAGS="" fi NNTPAUTHCFLAGS="-DNNTPAUTH" # Check whether --enable-nntpauth or --disable-nntpauth was given. if test "${enable_nntpauth+set}" = set; then enableval="$enable_nntpauth" test ${enableval} = "no" && NNTPAUTHCFLAGS="" fi test -z "$NNTPAUTHCFLAGS" && NNTPCFLAGS="-DNNTP" # Check whether --enable-nntp or --disable-nntp was given. if test "${enable_nntp+set}" = set; then enableval="$enable_nntp" test ${enableval} = "no" && NNTPCFLAGS="" fi trap '' 1 2 15 cat > confcache <<\EOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs. It is not useful on other systems. # If it contains results you don't want to keep, you may remove or edit it. # # By default, configure uses ./config.cache as the cache file, # creating it if it does not exist already. You can give configure # the --cache-file=FILE option to use a different cache file; that is # what configure does when it calls configure scripts in # subdirectories, so they share the cache. # Giving --cache-file=/dev/null disables caching, for debugging configure. # config.status only pays attention to the cache file if you give it the # --recheck option to rerun configure. # EOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, don't put newlines in cache variables' values. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. (set) 2>&1 | case `(ac_space=' '; set | grep ac_space) 2>&1` in *ac_space=\ *) # `set' does not quote correctly, so add quotes (double-quote substitution # turns \\\\ into \\, and sed turns \\ into \). sed -n \ -e "s/'/'\\\\''/g" \ -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p" ;; *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p' ;; esac >> confcache if cmp -s $cache_file confcache; then : else if test -w $cache_file; then echo "updating cache $cache_file" cat confcache > $cache_file else echo "not updating unwritable cache $cache_file" fi fi rm -f confcache trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15 test "x$prefix" = xNONE && prefix=$ac_default_prefix # Let make expand exec_prefix. test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' # Any assignment to VPATH causes Sun make to only execute # the first set of double-colon rules, so remove it if not needed. # If there is a colon in the path, we need to keep it. if test "x$srcdir" = x.; then ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d' fi trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15 # Transform confdefs.h into DEFS. # Protect against shell expansion while executing Makefile rules. # Protect against Makefile macro expansion. cat > conftest.defs <<\EOF s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%-D\1=\2%g s%[ `~#$^&*(){}\\|;'"<>?]%\\&%g s%\[%\\&%g s%\]%\\&%g s%\$%$$%g EOF DEFS=`sed -f conftest.defs confdefs.h | tr '\012' ' '` rm -f conftest.defs # Without the "./", some shells look in PATH for config.status. : ${CONFIG_STATUS=./config.status} echo creating $CONFIG_STATUS rm -f $CONFIG_STATUS cat > $CONFIG_STATUS </dev/null | sed 1q`: # # $0 $ac_configure_args # # Compiler output produced by configure, useful for debugging # configure, is in ./config.log if it exists. ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]" for ac_option do case "\$ac_option" in -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion" exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;; -version | --version | --versio | --versi | --vers | --ver | --ve | --v) echo "$CONFIG_STATUS generated by autoconf version 2.13" exit 0 ;; -help | --help | --hel | --he | --h) echo "\$ac_cs_usage"; exit 0 ;; *) echo "\$ac_cs_usage"; exit 1 ;; esac done ac_given_srcdir=$srcdir trap 'rm -fr `echo "Makefile" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15 EOF cat >> $CONFIG_STATUS < conftest.subs <<\\CEOF $ac_vpsub $extrasub s%@SHELL@%$SHELL%g s%@CFLAGS@%$CFLAGS%g s%@CPPFLAGS@%$CPPFLAGS%g s%@CXXFLAGS@%$CXXFLAGS%g s%@FFLAGS@%$FFLAGS%g s%@DEFS@%$DEFS%g s%@LDFLAGS@%$LDFLAGS%g s%@LIBS@%$LIBS%g s%@exec_prefix@%$exec_prefix%g s%@prefix@%$prefix%g s%@program_transform_name@%$program_transform_name%g s%@bindir@%$bindir%g s%@sbindir@%$sbindir%g s%@libexecdir@%$libexecdir%g s%@datadir@%$datadir%g s%@sysconfdir@%$sysconfdir%g s%@sharedstatedir@%$sharedstatedir%g s%@localstatedir@%$localstatedir%g s%@libdir@%$libdir%g s%@includedir@%$includedir%g s%@oldincludedir@%$oldincludedir%g s%@infodir@%$infodir%g s%@mandir@%$mandir%g s%@BINDIR@%$BINDIR%g s%@LIBDIR@%$LIBDIR%g s%@CC@%$CC%g s%@SET_MAKE@%$SET_MAKE%g s%@INCLUDES@%$INCLUDES%g s%@SOCKLIBS@%$SOCKLIBS%g s%@CPP@%$CPP%g s%@SITECFG@%$SITECFG%g s%@GNKSACFLAGS@%$GNKSACFLAGS%g s%@GNKSALDLAGS@%$GNKSALDLAGS%g s%@RECFLAGS@%$RECFLAGS%g s%@RELDFLAGS@%$RELDFLAGS%g s%@SCORECFLAGS@%$SCORECFLAGS%g s%@NNTPAUTHCFLAGS@%$NNTPAUTHCFLAGS%g s%@NNTPCFLAGS@%$NNTPCFLAGS%g CEOF EOF cat >> $CONFIG_STATUS <<\EOF # Split the substitutions into bite-sized pieces for seds with # small command number limits, like on Digital OSF/1 and HP-UX. ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script. ac_file=1 # Number of current file. ac_beg=1 # First line for current file. ac_end=$ac_max_sed_cmds # Line after last line for current file. ac_more_lines=: ac_sed_cmds="" while $ac_more_lines; do if test $ac_beg -gt 1; then sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file else sed "${ac_end}q" conftest.subs > conftest.s$ac_file fi if test ! -s conftest.s$ac_file; then ac_more_lines=false rm -f conftest.s$ac_file else if test -z "$ac_sed_cmds"; then ac_sed_cmds="sed -f conftest.s$ac_file" else ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file" fi ac_file=`expr $ac_file + 1` ac_beg=$ac_end ac_end=`expr $ac_end + $ac_max_sed_cmds` fi done if test -z "$ac_sed_cmds"; then ac_sed_cmds=cat fi EOF cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". case "$ac_file" in *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'` ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; *) ac_file_in="${ac_file}.in" ;; esac # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories. # Remove last slash and all that follows it. Not all systems have dirname. ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'` if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then # The file is in a subdirectory. test ! -d "$ac_dir" && mkdir "$ac_dir" ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`" # A "../" for each directory in $ac_dir_suffix. ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'` else ac_dir_suffix= ac_dots= fi case "$ac_given_srcdir" in .) srcdir=. if test -z "$ac_dots"; then top_srcdir=. else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;; /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;; *) # Relative path. srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix" top_srcdir="$ac_dots$ac_given_srcdir" ;; esac echo creating "$ac_file" rm -f "$ac_file" configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure." case "$ac_file" in *Makefile*) ac_comsub="1i\\ # $configure_input" ;; *) ac_comsub= ;; esac ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"` sed -e "$ac_comsub s%@configure_input@%$configure_input%g s%@srcdir@%$srcdir%g s%@top_srcdir@%$top_srcdir%g " $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file fi; done rm -f conftest.s* EOF cat >> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF exit 0 EOF chmod +x $CONFIG_STATUS rm -fr confdefs* $ac_clean_files test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1 uqwk-2.21/configure.in100600 35070 36 5261 6707076531 12620 0ustar jsuserdnl Process this file with autoconf to produce a configure script. dnl $Id: configure.in,v 1.3 1999/04/20 13:12:44 js Exp $ AC_INIT AC_SUBST(BINDIR) AC_SUBST(LIBDIR) dnl Checks for programs. if test -z "${CFLAGS}" ; then OLDCFLAGS="no" fi AC_PROG_CC AC_PROG_MAKE_SET dnl Where to locate the bourne shell? SHELL=/bin/sh AC_SUBST(SHELL) dnl Which CFLAGS to use? if test "${OLDCFLAGS}" = "no"; then if test ${GCC} = "yes" ; then CFLAGS="-O4 -Wall" else CFLAGS="-O2" fi fi AC_SUBST(CFLAGS) AC_SUBST(DEFS) AC_SUBST(INCLUDES) dnl Determine which libraries to use for programs using sockets NOSOCKLIBS=$LIBS dnl first, the socket functions SOCKET_FOUND=no SOCKLIBS= AC_CHECK_LIB(socket, socket,[SOCKET_FOUND=yes;SOCKLIBS="-lsocket"]) if test ${SOCKET_FOUND} = no; then AC_CHECK_LIB(bsd, socket,[SOCKET_FOUND=yes;SOCKLIBS="-lbsd";DEFS="$DEFS -D_BSD=43"]) if test ${SOCKET_FOUND} = no; then AC_CHECK_LIB(sun, socket,[SOCKET_FOUND=yes;SOCKLIBS="-lsun"]) fi fi dnl then gethostname GHN_FOUND=no AC_CHECK_LIB(nsl,gethostname,[GHN_FOUND=yes;SOCKLIBS="$SOCKLIBS -lnsl"]) if test ${GHN_FOUND} = no; then AC_CHECK_LIB(nsl,gethostname,[GHN_FOUND=yes;SOCKLIBS="$SOCKLIBS -lsun"]) fi AC_SUBST(SOCKLIBS) dnl Checks for header files. AC_HEADER_STDC dnl Checks for typedefs, structures, and compiler characteristics. AC_C_CONST AC_TYPE_SIZE_T dnl Checks for library functions. AC_CHECK_FUNCS(strdup) dnl Site configuration... dnl SITECFG="config-generic.h" dnl Handle --with-config=... argument to configure AC_ARG_WITH(config, [ --with-config=FILE site configuration to use [config-generic.h]], SITECFG=${withval},) AC_SUBST(SITECFG) dnl Features... dnl GNKSAlib... dnl AC_ARG_WITH(gnksa, [ --with-gnksa=DIR enable gnksalib support], GNKSACFLAGS="-DGNKSA -I${withval}";GNKSALDLAGS="-L${withval} -lgnksa",) AC_SUBST(GNKSACFLAGS) AC_SUBST(GNKSALDLAGS) dnl External Regex lib... dnl AC_ARG_WITH(regex, [ --with-regex=DIR regex lib to be used instead of broken vendor lib], RECFLAGS="-I${withval}";RELDFLAGS="-L${withval} -lregex",) AC_SUBST(RECFLAGS) AC_SUBST(RELDFLAGS) dnl Scoring... dnl SCORECFLAGS="-DSCORES" AC_ARG_ENABLE(scores, [ --disable-scores disable article scoring support], test ${enableval} = "no" && SCORECFLAGS="",) AC_SUBST(SCORECFLAGS) dnl NNTPAUTH... dnl NNTPAUTHCFLAGS="-DNNTPAUTH" AC_ARG_ENABLE(nntpauth, [ --disable-nntpauth disable nntp authentication support], test ${enableval} = "no" && NNTPAUTHCFLAGS="",) AC_SUBST(NNTPAUTHCFLAGS) dnl NNTP... dnl test -z "$NNTPAUTHCFLAGS" && NNTPCFLAGS="-DNNTP" AC_ARG_ENABLE(nntp, [ --disable-nntp disable nntp support], test ${enableval} = "no" && NNTPCFLAGS="",) AC_SUBST(NNTPCFLAGS) AC_OUTPUT(Makefile) uqwk-2.21/uqwk.h100600 35070 36 24653 7003030365 11456 0ustar jsuser/* * $Id: uqwk.h,v 1.9 1999/10/19 08:48:42 js Exp $ */ #ifdef HAVE_CONFIG #include HAVE_CONFIG #else #include "config-generic.h" #endif #include "uqwk-version.h" #ifdef NNTP_USE_ACTIVE #undef NNTP #define NNTP #define NNTP_ACTIVESTR "+full-active" #else #define NNTP_ACTIVESTR "" #endif #ifdef NNTPAUTH #undef NNTP #define NNTP #define NNTPAUTHSTR "auth" #else #define NNTPAUTHSTR "" #endif #ifdef NNTP #define NNTPSTR "+nntp" #else #define NNTPSTR "" #endif #ifdef SCORES #define SCORESTR "+scoring" #else #define SCORESTR "" #endif #ifdef GNKSA #define NO_SIZE_T /* don't ask... */ #define GNKSASTR "+gnksa" #define GNKSA_VERBOSE 1 #define GNKSA_HONOUR 2 #else #define GNKSASTR "" #endif #define UQWK_VERSION VERSION"/"CONFIGNAME""NNTPSTR""NNTPAUTHSTR""GNKSASTR""SCORESTR #ifdef ALLOCATE #define EXTERN #else #define EXTERN extern #endif #define PATH_LEN (256) /* Length for file names, etc. */ #define BUF_LEN (16384) /* Length of general purpose buffer */ #define QWK_EOL (227) /* QWK end-of-line */ #define QWK_ACT_FLAG (225) /* Active message flag */ #define QWK_PUBLIC ' ' /* Public message flags */ #define QWK_PUBLIC2 '-' #define QWK_PRIVATE '+' /* Private message flags */ #define QWK_PRIVATE2 '*' #define SLNP_MAILER SENDMAIL" -t" #define ZIP_MAILER SENDMAIL #define XPRT_MAILER SENDMAIL" -t" #define MAIL_CONF_NAME "Email" #ifdef SCORES #define GLOBAL_SCORE_FILE "global" #endif /* Defaults */ #define DEF_DO_DEBUG (0) #ifdef NNTPAUTH #define DEF_DO_AUTH (0) #define DEF_AUTH_USER "" #define DEF_AUTH_PASS "" #endif #define DEF_DO_MAIL (0) #define DEF_DO_NEWS (0) #ifdef SCORES #define DEF_DO_KILLS (1) #endif #define DEF_IGNORE0FD (1) #define DEF_INC_HDRS (1) #define DEF_PRT_OPTS (0) #define DEF_READ_ONLY (0) #define DEF_WAF_MODE (0) #define DEF_SLNP_MODE (1) #define DEF_ZIP_MODE (0) #define DEF_XRF_MODE (1) #define DEF_BW_KLUDGE (0) #define DEF_XPRT_MODE (0) #define DEF_SUM_MODE (0) #define DEF_SEL_MODE (0) #define DEF_EVERY_MODE (0) #define DEF_MAX_BLKS (4096) /* Exactly half a megabyte */ #define DEF_GRP_LEN (15) #define DEF_HOME_DIR "." #define DEF_USER_NAME "nobody" #define DEF_MAIL_FILE "unknown" #define DEF_NRC_FILE "unknown" #define DEF_REP_FILE "none" #define DEF_TRN_FILE "none" #define DEF_HOST_NAME "nowhere" #define DEF_SUM_FILE "none" #define DEF_SEL_FILE "none" #define DEF_NG_FILE "none" #ifdef SCORES #define DEF_KILL_DIR ".uqwk" #endif /* Runtime options */ EXTERN int do_debug; #ifdef NNTPAUTH EXTERN int do_auth; /* Do NNTP auth? */ #endif EXTERN int do_mail; /* Process mail? */ EXTERN int do_news; /* Process news? */ #ifdef SCORES EXTERN int do_kills; /* Process kill/score files? */ EXTERN int kill_thresh; /* global kill threshold */ EXTERN int group_kill_thresh; /* kill threshold within this group */ #endif EXTERN int ignore_0fd; EXTERN int inc_hdrs; /* Include headers in messages? */ EXTERN int prt_opts; /* Display options; no processing */ EXTERN int read_only; /* Don't rewrite mail and .newsrc */ EXTERN int max_blks; /* Maximum blocks per QWK packet */ EXTERN int grp_len; /* Maximum newsgroup name length */ EXTERN int waf_mode; /* Waffle type .newsrc */ EXTERN int slnp_mode; /* Write SLNP packet */ EXTERN int zip_mode; /* Write ZipNews packet */ EXTERN int xrf_mode; /* Cancel crosspostings */ EXTERN int bw_kludge; /* Blue Wave kludge */ EXTERN int xprt_mode; /* Expert mode */ EXTERN int sum_mode; /* Summary mode */ EXTERN int sel_mode; /* Selection mode */ EXTERN int every_mode; /* Write every grp to CONTROL.DAT */ #ifdef NNTPAUTH EXTERN char auth_user[PATH_LEN];/* NNTP auth user */ EXTERN char auth_pass[PATH_LEN];/* NNTP auth pass */ #else EXTERN char act_file[PATH_LEN]; /* Active file */ EXTERN char news_dir[PATH_LEN]; /* News spool dir */ #endif EXTERN char mail_file[PATH_LEN]; /* mail spool */ EXTERN char mail_dir[PATH_LEN]; /* dir for mail spool */ EXTERN char home_dir[PATH_LEN]; /* home directory */ EXTERN char user_name[PATH_LEN]; /* user's login name */ EXTERN char bbs_name[PATH_LEN]; /* BBS name */ EXTERN char bbs_city[PATH_LEN]; /* BBS city */ EXTERN char bbs_phone[PATH_LEN]; /* BBS phone number */ EXTERN char bbs_sysop[PATH_LEN]; /* BBS sysop name */ EXTERN char bbs_id[PATH_LEN]; /* BBS ID */ EXTERN char nrc_file[PATH_LEN]; /* .newsrc file */ EXTERN char rep_file[PATH_LEN]; /* Reply packet file name */ EXTERN char trn_file[PATH_LEN]; /* Newsgroup name translation table */ EXTERN char host_name[PATH_LEN]; /* Host machine name */ EXTERN char sum_file[PATH_LEN]; /* Summary file */ EXTERN char sel_file[PATH_LEN]; /* Selection file */ EXTERN char ng_file[PATH_LEN]; /* Desired ng file */ EXTERN char inews_path[PATH_LEN]; /* path to inews */ EXTERN char posting_agent[PATH_LEN]; /* posting agent (inews + '-h') */ #ifdef SCORES EXTERN char kill_dir[PATH_LEN];/* directory for score/kill files */ #endif #ifdef GNKSA EXTERN int gnksa_level; /* Validate messages before posting? */ #endif char *getenv(); char *Fgets(); char *ParseFrom(); struct act_ent *FindActive(); struct sub_ent *SubList(); struct sub_ent *MarkRead(); struct sub_ent *FixSub(); struct conf_ent *NewConference(); /* Various globals */ EXTERN char *progname; /* Program name */ EXTERN int msg_cnt; /* Total number of messages */ EXTERN int conf_cnt; /* Total number of conferences */ EXTERN FILE *msg_fd; /* MESSAGES.DAT file desc */ EXTERN char msg_fn[PATH_LEN]; /* SLNP *.MSG file name */ EXTERN FILE *ctl_fd; /* CONTROL.DAT file desc */ EXTERN FILE *ndx_fd; /* xxx.NDX file desc */ EXTERN char ndx_fn[PATH_LEN]; /* xxx.NDX file name */ EXTERN FILE *act_fd; /* Active file file desc */ EXTERN FILE *nrc_fd; /* .newsrc file desc */ EXTERN FILE *rep_fd; /* Reply packet file desc */ EXTERN FILE *nws_fd; /* ZipNews .nws file desc */ EXTERN FILE *idx_fd; /* ZipNews .idx file desc */ EXTERN FILE *mai_fd; /* ZipNews .mai file desc */ EXTERN int zip_flag; /* idx entry written for this ng? */ EXTERN char buf[BUF_LEN]; /* General purpose buffer */ EXTERN int blk_cnt; /* Blocks written to messages.dat */ EXTERN int sum_flag; /* Summary hdr for this ng yet? */ EXTERN FILE *sum_fd; /* Summary file desc */ EXTERN FILE *sel_fd; /* Selection file desc */ /* This is the stuff we remember about each spooled mail message */ EXTERN struct mail_ent { long begin; /* Offset of start of header */ long text; /* Offset to end of header, start of text */ long end; /* Offset to start of next message */ struct mail_ent *next; /* Pointer to next */ } *mail_list; /* This is stuff we remember about each "conference" */ EXTERN struct conf_ent { char *name; /* Conference name */ int number; /* Conference number */ int count; /* Number of articles in this conference */ struct conf_ent *next; /* Pointer to next */ } *conf_list, *last_conf; /* This is the QWK message header format */ struct qwk_hdr { char status; char number[7]; char date[8]; char time[5]; char to[25]; char from[25]; char subject[25]; char password[12]; char refer[8]; char blocks[6]; char flag; char conference[2]; char msg_num[2]; char tag; }; EXTERN struct qwk_hdr rep_hdr; /* Header for replies */ /* Stuff we remember about each active newsgroup */ EXTERN struct act_ent { char *name; /* Newsgroup name */ int hi; /* High article number */ int lo; /* Low article number */ struct act_ent *next; /* Pointer to next */ } *act_list; /* Stuff we remember about the .newsrc file */ EXTERN struct nrc_ent { char *name; /* Newsgroup name */ int subscribed; /* Subscribed flag */ struct sub_ent *sub; /* Subscription list */ int conf; /* Corresponding conference number */ struct nrc_ent *next; /* Pointer to next */ } *nrc_list; /* Stuff we remember about the newsgroup name translation table */ EXTERN struct trn_ent { char *old; /* Old name */ char *new; /* New name */ struct trn_ent *next; /* Pointer to next */ } *trn_list; /* Stuff we remember about a subscription list (in the .newsrc) */ struct sub_ent { int lo, hi; /* Range of articles */ struct sub_ent *next; /* Pointer to next */ }; /* Stuff we remember about the desired newsgroup list */ EXTERN struct ng_ent { char *name; /* Newsgroup name */ struct ng_ent *next; /* Pointer to next */ } *ng_list; /* Function prototypes */ #include #include #include #include #include void DefaultOptions(); void EnvOptions(); void CommandOptions(int, char **); void InitStuff(); int DoReply(); int DoNews(); int DoMail(); int DoClassicMail(); int DoMaildirMail(); void AddMessage(FILE *fd, struct mail_ent *me, char *xhdrs); void SLNPMessage(FILE *fd, struct mail_ent *me, char *xhdrs); void ZipMessage(FILE *fd, struct mail_ent *me, char *xhdrs); void QwkMessage(FILE *fd, struct mail_ent *me, char *xhdrs); void DoFromLine(long off); int CloseStuff(); int BadFlag (char *); void PrintOptions(); int ReadTrans(); int ReadNG(); void OutOfMemory(); void MakeMailList(); void OpenZipMail(); void inttoms(int, unsigned char[4]); int buftoint(unsigned char c[4]); void Spaces(char *, int); void PadNum(int, char *, int); void IntNum(int, char[2]); void PadString( char *, char *, int); void ParseDate(char *, struct qwk_hdr *); char *ParseFrom(char *); int WriteControl(); int WriteNewsrc(); int WriteAreas(); void TransName (char *); void WriteSub (FILE *fd, struct sub_ent *sp); int OpenZipFiles(); int ReadActive(); int ReadNewsrc(); int DoSelect(); int WriteJoin(); int DoGroup (struct nrc_ent *); void NdxClose (FILE *); void MsgClose (FILE *); int IsRead (int, struct sub_ent *); int DoArticle (char *, int, struct nrc_ent *, struct conf_ent *); int DoXref (FILE *, long); int SLNPArticle (FILE *, int); int ZipArticle (FILE *, int, struct nrc_ent *); int SumArticle (FILE *, int, long, struct nrc_ent *); void ws(FILE *fd, struct sub_ent *, struct sub_ent *); int Xref(char *); int GetHdr (FILE *, char *, int, char *); int DoZipReplies(); int SLNPReply(); int SendReply(); int SendWarning(char *); int CheckTo(char *, int); int SLuMail(char *); int SLuNews(char *); int SLbMail(char *); int SLbNews(char *); int SLPipe(FILE *, int, char *); void AppendBadArticle(char *); int ZipId(); int ZipMail(char *); int ZipNews(char *); int OffLine(FILE *, int); int QWKOffLine (int, FILE *); int GetLine(int *, FILE *); void Help(FILE *); int Subscribe(FILE *); int Unsubscribe(FILE *); int Groups(FILE *); int Allgroups(FILE *); int Shell(FILE *); int Catchup(FILE *); FILE *getactive_nntp(); void put_server (); uqwk-2.21/signal.c100600 35070 36 1544 7365521666 11735 0ustar jsuser/* $Id: */ #include #include #include "uqwk.h" char *strsignal(int sig) { struct { int s; char *str; } sigs[]= { {SIGSEGV,"segmentation error"}, {SIGILL,"illegal instruction"}, {SIGABRT,"abort signal"}, {SIGTERM,"termination signal"}, {SIGINT,"interrupt"}, {SIGKILL,"kill process"}, {SIGHUP,"hangup signal"}, {SIGQUIT,"quit signal"}, {SIGBUS,"bus error"}, {-99,"call for undefined signal message"}},*p; for(p=sigs;p->s!=-99;p++) if (p->s==sig) break; return p->str; } static void catchsig(int sig) { fprintf(stderr,"%s: caught signal # %d: %s\n",progname,sig,strsignal(sig)); exit(sig); } void install_signals(void) { int sigs[]={SIGINT,SIGKILL,SIGQUIT,SIGTERM,SIGSEGV,SIGILL,SIGHUP,SIGBUS,-1}; int *i; for(i=sigs;*i!=-1;i++) signal(*i,catchsig); }