#!/bin/bash # Thu Mar 11 02:13:02 EST 2004 # NAME: cjnews # DESCRIPTION: [the beginnings of] a command-line news reader # Copyright 2004, Chris F.A. Johnson # Released under the terms of the GNU General Public License ## fill in necessary information here host=$NNTPSERVER port=119 user= pass= configfile=$HOME/.cjnewsrc ## or put it in $configfile, which will be sourced [ -f "$configfile" ] && . "$configfile" ## meassage header arrays from[0]= groups[0]= subject[0]= date[0]= lines[0]= msg_id[0]= user_agent[0]= tcpread() { while IFS= read -r line <&3 do line=${line%$CR} case $line in .) break ;; *) printf "%s\n" "$line" ;; esac done } tcpcmd() { local IFS=${IFS}$'\r' cmd=$* echo $cmd >&3 read ok msg <&3 [ ${verbose:-0} -gt 0 ] && printf "%s\n" "$ok $msg" [ ${ok:-666} -lt 400 ] } quit() { tcpcmd quit [ ${verbose:-0} -gt 0 ] && echo Exit code: $1 exit $(( $1 % 255 )) } commas() { _COMMAS= local left num decimal case $1 in *.*) num=${1%.*} decimal=${1#.} ;; *) num=$1 decimal= ;; esac while : do case $num in ???|??|?) _COMMAS=${num}${_COMMAS:+,$_COMMAS}; break ;; *) left=${num%???} _COMMAS=${num#${left}}${_COMMAS:+,$_COMMAS} num=$left ;; esac done _COMMAS=${_COMMAS}${decimal:+.$decimal} [ ${SILENT_FUNCS:-0} -eq 1 ] || echo "$_COMMAS" } folder() { group "$@" } group() { [ -z "$1" ] && { printf "%s\n" "USAGE: $FUNCNAME [+]name.of.group"; return 192; } tcpcmd group "${1#+}" && group=${1#+} || return 192 printf "\nGroup:%s\n" "$group" prompt=$group set $msg commas $1; num=$_COMMAS commas $2; first=$_COMMAS commas $3; last=$_COMMAS printf "%s messages: %s to %s\n" "$num" "$first" "$last" } stat() { [ -z "$1" ] && { printf "%s\n" "USAGE: $FUNCNAME NUMBER" >&2; return 192; } tcpcmd stat "${@}" } parse_header() { local IFS=$'\n' local line local msg_num=${1:-$msg_num} for line in ${header[$msg_num]} do case $line in From:*) from[$msg_num]=${line#From: } ;; Newsgroups:*) groups[$msg_num]=${line#Newsgroups: } ;; Subject:*) subject[$msg_num]=${line#Subject: } ;; Date:*) date[$msg_num]=${line#Date: } ;; Lines:*) lines[$msg_num]=${line#Lines: } ;; Message-ID:*) msg_id[$msg_num]=${line#Message-ID: } ;; User-Agent:*) user_agent[$msg_num]=${line#User-Agent: } ;; Path:*) ;; Organization:*) ;; X-Trace:*) ;; X-Complaints-To:*) ;; NNTP-Posting-Date:*) ;; NNTP-Posting-Host:*) nntp_host[$msg_num]=${line#NNTP-Posting-Host: } ;; Xref:*) ;; esac done } full_header() { echo "$NL${header[$msg_num]}$NL" } show_header() { printf "\n" printf "Newsgroups: %s\n" "${groups[$msg_num]}" printf " Subject: %s\n" "${subject[$msg_num]}" printf " From: %s\n" "${from[$msg_num]}" printf " Date: %s\n" "${date[$msg_num]}" printf " Lines: %s\n" "${lines[$msg_num]}" printf "\n" } head() { local msg_num=$1 case $msg_num in *[^0-9]*|"") printf "%s\n" "USAGE: $FUNCNAME NUMBER" >&2 return 192 ;; esac tcpcmd head $msg_num && echo || return 192 header[$msg_num]=`tcpread` parse_header $msg_num show_header $msg_num } body() { [ -z "$1" ] && { printf "%s\n" "USAGE: $FUNCNAME NUMBER"; return 192; } tcpcmd body "${@}" && echo || return 192 tcpread } help() { echo " folder [+]GROUP - select GROUP group [+]GROUP - select GROUP head NUMBER - retrieve the head of message no. NUMBER body NUMBER - retrieve message no. NUMBER stat NUMBER - get statistics for message no. NUMBER help - show this screen quit - exit $progname " } SILENT_FUNCS=1 progname=${0##*/} HISTFILE=$HOME/.cnewshist [ -f "$HISTFILE" ] || touch $HISTFILE history -r CR=$'\r' NL=$'\n' exec 3<>/dev/tcp/$host/$port read ok msg <&3 echo "$ok $line" case $ok in 200|201) echo "Connected to $host" ;; *) quit 192 ;; esac [ -n "$user" ] && tcpcmd authinfo simple $user $pass || quit $ok while : do read -ep "${prompt:-$host}:: " cmd ## there must be an easier way to use history in a script history -w history -s "$cmd" history -a history -c history -r case $cmd in q|Q|bye|quit) break ;; group* ) $cmd ;; folder*) $cmd ;; stat*) $cmd ;; head*) $cmd ;; body*) $cmd ;; *) help ;; esac done tempfile=$HOME/.cnews-histfile-$$ uniq "$HISTFILE" > $tempfile mv -b $tempfile "$HISTFILE" quit 0