ron@mlfarm.com (Ronald Florence) (01/09/91)
It won't put gnus-post or Pnews out of business, but it works, both
for original postings and follow-ups. The code borrows from Richard
Goerwitz's tempname generator and from reply.icn. The limited ms-dos
support is untested. Perhaps someone can suggest how to include
support for VMS or other systems in this and reply.icn.
I hope this is useful to someone.
--
Ronald Florence ron@mlfarm.com
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create:
# post.icn
# This archive created: Wed Jan 9 10:26:12 1991
# By: Ronald Florence (Maple Lawn Farm, Stonington, CT)
export PATH; PATH=/bin:/usr/bin:$PATH
if test -f 'post.icn'
then
echo shar: "will not over-write existing file 'post.icn'"
else
cat << \SHAR_EOF > 'post.icn'
############################################################################
#
# Name: post.icn
#
# Title: News Poster
#
# Author: Ronald Florence (ron@mlfarm.com)
#
# Date: January 8, 1991
#
############################################################################
#
# This program posts a news article to Usenet via uux or mail.
# Given an optional argument (the name of a file containing a
# news article), it creates a follow-up article, with an
# attribution and quoted text.
#
# usage: post [news-article]
#
############################################################################
#
# Configure: smarthost, mode, editor or EDITOR environment variable.
#
############################################################################
#
# Requires: UNIX or MS-DOS.
# Bugs: ms-dos requires hard-coded system info.
#
############################################################################
global sitename, domain, tz
procedure main(arg)
smarthost := "news-feed" # Your news feed.
mode := "uux" # Use "mail" for a sendnews feed.
domain := ".UUCP"
if (find("UNIX", &features) & find("pipes", &features)) then {
console := "/dev/tty"
tmpdir := "/tmp/"
(inf := open("logname", "pr")) & (logname := !inf) & close(inf)
# Uuname sometimes pads with spaces.
(inf := open("uuname -l", "pr")) & (sitename := trim(!inf)) & close(inf)
(tz := getenv("TZ")) & tz ?:= (tab(many(&letters)), tab(upto(&letters)))
sigfile := getenv("HOME") || "/.signature"
editor := "/bin/vi"
}
else if find("MS-DOS", &features) then {
console := "CON"
tmpdir := ""
logname := &null
sitename := &null
tz := &null # Hours off GMT.
sigfile := &null
editor := "edlin"
}
(\logname & \sitename & \tz) | stop("post: missing system info")
article := open(tmpfile := tempname(tmpdir), "w") |
stop("post: cannot write temp file")
write(article, "Path: ", sitename, "!", logname)
write(article, "From: ", logname, "@", sitename, domain)
if \arg[1] then {
inf := open(arg[1]) | {
remove(tmpfile)
stop("post: cannot read ", arg[1])
}
reply_headers(inf, article)
every write(article, " > ", !inf)
close(inf)
}
else {
write(article, query("Newsgroups: "))
write(article, query("Subject: "))
every write(article, req_headers())
write(article, "\n")
}
edstr := (getenv("EDITOR") | editor) || " " || tmpfile || " < " || console
system(edstr)
writes("Are you sure you want to post this to Usenet y/n? ")
stdin := open(console)
upto('nN', read(stdin)) & {
remove(tmpfile)
stop("Article aborted.")
}
# Try to append the .signature.
\sigfile & (inf := open(sigfile)) & {
article := open(tmpfile, "a")
write(article, "--")
every write(article, !inf)
close(inf)
}
# Don't force an immediate poll.
if find("uux", mode) then mode ||:= " - -r"
# Sendnews format requires an initial `N'.
else if find("mail", mode) then {
inf := open(tmpfile)
outf := open(tmp2 := tempname(tmpdir), "w")
every write(outf, "N", !inf)
remove(tmpfile)
rename(tmp2, tmpfile)
}
mode ||:= " " || smarthost || "!rnews < " || tmpfile
(system(mode) = 0) & write("Article posted!")
remove(tmpfile)
end
procedure tempname(dir)
every temp_name := dir || "article." || right(1 to 999,3,"0") do {
close(open(temp_name)) & next
suspend \temp_name
}
end
procedure reply_headers(infile, art)
every s := !infile do s ? {
# Case-insensitive matches for headers.
tab(match("from: ", map(&subject))) & {
if find("<") then {
fullname := trim(tab(upto('<')))
address := (move(1), tab(find(">")))
}
else {
address := trim(tab(upto('(') | 0))
fullname := (move(1), tab(find(")")))
}
quoter := (\fullname | address)
}
tab(match("date: ", map(&subject))) & date := tab(0)
tab(match("message-id: ", map(&subject))) & id := tab(0)
match("subject: ", map(&subject)) & subject := s
match("newsgroups: ", map(&subject)) & newsgroup := tab(upto(',') | 0)
match("references: ", map(&subject)) & refs := s
(\quoter & *s = 0) & {
# Newsgroup and subject are required.
write(art, \newsgroup | query("Newsgroup: "))
write(art, \subject | query("Subject: "))
# Message-ID and Date go here.
every write(art, req_headers())
# Threaded readers need References.
write(art, \refs | "References:", " ", id)
write(art, "In-reply-to: ", quoter, "'s message of ", date)
write(art, "\nIn ", id, ", ", quoter, " writes:\n")
return
}
}
end
procedure req_headers()
# Crude, but it's a unique id.
uniq := "<"
&date || &clock ? while tab(upto(&digits)) do uniq ||:= tab(many(&digits))
uniq ||:= "@" || sitename || domain || ">"
# Date in RFC 822 format.
&dateline ? {
month := left((tab(find(" ")+1), tab(many(&letters))), 3) || " "
date := (tab(upto(&digits)), tab(many(&digits))) || " " || month
date ||:= (tab(upto(&digits)), right(tab(many(&digits)), 2))
}
# GMT would be better; this is allowed.
if (tz > 0) then zone := " -"
else zone := " +"
zone ||:= left(right(abs(tz), 2, "0"), 4, "0")
suspend "Message-ID: " || uniq
suspend "Date: " || date || " " || &clock || zone
end
procedure query(prompt)
writes(prompt)
ans := read()
return prompt || ans
end
SHAR_EOF
if test 5403 -ne "`wc -c < 'post.icn'`"
then
echo shar: "error transmitting 'post.icn'" '(should have been 5403 characters)'
fi
fi
exit 0
# End of shell archive
--
Ronald Florence ron@mlfarm.comron@mlfarm.com (Ronald Florence) (01/12/91)
This patch will add (Full Name) to the From line of outgoing postings
from post.icn. Most of the changes are added lines, so if you don't
have `patch' it shouldn't be too onerous to do manually.
If your passwd file keeps full names between a "-" and a "(", try
setting "unixtype" to "usg". Use "bsd" for Xenix, V7 or other passwd
files which have the full name the first item after the colon in the
field. The ms-dos support relies on a hard-coded full name (ugh!).
*** post.icn~ Tue Jan 8 19:57:00 1991
--- post.icn Thu Jan 10 23:15:24 1991
***************
*** 19,25 ****
#
############################################################################
#
! # Configure: smarthost, mode, editor or EDITOR environment variable.
#
############################################################################
#
--- 19,25 ----
#
############################################################################
#
! # Configure: smarthost, mode, unixtype, editor or EDITOR env. variable.
#
############################################################################
#
***************
*** 34,39 ****
--- 34,40 ----
smarthost := "news-feed" # Your news feed.
mode := "uux" # Use "mail" for a sendnews feed.
+ unixtype := "bsd" # Use "usg" for "-Full Name(" passwd file.
domain := ".UUCP"
if (find("UNIX", &features) & find("pipes", &features)) then {
***************
*** 43,48 ****
--- 44,57 ----
# Uuname sometimes pads with spaces.
(inf := open("uuname -l", "pr")) & (sitename := trim(!inf)) & close(inf)
(tz := getenv("TZ")) & tz ?:= (tab(many(&letters)), tab(upto(&letters)))
+ \logname & (inf := open("/etc/passwd")) & every s := !inf do s ? {
+ =(logname) & {
+ every tab(upto(':')+1) \4
+ if find("bsd", unixtype) then fullname := tab(upto(':'))
+ else fullname := (tab(upto('-')+1), tab(upto('(')))
+ break
+ }
+ }
sigfile := getenv("HOME") || "/.signature"
editor := "/bin/vi"
}
***************
*** 52,57 ****
--- 61,67 ----
logname := &null
sitename := &null
tz := &null # Hours off GMT.
+ fullname := &null
sigfile := &null
editor := "edlin"
}
***************
*** 59,65 ****
article := open(tmpfile := tempname(tmpdir), "w") |
stop("post: cannot write temp file")
write(article, "Path: ", sitename, "!", logname)
! write(article, "From: ", logname, "@", sitename, domain)
if \arg[1] then {
inf := open(arg[1]) | {
--- 69,77 ----
article := open(tmpfile := tempname(tmpdir), "w") |
stop("post: cannot write temp file")
write(article, "Path: ", sitename, "!", logname)
! writes(article, "From: ", logname, "@", sitename, domain)
! \fullname & writes(article, " (", fullname, ")")
! write(article)
if \arg[1] then {
inf := open(arg[1]) | {
--
Ronald Florence ron@mlfarm.com