1 /* $Id$ */
2 
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <string.h>
6 #include <time.h>
7 #include <stdlib.h>
8 #include <sys/types.h>
9 #include <sys/stat.h>
10 #include <stdarg.h>
11 #include <errno.h>
12 #include <huskylib/compiler.h>
13 
14 #ifdef HAS_DIRENT_H
15   #include <dirent.h>
16 #endif
17 #ifdef HAS_UNISTD_H
18   #include <unistd.h>
19 #endif
20 
21 #ifdef HAS_PROCESS_H
22   #include <process.h>
23 #endif
24 #ifdef HAS_DIRECT_H
25   #include <direct.h>
26 #endif
27 #ifdef HAS_IO_H
28   #include <io.h>
29 #endif
30 
31 #include <huskylib/huskylib.h>
32 #include <fidoconf/fidoconf.h>
33 #include <fidoconf/common.h>
34 
35 #ifdef USE_HPTZIP
36   #include <hptzip/hptzip.h>
37 #endif
38 
39 #include <huskylib/log.h>
40 #include "config.h"
41 #include "bsoutil.h"
42 
43 /* ANSI C knows nothing about this constant */
44 
45 #ifndef F_OK
46 #define F_OK 0
47 #endif
48 
49 time_t t;
50 unsigned long serial;
51 time_t lastt;
52 
53 const char outext[5]={'i', 'c', 'd', 'o', 'h'};
54 const char flowext[5]={'i', 'c', 'd', 'f', 'h'};
55 const char daynames[7][5]={"su","mo","tu","we","th","fr","sa"};
56 
57 
createPktName()58 char *createPktName()
59 {
60     unsigned long num;
61     static char name[9];
62 
63     t=time(NULL);
64     if (serial==MAXPATH) {
65         if (lastt==t)
66             return 0;
67         else
68             serial=0;
69     }
70     if(t == lastt)
71         serial++;
72     else
73         serial=0;
74     lastt=t;
75     num = (t<<8) + serial;
76     sprintf(name,"%08lx",num);
77     w_log(LL_DEBUG, "generated pkt name: %s", name);
78     return name;
79 }
80 
createDirIfNEx(char * dir)81 void createDirIfNEx(char *dir)
82 {   char *pp;
83 
84     if ( *(pp=(char*)(dir + strlen(dir) -1)) == PATH_DELIM )
85         *pp = '\0';        // we can't create "c:\dir\", only "c:\dir"
86 
87 /*    if (access(dir, F_OK))*/
88     if (!direxist(dir))
89     {
90         w_log(LL_DEBUG, "creating directory %s...", dir);
91         if (mymkdir(dir) && errno!=EEXIST)
92         {
93             w_log(LL_CRIT, "Can't create directory %s, errno=%d",
94                 dir, errno);
95             w_log(LL_DEBUG, "can't create, errno=%d. exiting!", errno);
96             exit(-1);
97         }
98     }
99 }
100 
addr2str(s_link * link)101 char *addr2str(s_link *link){
102     static char node[24];
103     if (link->hisAka.point!=0)
104         sprintf(node, "%u:%u/%u.%u", link->hisAka.zone, link->hisAka.net,
105                 link->hisAka.node, link->hisAka.point);
106     else
107         sprintf(node, "%u:%u/%u", link->hisAka.zone, link->hisAka.net,
108                 link->hisAka.node);
109 
110     return node;
111 }
112 
getNMSizeForLink(s_link * link,char * outb)113 unsigned long getNMSizeForLink(s_link *link, char *outb)
114 {
115     unsigned long NMSize=0;
116     struct stat fInfo;
117     char *fname=NULL;
118     char *p_flavour=NULL;
119     int i;
120 
121     w_log(LL_DEBUG, "guessing how much netmail this link has...");
122     // /outb/12345678.hut+'\0' = strlen(outb)+4
123     fname=(char *)smalloc(strlen(outb)+4);
124     strcpy(fname, outb);
125     p_flavour=fname+strlen(outb);
126     strcpy(p_flavour, "?ut");
127 
128     for (i=0;i<=4;i++)
129     {
130         *p_flavour=outext[i];
131         if (!stat(fname, &fInfo))
132         {
133             NMSize+=fInfo.st_size;
134             w_log(LL_DEBUG, "found file %s, size=%lu", fname, fInfo.st_size);
135         }
136     }
137     w_log(LL_DEBUG, "found %lu bytes of netmail.", NMSize);
138     nfree(fname);
139     return NMSize;
140 }
141 
142 
getBundleName(s_link * link,int flavour,char * outb)143 void getBundleName(s_link *link, int flavour, char *outb)
144 {
145     int i;
146     int day=0;
147     char *bundleName=NULL;
148     time_t t;
149     struct stat fInfo;
150     FILE *fp;
151     char *flowFile=NULL, *flowLine=NULL, *flowLineTmp=NULL;
152     char *sepDir=NULL, *outb_end=NULL;
153     int foundOtherFlavour=0;
154     char Idx='\0';
155     char *IdxPtr;
156     int outbLen=0;
157 
158     w_log(LL_DEBUG, "guessing bundle name...");
159     time(&t);
160     day=localtime(&t)->tm_wday;
161 
162     outbLen=strlen(outb)+30;
163     //  /outb.12b/12345678.pnt/12345678.sep/12345678.su0+'\0';
164     bundleName=(char *)smalloc(outbLen);
165     //  /outb.12b/12345678.pnt/12345678.flo+'\0';
166     flowFile=(char *)smalloc(outbLen-13);
167     flowLine=(char *)smalloc(256);
168     flowLineTmp=flowLine;
169 
170     memset(bundleName, 0, outbLen);
171     if (config->separateBundles)
172     {
173         sprintf(bundleName, "%ssep%c", outb, PATH_DELIM);
174         outb_end=bundleName+strlen(bundleName);
175     }
176     else
177     {
178         strcpy(bundleName, outb);
179         outb_end=bundleName+strlen(bundleName)-9;
180     }
181 
182     if (config->addr->point || link->hisAka.point)
183     {       // /outb.12b/12345678.pnt/12344321.su0
184         sprintf(outb_end, "%04x%04x.%2s0",
185                 (config->addr->node - link->hisAka.node) & 0xffff,
186                 (config->addr->point - link->hisAka.point) & 0xffff,
187                 daynames[day]);
188     } else
189     {       // /outb/12344321.su0
190         sprintf(outb_end, "%04x%04x.%2s0",
191                 (config->addr->net - link->hisAka.net) & 0xffff,
192                 (config->addr->node - link->hisAka.node) & 0xffff,
193                 daynames[day]);
194     }
195 
196     IdxPtr=bundleName+strlen(bundleName)-1;   // points to the last symbol before '\0'
197 
198     if (config->separateBundles)
199     {
200         sepDir=(char *)smalloc(strlen(bundleName)-11);
201         memset(sepDir, 0, strlen(bundleName)-11);
202         strncpy(sepDir, bundleName, strlen(bundleName)-12);
203         createDirIfNEx(sepDir);
204         nfree(sepDir);
205     }
206 
207     for (Idx='0';Idx<='z';Idx++)
208     {
209         if (Idx==('9'+1))
210             Idx='a';
211         *IdxPtr=Idx;
212 
213         if(stat(bundleName, &fInfo)) break; else
214             if((fInfo.st_size <= link->arcmailSize*1024) && (fInfo.st_size!=0))
215             {
216                 foundOtherFlavour=0;
217                 for(i=0;i<5;i++)
218                 {
219                     if(i==flavour) continue;
220                     sprintf(flowFile, "%s%clo", outb, flowext[i]);
221                     if (access(flowFile, F_OK)) continue;
222                     fp=fopen(flowFile, "r");
223                     while(fgets(flowLine, 256, fp)!=NULL)
224                     {
225                         flowLineTmp=flowLine;
226                         if(strlen(flowLineTmp)<2) continue;
227                         if (flowLineTmp[0]=='#' || flowLineTmp[0]=='^' || flowLineTmp[0]=='~')
228                             flowLineTmp++;
229                         if(strncmp(flowLineTmp, bundleName, strlen(bundleName))==0)
230                         {
231                             foundOtherFlavour=1;
232                             break;
233                         }
234                     }
235                     fclose(fp);
236                     if(foundOtherFlavour) break;
237                 }
238                 if (!foundOtherFlavour) break; // this file name is not used for other flavour so we can use it.
239             } else continue;
240     }
241 
242     copyString(bundleName, &(link->packFile));
243     w_log(LL_DEBUG, "bundle name generated: %s", link->packFile);
244     nfree(bundleName);
245     nfree(flowFile);
246     nfree(flowLine);
247 }
248 
addToFlow(s_link * link,int flavour,char * outb)249 int addToFlow(s_link *link, int flavour, char *outb)
250 {
251     FILE *fp;
252     char *line=NULL;
253     int foundOldBundle=0;
254     char *buff=NULL;
255     struct stat fInfo;
256 
257     sprintf(link->floFile,"%s%clo", outb, flowext[flavour]);
258 
259     w_log(LL_DEBUG, "adding bundle to flow file %s", link->floFile);
260 
261     if(stat(link->floFile, &fInfo)!=-1)
262     {
263         w_log(LL_DEBUG, "flow file exists.");
264 
265         fp=fopen(link->floFile, "r+");
266         if (fp==NULL)
267         {
268             w_log(LL_CRIT, "Can't open flow file for %2, errno=%d",
269                 addr2str(link), errno);
270             w_log(LL_DEBUG, "can't open flow file, errno=%d", errno);
271             return 0;
272         }
273 
274         line=(char *)smalloc(MAXPATH);
275         buff = smalloc(fInfo.st_size);
276         memset(buff, 0, fInfo.st_size);
277 
278         while(fgets(line, MAXPATH, fp)!=NULL)
279         {
280             strcat(buff, line);
281             if (strlen(line)<2) continue;
282             if (strncmp(line+1, link->packFile, strlen(link->packFile))==0)
283             {
284                 foundOldBundle=1;
285                 w_log(LL_DEBUG, "found old bundle, can't add it again.");
286                 break;
287             }
288         }
289 
290         if (!foundOldBundle)
291         {
292             w_log(LL_DEBUG, "now let's add our bundle.");
293             rewind(fp);
294             fprintf(fp, "^%s\n%s", link->packFile, buff);
295             w_log(LL_DEBUG, "added our bundle.");
296         }
297         nfree(buff);
298     }
299     else
300     {
301         w_log(LL_DEBUG, "creating new flow file.");
302         fp=fopen(link->floFile, "w");
303         if (fp==NULL)
304         {
305             w_log(LL_CRIT, "Can't open flow file for %s, errno=%d",
306                 addr2str(link), errno);
307             w_log(LL_DEBUG, "can't create flow file, errno=%d. returning.", errno);
308             return 0;
309         }
310         fprintf(fp, "^%s\n", link->packFile);
311         w_log(LL_DEBUG, "added our bundle.");
312     }
313     fclose(fp);
314     return 1;
315 }
316 
initLink(s_link * link)317 char *initLink(s_link *link)
318 {
319     char *outb;
320     w_log(LL_DEBUG, "allocating memory for this link...");
321 
322     /*    /outbound.12b/01234567.pnt/12345678.  +1 = strlen(outb)+5+13+9+1
323      and that's enough for nodes too. */
324 
325     outb=(char *)scalloc(strlen(config->outbound)+28, 1);
326     sprintf(outb, "%s", config->outbound);
327     if (config->addr->zone!=link->hisAka.zone)
328         sprintf(outb+strlen(outb)-1,".%03x%c",
329                 link->hisAka.zone, PATH_DELIM);
330 
331     if (link->hisAka.point==0)
332         sprintf(outb+strlen(outb), "%04x%04x.", link->hisAka.net, link->hisAka.node);
333     else
334         sprintf(outb+strlen(outb), "%04x%04x.pnt%c%08x.", link->hisAka.net,
335                 link->hisAka.node, PATH_DELIM, link->hisAka.point);
336 
337     link->bsyFile=(char *)smalloc(strlen(outb)+4); // *outb+"bsy"+'\0'
338     sprintf(link->bsyFile, "%sbsy", outb);
339     link->floFile=(char *)scalloc(strlen(outb)+4, 1);
340 
341     if (link->pktFile==NULL)
342         link->pktFile=(char *)smalloc(strlen(config->tempOutbound)+13);
343     else
344         link->pktFile=(char *)srealloc(link->pktFile,
345                                        strlen(config->tempOutbound)+13);
346     if (!link->arcmailSize)
347     {
348         if (!config->defarcmailSize)
349         {
350             link->arcmailSize=100;
351         } else
352             link->arcmailSize=config->defarcmailSize;
353     }
354     w_log(LL_DEBUG, "arcmailSize for this link is %d kb", link->arcmailSize);
355     return outb;
356 }
357 
358 
releaseLink(s_link * link,char ** outb)359 void releaseLink(s_link *link, char **outb)
360 {
361     w_log(LL_DEBUG, "freeing allocated memory for link.");
362     if (link==NULL) return;
363     nfree(link->bsyFile);
364     nfree(link->floFile);
365     nfree(link->packFile);
366     nfree(link->pktFile);
367     nfree(*outb);
368 }
369 
createBsy(s_link * link,char * outb)370 int createBsy(s_link *link, char *outb)
371 {
372     if (!access(link->bsyFile, F_OK))
373     {
374         w_log(LL_EXEC, "Link %s is busy now.", addr2str(link));
375         return 0;
376     } else
377     {
378         FILE *fp;
379         w_log(LL_DEBUG, "trying to create bsy flag for this link...");
380         fp=fopen(link->bsyFile, "w");
381         if (fp == NULL)
382         {
383             w_log(LL_BUSY, "Can't create bsyFile for %s, errno=%d",
384                 addr2str(link), errno);
385             w_log(LL_DEBUG, "couldn't create, errno=%d", errno);
386             return 0;
387         }
388         fprintf(fp, "%d", getpid());
389         fclose(fp);
390         w_log(LL_DEBUG, "bsy flag %s created successfully.", link->bsyFile);
391     }
392     return 1;
393 }
394 
removeBsy(s_link * link)395 void removeBsy(s_link *link)
396 {
397     w_log(LL_DEBUG, "removing bsy file for this link...");
398     if (access(link->bsyFile, F_OK)) {
399         w_log(LL_DEBUG, "can't acces bsy file %s, errno=%d. returning.", link->bsyFile, errno);
400         return;
401     }
402     if(remove(link->bsyFile))
403     {
404        w_log(LL_CRIT, "Can't remove bsyFile for %s, errno=%d",
405            addr2str(link), errno);
406        w_log(LL_DEBUG, "can't remove, errno=%d.", errno);
407     }
408 }
409 
packNetMailForLink(s_link * link)410 void packNetMailForLink(s_link *link)
411 {
412     int flavour=0;
413     int retval;
414     char *pktname=NULL;
415     char *execstr=NULL;
416     char *bsoNetMail=NULL;   // /outb.12b/12345678.pnt/12345678.hut
417     char *outbForLink=NULL; // /outb.12b/12345678.pnt/12345678.
418     char *dir=NULL;          // /outb.12b/12345678.pnt
419     unsigned long nmSize=0;
420 
421 
422     w_log(LL_DEBUG, "packNetmail for this link is on, trying to pack...");
423     if (link->packerDef == NULL)
424     {
425         w_log(LL_CRIT, "Packer for link %s undefined but 'packNetmail' is on, skipping...",
426             addr2str(link));
427         w_log(LL_DEBUG, "packer for this link is undefined, returning.");
428         return;
429     }
430 
431     outbForLink=initLink(link);
432     dir=(char *)smalloc(strlen(outbForLink)-9); // strlen(outb)-10 + '\0';
433     memset(dir, 0, strlen(outbForLink)-9);
434     strncpy(dir, outbForLink, strlen(outbForLink)-10);
435     if (access(dir, F_OK))
436     {
437         w_log(LL_DEBUG, "directory %s doesn't exist, skipping...", dir);
438         nfree(dir);
439         releaseLink(link, &outbForLink);
440         return;
441     }
442     nfree(dir);
443 
444     if (!createBsy(link, outbForLink)) {
445         releaseLink(link, &outbForLink);
446         return;
447     }
448 
449     execstr=(char *)smalloc(MAXPATH);
450     bsoNetMail=(char *)smalloc(strlen(outbForLink)+4);
451 
452     nmSize=getNMSizeForLink(link, outbForLink);
453 
454     if ((nmSize!=0) && (nmSize >= (link->maxUnpackedNetmail*1024)))
455     {
456         w_log(LL_POSTING, "Found %lu bytes of netmail for %s", nmSize, addr2str(link));
457 
458         for (flavour=0;flavour<5;flavour++)
459         {
460             sprintf(bsoNetMail, "%s%cut", outbForLink, outext[flavour]);
461 
462             if (!access(bsoNetMail, F_OK))
463                 if ((pktname=(char *)createPktName())!=NULL)
464                 {
465                     sprintf(link->pktFile, "%s%s.pkt",
466 		    config->tempOutbound, pktname);
467 
468                     w_log(LL_DEBUG, "found netmail packet %s, moving to %s",
469                           bsoNetMail, link->pktFile);
470 
471                     if (rename(bsoNetMail, link->pktFile))
472                     {
473                         w_log(LL_CRIT, "Error renaming %s to %s", bsoNetMail, link->pktFile);
474                         w_log(LL_DEBUG, "can't move, errno=%d. exiting!", errno);
475                         releaseLink(link, &outbForLink);
476                         return;
477                     }
478 
479                     getBundleName(link, flavour, outbForLink); // calculating bundleName;
480                     w_log(LL_EXEC, "Packing %s -> %s\n", bsoNetMail, link->packFile);
481                     if( fc_stristr(link->packerDef->call, ZIPINTERNAL) )
482                     {
483                         w_log(LL_DEBUG, "bundle %s: packing with zlib", link->packFile);
484 #ifdef USE_HPTZIP
485                         retval = PackWithZlib(link->packFile, link->pktFile);
486 #else
487                         retval = 1;
488                         w_log(LL_CRIT, "Can't use zipInternal packer, because bsopack is not compiled with libhptzip");
489 #endif
490                     } else {
491                         fillCmdStatement(execstr, link->packerDef->call,
492                                          link->packFile, link->pktFile, "");
493                         w_log(LL_DEBUG, "executing packer: %s", execstr);
494                         retval=system(execstr);
495                     }
496                     if (retval)
497                     {
498                         w_log(LL_CRIT, "Error executing packer, errorlevel %d", retval);
499                         w_log(LL_DEBUG, "packer returned errorlevel %d, errno=%d", retval, errno);
500                         releaseLink(link, &outbForLink);
501                         return;
502                     }
503 
504                     if (addToFlow(link, flavour, outbForLink))
505                         if(remove(link->pktFile)==-1)
506                             w_log(LL_CRIT, "Can't remove pktFile %s, errno=%d",
507                                 link->pktFile, errno);
508                 } // if (createPktName(pktname))
509         } // for()
510     } // if (nmSize...)
511     else
512     {
513         if (nmSize)
514             w_log(LL_POSTING, "Found %lu bytes of netmail for %s", nmSize, addr2str(link));
515     }
516 
517 
518     removeBsy(link);
519     releaseLink(link, &outbForLink);
520     nfree(execstr);
521     nfree(bsoNetMail);
522 }
523 
524