home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / OL.LZH / PROGS.LZH / POST.ICN < prev    next >
Text File  |  1991-09-05  |  7KB  |  210 lines

  1. ############################################################################
  2. #
  3. #    Name:     post.icn
  4. #
  5. #    Title:     News Poster
  6. #
  7. #    Author:     Ronald Florence
  8. #
  9. #    Version: 1.1
  10. #
  11. #    Date:     January 31, 1991
  12. #
  13. ############################################################################
  14. #
  15. #  This program posts a news article to Usenet via uux or mail.  
  16. #  Given an optional argument (the name of a file containing a
  17. #  news article), it creates a follow-up article, with an 
  18. #  attribution and quoted text.
  19. #
  20. #      usage: post [news-article]
  21. #
  22. ############################################################################
  23. #
  24. #  Configure: smarthost, mode, unixtype, editor or EDITOR env. variable.
  25. #
  26. ############################################################################
  27. #
  28. #  Requires: UNIX or MS-DOS
  29. #  Bugs: MS-DOS requires hard-coded system information
  30. #        Does not check validity of Newsgroups or Distribution.
  31. #
  32. ############################################################################
  33.  
  34. global sitename, domain, tz, tmpfile
  35.  
  36. procedure main(arg)
  37.   
  38.   smarthost := "news-feed"    # Your news feed.
  39.   mode := "uux"            # Use "mail" for a sendnews feed.
  40.   unixtype := "bsd"        # Use "usg" for "-Full Name(" passwd file.
  41.   domain := ".UUCP"
  42.  
  43.   if (find("UNIX", &features) & find("pipes", &features)) then {
  44.     console := "/dev/tty"
  45.     tmpdir := "/tmp/"
  46.     (inf := open("logname", "pr")) & (logname := !inf) & close(inf)
  47.                 # Uuname sometimes pads with spaces.
  48.     (inf := open("uuname -l", "pr")) & (sitename := trim(!inf)) & close(inf)
  49.     (tz := getenv("TZ")) & tz ?:= (tab(many(&letters)), tab(upto(&letters)))
  50.     \logname & (inf := open("/etc/passwd")) & every s := !inf do s ? {
  51.       =(logname) & {
  52.     every tab(upto(':')+1) \4 
  53.     if unixtype == "bsd" then fullname := tab(upto(',:'))
  54.     else fullname := (tab(upto('-')+1), tab(upto('(:')))
  55.     close(inf)
  56.     break
  57.       }    
  58.     }
  59.     sigfile := getenv("HOME") || "/.signature"
  60.     editor := "/bin/vi"
  61.   }
  62.   else if find("MS-DOS", &features) then {
  63.     console := "CON"
  64.     tmpdir := ""
  65.     logname := &null
  66.     sitename := &null
  67.     tz := &null            # Hours off GMT.
  68.     fullname := &null
  69.     sigfile := &null
  70.     editor := "edlin"
  71.   }
  72.   (\logname & \sitename & \tz) | stop("post: missing system info")
  73.   article := open(tmpfile := tempname(tmpdir), "w") | 
  74.     stop("post: cannot write temp file")
  75.   write(article, "Path: ", sitename, "!", logname)
  76.   writes(article, "From: ", logname, "@", sitename, domain)
  77.   \fullname & writes(article, " (", fullname, ")")
  78.   write(article)
  79.  
  80.   if \arg[1] then {
  81.     inf := open(arg[1]) | {
  82.       remove(tmpfile)
  83.       stop("post: cannot read ", arg[1])
  84.     }
  85.     reply_headers(inf, article)
  86.     every write(article, " > ", !inf)
  87.     close(inf)
  88.   }
  89.   else {
  90.     write(article, query("Newsgroups: "))
  91.     write(article, query("Subject: "))
  92.     write(article, query("Distribution: "))
  93.     every write(article, req_headers())
  94.     write(article, "\n")
  95.   }
  96.   edstr := (getenv("EDITOR") | editor) || " " || tmpfile || " < " || console
  97.   system(edstr)
  98.   writes("Are you sure you want to post this to Usenet y/n? ")
  99.   stdin := open(console)
  100.   upto('nN', read(stdin)) & {
  101.     remove(tmpfile)
  102.     exit(1)
  103.   }
  104.                 # Try to append the .signature.
  105.   \sigfile & (inf := open(sigfile)) & {
  106.     article := open(tmpfile, "a")
  107.     write(article, "--")
  108.     every write(article, !inf)
  109.     close(inf)
  110.   }
  111.                 # Don't force an immediate poll.
  112.   if mode == "uux" then mode ||:= " - -r"
  113.                 # Sendnews format requires an initial `N'.
  114.   else if mode == "mail" then {
  115.     inf := open(tmpfile)
  116.     outf := open(tmp2 := tempname(tmpdir), "w")
  117.     every write(outf, "N", !inf)
  118.     remove(tmpfile)
  119.     rename(tmp2, tmpfile)
  120.   }
  121.   mode ||:= " " || smarthost || "!rnews < " || tmpfile
  122.   (system(mode) = 0) & write("Article posted!")
  123.   remove(tmpfile)
  124. end
  125.  
  126.  
  127. procedure tempname(dir)
  128.     
  129.   every temp_name := dir || "article." || right(1 to 999,3,"0") do {
  130.     close(open(temp_name)) & next
  131.     suspend \temp_name
  132.   }
  133. end
  134.  
  135.  
  136. procedure reply_headers(infile, art)
  137.  
  138.   every s := !infile do s ? {
  139.                 # Case-insensitive matches for headers.
  140.     tab(match("from: ", map(&subject))) & {
  141.       if find("<") then {
  142.     fullname := trim(tab(upto('<')))
  143.     address := (move(1), tab(find(">")))
  144.       }
  145.       else {
  146.     address := trim(tab(upto('(') | 0))
  147.     fullname := (move(1), tab(find(")")))
  148.       }
  149.       quoter := (\fullname | address)
  150.     }
  151.     tab(match("date: ", map(&subject))) & date := tab(0)
  152.     tab(match("message-id: ", map(&subject))) & id := tab(0)
  153.     match("subject: ", map(&subject)) & subject := s
  154.     match("distribution: ", map(&subject)) & distribution := s
  155.     match("newsgroups: " | "followup-to: ", map(&subject)) & 
  156.       newsgroup := tab(upto(',') | 0)
  157.     match("references: ", map(&subject)) & refs := s
  158.     (\quoter & *s = 0) & {
  159.       find("poster", newsgroup) & {
  160.     write(quoter, " has requested followups by email.")
  161.     writes("Do you want to abort this posting y/n? ")
  162.     upto('yY', read()) & {
  163.       remove(tmpfile)
  164.       exit(1)
  165.     }
  166.     newsgroup := &null
  167.       }
  168.                 # Newsgroup and subject are required.
  169.       write(art, \newsgroup | query("Newsgroup: "))
  170.       write(art, \subject | query("Subject: "))
  171.       write(art, \distribution | query("Distribution: "))
  172.                 # Message-ID and Date go here.
  173.       every write(art, req_headers())
  174.                 # Threaded readers need References.
  175.       write(art, \refs | "References:", " ", id)
  176.       write(art, "In-reply-to: ", quoter, "'s message of ", date)
  177.       write(art, "\nIn ", id, ", ", quoter, " writes:\n")
  178.       return 
  179.     }
  180.   }
  181. end
  182.  
  183.  
  184. procedure req_headers()
  185.                 # Crude, but it's a unique id.
  186.   uniq := "<"
  187.   &date || &clock ? while tab(upto(&digits)) do uniq ||:= tab(many(&digits))
  188.   uniq ||:= "@" || sitename || domain || ">"
  189.                 # Date in RFC 822 format.
  190.   &dateline ? {
  191.     month := left((tab(find(" ")+1), tab(many(&letters))), 3) || " "
  192.     date := (tab(upto(&digits)), tab(many(&digits))) || " " || month
  193.     date ||:= (tab(upto(&digits)), right(tab(many(&digits)), 2))
  194.   }
  195.                 # GMT would be better; this is allowed.
  196.   if (tz > 0) then zone := " -"
  197.   else zone := " +"
  198.   zone ||:= left(right(abs(tz), 2, "0"), 4, "0")
  199.   suspend "Message-ID: " || uniq
  200.   suspend "Date: " || date || " " || &clock || zone
  201. end
  202.  
  203.  
  204. procedure query(prompt)
  205.  
  206.   writes(prompt)
  207.   ans := read()
  208.   return prompt || ans
  209. end
  210.