From: dhd@exnet.co.uk (Damon)
Newsgroups: news.admin.misc,news.future,news.groups,news.misc,news.software.readers,news.sysadmin
Subject: Re: NetNews, a blueprint for survival
Date: 12 Jan 93 10:17:32 GMT
Organization: ExNet Systems Ltd Public Access News, London, UK

In article <1is5qgINNbhl@rodan.UU.NET> rsalz@rodan.UU.NET (Rich Salz) writes:
>In <47e4wB4w164w@cellar.org> toad@cellar.org (Tony Shepps) writes:
>>have to ask: why hasn't this already happened?
>As others have pointed out, there are two major packages that do this
>already, and they have been available for >1 and >2 years.
>
>>Is it because the folks who write and maintain most of the news freeware
>>hang out at big, fully Internetted sites, and thus don't have to worry about
>>ugly UUCP connections for small tight-budget sites that have to maintain
>>their net status carefully?
>Sort of.  There are only so many hours in the day, and so much time that
>mgmt usually lets you spend on this sort of stuff.  Is the general
>populace served by a fast relaynews and nov, or by something which will
>reduce email news administration by some fraction?
>
>More importantly, unless you live in such an environment, it is hard to
>really know what the right "solution" is.  If there are things that can be
>done to make life easier for small tight-budget sites, the answers (at
>least the first draft) will have to come from such places.

I provide feeds from a Sun-based system.

For every (uucico) UUCP login Uxxx for a paying subscriber I also
provide them with a login account xxx.  Every system reboot (could do
it any time the news system is quiet) I scoop up a file called
.newssys from the home directories of `xxx's, check them for syntax and
munge them a bit, and tack them on to the end of a `sys.proto' file to
make a new `sys' file for C News.  The software seems to work fine and
took me less than 8 hours to write.

It is one /bin/sh script.

Seems very simple.

Also got a couple of customers off my back!

Although it uses NIS/YP it would be very easy to modify it to use an
ordinary password file; this version runs on SunOS 4.1.1_U1 to go with
the performance release of C News.

Software attached below (your feedback would be welcome):


#!/bin/sh
# @(#) autonews.sh 1.37@(#) 93/01/12 #
# Script to automatically incorporate feeds requested by UUCP users into
# news `sys' file.
#------------------------------------------------------------------------------
# THIS SOFTWARE IS SUPPLIED AS IS.  THIS SOFTWARE COMES WITH NO WARRANTY
# WHATSOEVER.  YOU MAY USE THIS SOFTWARE OR DERIVATIVES OF IT FREE OF CHARGE
# PROVIDED THAT THIS COPYRIGHT NOTICE REMAINS INTACT.
#
# Copyright (c) Damon Hart-Davis 1993.   d@hd.org, dhd@exnet.co.uk
#------------------------------------------------------------------------------
# This software runs on Sun 3s under SunOS 4.1 with C News Performance Release.
#------------------------------------------------------------------------------

# Only let others read the files we produce by default.
umask 033

# This script will have to be run by root (NOT suid) to be able to guarantee
# to inspect the users' chosen sys entry even if their files are otherwise
# protected from inpection.

# The feed requested by the UUCP user is specified in a file called `.newssys'
# in the home directory of their login account.

#---------------------------------------------------------------------------
# Format of a correct .newssys file:
#
#  1) The file must be in plain ASCII.
#  2) The file must consist of zero-or-more lines, each line present
#     consisting of exactly one group name, optionally preceeded by a single
#     `!'.
#  3) There must be no whitespace on a line except for the terminating `\n'.
#  4) Group names may consist only of letters, numbers, and the `.' character.
#  5) Group names must be at least one character long, and no `.' may start or
#     end a group name or be adjacent to any other `.'.
#  6) Whole file must be less than 240 bytes long.
#---------------------------------------------------------------------------

