1 /* EMAILPKT: Husky e-mailer
2  *
3  * (C) Copyleft Stas Degteff 2:5080/102@FIDOnet, g@grumbler.org
4  * (c) Copyleft Husky developers team http://husky.sorceforge.net/team.html
5  *
6  * $Id$
7  * Send FTN via email
8  *
9  * For latest version see http://husky.sorceforge.net/emailpkt
10  *
11  * This file is part of EMAILPKT, module of The HUSKY Fidonet Software.
12  *
13  * EMAILPKT is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public
15  * License as published by the Free Software Foundation; either
16  * version 2 of the License, or (at your option) any later version.
17  *
18  * EMAILPKT is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
21  * General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public
24  * License along with this library; see file COPYING. If not, write to the Free
25  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
26  *
27  * See also http://www.gnu.org, license may be found here.
28  *****************************************************************************
29  */
30 
31 /* libc */
32 #include <string.h>
33 #include <stdio.h>  /*FILE operations*/
34 #include <time.h>
35 #include <stdlib.h>
36 #include <errno.h>
37 #include <sys/types.h>
38 #include <ctype.h>
39 #include <limits.h>
40 
41 #include <smapi/compiler.h>
42 
43 #ifdef HAS_UNISTD_H
44 #  include <unistd.h>
45 #endif
46 #ifdef HAS_DIRENT_H
47 #  include <dirent.h>
48 #endif
49 
50 /* husky */
51 #include <fidoconf/log.h>
52 #include <fidoconf/temp.h>
53 #include <fidoconf/xstr.h>
54 
55 /* ./ */
56 #include "ecommon.h"
57 #include "version.h"
58 
59 #if defined(__MINGW32__) || defined(_MSC_VER)
60 #  define random() rand()
61 #endif
62 
63 #ifndef nfree
64 #  define nfree(a) ({ if (a != NULL) { fprintf(stderr,"hesend.c:%d nfree()\n",__LINE__); free(a); a = NULL; } })
65 #endif
66 
67 #define PROGRAMNAME "hesend"
68 #define TEMPEXT "emo"        /* "e-mail outgoing" */
69 #define TEMPFLOEXT "flo"
70 
71 s_fidoconfig *config=NULL;
72 static int sent = 0, allsent=0;           /* sent files count */
73 
74 int SAVEFLAG=0;  /* Save processed e-mail messages (for debugging) */
75 int debugflag=0; /* Execute in debug mode (not call sendmail, not remove files) */
76 
77 /* Write e-mail messsage with attached file (bundle)
78  * Return filename or NULL
79  */
writeMessage(const char * fullFileName,s_link link)80 char *writeMessage(const char *fullFileName, s_link link)
81 { char adr[ADRS_MAX];
82   char basefilename[NAME_MAX];
83   char *tempfilename=NULL, timebuf[32], *msgidbuf=NULL;
84   FILE *infd=NULL, *tempfd=NULL;
85   char *cp=NULL;
86   time_t t=0;
87   struct tm *tm=NULL;
88   int i;
89 
90   w_log(LL_FUNC,"writeMessage()");
91 
92   snprintaddr(adr, sizeof(adr), link.hisAka);
93 
94   w_log(LL_FILENAME, "Full file name: '%s'", fullFileName);
95   /* input file name */
96   if ((infd = fopen(fullFileName, "r")) == NULL) {
97       w_log( LL_ERR, "Can't open '%s': %s", fullFileName, strerror(errno));
98       return NULL;
99   }
100 
101   tempfd = createTempFileIn(config->tempOutbound, TEMPEXT, 'b', &tempfilename);
102   if( !tempfd ) {
103       fclose(infd);
104       w_log( LL_ERR, "Can't create temp file in '%s': %s",
105                      config->tempOutbound, strerror(errno));
106       return NULL;
107   } /*else w_log(LL_FILENAME, "tempfilename=%s", tempfilename);*/
108 
109   /* for netmail (.?ut) change ext to pkt */
110   i = sstrlen(fullFileName);
111   if( tolower(fullFileName[i-2]) == 'u' && tolower(fullFileName[i-1]) == 't' )
112   { if( (cp = makeUniqueDosFileName( "", "pkt", config)) )
113     { strncpy(basefilename, cp, sizeof(basefilename));
114       nfree( cp );
115     }else w_log(LL_CRIT, "Can't generate unique dos file name: memory too low" );
116   }else
117   {
118     sstrncpy( basefilename, (char*)basename(fullFileName), sizeof(basefilename) );
119     w_log(LL_FILENAME, "Base file name: '%s'", basefilename);
120   }
121 
122   /* print some headers */
123   if( link.emailFrom == NULL )
124   {
125      fprintf(tempfd, "From: \"%s\" <%s>\n", DEFAULT_FROMNAME, DEFAULT_FPOMADDR);
126      w_log(LL_WARN, "Undefined emailFrom for %s, use default: %s",
127           adr, DEFAULT_FPOMADDR );
128   }
129   else
130     fprintf(tempfd, "From: \"%s\" <%s>\n", DEFAULT_FROMNAME, link.emailFrom );
131 
132   fprintf(tempfd, "To: %s\n", link.email );
133 
134   if( link.emailSubj == NULL )
135   {
136      fprintf(tempfd, "Subject: %s\n", DEFAULT_SUBJECT );
137      w_log(LL_WARN, "Undefined emailSubj for %s, use default: %s",
138              link.emailSubj, DEFAULT_SUBJECT );
139   }
140   else fprintf(tempfd, "Subject: %s\n", link.emailSubj );
141 
142 
143   time (&t);
144   tm = localtime (&t);
145 
146   strftime(timebuf, sizeof (timebuf), "%a, %d %b %Y %H:%M:%S %z", tm);
147   fprintf(tempfd, "Date: %s\n", timebuf);
148 
149   strftime(timebuf, sizeof (timebuf), "%s", tm);
150 
151 /*
152     xscatprintf( &msgidbuf, "%s %ul", timebuf, (unsigned long)random());
153 */
154   if( link.emailFrom )
155     xscatprintf( &msgidbuf, "%s.%lu.%s", timebuf, (unsigned long)random(), link.emailFrom );
156   else if( link.ourAka[0].point )
157     xscatprintf( &msgidbuf,
158                     "%s.%lu@p%u.f%u.n%u.z%u.%s.org\n", timebuf,
159                     (unsigned long)random(), link.ourAka[0].point, link.ourAka[0].node,
160                     link.ourAka[0].net, link.ourAka[0].zone,
161                     link.ourAka[0].domain ? link.ourAka[0].domain : "fidonet" );
162   else
163     xscatprintf( &msgidbuf,
164                     "%s.%lu@f%u.n%u.z%u.%s.org\n", timebuf,
165                     (unsigned long)random(), link.ourAka[0].node,
166                     link.ourAka[0].net, link.ourAka[0].zone,
167                     link.ourAka[0].domain ? link.ourAka[0].domain : "fidonet" );
168 
169   fprintf( tempfd, "Message-ID: <%s>\n", msgidbuf );
170   fprintf( tempfd, "X-Mailer: %s\n", program_name);
171 
172   switch( link.emailEncoding ){
173 
174   case eeUUE:  /* uuencode file */
175 
176       w_log(LL_ENCODE, "Encode method for %s: UUE", adr );
177 
178       if( strlen(DEFAULTBODY)>0 )
179       {
180         fprintf(tempfd, "\n\n%s\n", DEFAULTBODY);
181       }
182 
183       uuencodeFile(infd, tempfd, basefilename, 0, 0);
184       break;
185 
186 /* SEAT internal "protocol" - MIME/base64 encoding */
187 /*
188   case eeIREX:
189 
190       fprintf(tempfd, "Mime-Version: 1.0\n");
191       fprintf(tempfd, "Content-Type: multipart/mixed; boundary=\"%s\"\n",MIMEBOUNDARY);
192 
193       fprintf(tempfd, "Ftn-File-ID: %s\n", msgidbuf );
194       fprintf(tempfd, "Ftn-Crc32: %X\n", crc32 );
195       fprintf(tempfd, "Ftn-Seg: %u-%u\n", segno, seg );
196       fprintf(tempfd, "Ftn-Seg-Crc32: %X\n", crc32seg );
197       fprintf(tempfd, "Ftn-Seg-ID: %u.%s", segno, msgidbuf );
198 
199       if( strlen(DEFAULTBODY)>0 )
200       {
201         fprintf(tempfd, "\n\n%s\n", DEFAULTBODY);
202       }
203 
204 //This is a MIME encoded message generated by Internet Rex.
205 //If your mailer doesn't support this type of coding,
206 //you can decode the file attached using a program like
207 //'munpack'.  'munpack' is available for anonymous FTP
208 //from ftp://ftp.andrew.cmu.edu/pub/mpack
209 
210 */
211   case eeSEAT:  /* SEAT "protocol" - MIME/base64 encoding */
212       w_log(LL_ENCODE, "Encode method for %s: SEAT (MIME)", adr );
213   case eeMIME:  /* MIME/base64 */
214       w_log(LL_ENCODE, "Encode method for %s: MIME", adr );
215   default:
216       w_log(LL_ENCODE, "Encode method for %s: MIME (default)", adr );
217 
218       /* Main section */
219       fprintf(tempfd, "Mime-Version: 1.0\n");
220       fprintf(tempfd, "Content-Type: multipart/mixed; boundary=\"%s\"\n",MIMEBOUNDARY);
221 
222       fprintf(tempfd, "\n--%s\n",MIMEBOUNDARY);
223       fprintf(tempfd, "Content-Type: text/plain");
224       if( strlen(DEFAULTBODY)>0 )
225       {
226         fprintf(tempfd, "\n\n%s\n", DEFAULTBODY);
227       }
228 
229       /* Attachment section */
230       fprintf(tempfd, "\n--%s\n",MIMEBOUNDARY);
231       fprintf(tempfd, "Content-Type: application/octet-stream; name=\"%s\"\n", basefilename);
232       fprintf(tempfd, "Content-Transfer-Encoding: base64\n");
233       fprintf(tempfd, "Content-Disposition: attachment; filename=\"%s\"\n\n", basefilename);
234 
235       base64encodeFile(infd, tempfd);
236 
237       fprintf(tempfd, "\n\n--%s--\n",MIMEBOUNDARY);
238       break;
239 
240 
241   } /* switch */
242 
243   fclose(infd);
244   fclose(tempfd);
245 
246   nfree(msgidbuf);
247 /*  nfree(cp);            not malloc'ed */
248 /*  nfree(basefilename);  not malloc'ed */
249   w_log(LL_FILENAME, "Return file name: '%s'", tempfilename );
250   w_log(LL_FUNC,"writeMessage() OK");
251   return sstrdup(tempfilename);
252 }
253 
254 /* Send written message
255  */
sendFile(const char * filename,s_link link)256 int sendFile(const char *filename, s_link link)
257 { char *buf=NULL, *cmd=NULL, *p=NULL;
258   int rc;
259 
260   w_log(LL_FUNC,"sendFile()");
261 
262   /* Contruct sendmail command
263      If $a and $f not present use 'sendmailcmd address < file'
264   */
265   cmd = sstrdup( config->sendmailcmd );
266 w_log(LL_DEBUGS,"%s::sendFile():%u Command construct: '%s'", __FILE__, __LINE__, cmd);
267   p=strstr(cmd, "$a");
268   if( p ){
269     *p++ = '%'; *p='s';
270     xscatprintf( &buf, cmd, link.email);
271   }
272   else
273     xscatprintf( &buf, "%s %s", config->sendmailcmd, link.email);
274   nfree(cmd);
275 
276 w_log(LL_DEBUGS,"%s::sendFile():%u Command construct: '%s'", __FILE__, __LINE__, cmd);
277 
278   p=strstr(buf, "$f");
279   if( p ){
280     *p++ = '%'; *p='s';
281     xscatprintf( &cmd, buf, filename);
282   }
283   else
284     xscatprintf( &cmd, "%s < %s", buf, filename);
285   nfree(buf);
286 
287   w_log(LL_EXEC,"Execute '%s'",cmd);
288   if( debugflag>1 ){
289     w_log(LL_ERR, "(debug) Cmd line: '%s'", cmd);
290   }else
291     if( (rc = system(cmd)) != 0)
292     {
293       w_log(LL_ERR, "Calling error (rc=%d)", rc );
294       w_log(LL_ERR, "(cmd line: '%s')", cmd);
295       nfree(cmd);
296       w_log(LL_FUNC,"sendFile() failed");
297       return rc;
298     }
299 
300   w_log(LL_FILESENT, "Sent '%s' to %s (%s)", filename, link.email,
301           snprintaddr(cmd, sstrlen(cmd), link.hisAka)
302      );
303 
304   /* todo: save to confirmation */
305   if( debugflag && !SAVEFLAG )
306      w_log(LL_DEL, "(debug) Remove '%s'",filename);
307   else if (!SAVEFLAG)
308      delete(filename);
309   else
310      w_log(LL_DEL, "(Save flag is set) Keep '%s'",filename);
311 
312   nfree(cmd);
313   w_log(LL_FUNC,"sendFile() OK");
314   return 0;
315 }
316 
317 
318 /* Process outbound netmail for link (.?ut): scan BSO & send ?ut for this link
319  */
processNet(s_link link)320 int processNet(s_link link)
321 { char adr[ADRS_MAX], *messagefile=NULL;
322   int lenvar=0, rc=0, RC=0, ch=0;
323   char flavorCharsUse[] = "ocid";   /* flavores for send netmail (hold not sent) */
324 
325   w_log(LL_FUNC,"processNet()");
326   adr[0]=0;
327 
328   if( (lenvar = strlen(link.pktFile)-3) <0 )
329   { w_log(LL_ERR, "Illegal pktFile for link %s (%s)",
330           snprintaddr(adr, sizeof(adr), link.hisAka), link.pktFile );
331     return 1;
332   }
333 
334   for( ch=strlen(flavorCharsUse)-1; ch >=0; ch--)
335   {
336     link.pktFile[lenvar]=flavorCharsUse[ch];
337 
338     if ( testfile(link.pktFile) )
339       continue;
340     w_log(LL_FILENAME, "pktFile '%s'", link.pktFile);
341 
342     if( (messagefile=writeMessage(link.pktFile, link)) == NULL)
343     { w_log(LL_ERR, "Skip on compose error: '%s'", link.pktFile );
344       RC++;
345       continue;
346     }
347     if( (rc = sendFile(messagefile,link)) !=0 )
348     { w_log(LL_ERR, "Skip on send error: '%s'", link.pktFile );
349       RC++;
350       continue;
351     }
352     sent++;
353     w_log(LL_SENT, "Sent '%s' to %s (%s)\n", link.pktFile, link.email,
354             snprintaddr(messagefile, strlen(messagefile) ,link.hisAka)
355        );
356 
357     if( debugflag )
358         w_log(LL_ERR, "(debug) Remove '%s'",link.floFile);
359     else if( (rc=delete(link.pktFile)) )
360     {    w_log(LL_ERR, "File '%s' not removed: %s", link.pktFile, strerror(rc));
361          RC++;
362     }
363     else
364         w_log(LL_DEL, "Removed '%s'", link.pktFile);
365 
366   }
367   w_log(LL_FUNC,"processNet() OK");
368   return rc;
369 }
370 
371 /* Process outbound echomail for link (.?lo): scan outbound for ?lo, read its
372  * and send files listed in.
373  */
processFlo(s_link link)374 int processFlo(s_link link)
375 { FILE *flofd=NULL, *tempflofd=NULL;
376   char buf[PATH_MAX], filetosend[PATH_MAX], *messagefile=NULL;
377   char *tempfloname=NULL;
378   int ch=0, replacefloflag=0, delflag = 0, truncflag = 0, lenvar = 0, rc=0;
379   char flavorCharsUse[] = "fcid";   /* flavores for send echomail */
380 
381   w_log(LL_FUNC,"processFlo()");
382 
383   if( (lenvar = strlen(link.floFile)-3) <0 )
384   { w_log(LL_ERR, "Illegal floFile for link %s (%s)",
385           snprintaddr(buf, sizeof(buf), link.hisAka), link.floFile );
386     return 1;
387   }
388 
389   /* scan directory for ?lo files */
390   for( ch=strlen(flavorCharsUse)-1; ch >=0; ch--)
391   {
392     link.floFile[lenvar]=flavorCharsUse[ch];
393 
394     if( testfile(link.floFile) )
395       continue;
396 
397     if( (flofd = fopen(link.floFile, "rt")) == NULL)
398     {  w_log(LL_ERR, "Cannot open '%s': %s", link.floFile, strerror(errno));
399        continue;
400     }
401 
402     if( NULL==(tempflofd = createTempFileIn(config->tempOutbound, TEMPFLOEXT, 't', &tempfloname)) )
403     { w_log(LL_ERR, "Can't create temporary .FLO file");
404       return 1;
405     }
406     w_log(LL_FILE,"Process '%s'",link.floFile);
407     replacefloflag=0;
408     /* read lines from flo file */
409     while (fgets(buf, sizeof(buf), flofd) != NULL)
410     { delflag = 0;
411       truncflag = 0;
412       if (buf[0] == '^')
413       {
414         delflag = 1;
415         strncpy(filetosend, buf+1, sizeof(filetosend));
416         if( strlen(filetosend)!=strlen(buf+1) )
417         { w_log(LL_ERR,"processFlo(): Too long filename '%s' in '%s', can't send", buf+1, link.floFile);
418           replacefloflag=1;
419           fprintf(tempflofd, "%s\r\n", buf);
420           continue;
421         }
422       }else if (buf[0] == '#')
423       {
424         truncflag = 1;
425         strncpy(filetosend, buf+1, sizeof(filetosend));
426         if( strlen(filetosend)!=strlen(buf+1) )
427         { w_log(LL_ERR,"processFlo(): Too long filename '%s' in '%s', can't send", buf+1, link.floFile);
428           replacefloflag=1;
429           fprintf(tempflofd, "%s\r\n", buf);
430           continue;
431         }
432       }else
433       { strncpy(filetosend, buf, sizeof(filetosend));
434         if( strlen(filetosend)!=strlen(buf) )
435         { w_log(LL_ERR,"processFlo(): Too long filename '%s' in '%s', can't send", buf, link.floFile);
436           replacefloflag=1;
437           fprintf(tempflofd, "%s\r\n", buf);
438           continue;
439         }
440       }
441 
442 /*        stripLeadingChars(filetosend,"\r\n");*/   /* remove the trailing \r & \n */
443       stripCRLF(filetosend);
444       if(strlen(filetosend)==0)
445         continue;
446 
447       /* Next block: don't remove file from .flo if file not exist */
448       if( testfile(filetosend) )
449       { w_log(LL_FLO, "File not exist! '%s'",filetosend);
450         replacefloflag=1;
451         if(delflag) fprintf(tempflofd, "^");
452         else if(truncflag) fprintf(tempflofd, "#");
453         fprintf( tempflofd, "%s\r\n", filetosend );
454         continue;
455       }
456       w_log(LL_FILE, "Bundle '%s'", filetosend);
457 
458       nfree(messagefile);
459       if( (messagefile=writeMessage(filetosend, link)) == NULL)
460       { w_log(LL_ERR, "Skip on compose error: '%s'", buf );
461         replacefloflag=1;
462         if(delflag) fprintf(tempflofd, "^");
463         else if(truncflag) fprintf(tempflofd, "#");
464         fprintf( tempflofd, "%s\r\n", filetosend );
465         continue;
466       }
467       if( (rc = sendFile(messagefile,link)) !=0 )
468       { w_log(LL_ERR, "Skip on send error: '%s'", buf );
469         nfree(messagefile);
470         replacefloflag=1;
471         if(delflag) fprintf(tempflofd, "^");
472         else if(truncflag) fprintf(tempflofd, "#");
473         fprintf( tempflofd, "%s\r\n", filetosend );
474         continue;
475       }
476       sent++;
477       w_log(LL_SENT, "Sent '%s' to %s (%s)\n", filetosend, link.email,
478               snprintaddr(messagefile, strlen(messagefile) ,link.hisAka)
479          );
480 
481       if( debugflag && delflag )
482           w_log(LL_ERR, "(debug) Delete file: '%s'", filetosend);
483       else if( delflag )
484       {
485         if( (rc=delete(filetosend)) )
486           w_log(LL_ERR, "Can't remove file '%s': %s", filetosend, strerror(rc));
487         else
488           w_log(LL_DEL, "Removed '%s'", filetosend);
489       }
490       else if( debugflag && truncflag )
491         w_log(LL_ERR, "(debug) Truncate file: '%s'", filetosend);
492       else if( truncflag )
493       {
494         if( (rc=truncat(filetosend)) )
495           w_log(LL_ERR, "Can't truncate file '%s': %s", filetosend, strerror(errno));
496         else
497           w_log(LL_TRUNC, "Truncated '%s'", filetosend);
498       }
499 
500       nfree(messagefile);
501     } /* while */
502     fclose(flofd);
503     fclose(tempflofd);
504     tempflofd=flofd=NULL;
505 
506     if( debugflag ){
507       if( replacefloflag )
508          w_log(LL_DEL, "Replace '%s'",link.floFile);
509       else w_log(LL_ERR, "(debug) Remove '%s'",link.floFile);
510     }
511     else
512     { delete(link.floFile);
513       if(replacefloflag)
514       {  w_log(LL_DEL, "Replace '%s'",link.floFile);
515          if( move_file(tempfloname, link.floFile, 1) )
516          w_log(LL_FILE, "Replaced '%s' with '%s'",link.floFile, tempfloname);
517       }else
518          delete( tempfloname );
519     }
520 
521   }/*for*/
522   if(tempflofd)
523   { fclose(tempflofd);
524     delete(tempfloname);
525   }
526   nfree(tempfloname);
527   w_log(LL_FUNC, "processFlo() OK");
528   return 0;
529 }
530 
531 
532 /* Process outbound filebox for link (.?lo): scan & send all files
533  */
processBox(s_link link)534 int processBox(s_link link)
535 {   DIR *boxP;
536     struct dirent * dp;
537     char path[PATH_MAX], adr[30], *messagefile;
538     unsigned pathlen=0;
539     int rc;
540 
541     w_log(LL_FUNC,"processBox()");
542     w_log(LL_FILENAME, "Filebox: %s", link.fileBox);
543     snprintaddr(adr,sizeof(adr),link.hisAka);
544     if ( link.fileBox==NULL || (pathlen=strlen( link.fileBox ))==0 )
545     { w_log(LL_BOX, "Not defined filebox for %s", adr );
546       return 0;
547     }
548 
549     if ( (boxP = opendir(link.fileBox))==NULL )
550     { w_log(LL_ERR, "Can't open filebox for %s: %s", adr, link.fileBox );
551       return 1;
552     }
553     w_log(LL_LINK, "Process filebox for %s (%s)", adr, link.fileBox );
554     strncpy( path, link.fileBox, sizeof(path) );
555     while( (dp = readdir(boxP)) != NULL ){
556 	path[pathlen]=0;
557 #ifdef DT_REG
558 /* struct direntry have member d_type in *NIX */
559         if( dp->d_type != DT_REG)
560         { w_log(LL_FILE, "%s is not regular file", dp->d_name );
561            continue; /* Send only regular files! */
562         }
563 #endif
564 	strncat(path,dp->d_name, sizeof(path));
565         if( testfile(path) )
566 	  continue;
567 	w_log(LL_FILE, "Sending file %s to %s", path, adr);
568 
569         if( (messagefile=writeMessage(path, link)) == NULL)
570         { w_log(LL_ERR, "Composing error: '%s', skip", path );
571 	  continue;
572 	}
573         if( (rc = sendFile(messagefile,link)) !=0 )
574         { w_log(LL_ERR, "Sending error: '%s', skip", path );
575 	  continue;
576 	}
577         sent++;
578         w_log(LL_SENT, "Sent %s to %s (%s)\n",
579                       path, link.email, adr, link.hisAka
580            );
581 
582         if( debugflag ){
583           w_log(LL_ERR, "(debug) Delete file: %s", path);
584         }else
585           if( (rc=delete(path)) )
586             w_log(LL_ERR, "File %s not removed: %s", path, strerror(rc));
587     }
588     (void)closedir(boxP);
589 
590   w_log(LL_FUNC,"processBox() OK");
591   return 0;
592 }
593 
594 /* Do send files.
595  *
596  */
send(void)597 int send(void)
598 { FILE *bsyfd;
599   int i, rc=0;
600   char adr[30];
601 
602   w_log(LL_FUNC,"send()");
603   adr[0]=0;
604 
605   for (i = 0; i < config->linkCount; i++)
606   {
607       if(   config->links[i].email != NULL
608         &&  setOutboundFilenames( &(config->links[i]), normal )==0 )
609       {
610           sent=0;
611           snprintaddr(adr,sizeof(adr),config->links[i].hisAka);
612           w_log(LL_LINK, "Process link %s", adr);
613 
614           if( (bsyfd = createbsy(config->links[i]))==NULL )
615             continue;
616           if( (rc += processNet(config->links[i])) )
617           {
618             w_log(LL_ERR,"Netmail send error.\n");
619           }
620           rc *= 10;
621           if( (rc = processFlo(config->links[i])) )
622           {
623             w_log(LL_ERR,"Echomail send error.\n");
624           }
625           rc *= 10;
626           if( (rc += processBox(config->links[i])) )
627           {
628             w_log(LL_ERR,"Filebox send error.\n");
629           }
630           fclose(bsyfd);
631           if(!delete(config->links[i].bsyFile))
632             w_log(LL_DEL, "Deleted bsy for %s", adr);
633           else
634             w_log(LL_ERR, "Can't delete bsy for %s: %s", adr, strerror(errno));
635 
636           if( sent )
637           {
638             allsent += sent;
639             w_log(LL_INFO, "Sent %d files to %s", sent, adr );
640           }
641           else
642             w_log(LL_INFO, "Nothing to send for %s", adr );
643 
644       }/*if*/
645   }/*for*/
646 
647   w_log(LL_FUNC,"send() OK");
648   return rc;
649 }
650 
651 
652 void
printver()653 printver()
654 { fprintf( stderr,	/* ITS4: ignore */
655            "%s - send FTN over email\n(part of the EmailPkt package, The Husky FidoSoft Project module) \n\n",
656            program_name );
657 }
658 
659 void
usage()660 usage()
661 { printver();
662   fprintf( stderr,	/* ITS4: ignore */
663 /*           "Usage: %s [-qVD] [-c configfile]\n", program_name); */
664            "Usage: hesend [-qVD] [-c configfile]\n");
665 #ifndef __UNIX__
666   fprintf( stderr,	/* ITS4: ignore */
667 /*           "or:    %s [--help] [--version] [--debug] [--quiet] [--config=configfile]\n", program_name);*/
668            "or:    hesend [--help] [--version] [--debug] [--quiet] [--config=configfile]\n");
669 #endif
670   exit(-1);
671 }
672 
673 int
main(int argc,char ** argv)674 main( int argc, char **argv)
675 { int rc=0, op=0, quiet=0;
676   char *cp=NULL;
677 #include "../h/cvsdate.h"
678 
679   program_name = GenVersionStr( PROGRAMNAME, VER_MAJOR, VER_MINOR, VER_PATCH, VER_BRANCH, cvs_date );
680 
681 #ifdef __UNIX__
682   opterr = 0;
683   while ((op = getopt(argc, argv, "DVc:d:hq")) != EOF)
684     switch (op) {
685     case 'c': /* config file */
686               cp=sstrdup(optarg);
687     case 'D': /* debug mode */
688               debugflag++;
689               break;
690     case 'q': /* quiet mode */
691               quiet=1;
692               break;
693     case 'V': /* version */
694               printver();
695               nfree(cp); nfree(program_name);
696               return 0;
697     case 'h': /* help */
698     default :
699               usage();
700               nfree(cp); nfree(program_name);
701               return 0;
702     }
703 
704 #else
705    for( op=1; op<argc; op++ ){
706      if(argv[op][0]=='-'){
707        if(argv[op][1]=='-'){
708          if(strcmp(argv[op]+2,"quiet"))
709                 quiet=0;
710          if(strcmp(argv[op]+2,"debug"))
711                 debugflag++;
712          if( strstr(argv[op]+2,"config=")==(argv[op]+2) ) {
713              cp = strchr(argv[op], '=');
714              if( cp ) cp = sstrdup(++cp);
715              else fprintf(stderr, "Strange error: --config=... not contents '='");
716          }
717          if(strcmp(argv[op]+2,"version")) {
718                 printver();
719                 nfree(cp); nfree(program_name);
720                 return 0;
721          }
722          if(strcmp(argv[op]+2,"help")) {
723                 usage();
724                 nfree(cp); nfree(program_name);
725                 return 0;
726          }
727        }else{
728          if(strchr(argv[op],'q'))
729                 quiet=0;
730          if(strchr(argv[op],'D'))
731                 debugflag++;
732          if(strchr(argv[op],'c')) {
733                 cp = sstrdup(argv[++op]); /* config-file */
734          }
735          if(strchr(argv[op],'V')) {
736                 printver();
737                 nfree(cp); nfree(program_name);
738                 return 0;
739          }
740          if(strchr(argv[op],'h')) {
741                 usage();
742                 nfree(cp); nfree(program_name);
743                 return 0;
744          }
745        }
746      }else{
747         fprintf(stderr,"Illegal parameter: %s", argv[op]);
748         nfree(cp); nfree(program_name);
749         return 1;
750      }
751    }
752 #endif
753 
754   set_module_vars();
755   config = readConfig(cp);
756   nfree(cp);
757   if(quiet) config->logEchoToScreen=0;
758 
759   if( !openLog( LOGFILE, program_name, config) )
760    fprintf(stderr, "Can't init log()! Use stderr instead.\n");
761 
762   if( sstrlen(config->sendmailcmd) )
763   {
764     if( debugflag )
765       w_log(LL_PRG,"Start %s (debug%u mode)", program_name, debugflag);
766     else w_log(LL_PRG,"Start %s", program_name);
767 
768     if (debugflag == 1)
769     {  SAVEFLAG++;
770        debugflag = 0;
771     }
772     rc = send();
773     w_log(LL_SUMMARY, "Summary sent %d files", allsent);
774   }
775   else
776     w_log(LL_CRIT, "sendmailcmd not defined in config! Abort.");
777 
778   disposeConfig(config);
779   w_log(LL_PRG,"Stop %s", program_name);
780   nfree(program_name);
781   closeLog();
782 
783   return rc;
784 }
785