add newt(1): nntp client for use with nntpfs(4)
This commit is contained in:
parent
5d3d085492
commit
8347075fd9
2 changed files with 378 additions and 0 deletions
246
rc/bin/newt
Executable file
246
rc/bin/newt
Executable file
|
@ -0,0 +1,246 @@
|
|||
#!/bin/rc
|
||||
# bloated, featureful usenet reader for use with nntpfs
|
||||
rfork en
|
||||
ramfs
|
||||
argv0=$0
|
||||
if(~ $#editor 0)
|
||||
editor=hold
|
||||
group=alt/test
|
||||
maxposts=30
|
||||
mnt=/mnt/news
|
||||
if(~ $#newtname 0)
|
||||
newtname=newt@dont-email.me
|
||||
fn enterpost{
|
||||
{
|
||||
echo From: $"newtname
|
||||
echo Newsgroups: `{echo $group | sed 's/\//\./g'}
|
||||
echo Subject: $"subject
|
||||
echo
|
||||
} >/tmp/post
|
||||
eval $editor /tmp/post
|
||||
cat /tmp/post >$mnt/$group/post
|
||||
}
|
||||
fn f { du -a $* | sed 's/^.* //g' }
|
||||
fn fmtd{
|
||||
date=`{cat}
|
||||
if(! ~ $date(1) [0-9]*)
|
||||
date=`{nshift $date}
|
||||
da=$date(1)
|
||||
switch($date(2)){
|
||||
case Jan; mo=1
|
||||
case Feb; mo=2
|
||||
case Mar; mo=3
|
||||
case Apr; mo=4
|
||||
case May; mo=5
|
||||
case Jun; mo=6
|
||||
case Jul; mo=7
|
||||
case Aug; mo=8
|
||||
case Sep; mo=9
|
||||
case Oct; mo=10
|
||||
case Nov; mo=11
|
||||
case Dec; mo=12
|
||||
}
|
||||
if(! ~ $date(3) `{date | awk '{print $6;}'})
|
||||
ti=$date(3)
|
||||
if not
|
||||
ti=`{echo $date(4) | awk '{print substr($0,0,5);}'}
|
||||
echo $mo/$da $ti
|
||||
}
|
||||
fn geth{
|
||||
for(i in $*){
|
||||
from=`{awk -F ' ' '{print $3;}' $i/xover}
|
||||
if(! ~ $#from 0 && ! ~ $#from 1){
|
||||
nfrom=`{
|
||||
for(i in $from){
|
||||
if(~ $i *@*)
|
||||
echo $i | sed 's/(<|>)//g'
|
||||
}
|
||||
}
|
||||
if(! ~ $#nfrom 0)
|
||||
from=$nfrom
|
||||
}
|
||||
if(! ~ $#from 0){
|
||||
date=`{awk -F ' ' '{print $4;}' $i/xover >[2]/dev/null | fmtd}
|
||||
awk -v date'='$"date -v from'='$from(1) -F ' ' \
|
||||
'{print " " $1 " " date " " from " " substr($2,0,50);}' $i/xover >[2]/dev/null
|
||||
}
|
||||
if not
|
||||
echo ' '$"i' nil nil nil'
|
||||
}
|
||||
}
|
||||
fn getposts{ ls | grep -e '^[0-9]+$' | sort -n | tail -$maxposts }
|
||||
fn k{
|
||||
kmnt=`{echo $mnt | sed 's/\//\\\//g'}
|
||||
f $mnt/$* |
|
||||
grep -v -e '\/([0-9]+(\/|$)|post$)' |
|
||||
sed 's/^'$"kmnt'\// g /g' |
|
||||
sort
|
||||
}
|
||||
fn nshift{ shift; echo $* }
|
||||
fn printhelp{
|
||||
echo '[0-9]+ print specified message
|
||||
b back
|
||||
e enter message
|
||||
f jump to first message
|
||||
g ... go to specified group
|
||||
h print message headlines
|
||||
help print this help message
|
||||
k ... list sub-groups under specified group
|
||||
l jump to last message
|
||||
n next
|
||||
p print message with minimal headers
|
||||
P print message with full headers
|
||||
q quit
|
||||
r reply to message
|
||||
y synchronize message list with server
|
||||
" print message in quoted form, suitable for reply
|
||||
|cmd pipe message body to a command
|
||||
||cmd pipe raw message to a command
|
||||
? print debug information'
|
||||
}
|
||||
fn printp{
|
||||
if(test -d $mnt/$group/$1){
|
||||
grep -e '(^From|^Newsgroups|^Subject|^Date)' $1/header
|
||||
echo
|
||||
cat $1/body
|
||||
}
|
||||
echo
|
||||
prompt=$group/$1
|
||||
}
|
||||
fn printpp{
|
||||
if(test -d $mnt/$group/$1){
|
||||
cat $1/article
|
||||
}
|
||||
echo
|
||||
prompt=$group/$1
|
||||
}
|
||||
fn usage{
|
||||
echo usage: $argv0 '[ -f newsgroup ] [ -m mountpoint ] [ -p maxposts ]' >[1=2]
|
||||
exit usage
|
||||
}
|
||||
while(~ $1 -*){
|
||||
switch($1){
|
||||
case -f
|
||||
group=`{echo $2 | sed 's/\./\//g'}
|
||||
shift
|
||||
case -m
|
||||
mnt=$2
|
||||
shift
|
||||
case -p
|
||||
maxposts=$2
|
||||
shift
|
||||
case *
|
||||
usage
|
||||
}
|
||||
shift
|
||||
}
|
||||
if(! ~ $#* 0)
|
||||
usage
|
||||
prompt=$group
|
||||
if(! test -d $mnt/$group){
|
||||
echo !$mnt/$group does not exist >[1=2]
|
||||
exit
|
||||
}
|
||||
builtin cd $mnt/$group
|
||||
go=()
|
||||
posts=`{getposts}
|
||||
geth $posts >/tmp/h
|
||||
post=$posts(1)
|
||||
echo $#posts messages
|
||||
while(){
|
||||
echo -n $"prompt': '
|
||||
cmd=`{read}
|
||||
switch($cmd){
|
||||
case [0-9]*
|
||||
post=$cmd(1)
|
||||
printp $post
|
||||
case b
|
||||
if(! ~ $post $posts(1)){
|
||||
post=`{echo $post^-1 | bc}
|
||||
printp $post
|
||||
}
|
||||
case e
|
||||
enterpost
|
||||
case f
|
||||
post=$posts(1)
|
||||
printp $post
|
||||
case g' '*
|
||||
ngroup=`{nshift $cmd | sed 's/\./\//g'}
|
||||
if(test -d $mnt/$ngroup){
|
||||
if(grep -s -e '^[0-9]+$' <{ls -p $mnt/$ngroup}){
|
||||
group=$ngroup
|
||||
builtin cd $mnt/$group
|
||||
go=()
|
||||
posts=`{getposts}
|
||||
geth $posts >/tmp/h
|
||||
post=$posts(1)
|
||||
prompt=$group
|
||||
echo $#posts messages
|
||||
}
|
||||
if not
|
||||
echo !$ngroup contains no messages
|
||||
}
|
||||
if not
|
||||
echo !$ngroup does not exist
|
||||
case h
|
||||
cat /tmp/h
|
||||
case help
|
||||
printhelp
|
||||
case k
|
||||
k $group
|
||||
case k' '*
|
||||
k `{nshift $cmd | sed 's/\./\//g'}
|
||||
case l
|
||||
post=$posts($#posts)
|
||||
printp $post
|
||||
case p
|
||||
printp $post
|
||||
case p' '*
|
||||
post=`{nshift $cmd}
|
||||
printp $post
|
||||
case P
|
||||
printpp $post
|
||||
case P' '*
|
||||
post=`{nshift $cmd}
|
||||
printpp $post
|
||||
case q
|
||||
exit
|
||||
case r
|
||||
if(test -f $mnt/$group/$post/header){
|
||||
subject='Re: '^`{grep -e '^Subject: ' $mnt/$group/$post/header | sed 's/^Subject: //g'}
|
||||
enterpost
|
||||
}
|
||||
if not
|
||||
echo !message missing
|
||||
case y
|
||||
posts=`{getposts}
|
||||
geth $posts >/tmp/h
|
||||
echo $#posts messages
|
||||
case '"'
|
||||
printp $post | sed 1d | sed 's/^/> /g' | sed 's/^> >/>>/g'
|
||||
case '||'*
|
||||
cmd=`{echo $"cmd | sed 's/^\|\|//g'}
|
||||
cat $mnt/$group/$post/article | eval $cmd
|
||||
case '|'*
|
||||
cmd=`{echo $"cmd | sed 's/^\|//g'}
|
||||
cat $mnt/$group/$post/body | eval $cmd
|
||||
case '?'
|
||||
echo mnt: $mnt
|
||||
echo group: $group
|
||||
echo maxposts: $maxposts
|
||||
echo posts: $posts
|
||||
echo post: $post
|
||||
case n *
|
||||
if(~ $post $posts(1) && ~ $#go 0){
|
||||
go=1
|
||||
printp $post
|
||||
}
|
||||
if not if(! ~ $post $posts($#posts)){
|
||||
go=1
|
||||
post=`{echo $post^+1 | bc}
|
||||
if(test $post -gt $posts($#posts))
|
||||
post=$posts($#posts)
|
||||
printp $post
|
||||
}
|
||||
}
|
||||
}
|
132
sys/man/1/newt
Normal file
132
sys/man/1/newt
Normal file
|
@ -0,0 +1,132 @@
|
|||
.TH NEWT 1
|
||||
.SH NAME
|
||||
newt \- network news transport protocol (NNTP) client
|
||||
.SH SYNOPSIS
|
||||
.B newt
|
||||
[
|
||||
.B -f
|
||||
.I newsgroup
|
||||
] [
|
||||
.B -m
|
||||
.I mountpoint
|
||||
] [
|
||||
.B -p
|
||||
.I maxposts
|
||||
]
|
||||
.SH DESCRIPTION
|
||||
.I Newt
|
||||
provides an interactive, text-based interface to NNTP
|
||||
articles served by
|
||||
.IR nntpfs (4) .
|
||||
.PP
|
||||
There are a number of options:
|
||||
.TP
|
||||
.B -f
|
||||
Load the specified newsgroup. Default is
|
||||
.B alt.test.
|
||||
.TP
|
||||
.B -m
|
||||
Directory where
|
||||
.I nntpfs
|
||||
is mounted. Default is
|
||||
.B /mnt/news.
|
||||
.TP
|
||||
.B -p
|
||||
Number of posts to display, up to and including the most recent post.
|
||||
.PP
|
||||
.I Newt
|
||||
starts by reading the list of messages in the
|
||||
.I newsgroup,
|
||||
printing out the number of messages, and then prompting for commands
|
||||
from standard input. The prompt itself presents the name of the group
|
||||
and the message number in the form of a file system path relative to the
|
||||
.I mountpoint.
|
||||
.PP
|
||||
The commands are:
|
||||
.PP
|
||||
.TP
|
||||
.I number
|
||||
Print message
|
||||
.I number.
|
||||
.TP
|
||||
.B b
|
||||
Print the previous message.
|
||||
.TP
|
||||
.B e
|
||||
Enter a new message, honoring the environment variable
|
||||
.I editor.
|
||||
Default is
|
||||
.IR hold (1) .
|
||||
.TP
|
||||
.B f
|
||||
Jump to the first message in the group.
|
||||
.TP
|
||||
.BI g " newsgroup
|
||||
Change to the specified
|
||||
.I newsgroup.
|
||||
The name of a group may be provided in dotted
|
||||
(\fIalt.test\fR) or path (\fIalt/test\fR) format.
|
||||
.TP
|
||||
.B h
|
||||
Print the disposition, date, sender and subject line
|
||||
of all messages in the group. These lines are suitable
|
||||
for selecting and sending to the prompt, in order to
|
||||
print messages either singly or in aggregate.
|
||||
.TP
|
||||
.B help
|
||||
Print a summary of the available commands.
|
||||
.TP
|
||||
.BI k " [newsgroup]
|
||||
Without an argument,
|
||||
.I k
|
||||
walks the directories under the current group
|
||||
and prints commands suitable for changing to each
|
||||
available sub-group. When provided with an argument,
|
||||
it instead walks the directories under the group specified
|
||||
by the argument.
|
||||
.TP
|
||||
.B l
|
||||
Jump to the last message in the group.
|
||||
.TP
|
||||
.B n, or enter key
|
||||
Print the next message.
|
||||
.TP
|
||||
.B p
|
||||
Print the current message with minimal headers.
|
||||
.TP
|
||||
.B P
|
||||
Print the raw message with full headers.
|
||||
.TP
|
||||
.B q
|
||||
Quit.
|
||||
.TP
|
||||
.B r
|
||||
Reply to the current message.
|
||||
.TP
|
||||
.B y
|
||||
Synchronize message list with the server.
|
||||
.TP
|
||||
.BI | command
|
||||
Run the
|
||||
.I command
|
||||
with the message body as standard input.
|
||||
.TP
|
||||
.BI || command
|
||||
Run the
|
||||
.I command
|
||||
with the whole message as standard input.
|
||||
.TP
|
||||
\fB"\fP
|
||||
Print the current message in quoted form, suitable for reply.
|
||||
.SH SOURCE
|
||||
.B /rc/bin/newt
|
||||
.SH "SEE ALSO"
|
||||
.IR nntpfs (4)
|
||||
.SH BUGS
|
||||
The list of available newsgroups offered by a given server
|
||||
may run to many megabytes in size. This complicates
|
||||
walking the list over a slow Internet connection, and renders
|
||||
searching all but infeasible.
|
||||
.SH HISTORY
|
||||
.I Newt
|
||||
first appeared in 9front (April, 2014).
|
Loading…
Reference in a new issue