# Basic method...
#
#  1) Look for all UUCP accounts by looking for all account names starting
#     with `U' in the map dumped with `ypcat passwd'.
#  2) Look for all those UUCP users who have a corresponding login account
#     (which should certainly include all paying customers, but not special
#     cases like `exnet').  Where the UUCP account name is Uxyzzy the normal
#     login account is taken to be called xyzzy.
#  3) Locate the `.newssys' file in the login account directory specified
#     in the YP/NIS passwd map for the user.  If that file is present, and
#     read-only, and is valid by the rules given above, copy it to the
#     `MINISYS' subdirectory as file name xyz.  Else leave any entry in the
#     MINISYS directory intact and complain to the user.
#  4) Once all the MINISYS entries have been made, the prototype news sys
#     file `/usr/lib/news/sys.proto' is copied to a new file
#     `/usr/lib/news/sys.tmp' followed by each xyz-type entry from the
#     MINISYS directory as follows:
#
#     Each MINISYS entry will be preceeded by the contents of the .pre.xyz file
#     in the MINISYS directory (if any, else `xyz:') without any newline
#     or space, and followed by the contents of the .post.xyz file (if any,
#     else `/!local:f:') without any space, and then a newline.
#
#  5) When all this is done, the /usr/lib/news/sys file will be replaced
#     (atomically) with the sys.tmp file.
#  6) All this will be done when the news system is guaranteed not to be 
#     running (in particular, when relaynews is not using the sys file);
#     preferably during system boot.
#  7) Entries in MINISYS, MINISYS itelf and the sys.* files will only be
#     writable at any time by the root or news users.

#---------------------------------------------------------------------------
# BASIC PARAMETERS.

# NEWSLIB is the directory in which the sys file and the MINISYS directory
# are to be found.
NEWSLIB=/usr/lib/news

# SYS is the name of the news `sys' file that we are going to reconstruct.
# Absolute pathname.
SYS=$NEWSLIB/sys

# SYSPROTO is the name of the prototype news `sys' file to which our entries
# are added.
# Absolute pathname.
SYSPROTO=$NEWSLIB/sys.proto

# SYSTMP is the name of the temporary news `sys' file we will work on.
# It must be in the same filesystem as $SYS to give atomic replacement
# behaviour.
# Absolute pathname.
SYSTMP=$NEWSLIB/sys.tmp

# NEWSSYS is the file in each UUCP user's normal login a/c home directory
# specifying the feed they require.
NEWSSYS=.newssys

# MINISYS is the directory in which our idea of the users' .newssys files,
# plus any bespoke leaders and trailers, are to be found.
# This path is relative to NEWSLIB
MINISYS=.minisys

# SYSADMIN is who we complain to when something goes wrong.
SYSADMIN=sysadmin

# MAXNEWSSYS is the maximum length of the NEWSSYS file in bytes.
MAXNEWSSYS=240

# PRE is the prefix .ppp. for the username xxx to find
# the start of xxx's sys line.  Eg, if $PRE is .pre. the start of
# the sys line to go with file xxx (all in the MINISYS dir) can be
# found in `.pre.xxx'.
# Must start and end with a `.'.
PRE=.pre.

# POST is the prefix .eee. for the username xxx to find
# the end of xxx's sys line.  Eg, if $POST is .post. the end of
# the sys line to go with file xxx (all in the MINISYS dir) can be
# found in `.post.xxx'.
# Must start and end with a `.'.
POST=.post.

#===========================================================================
# Start doing the real work here...

# Temporary file
TMP=/tmp/$$.autonews.tmp
TMP2=${TMP}2

#-----------------------
# Get the list of UUCP users from the NIS maps.
UUCPusers=`ypcat passwd | grep '^U' | awk -F: '{print $1}'`

if [ "$UUCPusers" = "" ]; then
    echo "$0: Apparently no UUCP users in NIS maps, please help." | \
        mail $SYSADMIN
    exit 1
fi

# DEBUG...
# echo NIS-mapped UUCP users: $UUCPusers

#-----------------------
# Now find which of these users `Uxyz' have corresponding login accounts `xyz'.

ULuserstmp=`echo $UUCPusers | sed -e 's/\<U//g'`
ULusers=`for u in $ULuserstmp;
            do
                ypmatch $u passwd >/dev/null 2>&1 && echo $u
            done`

# DEBUG...
# echo NIS-mapped users with UUCP a/cs: $ULusers

#-----------------------
# For each UUCP user with a login account, track down the NEWSSYS file
# and check if it is read-only, also check that it syntactically valid.

# Moan to the user and to the sysadmin if it is badly formatted, etc.

