#!/bin/bash

# NAME
#    skim
# USAGE
#    skim subjects
#    skim articles
#    skim cleanup
#    skim newarticle [FileName NewsGroups Subject]
#    skim replyto ArticleFile ...
#    skim post ArticleFile
#    skim postall
#    skim newsgroups
#    skim delete ArticleFile
#    skim keep ArticleFile
#    skim indexes
#    skim version
# NOTE
#    The description below is reference information. Refer to the accompanying
#    README for an introduction.
# DESCRIPTION
#
#    skim subjects:
#        Retrieve the subject header lines of all new articles in the 
#        subscribed groups. The subject header lines are appended to the files 
#        If SKIMAUTOSUBJECT is set, automatically select and kill subjects.
#
#    skim articles:
#        Retrieve the articles which were selected in the files 
#        $SKIMDIR/Subjects. The articles are stored in $SKIMDIR/Articles.
#        The subject lines of the articles which were not selected are 
#        appended to the files in $SKIMDIR/Skipped. The files in 
#        $SKIMDIR/Subjects are removed. 
#
#    skim delete ArticleFile
#        Delete an article from the directory $SKIMDIR/Articles by moving it
#        to the directory $SKIMDIR/Deleted. The article will no longer show up
#        in xskim. The article is physically removed when you execute the 
#        command 'skim cleanup'.
#
#        When you bypass the command 'skim delete ArticleFile' and use the 'rm'
#        command to remove it, you will find that xskim still shows the article
#        in it's article list. Xskim raises an error when you select an article
#        that was removed this way.
#
#    skim keep ArticleFile
#        Delete an article from the directory $SKIMDIR/Articles by moving it
#        to the directory $SKIMDIR/Kept. The article will no longer show up
#        in xskim. Skim never removes articles from $SKIMDIR/Kept.
#
#        When you bypass the command 'skim keep ArticleFile' and use the 'mv'
#        command move it to another location, you will find that xskim still 
#        shows the article in it's article list. Xskim raises an error when you
#        select an article that was moved this way.
#
#    skim cleanup:
#        Remove the files in $SKIMDIR/Skipped, $SKIMDIR/Killed and 
#        $SKIMDIR/Deleted. Use this command regularly to cleanup skim's 
#        accumulating administrative information. The NNTP server is not 
#        contacted.
#
#    skim replyto ArticleFile ...
#        Skim constructs a RFC-1036 compliant reply to one or more USENET news 
#        messages in $SKIMDIR/Articles, and puts the replies in $SKIMDIR/Post.
#        The filename of a reply is <ArticleFile>.reply.
#        Skim uses the following information to construct the reply:
#
#            - Various header lines of the original article.
#            - The environment variable SKIMFROM.
#            - The environment variable SKIMFREPLYTO (optional).
#            - The output of hostname(1).
#            - The body of the original article.
#            - Your ~/.signature, if it exists.
#
#    skim newarticle [FileName NewsGroups Subject]
#       Skim constructs a RFC-1036 compliant news article and puts it in 
#       $SKIMDIR/Post. When you don't specify the local filename, newsgroups 
#       and subject on the command line, Skim will prompt you for it. Skim 
#       also uses the following information:
#
#            - The environment variable SKIMFROM.
#            - The environment variable SKIMREPLYTO (optional).
#            - The output of hostname(1).
#            - Your ~/.signature, if it exists.
#
#    skim post ArticleFile
#       Skim posts the ArticleFile (which must reside in $SKIMDIR/Post) to the 
#       newsgroups specified in the 'Newsgroups:' line in the article. Use 
#       'skim newarticle' or 'skim replyto' to create an article.
#
#    skim postall
#       Skim posts all articles in $SKIMDIR/Post. Use with caution. When
#       there is garbage in $SKIMDIR/Post, you may be violating RFC-977 or
#       RFC-1036.
#
#    skim newsgroups
#       Retrieve the list of valid newsgroups from the server, and store it in
#       $SKIMDIR/Admin/AllNewsGroups.
#
#    skim indexes
#       Regenerate all the index files maintained by skim. You do not normally
#       need to use this command. Should skim's index files ever get 
#       out of date (for example, when you use the file manager or the 'rm'
#       command to remove an article file, instead of using 'skim delete'),
#       you can use the command 'skim indexes' to regenerate the index files.
#
#    skim version
#       Print the version of skim on the standard output.
#
# ENVIRONMENT
#    NNTPSERVER        : Hostname of the NNTP news server.
#    SKIMDIR           : Location of skim's per user directory structure. Defaults 
#                        to ~/Skim.
#    TMPDIR            : Directory to use for temporary files. Defaults to /tmp.
#    SKIMFROM          : Used to construct the 'From:' line of your news 
#                        messages. See RFC-822 for the semantics of the 'From:'
#                        line. Use one of the following patterns:
#
#                           "rpijlman@xs4all.nl"
#                           "rpijlman@xs4all.nl (Rene Pijlman)"
#                           "Rene Pijlman <rpijlman@xs4all.nl>"
#
#    SKIMREPLYTO       : This variable may optionally be defined, and causes a
#                        'Reply-To:' line to be included in your news messages.
#                        Use the same pattern as for SKIMFROM. See RFC-822 for
#                        the semantics of the Reply-To line.
#    SKIMORGANIZATION  : This variable may optionally be defined, and causes a
#                        'Organization:' line to be included in your news
#                        messages. See RFC-1036 for the semantics of the
#                        Organization line.
#    SKIMPROCESSES     : The maximum number of concurrent processes that talk 
#                        to the NNTP server. The default is 4. Set this
#                        to a higher number if you think this will improve
#                        the utilization of your dialup line. Set this to a
#                        lower number (e.g. 1) when either your machine or
#                        the news server is overloaded, or when your news
#                        server limits the maximum number of concurrent
#                        connections per client IP address.
#    SKIMAUTOSUBJECT     When this is set to "CaseSensitive" or 
#                        "CaseInsensitive", skim will automatically select and 
#                        kill subjects.
# FILES
#    $SKIMDIR/Admin/SubscribedNewsGroups
#        The list of news groups (one per line) to which the user is subscribed.
#        When this file does not exist, skim will create a default. Lines
#        with '#' on the first position are ignored.
#    $SKIMDIR/Subjects/
#        A directory with one file per news group. Skim will create this file
#        when 'skim subjects' is performed. The file contains all the subject 
#        header lines acummulated since the last 'skim articles' command. The
#        user must edit the subject files and select articles by shifting
#        lines to the right (>> in vi).
#    $SKIMDIR/Articles
#        A directory with one file per retrieved article. The pattern for file 
#        names is Group.ArticleNumber. Articles are added here when 'skim 
#        articles' is performed. Articles in this directory show up in xskim. 
#        When you've read an article you can either delete it using 'skim 
#        delete' or keep it using 'skim keep'. Only these two skim commands 
#        remove articles from the directory $SKIMDIR/Articles.
#    $SKIMDIR/Deleted
#        Articles are moved to this directory when you execute the command
#        'skim delete ArticleFile'. Articles are removed from this directory
#        when you execute the command 'skim cleanup'.
#    $SKIMDIR/Kept
#        Articles are moved to this directory when you execute the command
#        'skim keep ArticleFile'. Skim never removes articles from this
#        directory.
#    $SKIMDIR/Skipped
#        A directory with one file per news group. This is just a safety copy
#        of the subject lines which were not selected when 'skim articles'
#        was performed. Use 'skim cleanup' regularly to remove these files.
#    $SKIMDIR/Patterns/Subject/AutoSelect
#        A directory with one file per newsgroup, and optionally m4 include 
#        files. The files contain regular expressions which are used to 
#        automatically select subjects when 'skim subjects' is performed.
#    $SKIMDIR/Patterns/Subject/Kill
#        A directory with one file per newsgroup, and optionally m4 include 
#        files. The files contain regular expressions which are used to 
#        automatically kill subjects when 'skim subjects' is performed.
#    $SKIMDIR/Killed
#        A directory with one file per news group. The files contain the 
#        subjects which were automatically killed by skim. Use 'skim cleanup' 
#        regularly to remove these files.
#    $SKIMDIR/Post
#        This is where 'skim replyto' and 'skim newarticle' put the messages
#        they have constructed. 'skim postall' posts all articles it finds in
#        this directory.
#    $SKIMDIR/Posted
#        'skim posts' moves all messages it has posted successfully to this
#        directory. Skim never removes articles from this directory.
#    $SKIMDIR/Indexes/Articles
#        This is where skim stores article index files. The name of an article
#        index file is the name of it's newsgroup. The format is one article 
#        per line. Every line consists of the article number, a space and the 
#        subject line (which may contain spaces).
# COPYRIGHT
#    Skim - Off-line news reading package optimized for slow lines.
#    Copyright (C) 1995  Rene W.J. Pijlman
#
#    This program is free software; you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation; either version 2 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with this program; if not, write to the Free Software
#    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
# VERSION
#    Skim version 0.6.
#    /home/rene/sys/CVS_MasterSourceRepository/skim/skim,v 1.43 1995/08/14 22:16:43 rpijlman Exp

