Mercurial > noffle
annotate server.c @ 37:792eb10e936d noffle
[svn] Change returned status info for STAT_POST_OK, because\n"Message queued for posting" is no longer meaningful for local groups.
author | enz |
---|---|
date | Thu, 04 May 2000 09:16:09 +0100 |
parents | 526a4c34ee2e |
children | 8e972daaeab9 |
rev | line source |
---|---|
0 | 1 /* |
2 server.c | |
3 | |
37
792eb10e936d
[svn] Change returned status info for STAT_POST_OK, because\n"Message queued for posting" is no longer meaningful for local groups.
enz
parents:
26
diff
changeset
|
4 $Id: server.c 43 2000-05-04 08:16:09Z enz $ |
0 | 5 */ |
6 | |
7 #include "server.h" | |
8 #include <ctype.h> | |
9 #include <signal.h> | |
10 #include <stdarg.h> | |
11 #include <sys/time.h> | |
12 #include <sys/types.h> | |
13 #include <time.h> | |
14 #include <unistd.h> | |
15 #include "client.h" | |
16 #include "common.h" | |
17 #include "config.h" | |
18 #include "content.h" | |
26
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
19 #include "control.h" |
0 | 20 #include "database.h" |
21 #include "dynamicstring.h" | |
22 #include "fetch.h" | |
23 #include "fetchlist.h" | |
24 #include "group.h" | |
26
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
25 #include "itemlist.h" |
0 | 26 #include "lock.h" |
27 #include "log.h" | |
28 #include "online.h" | |
29 #include "outgoing.h" | |
26
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
30 #include "post.h" |
0 | 31 #include "protocol.h" |
32 #include "pseudo.h" | |
33 #include "request.h" | |
34 #include "util.h" | |
35 | |
36 struct | |
37 { | |
38 Bool running; | |
39 int artPtr; | |
40 Str grp; /* selected group, "" if none */ | |
41 } serv = { FALSE, 0, "" }; | |
42 | |
43 typedef struct Cmd | |
44 { | |
45 const char *name; | |
46 const char *syntax; | |
47 /* Returns false, if quit cmd */ | |
48 Bool (*cmdProc)( char *arg, const struct Cmd *cmd ); | |
49 } | |
50 Cmd; | |
51 | |
52 static Bool doArt( char *arg, const Cmd *cmd ); | |
53 static Bool doBody( char *arg, const Cmd *cmd ); | |
54 static Bool doGrp( char *arg, const Cmd *cmd ); | |
55 static Bool doHead( char *arg, const Cmd *cmd ); | |
56 static Bool doHelp( char *arg, const Cmd *cmd ); | |
57 static Bool doIhave( char *arg, const Cmd *cmd ); | |
58 static Bool doLast( char *arg, const Cmd *cmd ); | |
59 static Bool doList( char *arg, const Cmd *cmd ); | |
60 static Bool doListgrp( char *arg, const Cmd *cmd ); | |
61 static Bool doMode( char *arg, const Cmd *cmd ); | |
62 static Bool doNewgrps( char *arg, const Cmd *cmd ); | |
63 static Bool doNext( char *arg, const Cmd *cmd ); | |
64 static Bool doPost( char *arg, const Cmd *cmd ); | |
65 static Bool doSlave( char *arg, const Cmd *cmd ); | |
66 static Bool doStat( char *arg, const Cmd *cmd ); | |
67 static Bool doQuit( char *arg, const Cmd *cmd ); | |
68 static Bool doXhdr( char *arg, const Cmd *cmd ); | |
69 static Bool doXpat( char *arg, const Cmd *cmd ); | |
70 static Bool doXOver( char *arg, const Cmd *cmd ); | |
71 static Bool notImplemented( char *arg, const Cmd *cmd ); | |
72 static void putStat( unsigned int stat, const char *fmt, ... ); | |
73 | |
74 Cmd commands[] = | |
75 { | |
76 { "article", "ARTICLE [msg-id|n]", &doArt }, | |
77 { "body", "BODY [msg-id|n]", &doBody }, | |
78 { "head", "HEAD [msg-id|n]", &doHead }, | |
79 { "group", "GROUP grp", &doGrp }, | |
80 { "help", "HELP", &doHelp }, | |
81 { "ihave", "IHAVE (ignored)", &doIhave }, | |
82 { "last", "LAST", &doLast }, | |
83 { "list", "LIST [ACTIVE [pat]]|ACTIVE.TIMES [pat]|" | |
84 "EXTENSIONS|NEWSGROUPS [pat]|OVERVIEW.FMT", &doList }, | |
85 { "listgroup", "LISTGROUP grp", &doListgrp }, | |
86 { "mode", "MODE (ignored)", &doMode }, | |
87 { "newgroups", "NEWGROUPS [xx]yymmdd hhmmss [GMT]", &doNewgrps }, | |
88 { "newnews", "NEWNEWS (not implemented)", ¬Implemented }, | |
89 { "next", "NEXT", &doNext }, | |
90 { "post", "POST", &doPost }, | |
91 { "quit", "QUIT", &doQuit }, | |
92 { "slave", "SLAVE (ignored)", &doSlave }, | |
93 { "stat", "STAT [msg-id|n]", &doStat }, | |
94 { "xhdr", "XHDR over-field [m[-[n]]]", &doXhdr }, | |
95 { "xpat", "XPAT over-field m[-[n]] pat", &doXpat }, | |
96 { "xover", "XOVER [m[-[n]]]", &doXOver } | |
97 }; | |
98 | |
99 /* | |
100 Notice interest in reading this group. | |
101 Automatically subscribe if option set in config file. | |
102 */ | |
103 static void | |
104 noteInterest( void ) | |
105 { | |
106 FetchMode mode; | |
107 | |
108 Grp_setLastAccess( serv.grp, time( NULL ) ); | |
26
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
109 if ( ! Grp_local ( serv.grp ) && Cfg_autoSubscribe() && ! Online_true() ) |
0 | 110 { |
111 Fetchlist_read(); | |
112 if ( ! Fetchlist_contains( serv.grp ) ) | |
113 { | |
114 if ( strcmp( Cfg_autoSubscribeMode(), "full" ) == 0 ) | |
115 mode = FULL; | |
116 else if ( strcmp( Cfg_autoSubscribeMode(), "thread" ) == 0 ) | |
117 mode = THREAD; | |
118 else | |
119 mode = OVER; | |
120 Fetchlist_add( serv.grp, mode ); | |
121 Fetchlist_write(); | |
122 Pseudo_autoSubscribed(); | |
123 } | |
124 } | |
125 } | |
126 | |
127 static void | |
128 putStat( unsigned int stat, const char *fmt, ... ) | |
129 { | |
130 Str s, line; | |
131 va_list ap; | |
132 | |
133 ASSERT( stat <= 999 ); | |
134 va_start( ap, fmt ); | |
135 vsnprintf( s, MAXCHAR, fmt, ap ); | |
136 va_end( ap ); | |
137 snprintf( line, MAXCHAR, "%u %s", stat, s ); | |
138 Log_dbg( "[S] %s", line ); | |
139 printf( "%s\r\n", line ); | |
140 } | |
141 | |
142 static void | |
143 putTxtLn( const char *fmt, ... ) | |
144 { | |
145 Str line; | |
146 va_list ap; | |
147 | |
148 va_start( ap, fmt ); | |
149 vsnprintf( line, MAXCHAR, fmt, ap ); | |
150 va_end( ap ); | |
151 Prt_putTxtLn( line, stdout ); | |
152 } | |
153 | |
154 static void | |
155 putTxtBuf( const char *buf ) | |
156 { | |
157 if ( buf ) | |
158 Prt_putTxtBuf( buf, stdout ); | |
159 } | |
160 | |
161 static void | |
162 putEndOfTxt( void ) | |
163 { | |
164 Prt_putEndOfTxt( stdout ); | |
165 } | |
166 | |
167 static void | |
168 putSyntax( const Cmd *cmd ) | |
169 { | |
170 putStat( STAT_SYNTAX_ERR, "Syntax error. Usage: %s", cmd->syntax ); | |
171 } | |
172 | |
173 static Bool | |
174 getLn( Str line ) | |
175 { | |
176 return Prt_getLn( line, stdin ); | |
177 } | |
178 | |
179 static Bool | |
180 getTxtLn( Str line, Bool *err ) | |
181 { | |
182 return Prt_getTxtLn( line, err, stdin ); | |
183 } | |
184 | |
185 static Bool | |
186 notImplemented( char *arg, const Cmd *cmd ) | |
187 { | |
188 putStat( STAT_NO_PERMISSION, "Command not implemented" ); | |
189 return TRUE; | |
190 } | |
191 | |
192 static void | |
193 checkNewArts( const char *grp ) | |
194 { | |
195 if ( ! Online_true() | |
196 || strcmp( grp, serv.grp ) == 0 | |
197 || time( NULL ) - Grp_lastAccess( serv.grp ) < 1800 ) | |
198 return; | |
199 if ( Fetch_init( Grp_serv( grp ) ) ) | |
200 { | |
201 Fetch_getNewArts( grp, OVER ); | |
202 Fetch_close(); | |
203 } | |
204 } | |
205 | |
206 static void | |
207 postArts() | |
208 { | |
209 Str serv; | |
210 | |
211 Cfg_beginServEnum(); | |
212 while ( Cfg_nextServ( serv ) ) | |
213 if ( Fetch_init( serv ) ) | |
214 { | |
215 Fetch_postArts(); | |
216 Fetch_close(); | |
217 } | |
218 } | |
219 | |
220 static void | |
221 readCont( const char *name ) | |
222 { | |
223 Fetchlist_read(); | |
224 Cont_read( name ); | |
26
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
225 if ( ! Grp_local ( name ) |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
226 && ! Fetchlist_contains( name ) |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
227 && ! Online_true() ) |
0 | 228 { |
229 Pseudo_appGeneralInfo(); | |
230 Grp_setFirstLast( name, Cont_first(), Cont_last() ); | |
231 } | |
232 } | |
233 | |
234 static void | |
235 changeToGrp( const char *grp ) | |
236 { | |
237 checkNewArts( grp ); | |
238 Utl_cpyStr( serv.grp, grp ); | |
239 readCont( grp ); | |
240 serv.artPtr = Cont_first(); | |
241 } | |
242 | |
243 static Bool | |
244 doGrp( char *arg, const Cmd *cmd ) | |
245 { | |
246 int first, last, numb; | |
247 | |
248 if ( arg[ 0 ] == '\0' ) | |
249 putSyntax( cmd ); | |
250 else if ( ! Grp_exists( arg ) ) | |
251 putStat( STAT_NO_SUCH_GRP, "No such group" ); | |
252 else | |
253 { | |
254 changeToGrp( arg ); | |
255 first = Cont_first(); | |
256 last = Cont_last(); | |
257 numb = last - first + 1; | |
258 if ( first > last ) | |
259 first = last = numb = 0; | |
260 putStat( STAT_GRP_SELECTED, "%lu %lu %lu %s selected", | |
261 numb, first, last, arg ); | |
262 } | |
263 return TRUE; | |
264 } | |
265 | |
266 static Bool | |
267 testGrpSelected( void ) | |
268 { | |
269 if ( *serv.grp == '\0' ) | |
270 { | |
271 putStat( STAT_NO_GRP_SELECTED, "No group selected" ); | |
272 return FALSE; | |
273 } | |
274 return TRUE; | |
275 } | |
276 | |
277 static void | |
278 findServ( const char *msgId, Str result ) | |
279 { | |
280 const char *p, *pColon, *serv; | |
281 Str s, grp; | |
282 | |
283 Utl_cpyStr( result, "(unknown)" ); | |
284 if ( Db_contains( msgId ) ) | |
285 { | |
286 Utl_cpyStr( s, Db_xref( msgId ) ); | |
287 p = strtok( s, " \t" ); | |
288 if ( p ) | |
289 do | |
290 { | |
291 pColon = strstr( p, ":" ); | |
292 if ( pColon ) | |
293 { | |
294 Utl_cpyStrN( grp, p, pColon - p ); | |
295 serv = Grp_serv( grp ); | |
296 if ( Cfg_servIsPreferential( serv, result ) ) | |
297 Utl_cpyStr( result, serv ); | |
298 } | |
299 } | |
300 while ( ( p = strtok( NULL, " \t" ) ) ); | |
301 } | |
302 } | |
303 | |
304 static Bool | |
305 retrieveArt( const char *msgId ) | |
306 { | |
307 Str serv; | |
308 | |
309 findServ( msgId, serv ); | |
26
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
310 if ( strcmp( serv, "(unknown)" ) == 0 || strcmp( serv, "(local)" ) == 0 ) |
0 | 311 return FALSE; |
312 if ( ! Client_connect( serv ) ) | |
313 return FALSE; | |
314 Client_retrieveArt( msgId ); | |
315 Client_disconnect(); | |
316 return TRUE; | |
317 } | |
318 | |
319 static Bool | |
320 checkNumb( int numb ) | |
321 { | |
322 if ( ! testGrpSelected() ) | |
323 return FALSE; | |
324 if ( ! Cont_validNumb( numb ) ) | |
325 { | |
326 putStat( STAT_NO_SUCH_NUMB, "No such article" ); | |
327 return FALSE; | |
328 } | |
329 return TRUE; | |
330 } | |
331 | |
332 /* | |
333 Parse arguments for ARTICLE, BODY, HEAD, STAT commands. | |
334 Return message-ID and article number (0 if unknown). | |
335 */ | |
336 static Bool | |
337 whichId( const char **msgId, int *numb, char *arg ) | |
338 { | |
339 const Over *ov; | |
340 int n; | |
341 | |
342 if ( sscanf( arg, "%i", &n ) == 1 ) | |
343 { | |
344 if ( ! checkNumb( n ) ) | |
345 return FALSE; | |
346 serv.artPtr = n; | |
347 ov = Cont_get( n ); | |
348 *msgId = Ov_msgId( ov ); | |
349 *numb = n; | |
350 } | |
351 else if ( strcmp( arg, "" ) == 0 ) | |
352 { | |
353 if ( ! checkNumb( serv.artPtr ) ) | |
354 return FALSE; | |
355 ov = Cont_get( serv.artPtr ); | |
356 *msgId = Ov_msgId( ov ); | |
357 *numb = serv.artPtr; | |
358 } | |
359 else | |
360 { | |
361 *msgId = arg; | |
362 *numb = 0; | |
363 } | |
364 if ( ! Pseudo_isGeneralInfo( *msgId ) && ! Db_contains( *msgId ) ) | |
365 { | |
366 putStat( STAT_NO_SUCH_NUMB, "No such article" ); | |
367 return FALSE; | |
368 } | |
369 return TRUE; | |
370 } | |
371 | |
372 void | |
373 touchArticle( const char *msgId ) | |
374 { | |
375 int stat = Db_stat( msgId ); | |
376 stat |= DB_INTERESTING; | |
377 Db_setStat( msgId, stat ); | |
378 Db_updateLastAccess( msgId ); | |
379 } | |
380 | |
381 static void | |
382 touchReferences( const char *msgId ) | |
383 { | |
384 Str s; | |
385 int len; | |
386 char *p; | |
387 const char *ref = Db_ref( msgId ); | |
388 | |
389 while ( TRUE ) | |
390 { | |
391 p = s; | |
392 while ( *ref != '<' ) | |
393 if ( *(ref++) == '\0' ) | |
394 return; | |
395 len = 0; | |
396 while ( *ref != '>' ) | |
397 { | |
398 if ( *ref == '\0' || ++len >= MAXCHAR - 1 ) | |
399 return; | |
400 *(p++) = *(ref++); | |
401 } | |
402 *(p++) = '>'; | |
403 *p = '\0'; | |
404 if ( Db_contains( s ) ) | |
405 touchArticle( s ); | |
406 } | |
407 } | |
408 | |
409 static void | |
410 doBodyInDb( const char *msgId ) | |
411 { | |
412 int stat; | |
413 Str serv; | |
414 | |
415 touchArticle( msgId ); | |
416 touchReferences( msgId ); | |
417 stat = Db_stat( msgId ); | |
418 if ( Online_true() && ( stat & DB_NOT_DOWNLOADED ) ) | |
419 { | |
420 retrieveArt( msgId ); | |
421 stat = Db_stat( msgId ); | |
422 } | |
423 if ( stat & DB_RETRIEVING_FAILED ) | |
424 { | |
425 Db_setStat( msgId, stat & ~DB_RETRIEVING_FAILED ); | |
426 putTxtBuf( Db_body( msgId ) ); | |
427 } | |
428 else if ( stat & DB_NOT_DOWNLOADED ) | |
429 { | |
430 findServ( msgId, serv ); | |
431 if ( Req_contains( serv, msgId ) ) | |
432 putTxtBuf( Pseudo_alreadyMarkedBody() ); | |
26
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
433 else if ( strcmp( serv, "(unknown)" ) != 0 && |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
434 strcmp( serv, "(local)" ) != 0 && |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
435 Req_add( serv, msgId ) ) |
0 | 436 putTxtBuf( Pseudo_markedBody() ); |
437 else | |
438 putTxtBuf( Pseudo_markingFailedBody() ); | |
439 } | |
440 else | |
441 putTxtBuf( Db_body( msgId ) ); | |
442 } | |
443 | |
444 static Bool | |
445 doBody( char *arg, const Cmd *cmd ) | |
446 { | |
447 const char *msgId; | |
448 int numb; | |
449 | |
450 if ( ! whichId( &msgId, &numb, arg ) ) | |
451 return TRUE; | |
452 putStat( STAT_BODY_FOLLOWS, "%ld %s Body", numb, msgId ); | |
453 if ( Pseudo_isGeneralInfo( msgId ) ) | |
454 putTxtBuf( Pseudo_generalInfoBody() ); | |
455 else | |
456 doBodyInDb( msgId ); | |
457 putEndOfTxt(); | |
458 noteInterest(); | |
459 return TRUE; | |
460 } | |
461 | |
462 static void | |
463 doHeadInDb( const char *msgId ) | |
464 { | |
465 putTxtBuf( Db_header( msgId ) ); | |
466 } | |
467 | |
468 static Bool | |
469 doHead( char *arg, const Cmd *cmd ) | |
470 { | |
471 const char *msgId; | |
472 int numb; | |
473 | |
474 if ( ! whichId( &msgId, &numb, arg ) ) | |
475 return TRUE; | |
476 putStat( STAT_HEAD_FOLLOWS, "%ld %s Head", numb, msgId ); | |
477 if ( Pseudo_isGeneralInfo( msgId ) ) | |
478 putTxtBuf( Pseudo_generalInfoHead() ); | |
479 else | |
480 doHeadInDb( msgId ); | |
481 putEndOfTxt(); | |
482 return TRUE; | |
483 } | |
484 | |
485 static void | |
486 doArtInDb( const char *msgId ) | |
487 { | |
488 doHeadInDb( msgId ); | |
489 putTxtLn( "" ); | |
490 doBodyInDb( msgId ); | |
491 } | |
492 | |
493 static Bool | |
494 doArt( char *arg, const Cmd *cmd ) | |
495 { | |
496 const char *msgId; | |
497 int numb; | |
498 | |
499 if ( ! whichId( &msgId, &numb, arg ) ) | |
500 return TRUE; | |
501 putStat( STAT_ART_FOLLOWS, "%ld %s Article", numb, msgId ); | |
502 if ( Pseudo_isGeneralInfo( msgId ) ) | |
503 { | |
504 putTxtBuf( Pseudo_generalInfoHead() ); | |
505 putTxtLn( "" ); | |
506 putTxtBuf( Pseudo_generalInfoBody() ); | |
507 } | |
508 else | |
509 doArtInDb( msgId ); | |
510 putEndOfTxt(); | |
511 noteInterest(); | |
512 return TRUE; | |
513 } | |
514 | |
515 static Bool | |
516 doHelp( char *arg, const Cmd *cmd ) | |
517 { | |
518 unsigned int i; | |
519 | |
520 putStat( STAT_HELP_FOLLOWS, "Help" ); | |
521 putTxtBuf( "\nCommands:\n\n" ); | |
522 for ( i = 0; i < sizeof( commands ) / sizeof( commands[ 0 ] ); ++i ) | |
523 putTxtLn( "%s", commands[ i ].syntax ); | |
524 putEndOfTxt(); | |
525 return TRUE; | |
526 } | |
527 | |
528 static Bool | |
529 doIhave( char *arg, const Cmd *cmd ) | |
530 { | |
531 putStat( STAT_ART_REJECTED, "Command not used" ); | |
532 return TRUE; | |
533 } | |
534 | |
535 static Bool | |
536 doLast( char *arg, const Cmd *cmd ) | |
537 { | |
538 int n; | |
539 | |
540 if ( testGrpSelected() ) | |
541 { | |
542 n = serv.artPtr; | |
543 if ( ! Cont_validNumb( n ) ) | |
544 putStat( STAT_NO_ART_SELECTED, "No article selected" ); | |
545 else | |
546 { | |
547 while ( ! Cont_validNumb( --n ) && n >= Cont_first() ); | |
548 if ( ! Cont_validNumb( n ) ) | |
549 putStat( STAT_NO_PREV_ART, "No previous article" ); | |
550 else | |
551 { | |
552 putStat( STAT_ART_RETRIEVED, "%ld %s selected", | |
553 n, Ov_msgId( Cont_get( n ) ) ); | |
554 serv.artPtr = n; | |
555 } | |
556 } | |
557 } | |
558 return TRUE; | |
559 } | |
560 | |
561 static void | |
562 printGroups( const char *pat, void (*printProc)( Str, const char* ) ) | |
563 { | |
564 Str line; | |
565 const char *g; | |
566 FILE *f; | |
567 sig_t lastHandler; | |
568 int ret; | |
569 | |
570 putStat( STAT_GRPS_FOLLOW, "Groups" ); | |
571 fflush( stdout ); | |
572 Log_dbg( "[S FLUSH]" ); | |
573 if ( Grp_exists( pat ) ) | |
574 { | |
575 (*printProc)( line, pat ); | |
576 if ( ! Prt_putTxtLn( line, stdout ) ) | |
577 Log_err( "Writing to stdout failed." ); | |
578 } | |
579 else | |
580 { | |
581 lastHandler = signal( SIGPIPE, SIG_IGN ); | |
582 f = popen( "sort", "w" ); | |
583 if ( f == NULL ) | |
584 { | |
585 Log_err( "Cannot open pipe to 'sort'" ); | |
586 if ( Grp_firstGrp( &g ) ) | |
587 do | |
588 if ( Utl_matchPattern( g, pat ) ) | |
589 { | |
590 (*printProc)( line, g ); | |
591 if ( ! Prt_putTxtLn( line, stdout ) ) | |
592 Log_err( "Writing to stdout failed." ); | |
593 } | |
594 while ( Grp_nextGrp( &g ) ); | |
595 } | |
596 else | |
597 { | |
598 if ( Grp_firstGrp( &g ) ) | |
599 do | |
600 if ( Utl_matchPattern( g, pat ) ) | |
601 { | |
602 (*printProc)( line, g ); | |
603 if ( ! Prt_putTxtLn( line, f ) ) | |
604 { | |
605 Log_err( "Writing to 'sort' pipe failed." ); | |
606 break; | |
607 } | |
608 } | |
609 while ( Grp_nextGrp( &g ) ); | |
610 ret = pclose( f ); | |
611 if ( ret != EXIT_SUCCESS ) | |
612 Log_err( "sort command returned %i", ret ); | |
613 fflush( stdout ); | |
614 Log_dbg( "[S FLUSH]" ); | |
615 signal( SIGPIPE, lastHandler ); | |
616 } | |
617 } | |
618 putEndOfTxt(); | |
619 } | |
620 | |
621 static void | |
622 printActiveTimes( Str result, const char *grp ) | |
623 { | |
624 snprintf( result, MAXCHAR, "%s %ld", grp, Grp_created( grp ) ); | |
625 } | |
626 | |
627 static void | |
628 doListActiveTimes( const char *pat ) | |
629 { | |
630 printGroups( pat, &printActiveTimes ); | |
631 } | |
632 | |
633 static void | |
634 printActive( Str result, const char *grp ) | |
635 { | |
636 snprintf( result, MAXCHAR, "%s %i %i y", | |
637 grp, Grp_last( grp ), Grp_first( grp ) ); | |
638 } | |
639 | |
640 static void | |
641 doListActive( const char *pat ) | |
642 { | |
643 printGroups( pat, &printActive ); | |
644 } | |
645 | |
646 static void | |
647 printNewsgrp( Str result, const char *grp ) | |
648 { | |
649 snprintf( result, MAXCHAR, "%s %s", grp, Grp_dsc( grp ) ); | |
650 } | |
651 | |
652 static void | |
653 doListNewsgrps( const char *pat ) | |
654 { | |
655 printGroups( pat, &printNewsgrp ); | |
656 } | |
657 | |
658 static void | |
659 putGrp( const char *name ) | |
660 { | |
661 putTxtLn( "%s %lu %lu y", name, Grp_last( name ), Grp_first( name ) ); | |
662 } | |
663 | |
664 static void | |
665 doListOverFmt( void ) | |
666 { | |
667 putStat( STAT_GRPS_FOLLOW, "Overview format" ); | |
668 putTxtBuf( "Subject:\n" | |
669 "From:\n" | |
670 "Date:\n" | |
671 "Message-ID:\n" | |
672 "References:\n" | |
673 "Bytes:\n" | |
674 "Lines:\n" ); | |
675 putEndOfTxt(); | |
676 } | |
677 | |
678 static void | |
679 doListExtensions( void ) | |
680 { | |
681 putStat( STAT_CMD_OK, "Extensions" ); | |
682 putTxtBuf( " LISTGROUP\n" | |
683 " XOVER\n" ); | |
684 putEndOfTxt(); | |
685 } | |
686 | |
687 static Bool | |
688 doList( char *line, const Cmd *cmd ) | |
689 { | |
690 Str s, arg; | |
691 const char *pat; | |
692 | |
693 if ( sscanf( line, "%s", s ) != 1 ) | |
694 doListActive( "*" ); | |
695 else | |
696 { | |
697 Utl_toLower( s ); | |
698 strcpy( arg, Utl_restOfLn( line, 1 ) ); | |
699 pat = Utl_stripWhiteSpace( arg ); | |
700 if ( pat[ 0 ] == '\0' ) | |
701 pat = "*"; | |
702 if ( strcmp( "active", s ) == 0 ) | |
703 doListActive( pat ); | |
704 else if ( strcmp( "overview.fmt", s ) == 0 ) | |
705 doListOverFmt(); | |
706 else if ( strcmp( "newsgroups", s ) == 0 ) | |
707 doListNewsgrps( pat ); | |
708 else if ( strcmp( "active.times", s ) == 0 ) | |
709 doListActiveTimes( pat ); | |
710 else if ( strcmp( "extensions", s ) == 0 ) | |
711 doListExtensions(); | |
712 else | |
713 putSyntax( cmd ); | |
714 } | |
715 return TRUE; | |
716 } | |
717 | |
718 static Bool | |
719 doListgrp( char *arg, const Cmd *cmd ) | |
720 { | |
721 const Over *ov; | |
722 int first, last, i; | |
723 | |
724 if ( ! Grp_exists( arg ) ) | |
725 putStat( STAT_NO_SUCH_GRP, "No such group" ); | |
726 else | |
727 { | |
728 changeToGrp( arg ); | |
729 first = Cont_first(); | |
730 last = Cont_last(); | |
731 putStat( STAT_GRP_SELECTED, "Article list" ); | |
732 for ( i = first; i <= last; ++i ) | |
733 if ( ( ov = Cont_get( i ) ) ) | |
734 putTxtLn( "%lu", i ); | |
735 putEndOfTxt(); | |
736 } | |
737 return TRUE; | |
738 } | |
739 | |
740 static Bool | |
741 doMode( char *arg, const Cmd *cmd ) | |
742 { | |
743 putStat( STAT_READY_POST_ALLOW, "Ok" ); | |
744 return TRUE; | |
745 } | |
746 | |
747 static unsigned long | |
748 getTimeInSeconds( unsigned int year, unsigned int mon, unsigned int day, | |
749 unsigned int hour, unsigned int min, unsigned int sec ) | |
750 { | |
751 struct tm t = { 0 }; | |
752 | |
753 t.tm_year = year - 1900; | |
754 t.tm_mon = mon - 1; | |
755 t.tm_mday = day; | |
756 t.tm_hour = hour; | |
757 t.tm_min = min; | |
758 t.tm_sec = sec; | |
759 return mktime( &t ); | |
760 } | |
761 | |
762 | |
763 static Bool | |
764 doNewgrps( char *arg, const Cmd *cmd ) | |
765 { | |
766 time_t t, now, lastUpdate; | |
767 unsigned int year, mon, day, hour, min, sec, cent, len; | |
768 const char *g; | |
769 Str date, timeofday, file; | |
770 | |
771 if ( sscanf( arg, "%s %s", date, timeofday ) != 2 ) | |
772 { | |
773 putSyntax( cmd ); | |
774 return TRUE; | |
775 } | |
776 len = strlen( date ); | |
777 switch ( len ) | |
778 { | |
779 case 6: | |
780 if ( sscanf( date, "%2u%2u%2u", &year, &mon, &day ) != 3 ) | |
781 { | |
782 putSyntax( cmd ); | |
783 return TRUE; | |
784 } | |
785 now = time( NULL ); | |
786 cent = 1900; | |
787 while ( now > getTimeInSeconds( cent + 100, 1, 1, 0, 0, 0 ) ) | |
788 cent += 100; | |
789 year += cent; | |
790 break; | |
791 case 8: | |
792 if ( sscanf( date, "%4u%2u%2u", &year, &mon, &day ) != 3 ) | |
793 { | |
794 putSyntax( cmd ); | |
795 return TRUE; | |
796 } | |
797 break; | |
798 default: | |
799 putSyntax( cmd ); | |
800 return TRUE; | |
801 } | |
802 if ( sscanf( timeofday, "%2u%2u%2u", &hour, &min, &sec ) != 3 ) | |
803 { | |
804 putSyntax( cmd ); | |
805 return TRUE; | |
806 } | |
807 if ( year < 1970 || mon == 0 || mon > 12 || day == 0 || day > 31 | |
808 || hour > 23 || min > 59 || sec > 60 ) | |
809 { | |
810 putSyntax( cmd ); | |
811 return TRUE; | |
812 } | |
813 snprintf( file, MAXCHAR, "%s/groupinfo.lastupdate", Cfg_spoolDir() ); | |
814 t = getTimeInSeconds( year, mon, day, hour, min, sec ); | |
815 putStat( STAT_NEW_GRP_FOLLOW, "New groups since %s", arg ); | |
816 | |
817 if ( ! Utl_getStamp( &lastUpdate, file ) || t <= lastUpdate ) | |
818 { | |
819 if ( Grp_firstGrp( &g ) ) | |
820 do | |
821 if ( Grp_created( g ) > t ) | |
822 putGrp( g ); | |
823 while ( Grp_nextGrp( &g ) ); | |
824 } | |
825 putEndOfTxt(); | |
826 return TRUE; | |
827 } | |
828 | |
829 static Bool | |
830 doNext( char *arg, const Cmd *cmd ) | |
831 { | |
832 int n; | |
833 | |
834 if ( testGrpSelected() ) | |
835 { | |
836 n = serv.artPtr; | |
837 if ( ! Cont_validNumb( n ) ) | |
838 putStat( STAT_NO_ART_SELECTED, "No article selected" ); | |
839 else | |
840 { | |
841 while ( ! Cont_validNumb( ++n ) && n <= Cont_last() ); | |
842 if ( ! Cont_validNumb( n ) ) | |
843 putStat( STAT_NO_NEXT_ART, "No next article" ); | |
844 else | |
845 { | |
846 putStat( STAT_ART_RETRIEVED, "%ld %s selected", | |
847 n, Ov_msgId( Cont_get( n ) ) ); | |
848 serv.artPtr = n; | |
849 } | |
850 } | |
851 } | |
852 return TRUE; | |
853 } | |
854 | |
26
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
855 /* Cancel and return TRUE if need to send cancel message on to server. */ |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
856 static Bool |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
857 controlCancel( const char *cancelId ) |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
858 { |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
859 return ( Ctrl_cancel( cancelId ) == CANCEL_NEEDS_MSG ); |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
860 } |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
861 |
0 | 862 /* |
26
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
863 It's a control message. Currently we only know about 'cancel' |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
864 messages; others are passed on for outside groups, and logged |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
865 as ignored for local groups. |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
866 */ |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
867 static Bool |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
868 handleControl( ItemList *control, ItemList *newsgroups, |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
869 const char *msgId, const DynStr *art ) |
0 | 870 { |
26
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
871 const char *grp; |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
872 const char *op; |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
873 Bool err = FALSE; |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
874 Bool localDone = FALSE; |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
875 |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
876 op = Itl_first( control ); |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
877 if ( op == NULL ) |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
878 { |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
879 Log_err( "Malformed control line." ); |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
880 return TRUE; |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
881 } |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
882 else if ( strcasecmp( op, "cancel" ) == 0 ) |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
883 { |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
884 if ( controlCancel( Itl_next( control ) ) ) |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
885 localDone = TRUE; |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
886 else |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
887 return err; |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
888 } |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
889 |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
890 /* Pass on for outside groups. */ |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
891 for( grp = Itl_first( newsgroups ); |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
892 grp != NULL; |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
893 grp = Itl_next( newsgroups ) ) |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
894 { |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
895 if ( Grp_exists( grp ) && ! Grp_local( grp ) ) |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
896 { |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
897 if ( ! Out_add( Grp_serv( grp ), msgId, art ) ) |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
898 { |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
899 Log_err( "Cannot add posted article to outgoing directory" ); |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
900 err = TRUE; |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
901 } |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
902 break; |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
903 } |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
904 } |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
905 |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
906 if ( localDone ) |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
907 return err; |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
908 |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
909 /* Log 'can't do' for internal groups. */ |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
910 for( grp = Itl_first( newsgroups ); |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
911 grp != NULL; |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
912 grp = Itl_next( newsgroups ) ) |
0 | 913 { |
26
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
914 if ( Grp_exists( grp ) && Grp_local( grp ) ) |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
915 Log_inf( "Ignoring control '%s' for '%s'.", op, grp ); |
0 | 916 } |
26
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
917 |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
918 return err; |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
919 } |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
920 |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
921 static Bool |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
922 postArticle( ItemList *newsgroups, const char *msgId, const DynStr *art ) |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
923 { |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
924 const char *grp; |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
925 Bool err; |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
926 Bool oneLocal; |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
927 |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
928 err = oneLocal = FALSE; |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
929 |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
930 /* Run round first doing all local groups. */ |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
931 for( grp = Itl_first( newsgroups ); |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
932 grp != NULL; |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
933 grp = Itl_next( newsgroups ) ) |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
934 { |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
935 if ( Grp_local( grp ) ) |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
936 { |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
937 if ( ! oneLocal ) |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
938 { |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
939 if ( ! Post_open( DynStr_str( art ) ) ) |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
940 { |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
941 err = TRUE; |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
942 break; |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
943 } |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
944 else |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
945 oneLocal = TRUE; |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
946 } |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
947 |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
948 if ( ! Post_add( grp ) ) |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
949 err = TRUE; |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
950 } |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
951 } |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
952 if ( oneLocal ) |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
953 Post_close(); |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
954 |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
955 /* Now look for a valid external group. */ |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
956 for( grp = Itl_first( newsgroups ); |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
957 grp != NULL; |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
958 grp = Itl_next( newsgroups ) ) |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
959 { |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
960 if ( Grp_exists( grp ) && ! Grp_local( grp ) ) |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
961 { |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
962 if ( ! Out_add( Grp_serv( grp ), msgId, art ) ) |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
963 { |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
964 Log_err( "Cannot add posted article to outgoing directory" ); |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
965 err = TRUE; |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
966 } |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
967 break; |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
968 } |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
969 } |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
970 |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
971 return err; |
0 | 972 } |
973 | |
974 static Bool | |
975 doPost( char *arg, const Cmd *cmd ) | |
976 { | |
26
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
977 Bool err, replyToFound, dateFound, inHeader; |
0 | 978 DynStr *s; |
26
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
979 Str line, field, val, msgId, from; |
0 | 980 const char* p; |
26
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
981 ItemList * newsgroups, *control; |
0 | 982 |
983 /* | |
984 Get article and make following changes to the header: | |
985 - add/replace/cut Message-ID depending on config options | |
986 - add Reply-To with content of From, if missing | |
987 (some providers overwrite From field) | |
988 - rename X-Sender header to X-NOFFLE-X-Sender | |
989 (some providers want to insert their own X-Sender) | |
12
43631b72021f
[svn] Fixed bug: multiple line headers of posted articles were truncated
enz
parents:
0
diff
changeset
|
990 |
43631b72021f
[svn] Fixed bug: multiple line headers of posted articles were truncated
enz
parents:
0
diff
changeset
|
991 For doing this, it is not necessary to parse multiple-line |
43631b72021f
[svn] Fixed bug: multiple line headers of posted articles were truncated
enz
parents:
0
diff
changeset
|
992 headers. |
0 | 993 */ |
994 putStat( STAT_SEND_ART, "Continue (end with period)" ); | |
995 fflush( stdout ); | |
996 Log_dbg( "[S FLUSH]" ); | |
997 s = new_DynStr( 10000 ); | |
998 msgId[ 0 ] = '\0'; | |
999 from[ 0 ] = '\0'; | |
26
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
1000 newsgroups = control = NULL; |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
1001 replyToFound = dateFound = FALSE; |
0 | 1002 inHeader = TRUE; |
1003 while ( getTxtLn( line, &err ) ) | |
1004 { | |
1005 if ( inHeader ) | |
1006 { | |
1007 p = Utl_stripWhiteSpace( line ); | |
1008 if ( *p == '\0' ) | |
1009 { | |
1010 inHeader = FALSE; | |
1011 if ( from[ 0 ] == '\0' ) | |
1012 Log_err( "Posted message has no From field" ); | |
1013 if ( ! Cfg_removeMsgId() ) | |
1014 { | |
1015 if ( Cfg_replaceMsgId() ) | |
1016 { | |
1017 Prt_genMsgId( msgId, from, "NOFFLE" ); | |
1018 Log_dbg( "Replacing Message-ID with '%s'", msgId ); | |
1019 } | |
1020 else if ( msgId[ 0 ] == '\0' ) | |
1021 { | |
1022 Prt_genMsgId( msgId, from, "NOFFLE" ); | |
26
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
1023 |
0 | 1024 Log_inf( "Adding missing Message-ID '%s'", msgId ); |
1025 } | |
1026 else if ( ! Prt_isValidMsgId( msgId ) ) | |
1027 { | |
1028 Log_ntc( "Replacing invalid Message-ID with '%s'", | |
1029 msgId ); | |
1030 Prt_genMsgId( msgId, from, "NOFFLE" ); | |
1031 } | |
1032 DynStr_app( s, "Message-ID: " ); | |
1033 DynStr_appLn( s, msgId ); | |
1034 } | |
1035 if ( ! replyToFound && from[ 0 ] != '\0' ) | |
1036 { | |
1037 Log_dbg( "Adding Reply-To field to posted message." ); | |
1038 DynStr_app( s, "Reply-To: " ); | |
1039 DynStr_appLn( s, from ); | |
1040 } | |
26
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
1041 if ( ! dateFound ) |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
1042 { |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
1043 time_t t; |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
1044 |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
1045 time( &t ); |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
1046 strftime( val, MAXCHAR, "%d %b %Y %H:%M:%S %Z", |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
1047 localtime( &t ) ); |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
1048 DynStr_app( s, "Date: " ); |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
1049 DynStr_appLn( s, val ); |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
1050 } |
0 | 1051 DynStr_appLn( s, p ); |
1052 } | |
1053 else if ( Prt_getField( field, val, p ) ) | |
1054 { | |
1055 if ( strcmp( field, "message-id" ) == 0 ) | |
1056 strcpy( msgId, val ); | |
1057 else if ( strcmp( field, "from" ) == 0 ) | |
1058 { | |
1059 strcpy( from, val ); | |
1060 DynStr_appLn( s, p ); | |
1061 } | |
1062 else if ( strcmp( field, "newsgroups" ) == 0 ) | |
1063 { | |
26
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
1064 Utl_toLower( val ); |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
1065 newsgroups = new_Itl ( val, " ," ); |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
1066 DynStr_appLn( s, p ); |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
1067 } |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
1068 else if ( strcmp( field, "control" ) == 0 ) |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
1069 { |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
1070 control = new_Itl ( val, " " ); |
0 | 1071 DynStr_appLn( s, p ); |
1072 } | |
1073 else if ( strcmp( field, "reply-to" ) == 0 ) | |
1074 { | |
1075 replyToFound = TRUE; | |
1076 DynStr_appLn( s, p ); | |
1077 } | |
26
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
1078 else if ( strcmp( field, "date" ) == 0 ) |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
1079 { |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
1080 dateFound = TRUE; |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
1081 DynStr_appLn( s, p ); |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
1082 } |
0 | 1083 else if ( strcmp( field, "x-sender" ) == 0 ) |
1084 { | |
1085 DynStr_app( s, "X-NOFFLE-X-Sender: " ); | |
1086 DynStr_appLn( s, val ); | |
1087 } | |
1088 else | |
1089 DynStr_appLn( s, p ); | |
1090 } | |
1091 else | |
12
43631b72021f
[svn] Fixed bug: multiple line headers of posted articles were truncated
enz
parents:
0
diff
changeset
|
1092 DynStr_appLn( s, line ); |
0 | 1093 } |
1094 else | |
1095 DynStr_appLn( s, line ); | |
1096 } | |
1097 if ( inHeader ) | |
1098 Log_err( "Posted message has no body" ); | |
1099 if ( ! err ) | |
1100 { | |
26
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
1101 if ( newsgroups == NULL || Itl_count( newsgroups ) == 0 ) |
0 | 1102 { |
26
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
1103 Log_err( "Posted message has no valid Newsgroups header field" ); |
0 | 1104 err = TRUE; |
1105 } | |
26
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
1106 else |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
1107 { |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
1108 const char *grp; |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
1109 Bool knownGrp = FALSE; |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
1110 |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
1111 /* Check at least one group is known. */ |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
1112 for( grp = Itl_first( newsgroups ); |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
1113 grp != NULL; |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
1114 grp = Itl_next( newsgroups ) ) |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
1115 { |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
1116 if ( Grp_exists( grp ) ) |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
1117 { |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
1118 knownGrp = TRUE; |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
1119 break; |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
1120 } |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
1121 } |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
1122 |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
1123 if ( ! knownGrp ) |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
1124 { |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
1125 |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
1126 Log_err( "No known group in Newsgroups header field" ); |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
1127 err = TRUE; |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
1128 } |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
1129 else |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
1130 { |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
1131 err = ( control == NULL ) |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
1132 ? postArticle( newsgroups, msgId, s ) |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
1133 : handleControl( control, newsgroups, msgId, s ); |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
1134 } |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
1135 } |
0 | 1136 } |
1137 if ( err ) | |
1138 putStat( STAT_POST_FAILED, "Posting failed" ); | |
1139 else | |
1140 { | |
37
792eb10e936d
[svn] Change returned status info for STAT_POST_OK, because\n"Message queued for posting" is no longer meaningful for local groups.
enz
parents:
26
diff
changeset
|
1141 putStat( STAT_POST_OK, "Message posted" ); |
0 | 1142 if ( Online_true() ) |
1143 postArts(); | |
1144 } | |
26
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
1145 del_Itl( newsgroups ); |
526a4c34ee2e
[svn] Applied patch from Jim Hague: support for local groups / new command
enz
parents:
12
diff
changeset
|
1146 del_Itl( control ); |
0 | 1147 del_DynStr( s ); |
1148 return TRUE; | |
1149 } | |
1150 | |
1151 static void | |
1152 parseRange( const char *s, int *first, int *last, int *numb ) | |
1153 { | |
1154 int r, i; | |
1155 char* p; | |
1156 Str t; | |
1157 | |
1158 Utl_cpyStr( t, s ); | |
1159 p = Utl_stripWhiteSpace( t ); | |
1160 r = sscanf( p, "%i-%i", first, last ); | |
1161 if ( r < 1 ) | |
1162 { | |
1163 *first = serv.artPtr; | |
1164 *last = serv.artPtr; | |
1165 } | |
1166 else if ( r == 1 ) | |
1167 { | |
1168 if ( p[ strlen( p ) - 1 ] == '-' ) | |
1169 *last = Cont_last(); | |
1170 else | |
1171 *last = *first; | |
1172 } | |
1173 if ( *first < Cont_first() ) | |
1174 *first = Cont_first(); | |
1175 if ( *last > Cont_last() ) | |
1176 *last = Cont_last(); | |
1177 if ( *first > Cont_last() || *last < Cont_first() ) | |
1178 *last = *first - 1; | |
1179 *numb = 0; | |
1180 for ( i = *first; i <= *last; ++i ) | |
1181 if ( Cont_validNumb( i ) ) | |
1182 ++(*numb); | |
1183 } | |
1184 | |
1185 static Bool | |
1186 doXhdr( char *arg, const Cmd *cmd ) | |
1187 { | |
1188 int first, last, i, n, numb; | |
1189 enum { SUBJ, FROM, DATE, MSG_ID, REF, BYTES, LINES } what; | |
1190 const char *p; | |
1191 const Over *ov; | |
1192 Str whatStr; | |
1193 | |
1194 if ( ! testGrpSelected() ) | |
1195 return TRUE; | |
1196 if ( sscanf( arg, "%s", whatStr ) != 1 ) | |
1197 { | |
1198 putSyntax( cmd ); | |
1199 return TRUE; | |
1200 } | |
1201 Utl_toLower( whatStr ); | |
1202 if ( strcmp( whatStr, "subject" ) == 0 ) | |
1203 what = SUBJ; | |
1204 else if ( strcmp( whatStr, "from" ) == 0 ) | |
1205 what = FROM; | |
1206 else if ( strcmp( whatStr, "date" ) == 0 ) | |
1207 what = DATE; | |
1208 else if ( strcmp( whatStr, "message-id" ) == 0 ) | |
1209 what = MSG_ID; | |
1210 else if ( strcmp( whatStr, "references" ) == 0 ) | |
1211 what = REF; | |
1212 else if ( strcmp( whatStr, "bytes" ) == 0 ) | |
1213 what = BYTES; | |
1214 else if ( strcmp( whatStr, "lines" ) == 0 ) | |
1215 what = LINES; | |
1216 else | |
1217 { | |
1218 putStat( STAT_HEAD_FOLLOWS, "Unknown header (empty list follows)" ); | |
1219 putEndOfTxt(); | |
1220 return TRUE; | |
1221 } | |
1222 p = Utl_restOfLn( arg, 1 ); | |
1223 parseRange( p, &first, &last, &numb ); | |
1224 if ( numb == 0 ) | |
1225 putStat( STAT_NO_ART_SELECTED, "No articles selected" ); | |
1226 else | |
1227 { | |
1228 putStat( STAT_HEAD_FOLLOWS, "%s header %lu-%lu", | |
1229 whatStr, first, last ) ; | |
1230 for ( i = first; i <= last; ++i ) | |
1231 if ( ( ov = Cont_get( i ) ) ) | |
1232 { | |
1233 n = Ov_numb( ov ); | |
1234 switch ( what ) | |
1235 { | |
1236 case SUBJ: | |
1237 putTxtLn( "%lu %s", n, Ov_subj( ov ) ); | |
1238 break; | |
1239 case FROM: | |
1240 putTxtLn( "%lu %s", n, Ov_from( ov ) ); | |
1241 break; | |
1242 case DATE: | |
1243 putTxtLn( "%lu %s", n, Ov_date( ov ) ); | |
1244 break; | |
1245 case MSG_ID: | |
1246 putTxtLn( "%lu %s", n, Ov_msgId( ov ) ); | |
1247 break; | |
1248 case REF: | |
1249 putTxtLn( "%lu %s", n, Ov_ref( ov ) ); | |
1250 break; | |
1251 case BYTES: | |
1252 putTxtLn( "%lu %d", n, Ov_bytes( ov ) ); | |
1253 break; | |
1254 case LINES: | |
1255 putTxtLn( "%lu %d", n, Ov_lines( ov ) ); | |
1256 break; | |
1257 default: | |
1258 ASSERT( FALSE ); | |
1259 } | |
1260 } | |
1261 putEndOfTxt(); | |
1262 } | |
1263 return TRUE; | |
1264 } | |
1265 | |
1266 static Bool | |
1267 doXpat( char *arg, const Cmd *cmd ) | |
1268 { | |
1269 int first, last, i, n; | |
1270 enum { SUBJ, FROM, DATE, MSG_ID, REF } what; | |
1271 const Over *ov; | |
1272 Str whatStr, pat; | |
1273 | |
1274 if ( ! testGrpSelected() ) | |
1275 return TRUE; | |
1276 if ( sscanf( arg, "%s %i-%i %s", whatStr, &first, &last, pat ) != 4 ) | |
1277 { | |
1278 if ( sscanf( arg, "%s %i- %s", whatStr, &first, pat ) == 3 ) | |
1279 last = Cont_last(); | |
1280 else if ( sscanf( arg, "%s %i %s", whatStr, &first, pat ) == 3 ) | |
1281 last = first; | |
1282 else | |
1283 { | |
1284 putSyntax( cmd ); | |
1285 return TRUE; | |
1286 } | |
1287 } | |
1288 Utl_toLower( whatStr ); | |
1289 if ( strcmp( whatStr, "subject" ) == 0 ) | |
1290 what = SUBJ; | |
1291 else if ( strcmp( whatStr, "from" ) == 0 ) | |
1292 what = FROM; | |
1293 else if ( strcmp( whatStr, "date" ) == 0 ) | |
1294 what = DATE; | |
1295 else if ( strcmp( whatStr, "message-id" ) == 0 ) | |
1296 what = MSG_ID; | |
1297 else if ( strcmp( whatStr, "references" ) == 0 ) | |
1298 what = REF; | |
1299 else | |
1300 { | |
1301 putStat( STAT_HEAD_FOLLOWS, "invalid header (empty list follows)" ); | |
1302 putEndOfTxt(); | |
1303 return TRUE; | |
1304 } | |
1305 putStat( STAT_HEAD_FOLLOWS, "header" ) ; | |
1306 for ( i = first; i <= last; ++i ) | |
1307 if ( ( ov = Cont_get( i ) ) ) | |
1308 { | |
1309 n = Ov_numb( ov ); | |
1310 switch ( what ) | |
1311 { | |
1312 case SUBJ: | |
1313 if ( Utl_matchPattern( Ov_subj( ov ), pat ) ) | |
1314 putTxtLn( "%lu %s", n, Ov_subj( ov ) ); | |
1315 break; | |
1316 case FROM: | |
1317 if ( Utl_matchPattern( Ov_from( ov ), pat ) ) | |
1318 putTxtLn( "%lu %s", n, Ov_from( ov ) ); | |
1319 break; | |
1320 case DATE: | |
1321 if ( Utl_matchPattern( Ov_date( ov ), pat ) ) | |
1322 putTxtLn( "%lu %s", n, Ov_date( ov ) ); | |
1323 break; | |
1324 case MSG_ID: | |
1325 if ( Utl_matchPattern( Ov_msgId( ov ), pat ) ) | |
1326 putTxtLn( "%lu %s", n, Ov_msgId( ov ) ); | |
1327 break; | |
1328 case REF: | |
1329 if ( Utl_matchPattern( Ov_ref( ov ), pat ) ) | |
1330 putTxtLn( "%lu %s", n, Ov_ref( ov ) ); | |
1331 break; | |
1332 default: | |
1333 ASSERT( FALSE ); | |
1334 } | |
1335 } | |
1336 putEndOfTxt(); | |
1337 return TRUE; | |
1338 } | |
1339 | |
1340 static Bool | |
1341 doSlave( char *arg, const Cmd *cmd ) | |
1342 { | |
1343 putStat( STAT_CMD_OK, "Ok" ); | |
1344 return TRUE; | |
1345 } | |
1346 | |
1347 static Bool | |
1348 doStat( char *arg, const Cmd *cmd ) | |
1349 { | |
1350 const char *msgId; | |
1351 int numb; | |
1352 | |
1353 if ( ! whichId( &msgId, &numb, arg ) ) | |
1354 return TRUE; | |
1355 if ( numb > 0 ) | |
1356 putStat( STAT_ART_RETRIEVED, "%ld %s selected", | |
1357 numb, msgId ); | |
1358 else | |
1359 putStat( STAT_ART_RETRIEVED, "0 %s selected", msgId ); | |
1360 return TRUE; | |
1361 } | |
1362 | |
1363 static Bool | |
1364 doQuit( char *arg, const Cmd *cmd ) | |
1365 { | |
1366 putStat( STAT_GOODBYE, "Goodbye" ); | |
1367 return FALSE; | |
1368 } | |
1369 | |
1370 static Bool | |
1371 doXOver( char *arg, const Cmd *cmd ) | |
1372 { | |
1373 int first, last, i, n; | |
1374 const Over *ov; | |
1375 | |
1376 if ( ! testGrpSelected() ) | |
1377 return TRUE; | |
1378 parseRange( arg, &first, &last, &n ); | |
1379 if ( n == 0 ) | |
1380 putStat( STAT_NO_ART_SELECTED, "No articles selected" ); | |
1381 else | |
1382 { | |
1383 putStat( STAT_OVERS_FOLLOW, "Overview %ld-%ld", first, last ); | |
1384 for ( i = first; i <= last; ++i ) | |
1385 if ( ( ov = Cont_get( i ) ) ) | |
1386 putTxtLn( "%lu\t%s\t%s\t%s\t%s\t%s\t%d\t%d\t", | |
1387 Ov_numb( ov ), Ov_subj( ov ), Ov_from( ov ), | |
1388 Ov_date( ov ), Ov_msgId( ov ), Ov_ref( ov ), | |
1389 Ov_bytes( ov ), Ov_lines( ov ) ); | |
1390 putEndOfTxt(); | |
1391 } | |
1392 return TRUE; | |
1393 } | |
1394 | |
1395 static void | |
1396 putFatal( const char *fmt, ... ) | |
1397 { | |
1398 va_list ap; | |
1399 Str s; | |
1400 | |
1401 va_start( ap, fmt ); | |
1402 vsnprintf( s, MAXCHAR, fmt, ap ); | |
1403 va_end( ap ); | |
1404 Log_err( s ); | |
1405 putStat( STAT_PROGRAM_FAULT, "%s", s ); | |
1406 fflush( stdout ); | |
1407 Log_dbg( "[S FLUSH]" ); | |
1408 } | |
1409 | |
1410 /* Parse line, execute command and return FALSE, if it was the quit command. */ | |
1411 static Bool | |
1412 parseAndExecute( Str line ) | |
1413 { | |
1414 unsigned int i, n; | |
1415 Cmd *c; | |
1416 Str s, arg; | |
1417 Bool ret; | |
1418 | |
1419 if ( sscanf( line, "%s", s ) == 1 ) | |
1420 { | |
1421 Utl_toLower( s ); | |
1422 strcpy( arg, Utl_restOfLn( line, 1 ) ); | |
1423 n = sizeof( commands ) / sizeof( commands[ 0 ] ); | |
1424 for ( i = 0, c = commands; i < n; ++i, ++c ) | |
1425 if ( strcmp( c->name, s ) == 0 ) | |
1426 { | |
1427 ret = c->cmdProc( Utl_stripWhiteSpace( arg ), c ); | |
1428 fflush( stdout ); | |
1429 Log_dbg( "[S FLUSH]" ); | |
1430 return ret; | |
1431 } | |
1432 } | |
1433 putStat( STAT_NO_SUCH_CMD, "Command not recognized" ); | |
1434 fflush( stdout ); | |
1435 Log_dbg( "[S FLUSH]" ); | |
1436 return TRUE; | |
1437 } | |
1438 | |
1439 static void | |
1440 putWelcome( void ) | |
1441 { | |
1442 putStat( STAT_READY_POST_ALLOW, "NNTP server NOFFLE %s", | |
1443 Cfg_version() ); | |
1444 fflush( stdout ); | |
1445 Log_dbg( "[S FLUSH]" ); | |
1446 } | |
1447 | |
1448 static Bool | |
1449 initServ( void ) | |
1450 { | |
1451 ASSERT( ! serv.running ); | |
1452 if ( ! Lock_openDatabases() ) | |
1453 return FALSE; | |
1454 serv.running = TRUE; | |
1455 return TRUE; | |
1456 } | |
1457 | |
1458 static void | |
1459 closeServ( void ) | |
1460 { | |
1461 ASSERT( serv.running ); | |
1462 serv.running = FALSE; | |
1463 Lock_closeDatabases(); | |
1464 } | |
1465 | |
1466 void | |
1467 Serv_run( void ) | |
1468 { | |
1469 Bool done; | |
1470 int r; | |
1471 Str line; | |
1472 struct timeval timeOut; | |
1473 fd_set readSet; | |
1474 | |
1475 putWelcome(); | |
1476 done = FALSE; | |
1477 while ( ! done ) | |
1478 { | |
1479 FD_ZERO( &readSet ); | |
1480 FD_SET( STDIN_FILENO, &readSet ); | |
1481 /* Never hold lock more than 5 seconds (empirically good value, | |
1482 avoids to close/open databases, if clients sends several | |
1483 commands, but releases the lock often enough, for allowing | |
1484 multiple persons to read news at the same time) */ | |
1485 timeOut.tv_sec = 5; | |
1486 timeOut.tv_usec = 0; | |
1487 r = select( STDIN_FILENO + 1, &readSet, NULL, NULL, &timeOut ); | |
1488 if ( r < 0 ) | |
1489 done = TRUE; | |
1490 else if ( r == 0 ) | |
1491 { | |
1492 if ( serv.running ) | |
1493 closeServ(); | |
1494 } | |
1495 else /* ( r > 0 ) */ | |
1496 { | |
1497 if ( ! serv.running ) | |
1498 { | |
1499 if ( ! initServ() ) | |
1500 { | |
1501 putFatal( "Cannot init server" ); | |
1502 done = TRUE; | |
1503 } | |
1504 } | |
1505 if ( ! getLn( line ) ) | |
1506 { | |
1507 Log_inf( "Client disconnected. Terminating." ); | |
1508 done = TRUE; | |
1509 } | |
1510 else if ( ! parseAndExecute( line ) ) | |
1511 done = TRUE; | |
1512 } | |
1513 } | |
1514 if ( serv.running ) | |
1515 closeServ(); | |
1516 } |