1 /*****************************************************************************
2 * AreaFix library for Husky (FTN Software Package) supplemental file
3 *****************************************************************************
4 * Copyright (C) 1998-2003
5 *
6 * val khokhlov (Fido: 2:550/180), Kiev, Ukraine
7 *
8 * Based on original HPT code by Max Chernogor 2:464/108
9 *
10 * This file is part of libareafix.
11 *
12 * libareafix is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License as published by the
14 * Free Software Foundation; either version 2, or (at your option) any
15 * later version.
16 *
17 * This library is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with libareafix; see the file COPYING. If not, write to the Free
24 * Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
25 *****************************************************************************/
26 /* $Id$ */
27
28 /* libc */
29 #include <stdio.h>
30 #include <time.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <ctype.h>
34 #include <errno.h>
35
36 /* compiler.h */
37 #include <huskylib/compiler.h>
38 #include <huskylib/huskylib.h>
39
40 #ifdef HAS_UNISTD_H
41 #include <unistd.h>
42 #endif
43
44 #ifdef HAS_DOS_H
45 #include <dos.h>
46 #endif
47
48 /* smapi */
49
50 /* fidoconf */
51 #include <fidoconf/fidoconf.h>
52 #include <fidoconf/common.h>
53 #include <huskylib/xstr.h>
54 #include <fidoconf/areatree.h>
55 #include <fidoconf/afixcmd.h>
56 #include <fidoconf/arealist.h>
57
58 /* hpt */
59 /*
60 #include <global.h>
61 #include <toss.h>
62 */
63
64 #define DLLEXPORT
65 #include <huskylib/huskyext.h>
66 #include <areafix.h>
67 #include <query.h>
68 #include <afglobal.h>
69 #include <callback.h>
70
71 static time_t tnow;
72 const long secInDay = 3600*24;
73 const char czFreqArea[] = "freq";
74 const char czIdleArea[] = "idle";
75 const char czKillArea[] = "kill";
76 const char czChangFlg_hpt[] = "changed.qfl";
77 const char czChangFlg_htick[] = "filefix.qfl";
78 s_query_areas *queryAreasHead = NULL;
79
80 extern char *af_versionStr;
81
escapeConfigWord(char * src)82 char *escapeConfigWord(char *src)
83 /* Replace special characters with escape-sequiences: [ -> [[], ` -> [`], " -> ["], ...
84 * Return new string (malloc)
85 */
86 {
87 int c=1;
88 char *dst, *pp;
89
90 if( !src ) return NULL;
91
92 for( pp=src; *pp; pp++ )
93 {
94 switch( *pp )
95 {
96 case '"':
97 case '\'':
98 case '`':
99 case '[':
100 c+=2;
101 }
102 }
103
104 if( c<2 )
105 return sstrdup(src);
106
107 dst=smalloc(c+sstrlen(src));
108 for( pp=src, c=0; *pp; pp++ )
109 {
110 switch( *pp )
111 {
112 case '"':
113 case '\'':
114 case '`':
115 case '[':
116 dst[c++]='[';
117 dst[c++]=*pp;
118 dst[c++]=']';
119 break;
120 default:
121 dst[c++]=*pp;
122 }
123 }
124 return dst;
125 }
126
checkRefuse(char * areaName)127 int checkRefuse(char *areaName)
128 {
129 FILE *fp;
130 char *line;
131
132 if (af_robot->newAreaRefuseFile == NULL)
133 return 0;
134
135 fp = fopen(af_robot->newAreaRefuseFile, "r+b");
136 if (fp == NULL) {
137 w_log(LL_ERR, "Can't open newAreaRefuseFile \"%s\" : %d\n",
138 af_robot->newAreaRefuseFile, strerror(errno));
139 return 0;
140 }
141 while((line = readLine(fp)) != NULL)
142 {
143 line = trimLine(line);
144 if (patimat(areaName, line)) {
145 fclose(fp);
146 return 1;
147 }
148 }
149 fclose(fp);
150 return 0;
151 }
152
del_tok(char ** ac,char * tok)153 void del_tok(char **ac, char *tok) {
154 char *p, *q;
155
156 q = fc_stristr(*ac,tok);
157 if (q) {
158 p = q+strlen(tok);
159 while (*p && !isspace(*p)) p++;
160 if (*p) memmove(q, p+1, strlen(p+1)+1); /* begin or middle */
161 else {
162 if (q > *ac) *(q-1)='\0'; /* end */
163 else *q='\0'; /* "-token" defaults */
164 }
165 }
166 }
167
makeAreaParam(s_link * creatingLink,s_link_robot * r,char * c_area,char * msgbDir)168 char* makeAreaParam(s_link *creatingLink, s_link_robot *r, char* c_area, char* msgbDir)
169 {
170 char *msgbFileName=NULL;
171 char *msgbtype, *newAC=NULL, *desc, *quote_areaname;
172 char *cp, *buff=NULL, *d_area; /* temp. usage */
173
174 msgbFileName = makeMsgbFileName(af_config, c_area);
175
176 /* translating name of the area to lowercase/uppercase */
177 if (af_config->createAreasCase == eUpper) strUpper(c_area);
178 else strLower(c_area);
179
180 /* translating filename of the area to lowercase/uppercase */
181 if (af_config->areasFileNameCase == eUpper) strUpper(msgbFileName);
182 else strLower(msgbFileName);
183
184 if (r->autoCreateDefaults)
185 xstrscat(&newAC, " ", r->autoCreateDefaults, NULLP);
186
187 msgbtype = fc_stristr(newAC, "-b ");
188
189 if(!msgbDir)
190 msgbDir = creatingLink->areafix.baseDir ? creatingLink->areafix.baseDir : af_config->msgBaseDir;
191
192 quote_areaname = strchr(TRUE_COMMENT " \"", *c_area) ? "\"" : "";
193 d_area = escapeConfigWord(c_area);
194
195 if (stricmp(msgbDir, "passthrough")!=0 && NULL==fc_stristr(newAC,"passthrough"))
196 {
197 /* we have to find a file name */
198 int need_dos_file;
199
200 #ifndef MSDOS
201 need_dos_file = fc_stristr(newAC, "-dosfile")!=NULL;
202 #else
203 need_dos_file = 1;
204 #endif
205 if (creatingLink->autoAreaCreateSubdirs && !need_dos_file)
206 {
207 /* "subdirify" the message base path if the */
208 /* user wants this. this currently does not */
209 /* work with the -dosfile option */
210 for (cp = msgbFileName; *cp; cp++)
211 {
212 if (*cp == '.')
213 {
214 *cp = PATH_DELIM;
215 }
216 }
217 }
218 if (!need_dos_file)
219 xscatprintf(&buff, "EchoArea %s%s%s %s%s",
220 quote_areaname, d_area, quote_areaname,
221 msgbDir, msgbFileName);
222 else {
223 sleep(1); /* to prevent time from creating equal numbers */
224 xscatprintf(&buff,"EchoArea %s%s%s %s%8lx",
225 quote_areaname, d_area, quote_areaname,
226 msgbDir, (long)time(NULL));
227 }
228
229 } else {
230 /* passthrough */
231 xscatprintf(&buff, "EchoArea %s%s%s passthrough",
232 quote_areaname, d_area, quote_areaname);
233
234 del_tok(&newAC, "passthrough");
235 del_tok(&newAC, "-b "); /* del "-b msgbtype" from autocreate defaults */
236 del_tok(&newAC, "-$m "); /* del "-$m xxx" from autocreate defaults */
237 del_tok(&newAC, "-p "); /* del "-p xxx" from autocreate defaults */
238
239 del_tok(&newAC, "-killsb");
240 del_tok(&newAC, "-nokillsb");
241 del_tok(&newAC, "-tinysb");
242 del_tok(&newAC, "-notinysb");
243 del_tok(&newAC, "-pack");
244 del_tok(&newAC, "-nopack");
245 del_tok(&newAC, "-link");
246 del_tok(&newAC, "-nolink");
247 del_tok(&newAC, "-killread");
248 del_tok(&newAC, "-nokillread");
249 del_tok(&newAC, "-keepunread");
250 del_tok(&newAC, "-nokeepunread");
251 }
252
253 nfree(msgbFileName);
254 if (creatingLink->LinkGrp) {
255 if (fc_stristr(newAC, " -g ")==NULL)
256 xscatprintf(&buff, " -g %s", creatingLink->LinkGrp);
257 }
258
259 if (IsAreaAvailable(c_area, r->fwdFile, &desc,1)==1) {
260 if (desc) {
261 if (fc_stristr(newAC, " -d ")==NULL)
262 xscatprintf(&buff, " -d \"%s\"", desc);
263 nfree(desc);
264 }
265 }
266 if (newAC && (*newAC)) xstrcat(&buff, newAC);
267 nfree(newAC);
268 nfree(d_area);
269 return buff;
270 }
271
autoCreate(char * c_area,char * descr,hs_addr pktOrigAddr,ps_addr forwardAddr)272 e_BadmailReasons autoCreate(char *c_area, char *descr, hs_addr pktOrigAddr, ps_addr forwardAddr)
273 {
274 FILE *f;
275 char *fileName, *fileechoFileName;
276 char *buff=NULL, *hisaddr=NULL;
277 char *msgbDir=NULL, *bDir=NULL;
278 s_link *creatingLink;
279 s_area *area;
280 s_query_areas* areaNode=NULL;
281 size_t i=0;
282 unsigned int j;
283 char pass[] = "passthrough";
284 char CR;
285 s_link_robot *r;
286
287 w_log( LL_FUNC, "%s::autoCreate() begin", __FILE__ );
288
289 if(c_area == NULL)
290 {
291 w_log( LL_FUNC, "%s::autoCreate() rc=%d", __FILE__, BM_NO_AREATAG);
292 return BM_NO_AREATAG;
293 }
294
295 if (isPatternLine(c_area)) {
296 w_log( LL_FUNC, "%s::autoCreate() rc=%d", __FILE__, BM_ILLEGAL_CHARS);
297 return BM_ILLEGAL_CHARS;
298 }
299 if (call_isValid) {
300 int rc = (*call_isValid)(c_area);
301 if (rc != 0) {
302 w_log( LL_FUNC, "%s::autoCreate() rc=%d", __FILE__, rc );
303 return rc;
304 }
305 }
306
307 if (checkRefuse(c_area))
308 {
309 w_log(LL_WARN, "Can't create %s %s : refused by %s newAreaRefuseFile\n", af_robot->strA, c_area, af_robot->name);
310 return BM_DENY_NEWAREAREFUSEFILE;
311 }
312
313 creatingLink = getLinkFromAddr(af_config, pktOrigAddr);
314
315 if (creatingLink == NULL) {
316 w_log(LL_ERR, "creatingLink == NULL !!!");
317 w_log( LL_FUNC, "%s::autoCreate() rc=%d", __FILE__, BM_SENDER_NOT_FOUND );
318 return BM_SENDER_NOT_FOUND;
319 }
320
321 r = (*call_getLinkRobot)(creatingLink);
322 fileName = r->autoCreateFile ? r->autoCreateFile : (af_cfgFile ? af_cfgFile : getConfigFileName());
323
324 f = fopen(fileName, "a+b");
325 if (f == NULL) {
326 w_log( LL_ERR, "%s::autoCreate(): cannot open config file \"%s\", link %s, OS error: \"%s\", please check configuration (and run tparser!)",
327 __FILE__, fileName, aka2str5d(creatingLink->hisAka), strerror(errno) );
328 // fprintf(stderr, "autocreate: cannot open af_config file\n");
329 w_log( LL_FUNC, "%s::autoCreate() rc=%d", __FILE__, BM_CANT_OPEN_CONFIG);
330 return BM_CANT_OPEN_CONFIG;
331 }
332 /* setting up msgbase dir */
333 if (af_config->createFwdNonPass == 0 && forwardAddr)
334 msgbDir = pass;
335 else
336 msgbDir = r->baseDir;
337
338 if (af_robot->queueFile)
339 {
340 areaNode = af_CheckAreaInQuery(c_area, &pktOrigAddr, NULL, FIND);
341 if( areaNode ) /* if area in query */
342 {
343 if( stricmp(areaNode->type,czKillArea) == 0 ){
344 w_log( LL_FUNC, "%s::autoCreate() rc=%d", __FILE__, BM_AREA_KILLED );
345 return BM_AREA_KILLED; /* area already unsubscribed */
346 }
347 if( stricmp(areaNode->type,czFreqArea) == 0 &&
348 addrComp(pktOrigAddr, areaNode->downlinks[0])!=0)
349 {
350 w_log( LL_FUNC, "%s::autoCreate() rc=%d", __FILE__, BM_WRONG_LINK_TO_AUTOCREATE );
351 return BM_WRONG_LINK_TO_AUTOCREATE; /* wrong link to autocreate from */
352 }
353 if( stricmp(areaNode->type,czFreqArea) == 0 )
354 {
355 /* removinq area from query. it is autocreated now */
356 queryAreasHead->nFlag = 1; /* query was changed */
357 areaNode->type[0] = '\0'; /* mark as deleted */
358 }
359 if (af_config->createFwdNonPass == 0)
360 msgbDir = pass;
361 /* try to find our aka in links of queried area */
362 /* if not foun area will be passthrough */
363 for (i = 1; i < areaNode->linksCount; i++)
364 for(j = 0; j < af_config->addrCount; j++)
365 if (addrComp(areaNode->downlinks[i],af_config->addr[j])==0)
366 {
367 bDir = (creatingLink->filefix.baseDir) ? creatingLink->filefix.baseDir : af_config->fileAreaBaseDir;
368 msgbDir = creatingLink->areafix.baseDir;
369 break;
370 }
371 }
372 }
373
374 /* making address of uplink */
375 xstrcat(&hisaddr, aka2str(pktOrigAddr));
376
377 /* HPT stuff */
378 if (af_app->module == M_HPT) {
379 buff = makeAreaParam(creatingLink, r, c_area, msgbDir);
380 }
381 /* HTICK stuff */
382 else if (af_app->module == M_HTICK) {
383 char *NewAutoCreate = NULL;
384
385 fileechoFileName = makeMsgbFileName(af_config, c_area);
386 /* translating name of the area to lowercase/uppercase */
387 if (af_config->createAreasCase == eUpper) strUpper(c_area);
388 else strLower(c_area);
389 /* translating filename of the area to lowercase/uppercase */
390 if (af_config->areasFileNameCase == eUpper) strUpper(fileechoFileName);
391 else strLower(fileechoFileName);
392
393 if (bDir==NULL)
394 bDir = (creatingLink->filefix.baseDir) ? creatingLink->filefix.baseDir : af_config->fileAreaBaseDir;
395
396 if( strcasecmp(bDir,"passthrough") )
397 {
398 if (creatingLink->autoFileCreateSubdirs)
399 {
400 char *cp;
401 for (cp = fileechoFileName; *cp; cp++)
402 {
403 if (*cp == '.')
404 {
405 *cp = PATH_DELIM;
406 }
407 }
408 }
409 xscatprintf(&buff,"%s%s",bDir,fileechoFileName);
410 if (_createDirectoryTree(buff))
411 {
412 w_log(LL_ERROR, "cannot make all subdirectories for %s\n",
413 fileechoFileName);
414 nfree(buff);
415 w_log( LL_FUNC, "%s::autoCreate() rc=%d", __FILE__, BM_CANT_CREATE_PATH );
416 return BM_CANT_CREATE_PATH;
417 }
418 #if defined (__UNIX__)
419 if(af_config->fileAreaCreatePerms && chmod(buff, af_config->fileAreaCreatePerms))
420 w_log(LL_ERR, "Cannot chmod() for newly created filearea directory '%s': %s",
421 sstr(buff), strerror(errno));
422 #endif
423 nfree(buff);
424 }
425
426 /* write new line in config file */
427 { char *d_area = escapeConfigWord(c_area);
428 xscatprintf(&buff, "FileArea %s %s%s -a %s ",
429 d_area, bDir,
430 (strcasecmp(bDir,"passthrough") == 0) ? "" : fileechoFileName,
431 aka2str(*(creatingLink->ourAka))
432 );
433 nfree(d_area);
434 }
435
436 if ( creatingLink->LinkGrp &&
437 !( r->autoCreateDefaults && fc_stristr(r->autoCreateDefaults, "-g ") )
438 )
439 {
440 xscatprintf(&buff,"-g %s ",creatingLink->LinkGrp);
441 }
442
443 if (r->fwdFile && !descr)
444 /* try to find description in forwardFileRequestFile */
445 IsAreaAvailable(c_area, r->fwdFile, &descr, 1);
446
447 if (r->autoCreateDefaults) {
448 NewAutoCreate = sstrdup(r->autoCreateDefaults);
449 if ((fileName=strstr(NewAutoCreate,"-d ")) !=NULL ) {
450 if (descr) {
451 *fileName = '\0';
452 xscatprintf(&buff,"%s -d \"%s\"",NewAutoCreate,descr);
453 } else {
454 xstrcat(&buff, NewAutoCreate);
455 }
456 } else {
457 if (descr)
458 xscatprintf(&buff,"%s -d \"%s\"",NewAutoCreate,descr);
459 else
460 xstrcat(&buff, NewAutoCreate);
461 }
462 nfree(NewAutoCreate);
463 }
464 else if (descr)
465 {
466 xscatprintf(&buff,"-d \"%s\"",descr);
467 }
468 } /* end of HTICK stuff */
469
470 /* add newly created echo to af_config in memory */
471 parseLine(buff, af_config);
472 if (af_app->module == M_HTICK) RebuildFileAreaTree(af_config);
473 else RebuildEchoAreaTree(af_config);
474
475 /* subscribe uplink if he is not subscribed */
476 area = &( (*af_robot->areas)[ *(af_robot->areaCount)-1 ] );
477 if ( !isLinkOfArea(creatingLink,area) ) {
478 xscatprintf(&buff, " %s", hisaddr);
479 Addlink(af_config, creatingLink, area);
480 if (af_config->createAddUplink) {
481 xstrcat(&buff, " -def");
482 if (area) area->downlinks[area->downlinkCount-1]->defLink = 1;
483 }
484 }
485
486 /* subscribe downlinks if present */
487 if(areaNode) { /* areaNode == NULL if areafixQueueFile isn't used */
488 /* prevent subscribing of defuault links */
489 /* or not existing links */
490 for(i = 1; i < areaNode->linksCount; i++) {
491 if( ( isAreaLink( areaNode->downlinks[i],area ) == -1 ) &&
492 ( getLinkFromAddr(af_config,areaNode->downlinks[i])) &&
493 ( !isOurAka(af_config,areaNode->downlinks[i]) )
494 ) {
495 xstrcat( &buff, " " );
496 xstrcat( &buff, aka2str(areaNode->downlinks[i]) );
497 Addlink(af_config, getLinkFromAddr(af_config,areaNode->downlinks[i]), area);
498 }
499 }
500 }
501
502 /* subscribe links with autoSubscribe "on" */
503 for(i = 0; i < af_config->linkCount; i++)
504 {
505 r = (*call_getLinkRobot)(af_config->links[i]);
506 if(r->autoSubscribe && !isLinkOfArea(af_config->links[i], area))
507 {
508 xscatprintf(&buff, " %s", aka2str(af_config->links[i]->hisAka));
509 Addlink(af_config, af_config->links[i], area);
510 }
511 }
512
513 /* fix if dummys del \n from the end of file */
514 if( fseek (f, -2L, SEEK_END) == 0)
515 {
516 CR = getc (f); /* may be it is CR aka '\r' */
517 if (getc(f) != '\n') {
518 fseek (f, 0L, SEEK_END); /* not neccesary, but looks better ;) */
519 fputs (cfgEol(), f);
520 } else {
521 fseek (f, 0L, SEEK_END);
522 }
523 i = ftell(f); /* af_config length */
524 /* correct EOL in memory */
525 if(CR == '\r')
526 xstrcat(&buff,"\r\n"); /* DOS EOL */
527 else
528 xstrcat(&buff,"\n"); /* UNIX EOL */
529 }
530 else
531 {
532 xstrcat(&buff,cfgEol()); /* af_config depended EOL */
533 }
534
535 /* add line to af_config */
536 if ( fprintf(f, "%s", buff) != (int)(strlen(buff)) || fflush(f) != 0)
537 {
538 w_log(LL_ERR, "Error creating area %s, config write failed: %s!",
539 c_area, strerror(errno));
540 fseek(f, i, SEEK_SET);
541 setfsize(fileno(f), i);
542 }
543 fclose(f);
544 nfree(buff);
545
546 /* echoarea addresses changed by safe_reallocating of af_config->echoAreas[] */
547 if (af_app->module == M_HPT) carbonNames2Addr(af_config);
548
549 w_log(LL_AUTOCREATE, "%s %s autocreated by %s", af_robot->strA, c_area, hisaddr);
550
551 if (hook_onAutoCreate) (*hook_onAutoCreate)(c_area, descr, pktOrigAddr, forwardAddr);
552
553 /* check if downlinks are already paused, pause area if it is so */
554 /* skip if forwardAddr is NULL: will be checked in subscribe() */
555 if (af_robot->autoAreaPause && area->msgbType == MSGTYPE_PASSTHROUGH && forwardAddr == NULL) {
556 if (pauseArea(ACT_PAUSE, NULL, area)) sendAreafixMessages();
557 }
558
559 nfree(hisaddr);
560
561 /* val: update perl structures */
562 if (hook_onConfigChange) (*hook_onConfigChange)(PERL_CONF_AREAS);
563
564 /* create flag */
565 if (af_robot->autoCreateFlag) {
566 if (NULL == (f = fopen(af_robot->autoCreateFlag, "a")))
567 w_log(LL_ERR, "Could not open autoAreaCreate flag: %s", af_robot->autoCreateFlag);
568 else {
569 w_log(LL_FLAG, "Created autoAreaCreate flag: %s", af_robot->autoCreateFlag);
570 fclose(f);
571 }
572 }
573
574 w_log( LL_FUNC, "%s::autoCreate() end", __FILE__ );
575 return BM_MAIL_OK;
576 }
577
578
579 s_query_areas* af_AddAreaListNode(char *areatag, const char *type);
580 void af_DelAreaListNode(s_query_areas* node);
581 void af_AddLink(s_query_areas* node, ps_addr link);
582
af_CheckAreaInQuery(char * areatag,ps_addr uplink,ps_addr dwlink,e_query_action act)583 s_query_areas* af_CheckAreaInQuery(char *areatag, ps_addr uplink, ps_addr dwlink, e_query_action act)
584 {
585 size_t i = 0;
586 int bFind = 0;
587 s_query_areas *areaNode = NULL;
588 s_query_areas *tmpNode = NULL;
589
590 if( !queryAreasHead ) af_OpenQuery();
591 tmpNode = queryAreasHead;
592 while(tmpNode->next && !bFind)
593 {
594 if( tmpNode->next->name && !stricmp(areatag, tmpNode->next->name) )
595 bFind = 1;
596 tmpNode = tmpNode->next;
597 }
598
599 switch( act )
600 {
601 case FIND: /* Find area in query list */
602 if( !bFind || tmpNode == queryAreasHead )
603 tmpNode = NULL;
604 break;
605 case FINDFREQ: /* Find area with "freq" or "idle" state in query list (query-in-progress area) */
606 if( !bFind || tmpNode == queryAreasHead || stricmp(tmpNode->type,czKillArea) == 0 )
607 tmpNode = NULL;
608 break;
609 case ADDFREQ: /* Add downlink-node into existing query in list */
610 if( bFind ) {
611 if( stricmp(tmpNode->type,czKillArea) == 0 &&
612 uplink && addrComp(tmpNode->downlinks[0],*uplink) != 0 )
613 {
614 memcpy( &(tmpNode->downlinks[0]), uplink, sizeof(hs_addr) );
615 }
616 if( stricmp(tmpNode->type,czFreqArea) == 0 )
617 {
618 i = 1;
619 while( i < tmpNode->linksCount && addrComp(*dwlink, tmpNode->downlinks[i])!=0)
620 i++;
621 if(i == tmpNode->linksCount) {
622 af_AddLink( tmpNode, dwlink ); /* add link to queried area */
623 tmpNode->eTime = tnow + af_robot->forwardRequestTimeout*secInDay;
624 } else {
625 tmpNode = NULL; /* link already in query */
626 }
627 } else {
628 strcpy(tmpNode->type,czFreqArea); /* change state to @freq" */
629 af_AddLink( tmpNode, dwlink );
630 tmpNode->eTime = tnow + af_robot->forwardRequestTimeout*secInDay;
631 }
632 } else { /* area not found, so add it */
633 areaNode = af_AddAreaListNode( areatag, czFreqArea );
634 if(strlen( areatag ) > queryAreasHead->linksCount) /* max areanane lenght */
635 queryAreasHead->linksCount = strlen( areatag );
636 af_AddLink( areaNode, uplink );
637 af_AddLink( areaNode, dwlink );
638 areaNode->eTime = tnow + af_robot->forwardRequestTimeout*secInDay;
639 tmpNode =areaNode;
640 }
641 break;
642 case ADDIDLE: /* Create idle forward request for area into query list */
643 if( bFind ) {
644 } else {
645 areaNode = af_AddAreaListNode( areatag, czIdleArea );
646 if(strlen( areatag ) > queryAreasHead->linksCount)
647 queryAreasHead->linksCount = strlen( areatag );
648 af_AddLink( areaNode, uplink );
649 areaNode->eTime = tnow + af_robot->idlePassthruTimeout*secInDay;
650 w_log(LL_AREAFIX, "%s: make request idle for area: %s", af_robot->name, areaNode->name);
651 tmpNode =areaNode;
652 }
653 break;
654 case DELIDLE: /* Remove idle forward request to area from query list */
655 if( bFind && stricmp(tmpNode->type,czIdleArea) == 0 )
656 {
657 queryAreasHead->nFlag = 1;
658 tmpNode->type[0] = '\0';
659 w_log( LL_AREAFIX, "%s: idle request for %s removed from queue file", af_robot->name, tmpNode->name);
660 }
661 break;
662
663 }
664 return tmpNode;
665 }
666
af_Req2Idle(char * areatag,char * report,hs_addr linkAddr)667 char* af_Req2Idle(char *areatag, char* report, hs_addr linkAddr)
668 {
669 size_t i;
670 s_query_areas *tmpNode = NULL;
671 s_query_areas *areaNode = NULL;
672 if( !queryAreasHead ) af_OpenQuery();
673 tmpNode = queryAreasHead;
674 while(tmpNode->next)
675 {
676 areaNode = tmpNode->next;
677 if( ( areaNode->name ) &&
678 ( stricmp(areaNode->type,czFreqArea) == 0 ) &&
679 ( patimat(areaNode->name,areatag)==1) )
680 {
681 i = 1;
682 while( i < areaNode->linksCount)
683 {
684 if( addrComp(areaNode->downlinks[i],linkAddr) == 0)
685 break;
686 i++;
687 }
688 if( i < areaNode->linksCount )
689 {
690 if( i != areaNode->linksCount-1 )
691 memmove(&(areaNode->downlinks[i]),&(areaNode->downlinks[i+1]),
692 sizeof(hs_addr)*(areaNode->linksCount-i));
693 areaNode->linksCount--;
694 queryAreasHead->nFlag = 1; /* query was changed */
695 if(areaNode->linksCount == 1)
696 {
697 ps_link UPlink;
698 strcpy(areaNode->type,czIdleArea);
699 areaNode->bTime = tnow;
700 areaNode->eTime = tnow + af_robot->idlePassthruTimeout*secInDay;
701 w_log(LL_AREAFIX, "%s: make request idle for area: %s", af_robot->name, areaNode->name);
702 /* send unsubscribe message to uplink when moving from freq to idle
703 * because the last link waiting in queue cancelled its request */
704 UPlink = getLinkFromAddr(af_config, areaNode->downlinks[0]);
705 if (UPlink) forwardRequestToLink(areaNode->name, UPlink, NULL, 1);
706 }
707 xscatprintf(&report, " %s %s request canceled\r",
708 areaNode->name,
709 print_ch(49-strlen(areaNode->name), '.'));
710 w_log(LL_AREAFIX, "%s: request canceled for [%s] area: %s", af_robot->name, aka2str(linkAddr),
711 areaNode->name);
712 }
713 }
714 tmpNode = tmpNode->next;
715 }
716 return report;
717 }
718
af_GetQFlagName()719 char* af_GetQFlagName()
720 {
721 char *chanagedflag = NULL;
722 char *logdir = NULL;
723 const char *czChangFlg = af_app->module == M_HTICK ? czChangFlg_htick : czChangFlg_hpt;
724
725 #ifdef DEBUG_HPT
726 w_log(LL_FUNC, "af_GetQFlagName(): begin");
727 #endif
728 if (af_config->lockfile)
729 {
730 logdir = dirname(af_config->lockfile); /* slash-trailed */
731 xstrscat(&chanagedflag,logdir,(char*)czChangFlg,NULLP);
732 nfree(logdir);
733 }
734 else if (af_config->echotosslog)
735 {
736 logdir = dirname(af_config->echotosslog); /* slash-trailed */
737 xstrscat(&chanagedflag,logdir,(char*)czChangFlg,NULLP);
738 nfree(logdir);
739 }
740 else if (af_config->semaDir)
741 {
742 logdir = dirname(af_config->echotosslog); /* slash-trailed */
743 xstrscat(&chanagedflag,logdir,(char*)czChangFlg,NULLP);
744 nfree(logdir);
745 }
746 else
747 {
748 chanagedflag = (*call_sstrdup)(czChangFlg);
749 }
750
751 w_log(LL_FUNC, "af_GetQFlagName(): end");
752
753 return chanagedflag;
754 }
755
af_QueueReport()756 void af_QueueReport()
757 {
758 s_query_areas *tmpNode = NULL;
759 const char rmask[]="%-37.37s %-4.4s %11.11s %-16.16s %-7.7s\r";
760 char type[5]="\0\0\0\0";
761 char state[8]= "\0\0\0\0\0\0\0";
762 char link1[17]= {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
763 char link2[17]= {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
764 char* report = NULL;
765 char* header = NULL;
766 int netmail=0;
767 char *reportFlg = NULL;
768 s_message *msg = NULL;
769 char *ucStrA;
770
771 w_log(LL_FUNC, "af_QueueReport(): begin");
772
773 if( !af_robot->queueFile ){
774 w_log(LL_WARN, "queueFile for %s not defined in af_config", af_robot->name);
775 w_log(LL_FUNC, "af_QueueReport(): end");
776 return;
777 }
778
779 w_log(LL_DEBUGU, __FILE__ ":%u:af_QueueReport()", __LINE__);
780
781 reportFlg = af_GetQFlagName();
782
783 w_log(LL_DEBUGU, __FILE__ ":%u:af_QueueReport()", __LINE__);
784
785 if(!fexist(reportFlg))
786 {
787 w_log(LL_STOP, "Queue file hasn't been changed. Exiting...");
788 nfree(reportFlg);
789 return;
790 }
791
792 w_log(LL_DEBUGU, __FILE__":%u:af_QueueReport()", __LINE__);
793
794 if( !queryAreasHead ) af_OpenQuery();
795
796 tmpNode = queryAreasHead;
797
798 w_log(LL_DEBUGU, __FILE__":%u:af_QueueReport() tmpNode=%X", __LINE__, tmpNode);
799
800 ucStrA = sstrdup(af_robot->strA);
801 ucStrA[0] = (char) toupper(ucStrA[0]);
802
803 while(tmpNode->next)
804 {
805
806 w_log(LL_DEBUGU, __FILE__":%u:af_QueueReport() tmpNode=%X", __LINE__, tmpNode);
807
808 tmpNode = tmpNode->next;
809 strcpy(link1,aka2str(tmpNode->downlinks[0]));
810 strcpy(type,tmpNode->type);
811 if( stricmp(tmpNode->type,czFreqArea) == 0 )
812 {
813 strcpy(link2,aka2str(tmpNode->downlinks[1]));
814 if( strcmp(tmpNode->type,czFreqArea) == 0 )
815 {
816 queryAreasHead->nFlag = 1;
817 strUpper(tmpNode->type);
818 xscatprintf(&report,rmask, tmpNode->name, tmpNode->type,
819 link1,link2,
820 "request");
821 continue;
822 }
823 if (af_report_changes) continue; /* report changes in queue file only */
824 if(tmpNode->eTime < tnow )
825 {
826 strcpy(state,"rr_or_d");
827 }
828 else
829 {
830 int days = (tnow - tmpNode->bTime)/secInDay;
831 sprintf(state,"%2d days",days);
832 }
833 xscatprintf(&report,rmask, tmpNode->name, type,
834 link1,link2,
835 state);
836 }
837 if( stricmp(tmpNode->type,czKillArea) == 0 )
838 {
839 if( strcmp(tmpNode->type,czKillArea) == 0 )
840 {
841 queryAreasHead->nFlag = 1;
842 strUpper(tmpNode->type);
843 xscatprintf(&report,rmask, tmpNode->name, tmpNode->type,
844 link1,"",
845 "timeout");
846 continue;
847 }
848 if (af_report_changes) continue;
849 if(tmpNode->eTime < tnow )
850 {
851 strcpy(state,"to_kill");
852 }
853 else
854 {
855 int days = (tnow - tmpNode->bTime)/secInDay;
856 sprintf(state,"%2d days",days);
857 }
858 xscatprintf(&report,rmask, tmpNode->name, type,
859 link1,"",
860 state);
861
862 }
863 if( stricmp(tmpNode->type,czIdleArea) == 0 )
864 {
865 if( strcmp(tmpNode->type,czIdleArea) == 0 )
866 {
867 queryAreasHead->nFlag = 1;
868 strUpper(tmpNode->type);
869 xscatprintf(&report,rmask, tmpNode->name, tmpNode->type,
870 link1,"",
871 "timeout");
872 continue;
873 }
874 if (af_report_changes) continue;
875 if(tmpNode->eTime < tnow )
876 {
877 strcpy(state,"to_kill");
878 }
879 else
880 {
881 int days = (tnow - tmpNode->bTime)/secInDay;
882 sprintf(state,"%2d days",days);
883 }
884 xscatprintf(&report,rmask, tmpNode->name, type,
885 link1,"",
886 state);
887 }
888 }
889
890 if(!report) {
891 nfree(ucStrA);
892 remove(reportFlg);
893 nfree(reportFlg);
894 return;
895 }
896
897 w_log(LL_START, "Start generating queue report");
898 xscatprintf(&header, rmask,
899 ucStrA, "Act","From","By","Details");
900 xscatprintf(&header, "%s\r", print_ch(79,'-'));
901 xstrcat(&header, report);
902 report = header;
903 if (af_config->ReportTo) {
904 if (stricmp(af_config->ReportTo,"netmail")==0) netmail=1;
905 else if (getNetMailArea(af_config, af_config->ReportTo) != NULL) netmail=1;
906 } else netmail=1;
907
908 msg = makeMessage(&(af_config->addr[0]),&(af_config->addr[0]),
909 af_robot->fromName ? af_robot->fromName : af_versionStr,
910 netmail ? (af_config->sysop ? af_config->sysop : "Sysop") : "All", "Requests report",
911 netmail,
912 af_robot->reportsAttr);
913 msg->text = createKludges(af_config,
914 netmail ? NULL : af_config->ReportTo,
915 &(af_config->addr[0]), &(af_config->addr[0]),
916 af_versionStr);
917
918 msg->recode |= (REC_HDR|REC_TXT);
919
920 if (af_robot->reportsFlags)
921 xstrscat( &(msg->text), "\001FLAGS ", af_robot->reportsFlags, "\r", NULLP);
922 xstrcat( &(msg->text), report );
923
924 w_log(LL_STOP, "End generating queue report");
925
926 (*call_writeMsgToSysop)(msg);
927 nfree(msg);
928 nfree(ucStrA);
929 remove(reportFlg);
930 nfree(reportFlg);
931 w_log(LL_FUNC, "af_QueueReport(): end");
932 }
933
af_QueueUpdate()934 void af_QueueUpdate()
935 {
936 s_query_areas *tmpNode = NULL;
937 s_link *lastRlink = NULL;
938 s_link *dwlink = NULL;
939 s_message **tmpmsg = NULL;
940 size_t i = 0;
941 unsigned int j = 0;
942
943 tmpmsg = (s_message**) (*call_smalloc)( af_config->linkCount * sizeof(s_message*));
944 for (i = 0; i < af_config->linkCount; i++)
945 {
946 tmpmsg[i] = NULL;
947 }
948
949 w_log(LL_START, "Start updating queue file");
950 if( !queryAreasHead ) af_OpenQuery();
951
952 tmpNode = queryAreasHead;
953 while(tmpNode->next)
954 {
955 tmpNode = tmpNode->next;
956 if( tmpNode->eTime > tnow )
957 continue;
958 if( stricmp(tmpNode->type,czFreqArea) == 0 )
959 {
960 if(tmpNode->linksCount >= 1)
961 lastRlink = getLinkFromAddr(af_config,tmpNode->downlinks[0]);
962 if(tmpNode->linksCount >= 2)
963 dwlink = getLinkFromAddr(af_config,tmpNode->downlinks[1]);
964 if(lastRlink == NULL)
965 {
966 /* TODO: Make appropriate error message and remove (?) line */
967 continue;
968 }
969 forwardRequestToLink(tmpNode->name, lastRlink, NULL, 2);
970 w_log( LL_AREAFIX, "%s: request for %s is canceled for node %s",
971 af_robot->name, tmpNode->name, aka2str(lastRlink->hisAka));
972 if(dwlink && !forwardRequest(tmpNode->name, dwlink, &lastRlink))
973 {
974 tmpNode->downlinks[0] = lastRlink->hisAka;
975 tmpNode->bTime = tnow;
976 tmpNode->eTime = tnow + af_robot->forwardRequestTimeout*secInDay;
977 w_log( LL_AREAFIX, "%s: request for %s is going to node %s",
978 af_robot->name, tmpNode->name, aka2str(lastRlink->hisAka));
979 }
980 else
981 {
982 strcpy(tmpNode->type, czKillArea);
983 tmpNode->bTime = tnow;
984 tmpNode->eTime = tnow + af_robot->killedRequestTimeout*secInDay;
985 w_log( LL_AREAFIX, "%s: request for %s is going to be killed", af_robot->name, tmpNode->name);
986
987 /* send notification messages */
988 for (i = 1; i < tmpNode->linksCount; i++)
989 {
990 dwlink = getLinkFromAddr(af_config,tmpNode->downlinks[i]);
991 for (j = 0; j < af_config->linkCount; j++)
992 {
993 if ( addrComp(dwlink->hisAka,af_config->links[j]->hisAka)==0 && dwlink->sendNotifyMessages)
994 {
995 if (tmpmsg[j] == NULL)
996 {
997 char *rf = NULL;
998 s_link_robot *r = (*call_getLinkRobot)(dwlink);
999 rf = r->reportsFlags ? r->reportsFlags : af_robot->reportsFlags;
1000 tmpmsg[j] = makeMessage(dwlink->ourAka,
1001 &(dwlink->hisAka),
1002 af_robot->fromName ? af_robot->fromName : af_versionStr,
1003 dwlink->name,
1004 "Notification message", 1,
1005 r->reportsAttr ? r->reportsAttr : af_robot->reportsAttr);
1006 tmpmsg[j]->text = createKludges(af_config, NULL,
1007 dwlink->ourAka,
1008 &(dwlink->hisAka),
1009 af_versionStr);
1010 if (rf)
1011 xstrscat(&(tmpmsg[j]->text), "\001FLAGS ", rf, "\r", NULLP);
1012
1013 xstrcat(&tmpmsg[j]->text, "\r Your requests for the following areas were forwarded to uplinks,\r");
1014 xscatprintf(&tmpmsg[j]->text, " but no messages were received at least in %u days. Your requests\r",af_robot->forwardRequestTimeout);
1015 xstrcat(&tmpmsg[j]->text, " are killed by timeout.\r\r");
1016 }
1017 xscatprintf(&tmpmsg[j]->text, " %s\r",tmpNode->name);
1018 }
1019 }
1020 }
1021 tmpNode->linksCount = 1;
1022 }
1023 queryAreasHead->nFlag = 1; /* query was changed */
1024 continue;
1025 }
1026 if( stricmp(tmpNode->type,czKillArea) == 0 )
1027 {
1028 queryAreasHead->nFlag = 1;
1029 tmpNode->type[0] = '\0';
1030 w_log( LL_AREAFIX, "%s: request for %s removed from queue file", af_robot->name, tmpNode->name);
1031 continue;
1032 }
1033 if( stricmp(tmpNode->type,czIdleArea) == 0 )
1034 {
1035 ps_area delarea;
1036 int mandatoryal=0;
1037 queryAreasHead->nFlag = 1; /* query was changed */
1038 strcpy(tmpNode->type, czKillArea);
1039 tmpNode->bTime = tnow;
1040 tmpNode->eTime = tnow + af_robot->killedRequestTimeout*secInDay;
1041 w_log( LL_AREAFIX, "%s: request for %s is going to be killed", af_robot->name, tmpNode->name);
1042 if(tmpNode->linksCount >= 1)
1043 {
1044 dwlink = getLinkFromAddr(af_config, tmpNode->downlinks[0]);
1045 tmpNode->linksCount = 1;
1046 }
1047 /* TODO: Make sure that all of the following won't crash and will do
1048 * something reasonable when dwlink == NULL */
1049 /* delete area from config, unsubscribe at downlinks */
1050 delarea = (*call_getArea)(tmpNode->name);
1051 if(delarea != NULL && dwlink != NULL)
1052 mandatoryal=mandatoryCheck(delarea,dwlink);
1053 if (delarea && !mandatoryal) do_delete(dwlink, delarea);
1054 /* unsubscribe at uplink */
1055 if (dwlink && !(delarea && mandatoryal)) forwardRequestToLink(tmpNode->name, dwlink, NULL, 2);
1056 }
1057 }
1058 /* send notification messages */
1059 for (i = 0; i < af_config->linkCount; i++)
1060 {
1061 if (tmpmsg[i])
1062 {
1063 xscatprintf(&tmpmsg[i]->text, "\r\r--- %s %s\r", af_versionStr, af_robot->name);
1064 tmpmsg[i]->textLength = strlen(tmpmsg[i]->text);
1065 /*
1066 processNMMsg(tmpmsg[i], NULL,
1067 getNetMailArea(af_config,af_config->robotsArea),
1068 0, MSGLOCAL);
1069 closeOpenedPkt();
1070 freeMsgBuffers(tmpmsg[i]);
1071 */
1072 (*call_sendMsg)(tmpmsg[i]);
1073 w_log( LL_AREAFIX, "%s: write notification msg for %s", af_robot->name, aka2str(af_config->links[i]->hisAka));
1074 }
1075 nfree(tmpmsg[i]);
1076 }
1077 /* send msg to the links (forward requests to areafix) */
1078 sendAreafixMessages();
1079 w_log(LL_STOP, "End updating queue file");
1080 }
1081
af_OpenQuery()1082 int af_OpenQuery()
1083 {
1084 FILE *queryFile;
1085 char *line = NULL;
1086 char *token = NULL;
1087 struct tm tr;
1088 char seps[] = " \t\n";
1089
1090 if( queryAreasHead ) /* list already exists */
1091 return 0;
1092
1093 time( &tnow );
1094
1095 queryAreasHead = af_AddAreaListNode("\0","\0");
1096
1097 if( !af_robot->queueFile ) /* Queue File not defined in af_config */
1098 {
1099 w_log(LL_ERR, "queueFile for %s not defined in af_config", af_robot->name);
1100 return 0;
1101 }
1102 if ( (queryFile = fopen(af_robot->queueFile,"r")) == NULL ) /* can't open query file */
1103 {
1104 w_log(LL_ERR, "Can't open queueFile %s: %s", af_robot->queueFile, strerror(errno) );
1105 return 0;
1106 }
1107
1108 while ((line = readLine(queryFile)) != NULL)
1109 {
1110 s_query_areas *areaNode = NULL;
1111 token = strtok( line, seps );
1112 if( token != NULL )
1113 {
1114 areaNode = af_AddAreaListNode(token, "");
1115 if(strlen( areaNode->name ) > queryAreasHead->linksCount)
1116 queryAreasHead->linksCount = strlen( areaNode->name );
1117 token = strtok( NULL, seps );
1118 strncpy( areaNode->type ,token, 4);
1119 token = strtok( NULL, seps );
1120 memset(&tr, '\0', sizeof(tr));
1121 if(sscanf(token, "%d-%d-%d@%d:%d",
1122 &tr.tm_year,
1123 &tr.tm_mon,
1124 &tr.tm_mday,
1125 &tr.tm_hour,
1126 &tr.tm_min
1127 ) != 5)
1128 {
1129 af_DelAreaListNode(areaNode);
1130 continue;
1131 } else {
1132 tr.tm_year -= 1900;
1133 tr.tm_mon--;
1134 tr.tm_isdst =- 1;
1135 areaNode->bTime = mktime(&tr);
1136 }
1137 token = strtok( NULL, seps );
1138 memset(&tr, '\0', sizeof(tr));
1139 if(sscanf(token, "%d-%d-%d@%d:%d",
1140 &tr.tm_year,
1141 &tr.tm_mon,
1142 &tr.tm_mday,
1143 &tr.tm_hour,
1144 &tr.tm_min
1145 ) != 5)
1146 {
1147 af_DelAreaListNode(areaNode);
1148 continue;
1149 } else {
1150 tr.tm_year -= 1900;
1151 tr.tm_mon--;
1152 tr.tm_isdst =- 1;
1153 areaNode->eTime = mktime(&tr);
1154 }
1155
1156 token = strtok( NULL, seps );
1157 while( token != NULL )
1158 {
1159
1160 areaNode->linksCount++;
1161 areaNode->downlinks = (*call_srealloc)( areaNode->downlinks,
1162 sizeof(hs_addr)*areaNode->linksCount );
1163 memset(&(areaNode->downlinks[areaNode->linksCount-1]), 0, sizeof(hs_addr));
1164 parseFtnAddrZS(token,
1165 &(areaNode->downlinks[areaNode->linksCount-1]));
1166 token = strtok( NULL, seps );
1167 }
1168 }
1169 nfree(line);
1170 }
1171 fclose(queryFile);
1172 return 0;
1173 }
1174
af_CloseQuery()1175 int af_CloseQuery()
1176 {
1177 char buf[2*1024] = "";
1178 char *p;
1179 int nSpace = 0;
1180 size_t i = 0;
1181 struct tm t1,t2;
1182 int writeChanges = 0;
1183 FILE *queryFile=NULL;
1184 s_query_areas *delNode = NULL;
1185 s_query_areas *tmpNode = NULL;
1186 char *chanagedflag = NULL;
1187 FILE *QFlag = NULL;
1188
1189 w_log(LL_FUNC, __FILE__ ":%u:af_CloseQuery() begin", __LINE__);
1190
1191 if( !queryAreasHead ) { /* list does not exist */
1192 w_log(LL_FUNC, __FILE__ ":%u:af_CloseQuery() end", __LINE__);
1193 return 0;
1194 }
1195
1196 if(queryAreasHead->nFlag == 1) {
1197 writeChanges = 1;
1198 }
1199 if (writeChanges)
1200 {
1201 if ((queryFile = fopen(af_robot->queueFile, "w")) == NULL)
1202 {
1203 w_log(LL_ERR,"%s: queueFile not saved", af_robot->name);
1204 writeChanges = 0;
1205 }
1206 else
1207 {
1208 if( (chanagedflag = af_GetQFlagName()) != NULL)
1209 {
1210 if( (QFlag = fopen(chanagedflag,"w")) != NULL)
1211 fclose(QFlag);
1212 nfree(chanagedflag);
1213 }
1214 }
1215 }
1216
1217 tmpNode = queryAreasHead->next;
1218 nSpace = queryAreasHead->linksCount+1;
1219 p = buf+nSpace;
1220 while(tmpNode) {
1221 if(writeChanges && tmpNode->type[0] != '\0') {
1222 memset(buf, ' ' ,nSpace);
1223 memcpy(buf, tmpNode->name, strlen(tmpNode->name));
1224 t1 = *localtime( &tmpNode->bTime );
1225 t2 = *localtime( &tmpNode->eTime );
1226 sprintf( p , "%s %d-%02d-%02d@%02d:%02d\t%d-%02d-%02d@%02d:%02d" ,
1227 tmpNode->type,
1228 t1.tm_year + 1900,
1229 t1.tm_mon + 1,
1230 t1.tm_mday,
1231 t1.tm_hour,
1232 t1.tm_min,
1233 t2.tm_year + 1900,
1234 t2.tm_mon + 1,
1235 t2.tm_mday,
1236 t2.tm_hour,
1237 t2.tm_min );
1238 p = p + strlen(p);
1239 for(i = 0; i < tmpNode->linksCount; i++) {
1240 strcat(p," ");
1241 strcat(p,aka2str(tmpNode->downlinks[i]));
1242 }
1243 strcat(buf, "\n");
1244 fputs( buf , queryFile );
1245 p = buf+nSpace;
1246 }
1247 delNode = tmpNode;
1248 tmpNode = tmpNode->next;
1249 af_DelAreaListNode(delNode);
1250 }
1251
1252 nfree(queryAreasHead->name);
1253 nfree(queryAreasHead->downlinks);
1254 nfree(queryAreasHead->report);
1255 nfree(queryAreasHead);
1256
1257 if(queryFile) fclose(queryFile);
1258
1259 w_log(LL_FUNC, __FILE__ ":%u:af_CloseQuery() end", __LINE__);
1260 return 0;
1261 }
1262
af_MakeAreaListNode()1263 s_query_areas* af_MakeAreaListNode()
1264 {
1265 s_query_areas *areaNode =NULL;
1266 areaNode = (s_query_areas*)(*call_smalloc)( sizeof(s_query_areas) );
1267 memset( areaNode ,'\0', sizeof(s_query_areas) );
1268 return areaNode;
1269 }
1270
af_AddAreaListNode(char * areatag,const char * type)1271 s_query_areas* af_AddAreaListNode(char *areatag, const char *type)
1272 {
1273 s_query_areas *tmpNode = NULL;
1274 s_query_areas *tmpPrevNode = NULL;
1275 s_query_areas *newNode = af_MakeAreaListNode();
1276
1277 newNode->name = sstrlen(areatag) > 0 ? (*call_sstrdup)(areatag) : NULL;
1278 strcpy( newNode->type ,type);
1279
1280 tmpPrevNode = tmpNode = queryAreasHead;
1281
1282 while(tmpNode)
1283 {
1284 if( tmpNode->name && strlen(tmpNode->name) > 0 )
1285 if( stricmp(areatag,tmpNode->name) < 0 )
1286 break;
1287 tmpPrevNode = tmpNode;
1288 tmpNode = tmpNode->next;
1289 }
1290 if(tmpPrevNode)
1291 {
1292 tmpPrevNode->next = newNode;
1293 newNode->next = tmpNode;
1294 }
1295 return newNode;
1296 }
1297
af_DelAreaListNode(s_query_areas * node)1298 void af_DelAreaListNode(s_query_areas* node)
1299 {
1300 s_query_areas* tmpNode = queryAreasHead;
1301
1302 while(tmpNode->next && tmpNode->next != node)
1303 {
1304 tmpNode = tmpNode->next;
1305 }
1306 if(tmpNode->next)
1307 {
1308 tmpNode->next = node->next;
1309 nfree(node->name);
1310 nfree(node->downlinks);
1311 nfree(node->report);
1312 nfree(node);
1313 }
1314 }
1315
af_AddLink(s_query_areas * node,ps_addr link)1316 void af_AddLink(s_query_areas* node, ps_addr link)
1317 {
1318 node->linksCount++;
1319 node->downlinks = (*call_srealloc)( node->downlinks, sizeof(hs_addr)*node->linksCount );
1320 memcpy( &(node->downlinks[node->linksCount-1]) ,link, sizeof(hs_addr) );
1321 node->bTime = tnow;
1322 queryAreasHead->nFlag = 1; /* query was changed */
1323 }
1324
1325 /* originally from hpt/src/toss.c */
getAreaLink(s_area * area,hs_addr aka)1326 s_arealink *getAreaLink(s_area *area, hs_addr aka)
1327 {
1328 UINT i;
1329
1330 for (i = 0; i <area->downlinkCount; i++) {
1331 if (addrComp(aka, area->downlinks[i]->link->hisAka)==0) return area->downlinks[i];
1332 }
1333
1334 return NULL;
1335 }
1336
1337 /* originally from hpt/src/toss.c */
1338 /* import: type == 0, export: type != 0 */
1339 /* return value: 0 if access ok, 3 if import/export off, 4 if not linked, */
1340 /* 15 if area is paused */
checkAreaLink(s_area * area,hs_addr aka,int type)1341 int checkAreaLink(s_area *area, hs_addr aka, int type)
1342 {
1343 s_arealink *arealink = NULL;
1344 int writeAccess = 0;
1345
1346 arealink = getAreaLink(area, aka);
1347 if (arealink) {
1348 if (type==0) {
1349 if (!arealink->import) writeAccess = BM_DENY_IMPORT;
1350 } else {
1351 if (!arealink->aexport) writeAccess = BM_DENY_IMPORT;
1352 }
1353 } else {
1354 if (addrComp(aka, *area->useAka)!=0) writeAccess = BM_NOT_LINKED;
1355 }
1356
1357 if (writeAccess==0 && area->paused) writeAccess = BM_AREA_IS_PAUSED;
1358
1359 return writeAccess;
1360 }
1361