1 /*****************************************************************************
2  * HTICK --- FTN Ticker / Request Processor
3  *****************************************************************************
4  * Copyright (C) 1999 by
5  *
6  * Gabriel Plutzar
7  *
8  * Fido:     2:31/1
9  * Internet: gabriel@hit.priv.at
10  *
11  * Vienna, Austria, Europe
12  *
13  * This file is part of HTICK, which is based on HPT by Matthias Tichy,
14  * 2:2432/605.14 2:2433/1245, mtt@tichy.de
15  *
16  * HTICK is free software; you can redistribute it and/or modify it
17  * under the terms of the GNU General Public License as published by the
18  * Free Software Foundation; either version 2, or (at your option) any
19  * later version.
20  *
21  * HTICK is distributed in the hope that it will be useful, but
22  * WITHOUT ANY WARRANTY; without even the implied warranty of
23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
24  * General Public License for more details.
25  *
26  * You should have received a copy of the GNU General Public License
27  * along with HTICK; see the file COPYING.  If not, write to the Free
28  * Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
29  *****************************************************************************
30  * $Id$
31  *****************************************************************************/
32 
33 /* clib */
34 #include <string.h>
35 #include <stdlib.h>
36 #include <fcntl.h>
37 #include <errno.h>
38 #include <ctype.h>
39 #include <sys/types.h>
40 #include <sys/stat.h>
41 
42 /* compiler.h */
43 #include <huskylib/compiler.h>
44 #include <huskylib/huskylib.h>
45 
46 #ifdef __OS2__
47 # define INCL_DOSFILEMGR        /* for hidden() routine */
48 # include <os2.h>
49 #endif
50 
51 #ifdef HAS_IO_H
52 # include <io.h>
53 #endif
54 
55 #ifdef HAS_SHARE_H
56 # include <share.h>
57 #endif
58 
59 #ifdef HAS_UNISTD_H
60 # include <unistd.h>
61 #endif
62 
63 #ifdef HAS_DOS_H
64 # include <dos.h>
65 #endif
66 
67 #ifdef HAS_PROCESS_H
68 # include <process.h>
69 #endif
70 
71 /* fidoconf */
72 #include <fidoconf/fidoconf.h>
73 #include <fidoconf/common.h>
74 #include <huskylib/log.h>
75 #include <huskylib/dirlayer.h>
76 #include <huskylib/xstr.h>
77 #include <fidoconf/afixcmd.h>
78 #include <huskylib/recode.h>
79 #include <huskylib/crc.h>
80 #include <areafix/query.h>
81 #include <areafix/areafix.h>
82 
83 #if defined(A_HIDDEN) && !defined(_A_HIDDEN)
84 # define _A_HIDDEN A_HIDDEN
85 #endif
86 
87 /* htick */
88 #include <fcommon.h>
89 #include <global.h>
90 #include <toss.h>
91 #include <htickafix.h>
92 #include <add_desc.h>
93 #include <seenby.h>
94 #include <filecase.h>
95 #include "hatch.h"
96 #include "report.h"
97 
98 char *versionStr;
99 
100 /* tic keywords calculated crc (CCITT-16, polynom 0x1021) */
101 
102 #define CRC_CREATED      0xACDA /*0x4EC6 */
103 #define CRC_FILE         0x9AF9 /*0x1A66 */
104 #define CRC_ALTFILE      0x02B3 /* "ALTFILE" */
105 #define CRC_AREADESC     0xD824 /*0xB621 */
106 #define CRC_DESC         0x717B /*0xECBD */
107 #define CRC_AREA         0x825A /*0x825A */
108 #define CRC_CRC          0x5487 /*0x5487 */
109 #define CRC_REPLACES     0xCE24 /*0xCF01 */
110 #define CRC_ORIGIN       0xE52A /*0xFCDC */
111 #define CRC_FROM         0xFD30 /*0x1293 */
112 #define CRC_TO           0x7B50 /*0x7B50 */
113 #define CRC_PATH         0x5411 /*0x5411 */
114 #define CRC_SEENBY       0xF84C /*0xC3D4 */
115 #define CRC_PW           0x24AD /*0x24AD */
116 #define CRC_SIZE         0x94CE /*0x5593 */
117 #define CRC_DATE         0x54EA /*0xD4BD */
118 #define CRC_DESTINATION  0x6F36 /*0xA9D1 */
119 #define CRC_MAGIC        0x7FF4 /*0xD858 */
120 #define CRC_LDESC        0xEB38 /*0x5394 */
121 
122 /* Write netmail message into areaname or first netmail area (if areaname is NULL pointer)
123  */
writeNetmail(s_message * msg,char * areaName)124 void writeNetmail( s_message * msg, char *areaName )
125 {
126   HAREA netmail;
127   HMSG msgHandle;
128   UINT len = msg->textLength;
129   char *bodyStart;              /* msg-body without kludgelines start */
130   char *ctrlBuf;                /* Kludgelines */
131   XMSG msgHeader;
132   s_area *nmarea;
133 
134   if( ( msg == NULL ) )
135   {
136     w_log( LL_ERROR,
137            __FILE__
138            ":%i: Parameter is a NULL pointer: writeNetmail(NULL,areaname). This is a bug, please report it to developers.",
139            __LINE__ );
140     return;
141   }
142 
143   if( !config->netMailAreas )
144   {
145     w_log( LL_CRIT, "Netmail areas not defined, message dropped! Please check config." );
146     return;
147   }
148   if( !areaName || ( nmarea = getNetMailArea( config, areaName ) ) == NULL )
149     nmarea = &( config->netMailAreas[0] );
150 
151   netmail = MsgOpenArea( ( UCHAR * ) nmarea->fileName, MSGAREA_CRIFNEC, ( word ) nmarea->msgbType );
152 
153   if( netmail != NULL )
154   {
155     msgHandle = MsgOpenMsg( netmail, MOPEN_CREATE, 0 );
156 
157     if( msgHandle != NULL )
158     {
159       if( ( !config->recodeMsgBase ) && ( config->outtab != NULL ) )
160       {
161         recodeToTransportCharset( ( char * )msg->subjectLine );
162         recodeToTransportCharset( ( char * )msg->fromUserName );
163         recodeToTransportCharset( ( char * )msg->toUserName );
164         recodeToTransportCharset( ( char * )msg->text );
165       }
166 
167       msgHeader = createXMSG( config, msg, NULL, MSGLOCAL, NULL );
168       /* Create CtrlBuf for SMAPI */
169       {
170         byte *bb;               /* Prevent GCC warning "dereferencing type-punned pointer will break strict-aliasing rules" */
171 
172         ctrlBuf = ( char * )CopyToControlBuf( msg->text, &bb, &len );
173         bodyStart = bb;
174       }
175 
176       /* write message */
177       MsgWriteMsg( msgHandle, 0, &msgHeader, ( UCHAR * ) bodyStart, len, len, strlen( ctrlBuf ) + 1,
178                    ( UCHAR * ) ctrlBuf );
179       free( ctrlBuf );
180       MsgCloseMsg( msgHandle );
181 
182       w_log( LL_POSTING, "Wrote Netmail to: %u:%u/%u.%u",
183              msg->destAddr.zone, msg->destAddr.net, msg->destAddr.node, msg->destAddr.point );
184     }
185     else
186     {
187       w_log( LL_ERROR, "Could not write message to %s", areaName );
188     }                           /* endif */
189 
190     MsgCloseArea( netmail );
191   }
192   else
193   {
194 /*     printf("%u\n", msgapierr); */
195     w_log( LL_ERROR, "Could not open netmail area %s", areaName );
196   }                             /* endif */
197 }
198 
199 /* Write (create) TIC-file
200  * Return 0 if error, 1 if success
201  */
writeTic(char * ticfile,s_ticfile * tic)202 int writeTic( char *ticfile, s_ticfile * tic )
203 {
204   FILE *tichandle;
205   unsigned int i;
206   char *p;
207   s_area *filearea = NULL;
208 
209   if( ( ticfile == NULL ) || ( tic == NULL ) )
210   {
211     w_log( LL_ERROR,
212            __FILE__
213            ":%i: Parameter is a NULL pointer: writeTic(%s%s%s,%s). This is a bug, please report it to developers.",
214            __LINE__, ticfile ? "\"" : "", ticfile ? ticfile : "NULL", ticfile ? "\"" : "",
215            tic ? "tic" : "NULL" );
216     return 0;
217   }
218   tichandle = fopen( ticfile, "wb" );
219   if( !tichandle )
220   {
221     w_log( LL_ERROR, "Unable to open TIC file \"%s\": %s!!!\n", ticfile, strerror( errno ) );
222     return 0;
223   }
224 
225   fprintf( tichandle, "Created by HTick, written by Gabriel Plutzar\r\n" );
226   fprintf( tichandle, "File %s\r\n", tic->file );
227   fprintf( tichandle, "Area %s\r\n", tic->area );
228 
229   filearea = getFileArea( tic->area );
230 
231   if( !tic->areadesc && filearea && filearea->description )
232   {
233     tic->areadesc = sstrdup( filearea->description );
234     if( config->outtab )
235     {
236       recodeToTransportCharset( tic->areadesc );
237     }
238   }
239   if( tic->areadesc )
240     fprintf( tichandle, "Areadesc %s\r\n", tic->areadesc );
241 
242   for( i = 0; i < tic->anzdesc; i++ )
243     fprintf( tichandle, "Desc %s\r\n", tic->desc[i] );
244 
245   for( i = 0; i < tic->anzldesc; i++ )
246   {
247     while( ( p = strchr( tic->ldesc[i], 26 ) ) != NULL )
248       *p = ' ';
249     fprintf( tichandle, "LDesc %s\r\n", tic->ldesc[i] );
250   }
251 
252   if( tic->replaces )
253     fprintf( tichandle, "Replaces %s\r\n", tic->replaces );
254   if( tic->from.zone != 0 )
255     fprintf( tichandle, "From %s\r\n", aka2str( tic->from ) );
256   if( tic->to.zone != 0 )
257     fprintf( tichandle, "To %s\r\n", aka2str( tic->to ) );
258   if( tic->origin.zone != 0 )
259     fprintf( tichandle, "Origin %s\r\n", aka2str( tic->origin ) );
260   if( tic->size >= 0 )
261     fprintf( tichandle, "Size %u\r\n", tic->size );
262   if( tic->date != 0 )
263     fprintf( tichandle, "Date %lu\r\n", tic->date );
264   if( tic->crc_is_present || tic->crc ) /* FIXME: Look through all code to check up simultaneous change of a tic.crc and a tic.tic->crc */
265     fprintf( tichandle, "Crc %08lX\r\n", tic->crc );
266 
267   for( i = 0; i < tic->anzpath; i++ )
268     fprintf( tichandle, "Path %s\r\n", tic->path[i] );
269 
270   for( i = 0; i < tic->anzseenby; i++ )
271     fprintf( tichandle, "Seenby %s\r\n", aka2str( tic->seenby[i] ) );
272 
273   if( tic->password )
274     fprintf( tichandle, "Pw %s\r\n", tic->password );
275 
276   fclose( tichandle );
277   return 1;
278 }                               /* writeTic() */
279 
280 /* Free memory allocated in structure s_ticfile *tic
281  */
disposeTic(s_ticfile * tic)282 void disposeTic( s_ticfile * tic )
283 {
284   unsigned int i;
285 
286   if( ( tic == NULL ) )
287   {
288     w_log( LL_ERROR,
289            __FILE__
290            ":%i: Parameter is a NULL pointer: disposeTic(NULL). This is a bug, please report it to developers.",
291            __LINE__ );
292     return;
293   }
294   nfree( tic->seenby );
295   nfree( tic->file );
296   nfree(tic->altfile);
297   nfree( tic->area );
298   nfree( tic->areadesc );
299   nfree( tic->replaces );
300   nfree( tic->password );
301 
302   for( i = 0; i < tic->anzpath; i++ )
303     nfree( tic->path[i] );
304   nfree( tic->path );
305 
306   for( i = 0; i < tic->anzdesc; i++ )
307     nfree( tic->desc[i] );
308   nfree( tic->desc );
309 
310   for( i = 0; i < tic->anzldesc; i++ )
311     nfree( tic->ldesc[i] );
312   nfree( tic->ldesc );
313 }                               /* disposeTic() */
314 
315 /* Check TIC file validity
316  * Return: 0 if TIC is valid,
317  *         negative integer if error found in function arguments,
318  *         positive integer if information in TIC is bad (the value is the number of errors)
319  */
checkTic(const char * ticfilename,const s_ticfile * tic)320 static int checkTic( const char *ticfilename, const s_ticfile * tic )
321 {
322   int nRet = 0;
323 
324   if( ( ticfilename == NULL ) || ( tic == NULL ) )
325   {
326     w_log( LL_ERROR,
327            __FILE__
328            ":%i: Parameter is a NULL pointer: checkTic(%s%s%s,%s). This is a bug, please report it to developers.",
329            __LINE__, ticfilename ? "\"" : "", ticfilename ? ticfilename : "NULL",
330            ticfilename ? "\"" : "", tic ? "tic" : "NULL" );
331     return -1;
332   }
333   if( !tic->file )
334   {
335     w_log( LL_ERR, "File name is missing in TIC \"%s\" but required by FSC-87", ticfilename );
336     nRet++;
337   }
338 
339   if( !tic->area )
340   {
341     w_log( LL_ERR, "Filearea name is missing in TIC \"%s\" but required by FSC-87", ticfilename );
342     nRet++;
343   }
344 
345   if( !tic->crc_is_present )
346   {
347     w_log( LL_SECURITY, "CRC is missing in TIC \"%s\" but required by FSC-87", ticfilename );
348   }
349 
350   if( tic->size < 0 )
351   {
352     w_log( LL_ALERT, "There is no file size in TIC %s, FSC-87 says: \"SHOULD be required\"",
353            ticfilename );
354   }
355 
356   if( ( !tic->crc ) && ( tic->size > 0 ) )
357   {
358     w_log( LL_ERR,
359            "The size is not zero but CRC32 equals zero in TIC %s, it is impossible and this ticket file is wrong.",
360            ticfilename );
361     nRet++;
362   }
363 
364   if( ( !tic->size ) && ( tic->crc_is_present ) )
365   {
366     w_log( LL_ERR,
367            "The size equals zero but CRC32 is not zero in TIC %s, it is impossible and this ticket file is wrong.",
368            ticfilename );
369     nRet++;
370   }
371 
372   if( !tic->to.zone && !tic->to.net && !tic->to.node )
373   {
374     w_log( LL_SECURITY, "'To' address is missing in TIC \"%s\"", ticfilename );
375   }
376   else if( !tic->to.zone || !tic->to.net )
377   {
378     w_log( LL_ERR, "'To' address (%s) is illegal in TIC \"%s\"", aka2str( tic->to ), ticfilename );
379     nRet++;
380   }
381 
382   if( !tic->from.zone && !tic->from.net && !tic->from.node )
383   {
384     w_log( LL_ERR, "'From' address is missing in TIC \"%s\", required by FSC-87", ticfilename );
385     nRet++;
386   }
387   else if( !tic->from.zone || !tic->from.net )
388   {
389     w_log( LL_ERR, "Zone or net is missing in the 'From' address in TIC \"%s\"", ticfilename );
390     nRet++;
391   }
392 
393   if( !tic->origin.zone && !tic->origin.net && !tic->origin.node )
394   {
395     w_log( LL_ERR, "Originating address is missing in TIC \"%s\", required by FSC-87",
396            ticfilename );
397     /* nRet++; */
398   }
399   else if( !tic->origin.zone || !tic->origin.node )
400   {
401     w_log( LL_ERR, "Zone or node is missing in the originating address in TIC \"%s\"", ticfilename );
402     /* nRet++; */
403   }
404 
405   if( !tic->path )
406   {
407     w_log( LL_ALERT, "PATH lines are missing in TIC \"%s\", required by FSC-87", ticfilename );
408   }
409 
410   if( !tic->seenby )
411   {
412     w_log( LL_ALERT, "SEENBY lines are missing in TIC \"%s\", required by FSC-87", ticfilename );
413   }
414 
415   if( !tic->password )
416   {                             /* Mandatory field (FSC-87) */
417     w_log( LL_SECURITY, "Password is missing in TIC \"%s\", required by FSC-87", ticfilename );
418   }
419 
420   return nRet;
421 }                               /* checkTic */
422 
423 
424 /* Read TIC file and store values into 2nd parameter.
425  * Return 1 if success, 2 if bad data in tic, and 0 if file or parameter error.
426  * Clean 2nd parameter before processing if not error.
427  */
parseTic(char * ticfile,s_ticfile * tic)428 enum parseTic_result parseTic( char *ticfile, s_ticfile * tic )
429 {
430   FILE *tichandle;
431   char *line, *token, *param, *linecut = "", *emptyline = "";
432   s_link *ticSourceLink = NULL;
433   UINT16 key;
434   hs_addr Aka;
435   int rc = parseTic_success;
436 
437   if( ( ticfile == NULL ) || ( tic == NULL ) )
438   {
439     w_log( LL_ERROR,
440            __FILE__
441            ":%i: Parameter is a NULL pointer: parseTic(%s%s%s,%s). This is a bug, please report it to developers.",
442            __LINE__, ticfile ? "\"" : "", ticfile ? ticfile : "NULL", ticfile ? "\"" : "",
443            tic ? "tic" : "NULL" );
444     return parseTic_error;
445   }
446   memset( tic, '\0', sizeof( s_ticfile ) );
447   tic->size = -1;               /* For check existing a token "size" in TIC file */
448 
449 #ifndef HAS_sopen
450   tichandle = fopen( ticfile, "r" );
451 #else
452   {
453     int fh = 0;
454 
455     /* insure that ticfile won't be removed while parsing */
456 # if defined (__UNIX__) || defined (__DJGPP__)
457     fh = sopen( ticfile, O_RDWR | O_BINARY, SH_DENYNO, S_IWRITE | S_IREAD );
458 # else
459     fh = sopen( ticfile, O_RDWR | O_BINARY, SH_DENYRW );
460 # endif
461     if( fh < 0 )
462     {
463       w_log( LL_ERROR, "Can't open '%s': %s (sopen())", ticfile, strerror( errno ) );
464       return parseTic_error;
465     }
466     tichandle = fdopen( fh, "r" );
467   }
468 #endif
469 
470   if( !tichandle )
471   {
472     w_log( LL_ERROR, "Can't open '%s': %s", ticfile, strerror( errno ) );
473     return parseTic_error;
474   }
475 
476   while( ( line = readLine( tichandle ) ) != NULL )
477   {
478     line = trimLine( line );
479 
480     if( *line == 0 || *line == 10 || *line == 13 || *line == ';' || *line == '#' )
481       continue;
482 
483     if( config->MaxTicLineLength )
484     {
485       linecut = ( char * )smalloc( config->MaxTicLineLength + 1 );
486       strncpy( linecut, line, config->MaxTicLineLength );
487       linecut[config->MaxTicLineLength] = 0;
488       token = strtok( linecut, " \t" );
489     }
490     else
491       token = strtok( line, " \t" );
492 
493     if( token )
494     {
495       key = strcrc16( strUpper( token ), 0 );
496       /* calculate crc16 of tic                                   */
497       w_log( LL_DEBUGz, "#define CRC_%-12s 0x%X;", strUpper( token ), key );
498       param = stripLeadingChars( strtok( NULL, "\0" ), "\t" );
499       if( !param )
500       {
501         switch ( key )
502         {
503         case CRC_DESC:
504         case CRC_LDESC:
505           param = emptyline;
506           break;
507         case CRC_SIZE:
508           w_log( LL_ERR, "Wrong TIC \"%s\": \"Size\" without value!", ticfile );
509           tic->size = -1;
510           rc = parseTic_bad;
511           break;
512         default:
513           continue;
514         }
515       }
516       switch ( key )
517       {
518       case CRC_CREATED:
519       case CRC_MAGIC:
520         break;
521       case CRC_FILE:
522         tic->file = sstrdup( param );
523         break;
524       case CRC_ALTFILE:
525         tic->altfile = sstrdup(param);  /* just for reports */
526         break;
527       case CRC_AREADESC:
528         tic->areadesc = sstrdup( param );
529         break;
530       case CRC_AREA:
531         tic->area = sstrdup( param );
532         break;
533       case CRC_CRC:
534         tic->crc = strtoul( param, NULL, 16 );
535         tic->crc_is_present = 1;
536         break;
537       case CRC_SIZE:
538         if( param[0] == '-' )
539         {
540           w_log( LL_ERR, "Wrong TIC \"%s\": negative size (\"%s\")!", ticfile, param );
541           rc = parseTic_bad;
542         }
543         else
544         {
545           tic->size = tic->size = atoi( param );
546           if( ( !tic->size ) && ( !strcmp( param, "0" ) ) )
547           {
548             w_log( LL_ERR, "Wrong TIC \"%s\": value of size is \"%s\"! "
549                    "(May be pozitive integer or one zero", ticfile, param );
550             rc = parseTic_bad;
551           }
552         }
553         break;
554       case CRC_DATE:
555         tic->date = atoi( param );
556         break;
557       case CRC_REPLACES:
558         if( *param == '*' )
559         {
560           w_log( LL_TIC, "TIC %s: Illegal value: 'REPLACES %s', ignored", ticfile, param );
561           break;
562         }
563         tic->replaces = sstrdup( param );
564         break;
565       case CRC_PW:
566         tic->password = sstrdup( param );
567         break;
568       case CRC_FROM:
569         parseFtnAddrZS( param, &tic->from );
570         ticSourceLink = getLinkFromAddr( config, tic->from );
571         break;
572       case CRC_ORIGIN:
573         parseFtnAddrZS( param, &tic->origin );
574         break;
575       case CRC_TO:
576         parseFtnAddrZS( param, &tic->to );
577         if( !tic->to.zone || !tic->to.net )
578         {
579           w_log( LL_ERR, "No zone or net in the 'To' address (%s) in TIC %s", param, ticfile );
580           rc = parseTic_bad;
581         }
582         break;
583       case CRC_DESTINATION:
584         if( ticSourceLink && !ticSourceLink->FileFixFSC87Subset )
585           parseFtnAddrZS( param, &tic->to );
586         break;
587       case CRC_DESC:
588         tic->desc = srealloc( tic->desc, ( tic->anzdesc + 1 ) * sizeof( *tic->desc ) );
589         tic->desc[tic->anzdesc] = sstrdup( param );
590         tic->anzdesc++;
591         break;
592       case CRC_LDESC:
593         tic->ldesc = srealloc( tic->ldesc, ( tic->anzldesc + 1 ) * sizeof( *tic->ldesc ) );
594         tic->ldesc[tic->anzldesc] = sstrdup( param );
595         tic->anzldesc++;
596         break;
597       case CRC_SEENBY:
598         memset( &Aka, 0, sizeof( Aka ) );
599         if( parseFtnAddrZS( param, &Aka ) & FTNADDR_ERROR )
600         {
601           w_log( LL_TIC, "TIC %s: Illegal value: 'Seenby %s', ignored", ticfile, param );
602         }
603         else
604         {
605           seenbyAdd( &tic->seenby, &tic->anzseenby, &Aka );
606         }
607         break;
608       case CRC_PATH:
609         tic->path = srealloc( tic->path, ( tic->anzpath + 1 ) * sizeof( *tic->path ) );
610         tic->path[tic->anzpath] = sstrdup( param );
611         tic->anzpath++;
612         break;
613       default:
614         if( ticSourceLink && !ticSourceLink->FileFixFSC87Subset )
615         {
616           w_log( LL_WARNING, "Unknown Keyword %s in Tic File", token );
617           rc = parseTic_bad;
618         }
619       }                         /* switch */
620     }                           /* endif */
621     if( config->MaxTicLineLength )
622       nfree( linecut );
623     nfree( line );
624   }                             /* endwhile */
625 
626   fclose( tichandle );
627 
628   if( !tic->anzdesc )
629   {
630     tic->desc = srealloc( tic->desc, sizeof( *tic->desc ) );
631     tic->desc[0] = sstrdup( "no desc" );
632     tic->anzdesc = 1;
633   }
634 
635   return rc;
636 }                               /* parseTic */
637 
638 /* Save ticket file into filearea-specific directory
639  */
doSaveTic(char * ticfile,s_ticfile * tic,s_area * filearea)640 void doSaveTic( char *ticfile, s_ticfile * tic, s_area * filearea )
641 {
642   unsigned int i;
643   s_savetic *savetic;
644 
645   if( ( tic == NULL ) || ( filearea == NULL ) )
646   {
647     w_log( LL_ERROR,
648            __FILE__
649            ":%i: Parameter is a NULL pointer: doSaveTic(%s%s%s,%s,%s). This is a bug, please report it to developers.",
650            __LINE__, ticfile ? "\"" : "", ticfile ? ticfile : "", ticfile ? "\"" : "",
651            tic ? "tic" : "NULL", filearea ? "filearea" : "NULL" );
652     return;
653   }
654 
655   for( i = 0; i < config->saveTicCount; i++ )
656   {
657     savetic = &( config->saveTic[i] );
658     if( patimat( tic->area, savetic->fileAreaNameMask ) == 1 )
659     {
660       char *ticFname = NULL;
661       char *filename = NULL;
662 
663       if( ticfile )
664       {
665         ticFname = GetFilenameFromPathname( ticfile );
666         w_log( LL_FILENAME, "Saving Tic-File \"%s\" to \"%s\"", ticFname, savetic->pathName );
667         xscatprintf( &filename, "%s%s", savetic->pathName, ticFname );
668         if( copy_file( ticfile, filename, 1 ) != 0 )
669         {                       /* overwrite existing file if not same */
670           w_log( LL_ERROR, "File \"%s\" not found or not moveable", ticfile );
671         }
672       }
673       else
674       {
675         filename = makeUniqueDosFileName( savetic->pathName, "tic", config );
676         w_log( LL_FILENAME, "Saving Tic-File \"%s\" to \"%s\"", GetFilenameFromPathname( filename ),
677                savetic->pathName );
678         writeTic( filename, tic );
679       }
680       nfree( filename );
681 
682       if( filearea &&
683           filearea->msgbType != MSGTYPE_PASSTHROUGH && !filearea->sendorig && savetic->fileAction )
684       {
685         char *from = NULL, *to = NULL;
686 
687         xstrscat( &from, filearea->fileName, tic->file, NULL );
688         xstrscat( &to, savetic->pathName, tic->file, NULL );
689         if( savetic->fileAction == 1 )
690           copy_file( from, to, 1 );     /* overwrite existing file if not same */
691         if( savetic->fileAction == 2 )
692           link_file( from, to );
693         nfree( from );
694         nfree( to );
695       }
696       break;
697     };
698 
699   };
700   return;
701 }                               /* doSaveTic */
702 
703 
704 /*
705  *  create alternative filename for ticked file
706  *  - add counter 01 up to 99
707  *
708  *  requires:
709  *  - path of destination directory
710  *  - name of ticked file
711  *
712  *  returns:
713  *  - string pointer (allocated buffer) on success
714  *  - NULL on any problem
715  */
716 
altFilename(char * path,char * name)717 char *altFilename(char *path, char *name)
718 {
719   char              *altName = NULL;         /* return value */
720   char              *tempName = NULL;        /* temporary name */
721   char              *tempFilepath = NULL;    /* temporary filepath */
722   char              *modStr;
723   char              *remStr = NULL;
724   unsigned int      n = 1;
725   size_t            size;
726 
727   /* sanity checks */
728   if ((path == NULL) || (name == NULL)) return altName;
729 
730   /* allocate buffers */
731   size = strlen(name) + 4;         /* + dot + 2 digits + \0 */
732   tempName = smalloc(size);
733   size += strlen(path);
734   tempFilepath = smalloc(size);
735 
736 
737   /* prepare temp. name */
738   strcpy(tempName, name);
739   modStr = strchr(tempName, '.');         /* find first dot */
740   if (modStr == NULL)              /* no dot found */
741   {
742     /* find end of string */
743     modStr = tempName;
744     while (modStr[0] != 0) modStr++;
745 
746     modStr[0] = '.';               /* add dot */
747   }
748   else                             /* dot found */
749   {
750     /* get pointer to remaining part in original string */
751     remStr = strchr(name, '.');
752   }
753   modStr++;                        /* skip dot */
754   modStr[0] = 0;                   /* end string */
755 
756   if (isDOSLikeName(name))         /* DOS filename */
757   {
758     if (remStr)                    /* more chars follow */
759     {
760       remStr++;                    /* skip dot */
761       modStr[0] = remStr[0];       /* copy first char behind dot */
762       modStr++;                    /* and skip it */
763       remStr = NULL;               /* don't care about the remaining chars */
764     }
765   }
766 
767   /* check alternative names */
768   while (n < 99)
769   {
770     /* complete temp. filename */
771     sprintf(modStr, "%.2d", n);              /* add counter */
772     if (remStr) strcat(modStr, remStr);      /* add remaining part */
773 
774     strcpy(tempFilepath, path);              /* build full filepath */
775     strcat(tempFilepath, tempName);
776 
777     if (!fexist(tempFilepath)) break;        /* unused filename */
778     else n++;                                /* try next one */
779   }
780 
781   if (n <= 99) altName = tempName;           /* found alternative */
782   else nfree(tempName);                      /* found none */
783   nfree(tempFilepath);
784 
785   return altName;
786 }
787 
788 
789 /* Send a file "filename" to all subscribers of fileecho.
790  * Return: 0 if success, positive integer if error, negative integer if illegal call
791  */
sendToLinks(int isToss,s_area * filearea,s_ticfile * tic,const char * filename)792 int sendToLinks( int isToss, s_area * filearea, s_ticfile * tic, const char *filename )
793                 /*
794                  * isToss == 1 - tossing
795                  * isToss == 0 - hatching
796                  */
797 {
798   unsigned int i, z;
799   char descr_file_name[256], newtickedfile[256], fileareapath[256];
800   char timestr[40];
801   time_t acttime;
802   hs_addr *old_seenby = NULL;
803   hs_addr old_from, old_to;
804   int old_anzseenby = 0;
805   int readAccess;
806   int cmdexit;
807   char *comm;
808   char *p;
809   unsigned int minLinkCount;
810 
811   if( ( filearea == NULL ) || ( tic == NULL ) || ( filename == NULL ) )
812   {
813     w_log( LL_ERROR,
814            __FILE__
815            ":%i: Parameter is a NULL pointer: sendToLinks(%i,%s,%s,%s%s%s). This is a bug, please report it to developers.",
816            __LINE__, isToss, filearea ? "filearea" : "NULL", tic ? "tic" : "NULL",
817            filename ? "\"" : "", filename ? filename : "NULL", filename ? "\"" : "" );
818     return TIC_UnknownError;
819   }
820 
821   if( isToss == 1 )
822     minLinkCount = 2;           /*  uplink and downlink */
823   else
824     minLinkCount = 1;           /*  only downlink */
825 
826   if( !fexist( filename ) )
827   {
828     /* origin file does not exist */
829     w_log( LL_ERROR, "File \"%s\" not found, nothing to send to links", filename );
830     return TIC_NotRecvd;
831   }
832 
833   if( filearea->msgbType != MSGTYPE_PASSTHROUGH )
834     strcpy( fileareapath, filearea->fileName );
835   else
836     strcpy( fileareapath, config->passFileAreaDir );
837   p = strrchr( fileareapath, PATH_DELIM );
838   if( p )
839     strLower( p + 1 );
840 
841   _createDirectoryTree( fileareapath );
842 
843   if( isToss == 1 && tic->replaces != NULL && filearea->msgbType != MSGTYPE_PASSTHROUGH
844       && !filearea->noreplace )
845   {
846     /* Delete old file[s] */
847     int num_files;
848     char *repl;
849 
850     repl = strrchr( tic->replaces, PATH_DELIM );
851     if( repl == NULL )
852       repl = tic->replaces;
853     else
854       repl++;
855     num_files = removeFileMask( fileareapath, repl );
856     if( num_files > 0 )
857     {
858       w_log( LL_DEL, "%d file[s] with filemask %s are removed", num_files, repl );
859     }
860   }
861 
862   strcpy( newtickedfile, fileareapath );
863   strcat( newtickedfile, MakeProperCase( tic->file ) );
864 
865   /* check for duplicates in the filearea */
866   if (filearea->msgbType != MSGTYPE_PASSTHROUGH && fexist(newtickedfile))
867   {
868     if (filearea->rename)             /* rename new file */
869     {
870       comm = altFilename(&fileareapath[0], tic->file);
871       if (comm != NULL)     /* found alternative name */
872       {
873         strcpy(newtickedfile, fileareapath);
874         strcat(newtickedfile, comm);
875         tic->altfile = comm;
876         w_log('6',"Created alternative name %s for file %s.", comm, tic->file);
877       }
878       else                  /* namespace exceeded or error */
879       {
880         w_log(LL_ERROR,"Couldn't create alternative name for file %s in filearea %s.", tic->file, tic->area);
881         return(TIC_NotOpen);
882       }
883     }
884     else if (filearea->noreplace)     /* don't overwrite old file */
885     {
886       w_log(LL_ERROR,"File %s in filearea %s already exists. Can't replace it", tic->file, tic->area);
887       return(TIC_NotOpen);
888     }
889   }
890 
891   if( isToss == 1 )
892   {
893     if (!filearea->sendorig && tic->altfile == NULL)
894     {
895       /* overwrite existing file if not same */
896       if( move_file( filename, newtickedfile, 1 ) != 0 )
897       {
898         w_log( LL_ERROR, "Can't copy file %s to %s: %s",
899                filename, newtickedfile, strerror( errno ) );
900         return TIC_NotOpen;
901       }
902       else
903       {
904         w_log( LL_CREAT, "Moved %s to %s", filename, newtickedfile );
905       }
906     }
907     else
908     {
909       /* overwrite existing file if not same */
910       if( copy_file( filename, newtickedfile, 1 ) != 0 )
911       {
912         w_log( LL_ERROR, "Can't copy file %s to %s: %s",
913                filename, newtickedfile, strerror( errno ) );
914         return TIC_NotOpen;
915       }
916       else
917       {
918         w_log( LL_CREAT, "Put %s to %s", filename, newtickedfile );
919       }
920       strcpy( newtickedfile, config->passFileAreaDir );
921       strcat( newtickedfile, MakeProperCase( tic->file ) );
922       /* overwrite existing file if not same */
923       if( move_file( filename, newtickedfile, 1 ) != 0 )
924       {
925         w_log( LL_ERROR, "Can't move file %s  to %s: %s",
926                filename, newtickedfile, strerror( errno ) );
927         return TIC_NotOpen;
928       }
929       else
930       {
931         w_log( LL_CREAT, "Moved %s to %s", filename, newtickedfile );
932       }
933     }
934   }
935   else if( strcasecmp( filename, newtickedfile ) != 0 )
936   {
937     /* overwrite existing file if not same */
938     if( copy_file( filename, newtickedfile, 1 ) != 0 )
939     {
940       w_log( LL_ERROR, "Can't copy file %s to %s: %s", filename, newtickedfile, strerror( errno ) );
941       return TIC_NotOpen;
942     }
943     else
944     {
945       w_log( LL_CREAT, "Put %s to %s", filename, newtickedfile );
946     }
947     if (filearea->sendorig || tic->altfile)
948     {
949       strcpy( newtickedfile, config->passFileAreaDir );
950       strcat( newtickedfile, MakeProperCase( tic->file ) );
951       if( copy_file( filename, newtickedfile, 1 ) != 0 )
952       {
953         w_log( LL_ERROR, "Can't copy file \"%s\" to \"%s\": %s",
954                filename, newtickedfile, strerror( errno ) );
955         return TIC_NotOpen;
956       }
957       else
958       {
959         w_log( LL_CREAT, "Put \"%s\" to \"%s\"", filename, newtickedfile );
960       }
961     }
962   }
963 
964   if( tic->anzldesc == 0 && config->fDescNameCount && !filearea->nodiz && isToss )
965     GetDescFormDizFile( newtickedfile, tic );
966 
967   if( config->announceSpool )
968     doSaveTic4Report( tic );
969 
970   if( filearea->msgbType != MSGTYPE_PASSTHROUGH )
971   {
972     strcpy( descr_file_name, filearea->fileName );
973     strcat( descr_file_name, config->fileDescription );
974     adaptcase( descr_file_name );
975     if (tic->altfile) comm = tic->altfile;    /* use alternative name */
976     else comm = tic->file;                    /* use original name */
977     removeDesc( descr_file_name, comm );
978     if( tic->anzldesc > 0 )
979       add_description( descr_file_name, comm, tic->ldesc, tic->anzldesc );
980     else
981       add_description( descr_file_name, comm, tic->desc, tic->anzdesc );
982   }
983 
984   if( filearea->downlinkCount >= minLinkCount )
985   {
986     /* Adding path & seenbys */
987     time( &acttime );
988     strcpy( timestr, asctime( gmtime( &acttime ) ) );
989     timestr[strlen( timestr ) - 1] = 0;
990     if( timestr[8] == ' ' )
991       timestr[8] = '0';
992 
993     tic->path = srealloc( tic->path, ( tic->anzpath + 1 ) * sizeof( *tic->path ) );
994     tic->path[tic->anzpath] = NULL;
995     xscatprintf( &tic->path[tic->anzpath], "%s %lu %s UTC %s",
996                  aka2str( *filearea->useAka ), ( unsigned long )time( NULL ), timestr, versionStr );
997     tic->anzpath++;
998   }
999 
1000   if( isToss == 1 )
1001   {
1002     /*  Save seenby structure */
1003     old_seenby = smalloc( tic->anzseenby * sizeof( hs_addr ) );
1004     memcpy( old_seenby, tic->seenby, tic->anzseenby * sizeof( hs_addr ) );
1005     old_anzseenby = tic->anzseenby;
1006     memcpy( &old_from, &tic->from, sizeof( hs_addr ) );
1007     memcpy( &old_to, &tic->to, sizeof( hs_addr ) );
1008   }
1009   else
1010   {
1011     memset( &old_from, 0, sizeof( hs_addr ) );
1012     memset( &old_to, 0, sizeof( hs_addr ) );
1013   }
1014 
1015   if( tic->anzseenby > 0 )
1016   {
1017     for( i = 0; i < filearea->downlinkCount; i++ )
1018     {
1019       s_link *downlink = filearea->downlinks[i]->link;
1020 
1021       if( ( seenbyComp( tic->seenby, tic->anzseenby, downlink->hisAka ) ) &&
1022           ( e_readCheck( config, filearea, downlink ) == 0 ) )
1023       { /*  if link is not in seen-by list & */
1024         /*  if link can receive files from the filearea */
1025         /*  Adding Downlink to Seen-By */
1026         /*
1027          * tic->seenby=srealloc(tic->seenby,(tic->anzseenby+1)*sizeof(hs_addr));
1028          * memcpy(&tic->seenby[tic->anzseenby],&downlink->hisAka,sizeof(hs_addr));
1029          * tic->anzseenby++;
1030          */
1031         seenbyAdd( &tic->seenby, &tic->anzseenby, &downlink->hisAka );
1032       }
1033     }
1034   }
1035   else
1036     w_log( LL_WARN, "Seen-By list is empty in TIC file for \"%s\" (wrong TIC)!",
1037            tic->file ? tic->file : "" );
1038 
1039   /* (dmitry) FixMe: Put correct AKA here if To: is missing in tic */
1040   if( isOurAka( config, tic->to ) && seenbyComp( tic->seenby, tic->anzseenby, tic->to ) )
1041     seenbyAdd( &tic->seenby, &tic->anzseenby, &tic->to );
1042   else
1043     seenbyAdd( &tic->seenby, &tic->anzseenby, filearea->useAka );
1044 
1045   seenbySort( tic->seenby, tic->anzseenby );
1046 
1047   /* Checking to whom I shall forward */
1048   for( i = 0; i < filearea->downlinkCount; i++ )
1049   {
1050     s_link *downlink = filearea->downlinks[i]->link;
1051 
1052     if( addrComp( old_from, downlink->hisAka ) != 0 &&
1053         addrComp( old_to, downlink->hisAka ) != 0 &&
1054         addrComp( tic->origin, downlink->hisAka ) != 0 )
1055     {
1056       /* Forward file to */
1057 
1058       readAccess = e_readCheck( config, filearea, downlink );
1059       switch ( readAccess )
1060       {
1061       case 0:
1062         break;
1063       case 5:
1064         w_log( LL_FROUTE, "Link %s is paused", aka2str( downlink->hisAka ) );
1065         break;
1066       case 4:
1067         w_log( LL_FROUTE, "Link %s is not subscribed to File Area %s",
1068                aka2str( old_from ), tic->area );
1069         break;
1070       case 3:
1071         w_log( LL_FROUTE, "No export (or write only) to link %s", aka2str( downlink->hisAka ) );
1072         break;
1073       case 2:
1074         w_log( LL_FROUTE, "Link's %s level provides no access", aka2str( downlink->hisAka ) );
1075         break;
1076       case 1:
1077         w_log( LL_FROUTE, "The group the area %s belongs to is neither in PublicGroup nor in link's %s AccessGrp",
1078                           filearea->areaName, aka2str( downlink->hisAka ) );
1079         break;
1080       }
1081 
1082       if( readAccess == 0 )
1083       {
1084         if( isToss == 1 && seenbyComp( old_seenby, old_anzseenby, downlink->hisAka ) == 0 )
1085         {
1086           w_log( LL_FROUTE, "File %s was already seen by %s", tic->file, aka2str( downlink->hisAka ) );
1087         }
1088         else
1089         {
1090           PutFileOnLink( newtickedfile, tic, downlink );
1091         }
1092       }                         /* if readAccess == 0 */
1093     }                           /* Forward file */
1094   }
1095   /* execute external program */
1096   for( z = 0; z < config->execonfileCount; z++ )
1097   {
1098     if( stricmp( filearea->areaName, config->execonfile[z].filearea ) != 0 )
1099       continue;
1100     if( patimat( tic->file, config->execonfile[z].filename ) == 0 )
1101       continue;
1102     else
1103     {
1104       comm = ( char * )smalloc( strlen( config->execonfile[z].command ) + 1
1105                                 + ( filearea->msgbType !=
1106                                     MSGTYPE_PASSTHROUGH ? strlen( filearea->
1107                                                                   fileName ) : strlen( config->
1108                                                                                        passFileAreaDir ) )
1109                                 + strlen( tic->file ) + 1 );
1110       if( comm == NULL )
1111       {
1112         w_log( LL_ERROR, "Exec failed - not enough memory" );
1113         continue;
1114       }
1115       sprintf( comm, "%s %s%s", config->execonfile[z].command,
1116                ( filearea->msgbType !=
1117                  MSGTYPE_PASSTHROUGH ? filearea->fileName : config->passFileAreaDir ), tic->file );
1118       w_log( LL_EXEC, "Executing \"%s\"", comm );
1119       if( ( cmdexit = system( comm ) ) != 0 )
1120       {
1121         w_log( LL_ERROR, "Exec failed with exit code %d", cmdexit );
1122       }
1123       nfree( comm );
1124     }
1125   }
1126 
1127   if( isToss == 1 )
1128     nfree( old_seenby );
1129   return ( TIC_OK );
1130 }                               /* sendToLinks */
1131 
1132 #if !defined(__UNIX__)
1133 
1134 /* FIXME: This code is nonportable and should therefore really be part
1135           of a porting library like huskylib or !!!
1136 */
1137 
1138 # if defined(__NT__)
1139 /* we can't include windows.h for several reasons ... */
1140 #  define GetFileAttributes GetFileAttributesA
1141 # endif
1142 
1143 
hidden(char * filename)1144 int hidden( char *filename )
1145 {
1146 # if (defined(__TURBOC__) && !defined(__OS2__)) || defined(__DJGPP__)
1147   unsigned fattrs;
1148 
1149   _dos_getfileattr( filename, &fattrs );
1150   return fattrs & _A_HIDDEN;
1151 # elif defined(__NT__)
1152   unsigned fattrs;
1153 
1154   fattrs = ( GetFileAttributes( filename ) & 0x2 ) ? _A_HIDDEN : 0;
1155   return fattrs & _A_HIDDEN;
1156 # elif defined (__OS2__)
1157   FILESTATUS3 fstat3;
1158   const char *p;
1159   char *q, *backslashified;
1160 
1161   /* Under OS/2 users can also use "forward slashes" in filenames because
1162    * the OS/2 C libraries support this, but the OS/2 API itself does not
1163    * support this, and as we are calling an OS/2 API here we must first
1164    * transform slashes into backslashes */
1165 
1166   backslashified = ( char * )smalloc( strlen( filename ) + 1 );
1167   for( p = filename, q = backslashified; *p; q++, p++ )
1168   {
1169     if( *p == '/' )
1170       *q = '\\';
1171     else
1172       *q = *p;
1173   }
1174   *q = '\0';
1175 
1176   DosQueryPathInfo( ( PSZ ) backslashified, 1, &fstat3, sizeof( fstat3 ) );
1177 
1178   free( backslashified );
1179 
1180   return fstat3.attrFile & FILE_HIDDEN;
1181 # else
1182 #  error "Don't know how to check for hidden files on this platform"
1183   return 0;                     /* well, we can't check if we don't know about the host */
1184 # endif
1185 }
1186 #endif
1187 
1188 /*
1189  * Return: 0 if success (look for TIC_OK in htick/h/toss.h),
1190  * positive integer if error in TIC or file (see htick/h/toss.h),
1191  * negative integer if illegal call (look for TIC_UnknownError in htick/h/toss.h).
1192  */
processTic(char * ticfile,e_tossSecurity sec)1193 enum TIC_state processTic( char *ticfile, e_tossSecurity sec )
1194 {
1195   s_ticfile tic;
1196   size_t j;
1197   FILE *flohandle;
1198   husky_DIR *dir;
1199   char *file;
1200 
1201   char tickedfile[256], linkfilepath[256];
1202   char dirname[256], *realfile, *findfile, *pos;
1203   char *newticfile;
1204   s_area *filearea;
1205   s_link *from_link, *to_link;
1206   int busy;
1207   struct stat stbuf;
1208   int writeAccess;
1209   int fileisfound = 0;
1210   int rc = 0;
1211   char *tic_origin;
1212 
1213   w_log( LL_TIC, "Processing Tic-File %s", ticfile );
1214 
1215   if( ( ticfile == NULL ) )
1216   {
1217     w_log( LL_ERROR,
1218            __FILE__
1219            ":%i: Parameter is a NULL pointer: processTic(%s,sec). This is a bug, please report it to developers.",
1220            __LINE__, ticfile ? "\"" : "", ticfile ? ticfile : "NULL", ticfile ? "\"" : "" );
1221     return TIC_UnknownError;
1222   }
1223 
1224   if( ( j = strlen( ticfile ) ) > sizeof( tickedfile ) )
1225   {
1226     w_log( LL_ERROR, "File name too long: %u. Htick limit is %u characters.", j,
1227            sizeof( tickedfile ) );
1228     w_log( LL_TIC, "Ticket file \"%s\" is skipped", ticfile );
1229     return TIC_UnknownError;
1230   }
1231 
1232   switch ( parseTic( ticfile, &tic ) )
1233   {
1234   case parseTic_error:
1235     return TIC_NotOpen;
1236   case parseTic_bad:
1237     return TIC_WrongTIC;
1238   }
1239 
1240   {
1241     int r = checkTic( ticfile, &tic );
1242 
1243     if( r > 0 )
1244       return TIC_WrongTIC;
1245     if( r < 0 )
1246       return TIC_UnknownError;
1247   }
1248 
1249   if( tic.file && strpbrk( tic.file, "/\\:" ) )
1250   {
1251     w_log( LL_SECURITY, "Directory separator found in 'File' token: '%s' of %s TIC file", tic.file,
1252            ticfile );
1253     return TIC_Security;
1254   }
1255   if( tic.replaces && strpbrk( tic.replaces, "/\\:" ) )
1256   {
1257     w_log( LL_SECURITY, "Directory separator found in 'Replace' token: '%s' of %s TIC file",
1258            tic.replaces, ticfile );
1259     return TIC_Security;
1260   }
1261 
1262   if( tic.size < 0 )
1263     w_log( LL_TIC, "File \"%s\": size: not specified, area: %s, from: %s, orig: %s",
1264            tic.file, tic.area, aka2str( tic.from ), tic_origin = aka2str5d( tic.origin ) );
1265   else
1266     w_log( LL_TIC, "File \"%s\": size: %ld, area: %s, from: %s, orig: %s",
1267            tic.file, tic.size, tic.area, aka2str( tic.from ), tic_origin =
1268            aka2str5d( tic.origin ) );
1269   nfree( tic_origin );
1270 
1271   if( tic.to.zone != 0 )
1272   {
1273     if( !isOurAka( config, tic.to ) )
1274     {
1275       /* Forwarding tic and file to another link? */
1276       to_link = getLinkFromAddr( config, tic.to );
1277       if( ( to_link != NULL ) && ( to_link->forwardPkts != fOff ) )
1278       {                         /*FIXME: should use (new) forwardTICs! */
1279         /* Send the ticket and a file to the address in line "To" of ticket. ("Transit TICs routing") */
1280         if( !
1281             ( ( to_link->forwardPkts == fSecure ) && ( sec != secProtInbound )
1282               && ( sec != secLocalInbound ) ) )
1283         {                       /* Forwarding */
1284           w_log( LL_TIC, "Forward TIC \"%s\" (and file \"%s\") to %s", ticfile, tic.file,
1285                  aka2str( tic.to ) );
1286           busy = 0;
1287           if( createOutboundFileNameAka( to_link,
1288                                          to_link->fileEchoFlavour, FLOFILE,
1289                                          SelectPackAka( to_link ) ) == 0 )
1290           {
1291             strcpy( linkfilepath, to_link->floFile );
1292             if( !busy )
1293             {                   /*  FIXME: it is always not busy!!! */
1294               *( strrchr( linkfilepath, PATH_DELIM ) ) = 0;
1295               newticfile = makeUniqueDosFileName( linkfilepath, "tic", config );
1296               if( move_file( ticfile, newticfile, 0 ) == 0 )
1297               {                 /* don't overwrite existing file */
1298                 strcpy( tickedfile, ticfile );
1299                 *( strrchr( tickedfile, PATH_DELIM ) + 1 ) = 0;
1300                 j = strlen( tickedfile );
1301                 strcat( tickedfile, tic.file );
1302                 adaptcase( tickedfile );
1303                 strcpy( tic.file, tickedfile + j );
1304                 flohandle = fopen( to_link->floFile, "a" );
1305                 fprintf( flohandle, "^%s\n", tickedfile );
1306                 fprintf( flohandle, "^%s\n", newticfile );
1307                 fclose( flohandle );
1308                 if( to_link->bsyFile )
1309                 {
1310                   remove( to_link->bsyFile );
1311                   nfree( to_link->bsyFile );
1312                 }
1313                 nfree( to_link->floFile );
1314               }
1315             }
1316           }
1317           doSaveTic( ticfile, &tic, NULL );
1318           disposeTic( &tic );
1319           return TIC_OK;
1320         }
1321       }
1322       /* not to us and no forward */
1323       w_log( LL_SECURITY, "Tic File addressed to %s, not to us", aka2str( tic.to ) );
1324       disposeTic( &tic );
1325       return TIC_NotForUs;
1326     }
1327   }
1328 
1329   /* Security Check */
1330   from_link = getLinkFromAddr( config, tic.from );
1331   if( from_link == NULL )
1332   {
1333     w_log( LL_SECURITY, "Tic from unknown link \"%s\".", aka2str( tic.from ) );
1334     disposeTic( &tic );
1335     return TIC_Security;
1336   }
1337 
1338   if( tic.password && ( ( from_link->ticPwd == NULL ) ||
1339                         ( stricmp( tic.password, from_link->ticPwd ) != 0 ) ) )
1340   {
1341     w_log( LL_SECURITY, "Wrong Password \"%s\" from \"%s\"", tic.password, aka2str( tic.from ) );
1342     disposeTic( &tic );
1343     return TIC_Security;
1344   }
1345 
1346   /* Extract directory name from ticket pathname (strip file name), construct full name of file,
1347    * adopt full pathname into real disk file, update file name in ticket */
1348   strcpy( tickedfile, ticfile );
1349   *( strrchr( tickedfile, PATH_DELIM ) + 1 ) = 0;
1350   j = strlen( tickedfile );
1351   strcat( tickedfile, tic.file );
1352   adaptcase( tickedfile );
1353   strcpy( tic.file, tickedfile + j );
1354 
1355   /* Receive file? */
1356   if( !fexist( tickedfile ) )
1357   {
1358     if( from_link->delNotReceivedTIC )
1359     {
1360       w_log( LL_TIC, "File %s from filearea %s has not been received, removing its TIC", tic.file, tic.area );
1361       disposeTic( &tic );
1362       return TIC_OK;
1363     }
1364     else
1365     {
1366       w_log( LL_TIC, "File %s from filearea %s has not been received, waiting", tic.file, tic.area );
1367       disposeTic( &tic );
1368       return TIC_NotRecvd;
1369     }
1370   }
1371 
1372 #if !defined(__UNIX__)
1373   if( hidden( tickedfile ) )
1374   {
1375     w_log( LL_TIC, "File %s from filearea %s has not been completely received, waiting", tic.file, tic.area );
1376     disposeTic( &tic );
1377     return TIC_NotRecvd;
1378   }
1379 #endif
1380 
1381   filearea = getFileArea( tic.area );
1382 
1383   w_log( LL_DEBUGU, __FILE__ ":%u:processTic(): filearea %sfound", __LINE__,
1384          filearea ? "" : "not " );
1385   if( filearea == NULL && from_link->filefix.autoCreate )
1386   {
1387     char *descr = NULL;
1388 
1389     if( tic.areadesc )
1390       descr = sstrdup( tic.areadesc );
1391     if( config->intab && descr )
1392       recodeToInternalCharset( descr );
1393     autoCreate( tic.area, descr, tic.from, NULL );
1394     filearea = getFileArea( tic.area );
1395     w_log( LL_DEBUGU, __FILE__ ":%u:processTic(): filearea %sfound", __LINE__,
1396            filearea ? "" : "not " );
1397     nfree( descr );
1398   }
1399 
1400   if( filearea == NULL )
1401   {
1402     if( from_link->filefix.autoCreate )
1403     {
1404       w_log( LL_ERROR, "Cannot create File Area %s", tic.area );
1405       if( !quiet )
1406         fprintf( stderr, "Cannot create File Area %s !\n", tic.area );
1407     }
1408     else
1409     {
1410       w_log( LL_ERROR, "Cannot open File Area %s, autocreate not allowed", tic.area );
1411       if( !quiet )
1412         fprintf( stderr, "Cannot open File Area %s, autocreate not allowed !\n", tic.area );
1413     }
1414     disposeTic( &tic );
1415     return TIC_NotOpen;
1416   }
1417 
1418   if( stat( tickedfile, &stbuf ) )
1419   {
1420     w_log( LL_ERR, "Can't check size of file \"%s\": %s. Skipping the file.", tickedfile,
1421            strerror( errno ) );
1422     stbuf.st_size = tic.size;
1423     return TIC_NotOpen;
1424   }
1425 
1426   /* Check CRC Value and reject faulty files depending on noCRC flag */
1427   if( !filearea->noCRC && tic.crc_is_present )
1428   {
1429     unsigned long crc;
1430 
1431     crc = filecrc32( tickedfile );
1432     if( ( tic.size >= 0 && ( tic.size != stbuf.st_size ) ) || ( tic.crc != crc ) )
1433     {
1434       w_log( LL_TIC, "%s of file '%s' differs with TIC. I try to find "
1435              "file with another suffix",
1436              ( tic.size != stbuf.st_size ) ? "Size" : "CRC32", tickedfile );
1437       strncpy( dirname, tickedfile, sizeof( dirname ) );
1438       pos = strrchr( dirname, PATH_DELIM );
1439       if( pos && ( pos - dirname + 4 < sizeof( dirname ) ) )
1440       {
1441         *pos = 0;
1442         findfile = pos + 1;
1443         pos = strrchr( findfile, '.' );
1444         if( pos && ( pos - dirname + 2 < sizeof( dirname ) ) )
1445         {
1446 
1447           *( ++pos ) = 0;
1448           strcat( findfile, "*" );
1449           dir = husky_opendir( dirname );
1450 
1451           if( dir )
1452           {
1453             while( ( file = husky_readdir( dir ) ) != NULL )
1454             {
1455               if( patimat( file, findfile ) )
1456               {
1457                 if( stat( file, &stbuf ) )
1458                 {
1459                   w_log( LL_ERR, "Can't check size of file \"%s\": %s. Skipping the file.",
1460                          file, strerror( errno ) );
1461                   stbuf.st_mode = 0;    /* to indicate empty structure (mode can't be zero in POSIX) */
1462                   stbuf.st_size = 0;
1463                 }
1464                 else
1465                 {
1466                   if( !stbuf.st_size && !tic.size )
1467                   {             /* file empty AND size from TIC is 0 */
1468                     /* CRC32 of an empty file is equal to zero */
1469                     if( strlen( dirname ) + strlen( file ) + 1 >= sizeof( dirname ) )
1470                     {
1471                       w_log( LL_ERR, "Path too long (max %i bytes): \"%s%c%s\"",
1472                              sizeof( dirname ), dirname, PATH_DELIM, file );
1473                     }
1474                     else
1475                     {
1476                       fileisfound = 1;
1477                       sprintf( dirname + strlen( dirname ), "%c%s", PATH_DELIM, file );
1478                       break;
1479                     }
1480                   }
1481                   else if( ( tic.size < 0 ) || ( stbuf.st_size == tic.size ) )
1482                   {
1483                     /* size not specified in TIC OR size from TIC eq filesize */
1484                     crc = filecrc32( file );
1485                     if( crc == tic.crc )
1486                     {
1487                       if( strlen( dirname ) + strlen( file ) + 1 >= sizeof( dirname ) )
1488                       {
1489                         w_log( LL_ERR, "Path too long (max %i bytes): \"%s%c%s\"",
1490                                sizeof( dirname ), dirname, PATH_DELIM, file );
1491                       }
1492                       else
1493                       {
1494                         fileisfound = 1;
1495                         sprintf( dirname + strlen( dirname ), "%c%s", PATH_DELIM, file );
1496                         break;
1497                       }
1498                     }
1499                   }
1500                 }
1501               }
1502             }
1503             husky_closedir( dir );
1504           }
1505         }
1506       }
1507 
1508       if( fileisfound )
1509       {
1510         realfile = sstrdup( dirname );
1511         *( strrchr( dirname, PATH_DELIM ) ) = 0;
1512         findfile = makeUniqueDosFileName( dirname, "tmp", config );
1513         if( rename( tickedfile, findfile ) != 0 )
1514         {
1515           w_log( LL_ERROR, "Can't rename file \"%s\" to temporary \"%s\": %s", tickedfile, findfile,
1516                  strerror( errno ) );
1517           nfree( findfile );
1518           nfree( realfile );
1519           disposeTic( &tic );
1520           return TIC_NotRecvd;
1521         }
1522         if( rename( realfile, tickedfile ) != 0 )
1523         {
1524           w_log( LL_ERROR, "Can't rename file \"%s\" to \"%s\": %s", realfile, tickedfile,
1525                  strerror( errno ) );
1526           if( rename( findfile, tickedfile ) != 0 )
1527           {
1528             w_log( LL_ERROR, "Can't rename a file back from temporary \"%s\" to \"%s\": %s",
1529                    tickedfile, findfile, strerror( errno ) );
1530           }
1531           nfree( findfile );
1532           nfree( realfile );
1533           disposeTic( &tic );
1534           return TIC_CantRename;
1535         }
1536         if( rename( findfile, realfile ) != 0 )
1537         {
1538           remove( findfile );
1539         }
1540         nfree( findfile );
1541         nfree( realfile );
1542       }
1543       else
1544       {
1545         w_log( LL_TIC, "Wrong CRC for file \"%s\", skipping this file (in tic:%08lx, need:%08lx)",
1546                tic.file, tic.crc, crc );
1547         disposeTic( &tic );
1548         return TIC_NotRecvd;
1549       }
1550     }
1551     else
1552       fileisfound = 1;
1553   }
1554   else
1555   {                             /* Search of a file in the size */
1556     if( stbuf.st_size == tic.size )
1557     {
1558       fileisfound = 1;
1559     }
1560     else
1561     {
1562       /* FIXME: Place here search of a file in his size (in same inbound as a ticket) */
1563     }
1564   }
1565 
1566   if( !stbuf.st_mode )
1567     stat( tickedfile, &stbuf );  /* Read the size of a file if function stat() has not been called earlier */
1568   tic.size = stbuf.st_size;     /* FIXME: may be wrong result for big file */
1569 
1570   /* do toss zero-length files */
1571   if( !tic.size )
1572   {
1573     w_log( LL_WARNING, "File \"%s\" from filearea %s has zero size", tic.file, tic.area );
1574   }
1575 
1576   writeAccess = e_writeCheck( config, filearea, getLinkFromAddr( config, tic.from ) );
1577 
1578   switch ( writeAccess )
1579   {
1580   case 0:
1581     break;
1582   case 4:
1583     w_log( LL_SECURITY, "Link %s not subscribed to File Area %s", aka2str( tic.from ), tic.area );
1584     disposeTic( &tic );
1585     return TIC_WrongTIC;
1586   case 3:
1587     w_log( LL_SECURITY, "No import (or read only) from link %s", aka2str( from_link->hisAka ) );
1588     disposeTic( &tic );
1589     return TIC_WrongTIC;
1590   case 2:
1591     w_log( LL_SECURITY, "Link's %s level provides no access", aka2str( from_link->hisAka ) );
1592     disposeTic( &tic );
1593     return TIC_WrongTIC;
1594   case 1:
1595     w_log( LL_SECURITY, "The group the area %s belongs to is neither in PublicGroup nor in link's %s AccessGrp",
1596                         filearea->areaName, aka2str( from_link->hisAka ) );
1597     disposeTic( &tic );
1598     return TIC_WrongTIC;
1599   }
1600 
1601   rc = sendToLinks( 1, filearea, &tic, tickedfile );
1602 
1603   if( rc == TIC_OK )            /* TIC_OK = 0 in htick/h/toss.h */
1604     doSaveTic( ticfile, &tic, filearea );
1605 
1606   disposeTic( &tic );
1607   return ( rc );
1608 }                               /* processTic */
1609 
1610 /* Toss TIC-files in the specified directory
1611  */
processDir(char * directory,e_tossSecurity sec)1612 void processDir( char *directory, e_tossSecurity sec )
1613 {
1614   husky_DIR *dir;
1615   char *file;
1616   char *dummy = NULL;
1617   int rc;
1618 
1619   if( ( directory == NULL ) )
1620   {
1621     w_log( LL_ERROR,
1622            __FILE__
1623            ":%i: Parameter is a NULL pointer: processDir(%s%s%s,sec). This is a bug, please report it to developers.",
1624            __LINE__, directory ? "\"" : "", directory ? directory : "NULL", directory ? "\"" : "" );
1625     return;
1626   }
1627 
1628   dir = husky_opendir( directory );
1629   if( dir == NULL )
1630     return;
1631 
1632   while( ( file = husky_readdir( dir ) ) != NULL )
1633   {
1634 #ifdef DEBUG_HPT
1635     printf( "testing %s\n", file );
1636 #endif
1637 
1638     if( ( ( cmToss == 1 ) && ( patimat( file, "*.TIC" ) == 1 ) ) ||
1639         ( ( cmToss == 2 ) && ( ( patimat( file, "*.BAD" ) == 1 ) ||
1640                                ( patimat( file, "*.SEC" ) == 1 ) ||
1641                                ( patimat( file, "*.ACS" ) == 1 ) ||
1642                                ( patimat( file, "*.NTU" ) == 1 ) ) ) )
1643     {
1644       xstrscat( &dummy, directory, file, NULL );
1645 
1646 #if !defined(__UNIX__)
1647       if( !hidden( dummy ) )
1648       {
1649 #endif
1650         rc = processTic( dummy, sec );
1651         if( cmToss == 1 )
1652         {
1653           switch ( rc )
1654           {
1655           case TIC_Security:   /* pktpwd problem */
1656             changeFileSuffix( dummy, "sec", 1 );
1657             break;
1658           case TIC_NotOpen:    /* could not open file */
1659           case TIC_CantRename:
1660           case TIC_IOError:
1661             changeFileSuffix( dummy, "acs", 1 );
1662             break;
1663           case TIC_WrongTIC:   /* not/wrong pkt */
1664             changeFileSuffix( dummy, "bad", 1 );
1665             break;
1666           case TIC_NotForUs:   /* not to us */
1667             changeFileSuffix( dummy, "ntu", 1 );
1668             break;
1669           case TIC_NotRecvd:   /* file not recieved */
1670             break;
1671           case TIC_OK:         /* OK */
1672             remove( dummy );
1673             break;
1674           default:             /* Unknown, do nothing */
1675             break;
1676           }                     /* switch */
1677         }
1678         else if( rc == TIC_OK )
1679         {
1680           remove( dummy );
1681         }
1682 #if !defined(__UNIX__)
1683       }
1684 #endif
1685       nfree( dummy );
1686     }                           /* if */
1687   }                             /* while */
1688   husky_closedir( dir );
1689 }                               /* processDir() */
1690 
1691 /* Scan directory with postponed files
1692  */
checkTmpDir(void)1693 void checkTmpDir( void )
1694 {
1695   char tmpdir[256], newtickedfile[256], newticfile[256];
1696   husky_DIR *dir = NULL;
1697   char *file = NULL;
1698   s_link *link = NULL;
1699   s_ticfile tic;
1700   s_area *filearea = NULL;
1701   FILE *flohandle = NULL;
1702   int error = 0;
1703 
1704   w_log( LL_TIC, "Checking tmp dir" );
1705   strcpy( tmpdir, config->busyFileDir );
1706   dir = husky_opendir( tmpdir );
1707   if( dir == NULL )
1708     return;
1709 
1710   while( ( file = husky_readdir( dir ) ) != NULL )
1711   {
1712     int file_length = strlen( file );
1713 
1714     if( file_length != 12 )
1715       continue;                 /* Check only ticket files: 8 characters followed by ".tic" */
1716     if( stricmp( file + 8, ".TIC" ) == 0 )
1717     {
1718       char *ticfile = ( char * )smalloc( strlen( tmpdir ) + file_length + 1 );
1719 
1720       if( !ticfile )
1721         continue;
1722       strcpy( ticfile, tmpdir );
1723       strcat( ticfile, file );
1724 
1725       memset( &tic, 0, sizeof( tic ) );
1726       if( parseTic( ticfile, &tic ) != parseTic_success )
1727         continue;
1728       if( checkTic( ticfile, &tic ) )
1729         continue;
1730       link = getLinkFromAddr( config, tic.to );
1731       if( !link )
1732         continue;
1733       /*  createFlo doesn't  support ASO!!! */
1734       /* if (createFlo(link,cvtFlavour2Prio(link->fileEchoFlavour))==0) { */
1735       if( createOutboundFileNameAka( link, link->fileEchoFlavour, FLOFILE, SelectPackAka( link ) )
1736           == 0 )
1737       {
1738         filearea = getFileArea( tic.area );
1739         if( filearea != NULL )
1740         {
1741           if( filearea->msgbType != MSGTYPE_PASSTHROUGH && !filearea->sendorig )
1742             strcpy( newtickedfile, filearea->fileName );
1743           else
1744             strcpy( newtickedfile, config->passFileAreaDir );
1745           strcat( newtickedfile, tic.file );
1746           adaptcase( newtickedfile );
1747           if( !link->noTIC )
1748           {
1749             if( config->separateBundles )
1750             {
1751               strcpy( newticfile, link->floFile );
1752               sprintf( strrchr( newticfile, '.' ), ".sep%c", PATH_DELIM );
1753             }
1754             else
1755             {
1756               strcpy( newticfile, config->ticOutbound );
1757             }
1758             _createDirectoryTree( newticfile );
1759             strcat( newticfile, strrchr( ticfile, PATH_DELIM ) + 1 );
1760             if( !fexist( ticfile ) )
1761               w_log( LL_ERROR, "File %s not found", ticfile );
1762             else if( move_file( ticfile, newticfile, 1 ) != 0 )
1763             {                   /* overwrite existing file if not the same */
1764               w_log( LL_ERROR, "File %s not moveable to %s: %s",
1765                      ticfile, newticfile, strerror( errno ) );
1766               error = 1;
1767             }
1768           }
1769           else
1770             remove( ticfile );
1771           if( !error )
1772           {
1773             flohandle = fopen( link->floFile, "a" );
1774             fprintf( flohandle, "%s\n", newtickedfile );
1775             if( !link->noTIC )
1776               fprintf( flohandle, "^%s\n", newticfile );
1777             fclose( flohandle );
1778 
1779             w_log( LL_TIC, "Forwarding save file \"%s\" for %s",
1780                    tic.file, aka2str( link->hisAka ) );
1781           }
1782         }                       /* if filearea */
1783       }                         /* if createFlo */
1784       if( link->bsyFile )
1785       {
1786         remove( link->bsyFile );
1787         nfree( link->bsyFile );
1788       }
1789       nfree( link->floFile );
1790       disposeTic( &tic );
1791       nfree( ticfile );
1792     }                           /* if ".TIC" */
1793   }                             /* while */
1794   husky_closedir( dir );
1795 }
1796 
1797 /*
1798  * Return: 0 if error, 1 if success
1799  */
putMsgInArea(s_area * echo,s_message * msg,int strip,dword forceattr)1800 int putMsgInArea( s_area * echo, s_message * msg, int strip, dword forceattr )
1801 {
1802   char *ctrlBuff, *textStart, *textWithoutArea;
1803   UINT textLength = ( UINT ) msg->textLength;
1804   HAREA harea = NULL;
1805   HMSG hmsg;
1806   XMSG xmsg;
1807   char /**slash,*/ *p, *q, *tiny;
1808   int rc = 0;
1809 
1810   if( ( echo == NULL ) || ( msg == NULL ) )
1811   {
1812     w_log( LL_ERROR, __FILE__ ":%i: Parameter is a NULL pointer: putMsgInArea(%s,%s,%i,%u). "
1813            "This is a bug, please report it to developers.",
1814            __LINE__, echo ? "echo" : "NULL", msg ? "msg" : "NULL", strip, ( unsigned )forceattr );
1815     return 0;
1816   }
1817 
1818   if( echo->msgbType == MSGTYPE_PASSTHROUGH )
1819   {
1820     w_log( LL_ERROR, "Can't put a message to passthrough area %s!", echo->areaName );
1821     return rc;
1822   }
1823 
1824   if( !msg->netMail )
1825   {
1826     msg->destAddr.zone = echo->useAka->zone;
1827     msg->destAddr.net = echo->useAka->net;
1828     msg->destAddr.node = echo->useAka->node;
1829     msg->destAddr.point = echo->useAka->point;
1830   }
1831 
1832   harea = MsgOpenArea( ( UCHAR * ) echo->fileName, MSGAREA_CRIFNEC,
1833                        ( word ) ( echo->msgbType | ( msg->netMail ? 0 : MSGTYPE_ECHO ) ) );
1834   if( harea != NULL )
1835   {
1836     hmsg = MsgOpenMsg( harea, MOPEN_CREATE, 0 );
1837     if( hmsg != NULL )
1838     {
1839 
1840       textWithoutArea = msg->text;
1841 
1842       if( ( strip == 1 ) && ( strncmp( msg->text, "AREA:", 5 ) == 0 ) )
1843       {
1844         /*  jump over AREA:xxxxx\r */
1845         while( *( textWithoutArea ) != '\r' )
1846           textWithoutArea++;
1847         textWithoutArea++;
1848         textLength -= ( size_t ) ( textWithoutArea - msg->text );
1849       }
1850 
1851       if( echo->killSB )
1852       {
1853         tiny = strrstr( textWithoutArea, " * Origin:" );
1854         if( tiny == NULL )
1855           tiny = textWithoutArea;
1856         if( NULL != ( p = strstr( tiny, "\rSEEN-BY: " ) ) )
1857         {
1858           p[1] = '\0';
1859           textLength = ( size_t ) ( p - textWithoutArea + 1 );
1860         }
1861       }
1862       else if( echo->tinySB )
1863       {
1864         tiny = strrstr( textWithoutArea, " * Origin:" );
1865         if( tiny == NULL )
1866           tiny = textWithoutArea;
1867         if( NULL != ( p = strstr( tiny, "\rSEEN-BY: " ) ) )
1868         {
1869           p++;
1870           if( NULL != ( q = strstr( p, "\001PATH: " ) ) )
1871           {
1872             /*  memmove(p,q,strlen(q)+1); */
1873             memmove( p, q, textLength - ( size_t ) ( q - textWithoutArea ) + 1 );
1874             textLength -= ( size_t ) ( q - p );
1875           }
1876           else
1877           {
1878             p[0] = '\0';
1879             textLength = ( size_t ) ( p - textWithoutArea );
1880           }
1881         }
1882       }
1883 
1884       {
1885         byte *bb;               /* Prevent GCC warning "dereferencing type-punned pointer will break strict-aliasing rules" */
1886 
1887         ctrlBuff = ( char * )CopyToControlBuf( textWithoutArea, &bb, &textLength );
1888         textStart = bb;
1889       }
1890       /*  textStart is a pointer to the first non-kludge line */
1891       xmsg = createXMSG( config, msg, NULL, forceattr, NULL );
1892 
1893       if( MsgWriteMsg( hmsg, 0, &xmsg, ( byte * ) textStart, ( dword )
1894                        textLength, ( dword ) textLength,
1895                        ( dword ) strlen( ctrlBuff ), ( byte * ) ctrlBuff ) != 0 )
1896         w_log( LL_ERROR, "Could not write msg in %s!", echo->fileName );
1897       else
1898         rc = 1;                 /*  normal exit */
1899 
1900       if( MsgCloseMsg( hmsg ) != 0 )
1901       {
1902         w_log( LL_ERROR, "Could not close msg in %s!", echo->fileName );
1903         rc = 0;
1904       }
1905       nfree( ctrlBuff );
1906 
1907     }
1908     else
1909       w_log( LL_ERROR, "Could not create new msg in %s!", echo->fileName );
1910     /* endif */
1911     MsgCloseArea( harea );
1912   }
1913   else
1914     w_log( LL_ERROR, "Could not open/create EchoArea %s!", echo->fileName );
1915   /* endif */
1916   return rc;
1917 }
1918 
1919 /*
1920  * Return: o if error, 1 of success
1921  */
putMsgInBadArea(s_message * msg,hs_addr pktOrigAddr)1922 int putMsgInBadArea( s_message * msg, hs_addr pktOrigAddr )
1923 {
1924   char *tmp = NULL, *line = NULL, *textBuff = NULL, *areaName = NULL, *reason = NULL;
1925 
1926   if( ( msg == NULL ) )
1927   {
1928     w_log( LL_ERROR,
1929            __FILE__
1930            ":%i: Parameter is a NULL pointer: putMsgInBadArea(NULL,pktOrigAddr). This is a bug, please report it to developers.",
1931            __LINE__ );
1932     return 0;
1933   }
1934 
1935   /*  get real name area */
1936   line = strchr( msg->text, '\r' );
1937   if( strncmp( msg->text, "AREA:", 5 ) == 0 )
1938   {
1939     *line = 0;
1940     xstrcat( &areaName, msg->text + 5 );
1941     *line = '\r';
1942   }
1943   reason = "report to passthrough area";
1944   tmp = msg->text;
1945 
1946   while( ( line = strchr( tmp, '\r' ) ) != NULL )
1947   {
1948     if( *( line + 1 ) == '\x01' )
1949       tmp = line + 1;
1950     else
1951     {
1952       tmp = line + 1;
1953       *line = 0;
1954       break;
1955     }
1956   }
1957 
1958   xstrscat( &textBuff, msg->text, "\rFROM: ", aka2str( pktOrigAddr ), "\rREASON: ", reason, "\r",
1959             NULL );
1960 
1961   if( areaName )
1962     xscatprintf( &textBuff, "AREANAME: %s\r\r", areaName );
1963   xstrcat( &textBuff, tmp );
1964   nfree( areaName );
1965   nfree( msg->text );
1966   msg->text = textBuff;
1967   msg->textLength = strlen( msg->text );
1968   if( putMsgInArea( &( config->badArea ), msg, 0, 0 ) )
1969   {
1970     return 1;
1971   }
1972   return 0;
1973 }
1974 
1975 /* Append tearline and origin lines into message text and create message in the
1976  * specified area.
1977  * If areaName is NULL pointer or does not exist: netmail will be placed in the first
1978  * netmail area, echomail will be placed in badarea.
1979  */
writeMsgToSysop(s_message * msg,char * areaName,char * origin)1980 void writeMsgToSysop( s_message * msg, char *areaName, char *origin )
1981 {
1982   s_area *echo;
1983 
1984   if( ( msg == NULL ) )
1985   {
1986     w_log( LL_ERROR,
1987            __FILE__
1988            ":%i: Parameter is a NULL pointer: writeMsgToSysop(NULL,...). This is a bug, please report it to developers.",
1989            __LINE__ );
1990     return;
1991   }
1992 
1993   xscatprintf( &( msg->text ), " \r--- %s\r * Origin: %s (%s)\r",
1994                ( config->tearline ) ? config->tearline : "",
1995                origin ? origin : ( config->origin ) ? config->origin : config->name,
1996                aka2str( msg->origAddr ) );
1997 
1998   msg->textLength = strlen( msg->text );
1999   if( msg->netMail == 1 )
2000     writeNetmail( msg, areaName );
2001   else
2002   {
2003     echo = getArea( config, areaName );
2004     if( echo != &( config->badArea ) && echo->msgbType != MSGTYPE_PASSTHROUGH )
2005     {
2006       putMsgInArea( echo, msg, 1, MSGLOCAL );
2007       w_log( LL_POSTING, "Post report message to %s area", echo->areaName );
2008     }
2009     else
2010     {
2011       w_log( LL_POSTING, "Post report message to %s area", config->badArea.areaName );
2012       putMsgInBadArea( msg, msg->origAddr );
2013     }
2014   }
2015 }
2016 
toss()2017 void toss(  )
2018 {
2019 
2020   w_log( LL_INFO, "Start tossing..." );
2021 
2022   if (config->localInbound && config->localInbound[0] ) processDir( config->localInbound, secLocalInbound );
2023   if (config->protInbound && config->protInbound[0] ) processDir( config->protInbound, secProtInbound );
2024   if (config->inbound && config->inbound[0] ) processDir( config->inbound, secInbound );
2025 
2026 }
2027