allow_null_glob_expansion=True

USAGE=\
"Usage: skim subjects\n\
       skim articles\n\
       skim cleanup\n\
       skim newarticle [FileName NewsGroups Subject] \n\
       skim replyto ArticleFile ...\n\
       skim post ArticleFile\n\
       skim postall\n\
       skim newsgroups\n\
       skim delete ArticleFile\n\
       skim keep ArticleFile\n\
       skim indexes\n\
       skim version\
"
export IAmSkim=1

# A SPACE and a TAB.
Blank=" 	"

if [ $# -lt 1 ]
then
    echo -e "$USAGE" 1>&2
    exit 1
fi

if [ "$NNTPSERVER" = "" ]
then
    echo "Environment variable NNTPSERVER is not set" 1>&2
    exit 1
fi

# Use default value for $SKIMDIR when not set.
if [ "$SKIMDIR" = "" ]
then
    export SKIMDIR=~/Skim
fi

export SkimTmp=${TMPDIR:-/tmp}

SkimProcesses=${SKIMPROCESSES:-4}
if [ "$SkimProcesses" -lt 1 ]
then
    echo "Invalid value for \$SKIMPROCESSES: $SKIMPROCESSES" 1>&2
    exit 1
fi

SkimDirectories="$SKIMDIR \
                 $SKIMDIR/Admin \
                 $SKIMDIR/Subjects \
                 $SKIMDIR/Skipped \
                 $SKIMDIR/Deleted \
                 $SKIMDIR/Kept \
                 $SKIMDIR/Articles \
                 $SKIMDIR/Indexes \
                 $SKIMDIR/Indexes/Articles \
                 $SKIMDIR/CurrentArticleNumber \
                 $SKIMDIR/Post \
                 $SKIMDIR/Posted"

if [ "$SKIMAUTOSUBJECT" = "CaseSensitive" -o \
     "$SKIMAUTOSUBJECT" = "CaseInsensitive" ]
then
    SkimDirectories="$SkimDirectories \
                     $SKIMDIR/Patterns \
                     $SKIMDIR/Patterns/Subject \
                     $SKIMDIR/Patterns/Subject/AutoSelect \
                     $SKIMDIR/Patterns/Subject/Kill \
                     $SKIMDIR/Killed"
elif [ "$SKIMAUTOSUBJECT" != "" ]
then
    echo "Invalid value in \$SKIMAUTOSUBJECT: $SKIMAUTOSUBJECT" 1>&2
    exit 1
fi

# Create missing parts of directory structure.
for Directory in $SkimDirectories
do
    if [ ! -d $Directory ]
    then
	mkdir $Directory
	if [ $? -ne 0 ]
	then
	    echo "Cannot create directory $Directory" 1>&2
	    exit 1
	fi
    fi
done

# Create default SubscribedNewsGroups if necessary.
if [ ! -f $SKIMDIR/Admin/SubscribedNewsGroups ]
then
    echo "# These are the default news groups you are subscribed to." \
          >> $SKIMDIR/Admin/SubscribedNewsGroups
    echo "news.announce.newusers" >> $SKIMDIR/Admin/SubscribedNewsGroups
    echo "news.newusers.questions" >> $SKIMDIR/Admin/SubscribedNewsGroups
    echo "comp.os.linux.advocacy" >> $SKIMDIR/Admin/SubscribedNewsGroups
fi

# Create default current article numbers if necessary.
for Group in `ListSubscribedNewsGroups`
do
    if [ ! -f $SKIMDIR/CurrentArticleNumber/$Group ]
    then
	echo 1 >$SKIMDIR/CurrentArticleNumber/$Group
    fi
done

if [ "$SKIMAUTOSUBJECT" != "" ]
then 
    # Create empty pattern file if necessary.
    for Group in `ListSubscribedNewsGroups`
    do
	if [ ! -f $SKIMDIR/Patterns/Subject/Kill/$Group ]
	then
	    echo "include(AllGroups)" >$SKIMDIR/Patterns/Subject/Kill/$Group
	fi

	if [ ! -f $SKIMDIR/Patterns/Subject/AutoSelect/$Group ]
	then
	    echo "include(AllGroups)" \
	        >$SKIMDIR/Patterns/Subject/AutoSelect/$Group
	fi
    done

    if [ ! -f $SKIMDIR/Patterns/Subject/Kill/AllGroups ]
    then
	touch $SKIMDIR/Patterns/Subject/Kill/AllGroups
    fi

    if [ ! -f $SKIMDIR/Patterns/Subject/AutoSelect/AllGroups ]
    then
	touch $SKIMDIR/Patterns/Subject/AutoSelect/AllGroups
    fi
fi

if [ "$1" = "subjects" ]
then
    if [ $# -gt 1 ]
    then
	echo -e "$USAGE" 1>&2 
	exit 1
    fi

    Dispatch GetSubjectsInGroup `ListSubscribedNewsGroups`

elif [ "$1" = "articles" ]
then
    if [ $# -gt 1 ]
    then
	echo -e "$USAGE" 1>&2 
	exit 1
    fi

    Dispatch GetArticlesInGroup `ListSubscribedNewsGroups`

elif [ "$1" = "cleanup" ]
then
    if [ $# -gt 1 ]
    then
	echo -e "$USAGE" 1>&2 
	exit 1 
    fi

    rm -f $SKIMDIR/Skipped/* \
          $SKIMDIR/Killed/* \
          $SKIMDIR/Deleted/*

elif [ "$1" = "replyto" ]
then
    if [ $# -lt 2 ]
    then
	echo -e "$USAGE" 1>&2
	exit 1
    fi
    shift 1
    ReplyTo $*
elif [ "$1" = "newarticle" ]
then
    if [ $# -eq 1 ]
    then
        NewArticle
    elif [ $# -eq 4 ]
    then
	NewArticle "$2" "$3" "$4"
    else
	echo -e "$USAGE" 1>&2
	exit 1
    fi
elif [ "$1" = "postall" ]
then
    if [ $# -ne 1 ]
    then
	echo -e "$USAGE" 1>&2
	exit 1
    fi

    (
	cd $SKIMDIR/Post
	for Article in *
	do
	    echo "Article: $Article"
	    PostArticle $Article
	    if [ $? -eq 0 ]
	    then
		mv $Article ../Posted
		echo "Article posted successfully."
	    else
		echo "Article not posted." 1>&2
		exit 1
	    fi
	done
    )
elif [ "$1" = "post" ]
then
    if [ $# -ne 2 ]
    then
	echo -e "$USAGE" 1>&2
	exit 1
    fi
    (
	cd $SKIMDIR/Post
	PostArticle $2
	if [ $? -eq 0 ]
	then
	    mv $2 ../Posted
	    echo "Article posted successfully."
	else
	    echo "Article not posted." 1>&2
	    exit 1
	fi
    )
elif [ "$1" = "newsgroups" ]
then
    if [ $# -ne 1 ]
    then
	echo -e "$USAGE" 1>&2
	exit 1
    fi

    if [ -f $SKIMDIR/Admin/AllNewsGroups ]
    then
	cp $SKIMDIR/Admin/AllNewsGroups $SKIMDIR/Admin/AllNewsGroups.previous
    fi

    GetListOfGroups | sed "s/[$Blank].*//" >$SKIMDIR/Admin/AllNewsGroups

    if [ -f $SKIMDIR/Admin/AllNewsGroups.previous ]
    then
	diff $SKIMDIR/Admin/AllNewsGroups.previous \
	     $SKIMDIR/Admin/AllNewsGroups >$SKIMDIR/Admin/AllNewsGroups.diff
    fi
elif [ "$1" = "indexes" ]
then
    if [ $# -ne 1 ]
    then
	echo -e "$USAGE" 1>&2
	exit 1
    fi

    rm -f $SKIMDIR/Indexes/Articles/*

    RebuildArticleIndexes

elif [ $1 = "delete" -o $1 = "keep" ]
then
    if [ $# != 2 ]
    then
	echo -e "$USAGE" 1>&2
	exit 1
    fi

    if [ $1 = "delete" ]
    then
        mv $SKIMDIR/Articles/$2 $SKIMDIR/Deleted
    elif [ $1 = "keep" ]
    then
        mv $SKIMDIR/Articles/$2 $SKIMDIR/Kept
    else
        echo "Can't happen" 1>&2
        exit 1
    fi

    # Remove the article from the index files.
    TmpIndex=${SkimTmp}/articleindex.$$

    Group=`echo $2 | sed -e 's/\.[0-9]*$//'`
    ArticleNumber=`echo $2 | sed -e 's/^.*\.//'`

    mv -f $SKIMDIR/Indexes/Articles/$Group $TmpIndex
    grep -v "^$ArticleNumber" $TmpIndex >$SKIMDIR/Indexes/Articles/$Group

    rm -f $TmpIndex

    # Remove if empty.
    if [ ! -s $SKIMDIR/Indexes/Articles/$Group ]
    then
	rm -f $SKIMDIR/Indexes/Articles/$Group
    fi
elif [ "$1" = "version" ]
then
    if [ $# -ne 1 ]
    then
	echo -e "$USAGE" 1>&2
	exit 1
    fi
    echo "skim version 0.6"
else
    echo -e "$USAGE" 1>&2
    exit 1
fi

wait

exit 0
