comparison src/post.c @ 150:1c7303c71f66 noffle

[svn] * src/protocol.c: Fix bug in Prt_getLn if we should read a line starting with '\0' - according to the leafnode mailing list, this has been seen in the wild. * docs/inews.1,docs/noffle.1,docs/noffle.conf.5, packages/redhat/noffle.spec,src/configfile.h,src/configfile.c, src/noffle.c,src/post.h,src/post.c: Removed use of getopt_long, and added inews mode - the Noffle executable behaves as inews is invoked as inews. This includes adding From: and Organization: headers if necessary - add configs to override defaults for the From: domain and specify the organization. For all my fellow trn-heads out there, and users of any other ageing newsreader that expects inews. Updated RPM spec to create inews link to noffle on install.
author bears
date Thu, 26 Oct 2000 22:21:13 +0100
parents 55ba957023f9
children ca9769519c96
comparison
equal deleted inserted replaced
149:bfeea2bc09b6 150:1c7303c71f66
1 /* 1 /*
2 post.c 2 post.c
3 3
4 $Id: post.c 202 2000-08-23 09:52:25Z enz $ 4 $Id: post.c 227 2000-10-26 21:21:13Z bears $
5 */ 5 */
6 6
7 #if HAVE_CONFIG_H 7 #if HAVE_CONFIG_H
8 #include <config.h> 8 #include <config.h>
9 #endif 9 #endif
10 10
11 #include <errno.h>
12 #include <pwd.h>
11 #include <stdio.h> 13 #include <stdio.h>
14 #include <sys/types.h>
15 #include <unistd.h>
12 #include "post.h" 16 #include "post.h"
13 #include <string.h> 17 #include <string.h>
14 #include "common.h" 18 #include "common.h"
15 #include "configfile.h" 19 #include "configfile.h"
16 #include "content.h" 20 #include "content.h"
23 #include "over.h" 27 #include "over.h"
24 #include "protocol.h" 28 #include "protocol.h"
25 #include "util.h" 29 #include "util.h"
26 #include "portable.h" 30 #include "portable.h"
27 31
32 #define BEGIN_SIG "-- "
33 #define SIG_FILE "/.signature"
34
28 struct OverInfo 35 struct OverInfo
29 { 36 {
30 Str subject; 37 Str subject;
31 Str from; 38 Str from;
32 Str date; 39 Str date;
41 DynStr *text; /* Processed article text */ 48 DynStr *text; /* Processed article text */
42 ItemList *newsgroups; /* Newsgroups for dispatch */ 49 ItemList *newsgroups; /* Newsgroups for dispatch */
43 ItemList *control; /* Control message? NULL if not */ 50 ItemList *control; /* Control message? NULL if not */
44 Bool approved; /* Has Approved: header? */ 51 Bool approved; /* Has Approved: header? */
45 Bool posted; /* Has it been put in the article database? */ 52 Bool posted; /* Has it been put in the article database? */
53 int flags; /* Posting flags */
46 struct OverInfo over; 54 struct OverInfo over;
47 }; 55 };
48 56
49 static struct Article article = { NULL, NULL, NULL, FALSE, FALSE, 57 static struct Article article = { NULL, NULL, NULL, FALSE, FALSE, 0,
50 { "", "", "", "", "", 0, 0 } }; 58 { "", "", "", "", "", 0, 0 } };
51 59
52 /* Add the article to a group. */ 60 /* Add the article to a group. */
53 static Bool 61 static Bool
54 addToGroup( const char * grp ) 62 addToGroup( const char * grp )
161 static Bool 169 static Bool
162 getArticleText( const char *p ) 170 getArticleText( const char *p )
163 { 171 {
164 DynStr * s; 172 DynStr * s;
165 Str line, field, value; 173 Str line, field, value;
166 Bool replyToFound, pathFound; 174 Bool replyToFound, pathFound, orgFound;
167 time_t t; 175 time_t t;
176 int sigLines;
168 177
169 s = new_DynStr( 10000 ); 178 s = new_DynStr( 10000 );
170 article.text = s; 179 article.text = s;
171 180
172 memset( &article.over, 0, sizeof( article.over ) ); 181 memset( &article.over, 0, sizeof( article.over ) );
173 replyToFound = pathFound = FALSE; 182 replyToFound = pathFound = orgFound = FALSE;
174 183
175 /* Grab header lines first, getting overview info as we go. */ 184 /* Grab header lines first, getting overview info as we go. */
176 while ( ( p = Utl_getHeaderLn( line, p ) ) != NULL 185 while ( ( p = Utl_getHeaderLn( line, p ) ) != NULL
177 && line[ 0 ] != '\0' 186 && line[ 0 ] != '\0'
178 && Prt_getField( field, value, line ) ) 187 && Prt_getField( field, value, line ) )
220 else if ( strcmp ( field, "path" ) == 0 ) 229 else if ( strcmp ( field, "path" ) == 0 )
221 { 230 {
222 pathFound = TRUE; 231 pathFound = TRUE;
223 DynStr_appLn( s, line ); 232 DynStr_appLn( s, line );
224 } 233 }
234 else if ( strcmp ( field, "organization" ) == 0 )
235 {
236 orgFound = TRUE;
237 DynStr_appLn( s, line );
238 }
225 else if ( strcmp ( field, "x-sender" ) == 0 ) 239 else if ( strcmp ( field, "x-sender" ) == 0 )
226 { 240 {
227 DynStr_app( s, "X-NOFFLE-X-Sender: " ); 241 DynStr_app( s, "X-NOFFLE-X-Sender: " );
228 DynStr_appLn( s, value ); 242 DynStr_appLn( s, value );
229 } 243 }
234 } 248 }
235 249
236 /* Now sort header-related issues */ 250 /* Now sort header-related issues */
237 if ( article.over.from[ 0 ] == '\0' ) 251 if ( article.over.from[ 0 ] == '\0' )
238 { 252 {
239 Log_err( "Posted message has no From field" ); 253 if ( article.flags & POST_ADD_FROM )
240 return FALSE; 254 {
255 Log_dbg( "Adding From field to posted message." );
256 DynStr_app( s, "From: " );
257 if ( ! Prt_genFromHdr( article.over.from ) )
258 {
259 Log_err( "Can't generate From field" );
260 return FALSE;
261 }
262 DynStr_appLn( s, article.over.from );
263 }
264 else
265 {
266 Log_err( "Posted message has no From field" );
267 return FALSE;
268 }
241 } 269 }
242 if ( article.over.subject[ 0 ] == '\0' ) 270 if ( article.over.subject[ 0 ] == '\0' )
243 { 271 {
244 Log_err( "Posted message has no Subject field" ); 272 Log_err( "Posted message has no Subject field" );
245 return FALSE; 273 return FALSE;
293 Log_dbg( "Adding Reply-To field to posted message." ); 321 Log_dbg( "Adding Reply-To field to posted message." );
294 DynStr_app( s, "Reply-To: " ); 322 DynStr_app( s, "Reply-To: " );
295 DynStr_appLn( s, article.over.from ); 323 DynStr_appLn( s, article.over.from );
296 } 324 }
297 325
326 /* Ensure Organization header if required */
327 if ( ( ! orgFound ) && ( article.flags & POST_ADD_ORG ) )
328 {
329 Str org;
330
331 Utl_cpyStr( org, Cfg_organization() );
332 if ( org[ 0 ] != '\0' )
333 {
334 Log_dbg( "Adding Organization field to posted message." );
335 DynStr_app( s, "Organization: " );
336 DynStr_appLn( s, org );
337 }
338 }
339
298 /* OK, header ready to roll. Something to accompany it? */ 340 /* OK, header ready to roll. Something to accompany it? */
299 if ( p == NULL || p[ 0 ] == '\0' ) 341 if ( p == NULL || p[ 0 ] == '\0' )
300 { 342 {
301 Log_err( "Posted message has no body" ); 343 Log_err( "Posted message has no body" );
302 return FALSE; 344 return FALSE;
303 } 345 }
304 346
305 /* Add the empty line separating header and body */ 347 /* Add the empty line separating header and body */
306 DynStr_appLn( s, "" ); 348 DynStr_appLn( s, "" );
307 349
308 /* Now pop on the rest of the body and count the lines & bytes */ 350 /* Now pop on the rest of the body */
309 DynStr_app( s, p ); 351 DynStr_app( s, p );
310 for ( p++, article.over.lines = 0; *p != '\0'; p++ ) 352
353 /* Add a signature if requested to do so and if one found. */
354 sigLines = 0;
355 if ( article.flags & POST_ADD_SIG )
356 {
357 Str sigfile;
358 struct passwd *pwd;
359 FILE *f;
360
361 /* Generate sig file path */
362 pwd = getpwuid( getuid() );
363 Utl_cpyStr( sigfile, pwd->pw_dir );
364 Utl_catStr( sigfile, SIG_FILE );
365
366 f = fopen( sigfile, "r" );
367 if ( f == NULL )
368 {
369 /* If err is ENOENT, file doesn't exist. This is OK. */
370 if ( errno != ENOENT )
371 {
372 Log_err( "Can't access .signature file (%s), "
373 "article not posted.",
374 strerror( errno ) );
375 return FALSE;
376 }
377 }
378 else
379 {
380 /* OK, try to add it. */
381 Str sline;
382
383 Log_dbg( "Adding .signature to posted message." );
384
385 DynStr_appLn( s, BEGIN_SIG );
386 sigLines++;
387 while ( Prt_getLn( sline, f, 0 ) )
388 {
389 DynStr_appLn( s, sline );
390 sigLines++;
391 }
392
393 if ( ferror( f ) )
394 {
395 Log_err( "Error reading .signature file (%s), "
396 "article not posted.",
397 strerror( errno ) );
398 fclose( f );
399 return FALSE;
400 }
401
402 fclose( f );
403 }
404 }
405
406 /*
407 * Count the lines & bytes. This counts the original number of
408 * lines in the supplied body, so add in the number of signature
409 * lines added, including the separator.
410 */
411 for ( p++, article.over.lines = sigLines; *p != '\0'; p++ )
311 if ( *p == '\n' ) 412 if ( *p == '\n' )
312 article.over.lines++; 413 article.over.lines++;
313 article.over.bytes = DynStr_len( s ); 414 article.over.bytes = DynStr_len( s );
314 415
315 return TRUE; 416 return TRUE;
426 return postExternal() && err; 527 return postExternal() && err;
427 } 528 }
428 529
429 /* Register an article for posting. */ 530 /* Register an article for posting. */
430 Bool 531 Bool
431 Post_open( const char * text ) 532 Post_open( const char * text, unsigned flags )
432 { 533 {
433 if ( article.text != NULL ) 534 if ( article.text != NULL )
434 { 535 {
435 Log_err( "Busy article in Post_open." ); 536 Log_err( "Busy article in Post_open." );
436 return FALSE; 537 return FALSE;
437 } 538 }
438 539
540 article.flags = flags;
541
439 if ( ! getArticleText( text ) ) 542 if ( ! getArticleText( text ) )
440 return FALSE; 543 return FALSE;
441 544
442 if ( Db_contains( article.over.msgId ) ) 545 if ( Db_contains( article.over.msgId ) )
443 { 546 {
451 554
452 /* Process the posting */ 555 /* Process the posting */
453 Bool 556 Bool
454 Post_post( void ) 557 Post_post( void )
455 { 558 {
559 if ( article.flags & POST_DEBUG )
560 {
561 fputs( DynStr_str( article.text ), stdout );
562 return TRUE;
563 }
564
456 if ( ! checkPostableNewsgroup() ) 565 if ( ! checkPostableNewsgroup() )
457 return FALSE; 566 return FALSE;
458 567
459 return ( article.control == NULL ) 568 return ( article.control == NULL )
460 ? ! postArticle() 569 ? ! postArticle()