for u in $ULusers;
    do
        cat /dev/null >$TMP
        (
        # Get user's login dir from the NIS map.
        L=`ypmatch $u passwd | awk -F: '{print $6}'`

        if [ "$L" = "" ]; then
            # User's home directory is missing
            echo "$0: error: $u home directory not in NIS map."
            continue;
        fi

        if [ ! -f "$L/$NEWSSYS" ]; then
            # File is missing
            echo "$0: error: $L/$NEWSSYS news-feed-spec file is missing."
            continue;
        fi

        # Make our copy of the file in $TMP
        cp $L/$NEWSSYS $TMP

        # I fail to check if the file is read-only...
        
        # Check that the file is not too long.
        if [ `wc -c <$TMP` -gt $MAXNEWSSYS ]; then
            echo "$0: error: $NEWSSYS file too long---$MAXNEWSSYS bytes max."
            continue;
        fi
        
        # Check that there are no lines starting `to.'.
        if grep '^to[.]' $TMP; then
            echo "$0: error: no lines starting to.; to.$u added automatically."
            continue;
        fi
        
        # Check that there are no blank lines.
        if grep -s '^$' $TMP; then
            echo "$0: error: blank line in $NEWSSYS file."
            continue;
        fi

        # Check that there are no nasty characters (such as spaces) present.
        # A `!' is allowed as the first character on a line.
        if sed -e 's/^\!//' $TMP | egrep '[^-a-zA-Z0-9.]'; then
            echo "$0: error: illegal character in group name."
            continue;
        fi

        # Check that `.' does not start or end a name, or appear next to
        # another `.'.
        if egrep '(^[.])|([.][.])|([.]$)' $TMP; then
            echo "$0: error: syntax error with dots in group name."
            continue;
        fi

        # Convert file into single-line form and copy to place in MINISYS
        # directory.  Append a `to.xxx' entry always.
        awk '{printf("%s,",$0)} END{print LAST}' LAST=to.$u <$TMP \
            >$NEWSLIB/$MINISYS/$u

        ) > $TMP2 2>&1 

        # If any errors were produced, mail them to user and
        # copy to stdout (assumed to go to sysadmin).
        if [ -s $TMP2 ]; then
            echo Mailing user $u to report problems.
            (echo ''; cat $TMP2) | /usr/ucb/mail $u
            cat $TMP2
        fi
    done

rm -f $TMP $TMP2

#-----------------------
# Now go and construct the new format of the sys file from the sysfile prototype
# and the xxx user files in MINISYS.
rm -f $SYSTMP
cat $SYSPROTO > $SYSTMP

# Go to new working directory.
cd $NEWSLIB/$MINISYS

# Susers is the list of users for whom we have potential sys lines here.
Susers=`cd $NEWSLIB/$MINISYS; /bin/ls | egrep -v '^[.]'`

for u in $Susers;
    do
        if [ -d $u ]; then
            # Ignore directories such as `SCCS'.
            continue;
        fi

        if [ ! -r $u ]; then
            echo "$0: error: 'pwd'/$u not readable."
            continue;
        fi

        # Don't add user xxx to sys file if xxx and Uxxx users can't be found.
        ypmatch $u passwd >/dev/null || continue;
        ypmatch U$u passwd >/dev/null || continue;
        
        # If there is a special line start, use that, else use std one.
        if [ -f $PRE$u -a -r $PRE$u ]; then
            # Carefully remove any trailing whitespace.
            echo -n `cat $PRE$u` >> $SYSTMP
        else
            # Sys line for user xxx starts `xxx:'.
            echo -n $u: >> $SYSTMP
        fi

        # Add the body of the sys line, removing trailing whitespace.
        echo -n `cat $u` >> $SYSTMP
        
        # If there is a special line end, use that, else use std one.
        if [ -f $POST$u -a -r $POST$u ]; then
            # Carefully remove any trailing whitespace.
            echo -n `cat $POST$u` >> $SYSTMP
        else
            # Sys line for user xxx starts `xxx:'.
            echo -n '/all,!local:f:' >> $SYSTMP
        fi

        # Add a newline...
        echo '' >> $SYSTMP
    done

# Now, atomically replace sys file with new version.
mv -f $SYSTMP $SYS
/usr/etc/chown root.wheel $SYS
chmod a+r,a-wx $SYS

#-----------------------
rm -f $TMP $TMP2
-- 
Damon Hart-Davis        London, UK        Internet: dhd@exnet.co.uk, d@hd.org

Public-access UNIX (Suns), news and mail for UK#5 per month.  FIRST MONTH FREE.
[1.36] Cheap Sun eqpt.  UUCP news/mail feeds.  Tel/Fax: +44 81 755 0077.