summaryrefslogtreecommitdiffstats
path: root/tcllib/examples/nntp/postnews
blob: 51842b3cbc66d328e289c0352f606e08ae323602 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
#!/usr/bin/env tclsh
## -*- tcl -*-
# This application is like 'postit', but written in tcl.
# The only package used is 'nntp' from 'tcllib'.
#
# Takes two arguments: 
# 1) The path to the file listing the articles to push
#    into the NNTP network
# 2) The name of the newsserver to push the articles to.
#
# The path to the spool directory is 1 level above the
# article file.

# Check number of arguments

if {[llength $argv] != 2} {
    puts stderr "$argv0: wrong # args, should be \"$argv0 articles newsserver\""
    exit 1
}

# Retrieve arguments

set articlefile [lindex $argv 0]
set newsserver  [lindex $argv 1]

# Validate file

if {![file exists $articlefile]} {
    puts stderr "$argv0: $articlefile does not exist"
    exit 1
}
if {[file isdirectory $articlefile]} {
    puts stderr "$argv0: $articlefile is not a file"
    exit 1
}
if {![file readable $articlefile]} {
    puts stderr "$argv0: $articlefile is not readable"
    exit 1
}

# Get path and article information

set spoolpath [file dirname [file dirname [file join [pwd] $articlefile]]]
set articles  [split [read [set fh [open $articlefile r]]][close $fh] \n]

puts "spooling from $spoolpath"

# Now we are ready to deal with the newsserver

package require nntp ; # from tcllib

proc nntp_cmd {exit title cmd {oktitle {}}} {
    global argv0 

    puts -nonewline stdout $title
    flush stdout
    if {[catch {
	set res [uplevel 1 $cmd]
    } msg]} {
	puts stdout " error: $msg"
	#puts stderr "$argv0: nntp error: $msg"
	if {$exit} {
	    exit 1
	}
	return 0
    } else {
	if {$oktitle != {}} {
	    puts stdout " $res $oktitle"
	} else {
	    puts stdout " $res"
	}
	return 1
    }
}

# Introduce us to the server

nntp_cmd 1 {open       } {set news [nntp::nntp $newsserver]}
nntp_cmd 1 {mode reader} {$news mode_reader}

# Iterate over all articles in the file.

set lastgroup {}

foreach article $articles {
    set article [string trim $article]
    if {$article == {}} {continue}

    foreach {msgfile id} [split $article] {break}

    # We have to validate the message files too.
    # Invalid files are skipped.

    set msgpath [file join $spoolpath $msgfile]

    if {![file exists $msgpath]} {
	puts stderr "article error: $msgfile does not exist"
	continue
    }
    if {[file isdirectory $msgpath]} {
	puts stderr "article error: $msgfile is not a file"
	continue
    }
    if {![file readable $msgpath]} {
	puts stderr "article error: $msgfile is not readable"
	continue
    }

    set group [join [file split [file dirname $msgfile]] .]

    if {[string compare $group $lastgroup] != 0} {

	if {![nntp_cmd 0 {set group  } {$news group $group}]} {
	    # Group does not exist or other error.
	    # Skip the article, can't post it.
	    continue
	}

	set lastgroup $group
    }

    # Group of the message is current, the message file itself is valid.
    # Proceed and check for existence of the article on the server.
    #                mode reader
    if {[nntp_cmd 0 {stat       } {$news stat $id} {article is present, skip}]} {
	continue
    }

    #continue

    if {[catch {
	set msg [read [set fh [open $msgpath r]]][close $fh]
    }]} {
	puts stderr "article error: $msgfile was deleted between check and actual posting"
        continue
    }

    puts stdout "post [llength [split $msg \n]] lines $id"

    nntp_cmd 0 {post       } {$news post $msg}
}

nntp_cmd 1 {quit       } {$news quit}
exit