Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/cmd/cs/vcs_src/ifs_news.c
1810 views
1
/***********************************************************************
2
* *
3
* This software is part of the ast package *
4
* Copyright (c) 1990-2011 AT&T Intellectual Property *
5
* and is licensed under the *
6
* Eclipse Public License, Version 1.0 *
7
* by AT&T Intellectual Property *
8
* *
9
* A copy of the License is available at *
10
* http://www.eclipse.org/org/documents/epl-v10.html *
11
* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
12
* *
13
* Information and Software Systems Research *
14
* AT&T Research *
15
* Florham Park NJ *
16
* *
17
* Glenn Fowler <[email protected]> *
18
* *
19
***********************************************************************/
20
/*
21
* File: ifs_news.c
22
*/
23
24
#include "ifs_agent.h"
25
#include <stdio.h>
26
27
struct {
28
char *Group[ 256 ];
29
int version;
30
} NewsData;
31
32
/*
33
*name: NewsCommand
34
*/
35
int
36
NewsCommand( nFile, cmd, arg )
37
NetFile *nFile;
38
char *cmd, *arg;
39
{
40
char buf[ STRLEN ];
41
42
if( cmd == NULL )
43
return -1;
44
sfsprintf( buf, sizeof(buf), arg ? "%s %s\r\n" : "%s\r\n", cmd, arg );
45
NetWrite( nFile, buf, strlen(buf) );
46
debug_logit( buf );
47
return 0;
48
}
49
50
/*
51
*name: NewsReply
52
*/
53
int
54
NewsReply( nFile, buf, bsize )
55
NetFile *nFile;
56
char *buf;
57
int bsize;
58
{
59
char tmpbuf[ STRLEN ];
60
61
if( buf == NULL ) {
62
buf = tmpbuf;
63
bsize = sizeof(tmpbuf);
64
}
65
if( NetGets( nFile, buf, bsize ) == NULL ) {
66
debug_logit( "FtpReply: NetGets return NULL\n" );
67
return -1;
68
}
69
debug_logit( buf );
70
return (int)strtol( buf, (char**)0, 0 );
71
}
72
73
/*
74
*name: NewsXferFile
75
*/
76
int
77
NewsXferFile( nFile, destfile )
78
NetFile *nFile;
79
char *destfile;
80
{
81
FILE *fp;
82
char buf[ STRLEN ], *ptr;
83
84
fp = (destfile ? fopen( destfile, "w" ) : NULL);
85
while( NetGets( nFile, buf, sizeof(buf) ) != NULL ) {
86
if( (ptr = strchr( buf, '\r' )) != NULL && ptr[1] == '\n' ) {
87
*ptr = '\0';
88
}
89
if( buf[0] == '.' && buf[1] == '\0' ) { /* end of file */
90
if( fp ) fclose( fp );
91
return 0;
92
}
93
if( fp ) fprintf( fp, "%s\n", buf );
94
}
95
cserrno = E_DATAXFER;
96
return -1;
97
}
98
99
/*
100
*name: NewsListGroups
101
*/
102
int
103
NewsListGroups( srv )
104
struct server_info *srv;
105
{
106
struct mount_item *mitem = srv->mitem;
107
NetFile *nFile = mitem->nFile;
108
char destfile[ STRLEN ];
109
110
NewsCommand( nFile, "LIST", NULL );
111
if( NewsReply( nFile, NULL, 0 ) != 215 ) {
112
logit( "<news>: LIST error\n" );
113
cserrno = E_DATAXFER;
114
return -1;
115
}
116
117
/* 215 Newsgroups in form "group high low flags". */
118
sfsprintf( destfile, sizeof(destfile), "%s/._dir", srv->lpath );
119
MakePath( destfile );
120
return NewsXferFile( nFile, destfile );
121
}
122
123
/*
124
*name: NewsEnterGroup
125
*/
126
int
127
NewsEnterGroup( srv, group, lpath )
128
struct server_info *srv;
129
char *group;
130
char *lpath;
131
{
132
struct mount_item *mitem = srv->mitem;
133
NetFile *nFile = mitem->nFile;
134
FILE *fp;
135
char buf[ STRLEN ];
136
char *arg[ 10 ];
137
char *oldgroup;
138
139
oldgroup = NewsData.Group[ nFile->socket ];
140
if( oldgroup != NULL ) {
141
if( strcmp( group, oldgroup ) == 0 )
142
return 0;
143
free( oldgroup );
144
}
145
NewsData.Group[ nFile->socket ] = strdup( group );
146
NewsCommand( nFile, "GROUP", group );
147
if( NewsReply( nFile, buf, sizeof(buf) ) != 211 ||
148
SplitFields( arg, 5, buf, ' ' ) != 5 ) {
149
logit( "<news>: unknown group\n" );
150
cserrno = E_DATAXFER;
151
return -1;
152
}
153
154
/* 211 num min max group-name */
155
if( lpath == NULL )
156
return 0;
157
158
sfsprintf( buf, sizeof(buf), "%d-%d", (int)strtol( arg[2], (char**)0, 0 ), (int)strtol( arg[3], (char**)0, 0 ) );
159
NewsCommand( nFile, "XOVER", buf );
160
if( NewsReply( nFile, NULL, 0 ) != 224 ) {
161
logit( "<news>: xover error\n" );
162
cserrno = E_DATAXFER;
163
return -1;
164
}
165
166
/* 224 data follows */
167
sfsprintf( buf, sizeof(buf), "%s/._dir", lpath );
168
MakePath( buf );
169
if( NewsXferFile( nFile, buf ) == -1 ) {
170
return -1;
171
}
172
chdir( lpath );
173
if( (fp = fopen( "._dir", "r" )) != NULL ) {
174
while( fgets( buf, sizeof(buf), fp ) != NULL ) {
175
if( SplitFields( arg, 7, buf, '\t' ) == 7 ) {
176
MakeImageFile( arg[0], (int)strtol( arg[6], (char**)0, 0 ) );
177
}
178
}
179
fclose( fp );
180
}
181
return 0;
182
}
183
184
/*
185
*name: NewsGetArticle
186
*/
187
int
188
NewsGetArticle( srv, group, article )
189
struct server_info *srv;
190
char *group;
191
char *article;
192
{
193
struct mount_item *mitem = srv->mitem;
194
NetFile *nFile = mitem->nFile;
195
196
if( NewsEnterGroup( srv, group, NULL ) == -1 )
197
return -1;
198
NewsCommand( nFile, "ARTICLE", article );
199
if( NewsReply( nFile, NULL, 0 ) != 220 ) {
200
logit( "<news>: get article error\n" );
201
cserrno = E_DATAXFER;
202
return -1;
203
}
204
return NewsXferFile( nFile, srv->lpath );
205
}
206
207
/*
208
*name: NewsConnect
209
*/
210
int
211
NewsConnect( srv )
212
struct server_info *srv;
213
{
214
struct mount_item *mitem = srv->mitem;
215
NetFile *nFile = mitem->nFile;
216
int port;
217
218
if( nFile != NULL ) {
219
NewsCommand( nFile, "MODE", "READER" );
220
if( NewsReply( nFile, NULL, 0 ) == 200 ) {
221
return 0;
222
}
223
NetClose( nFile );
224
}
225
logit( "<news>: connect\n" );
226
port = (mitem->port ? mitem->port : 119);
227
if( (nFile = NetConnect( srv, mitem->host, port )) == NULL )
228
return -1;
229
if( NewsReply( nFile, NULL, 0 ) != 200 ) {
230
NetClose( nFile );
231
return -1;
232
}
233
NewsCommand( nFile, "MODE", "READER" );
234
if( NewsReply( nFile, NULL, 0 ) != 200 ) {
235
NetClose( nFile );
236
return -1;
237
}
238
mitem->nFile = nFile;
239
return 0;
240
}
241
242
/*
243
*name: NewsDisconnect
244
*/
245
int
246
NewsDisconnect( srv )
247
struct server_info *srv;
248
{
249
struct mount_item *mitem = srv->mitem;
250
NetFile *nFile = mitem->nFile;
251
252
if( nFile != NULL ) {
253
NetClose( nFile );
254
mitem->nFile = NULL;
255
}
256
return 0;
257
}
258
259
/*
260
*name: NewsGetFile
261
*/
262
int
263
NewsGetFile( srv )
264
struct server_info *srv;
265
{
266
struct mount_item *mitem = srv->mitem;
267
char group[ STRLEN ];
268
char *rpath, *article;
269
270
if( mitem->nFile == NULL )
271
if( NewsConnect( srv ) == -1 )
272
return -1;
273
if( NetDataReady( mitem->nFile ) ) { /* 503 Timeout or invalid mode */
274
NewsDisconnect( srv );
275
if( NewsConnect( srv ) == -1 )
276
return -1;
277
}
278
279
rpath = srv->rpath;
280
if( *rpath == '\0' ) {
281
return NewsListGroups( srv );
282
}
283
284
strcpy( group, rpath+1 ); /* group(/article) */
285
if( (article = strchr( group, '/' )) == NULL ) {
286
return NewsEnterGroup( srv, group, srv->lpath );
287
}
288
289
*article++ = '\0';
290
if( strchr( article, '/' ) != NULL ) { /* too many arguments */
291
logit( "<news>: invalid path\n" );
292
return -1;
293
}
294
return NewsGetArticle( srv, group, article );
295
}
296
297
/*
298
*name: NewsPutFile
299
*/
300
int
301
NewsPutFile( srv )
302
struct server_info *srv;
303
{
304
return 0;
305
}
306
307
/*
308
*name: NewsNop
309
*/
310
int
311
NewsNop( srv )
312
struct server_info *srv;
313
{
314
return 0;
315
}
316
317
/*
318
*name: NewsInit
319
* Initial the data and functions in agent_item
320
*/
321
int
322
NewsInit( tbl )
323
struct agent_item *tbl;
324
{
325
tbl->localdata = (char *) &NewsData;
326
tbl->connect = NewsConnect;
327
tbl->disconnect = NewsDisconnect;
328
tbl->listdents = NewsGetFile;
329
tbl->getfile = NewsGetFile;
330
tbl->putfile = NewsPutFile;
331
tbl->userdef = NewsNop;
332
return 0;
333
}
334
335
336