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