1 /*
2 * fconf.c
3 *
4 * Written by Tobias Ernst et. al.
5 * Released to the public domain.
6 *
7 * Reads a husky project fidoconfig config file.
8 *
9 * There are two ways of reading the fidoconfig file: If the macro
10 * USE_FIDOCONFIG is defined, we will use the routines of the fidoconfig
11 * library. This is very easy, but as soon as a single new keyword is
12 * introduced to fidoconfig, you must recompile (or at least relink, but
13 * usually the interface also changes) Msged, because otherwise the
14 * library routines will complain about unknown keywords.
15 *
16 * Therefore, this file also contains routines that directly parse the
17 * fidoconfig file and simply ignore all unknown keywords. This is good for
18 * doing binary releases, as this code has a high chance of continuing to work
19 * even if the fidoconfig library is modified and new keywords are introduced.
20 * It is even resistant against the addition of new flags to area definitions
21 * - but of course if area definitions would be changed fundamentally, this
22 * code has to be adapted.
23 *
24 * Using the USE_FIDOCONFIG code is your choice if you compile Msged on your
25 * own and have no problem to update and recompile Msged every time you
26 * upgrade your fidoconfig and other Husky sources.
27 *
28 * For doing binary releases, or if you don't want to regularly update Msged
29 * along with the other tools, you should not use the USE_FIDOCONFIG code.
30 *
31 */
32
33 #ifdef USE_FIDOCONFIG
34 #include <fidoconf/fidoconf.h>
35 #else
36 #include <stdlib.h>
37 #include <stdio.h>
38 #endif
39
40 #include <time.h>
41 #include <string.h>
42 #include "version.h"
43 #include "addr.h"
44 #include "areas.h"
45 #include "nedit.h"
46 #include "msged.h"
47 #include "strextra.h"
48 #include "memextra.h"
49 #include "config.h"
50 #include "fconf.h"
51 #include "version.h"
52 #include "group.h"
53 #include "environ.h"
54
55 #ifdef USE_FIDOCONFIG
56
57 /* ===================================================================== */
58 /* Part 1: Fidoconfig routines that use the Fidoconfig library */
59 /* ===================================================================== */
60
fc_copy_address(FIDO_ADDRESS * a,hs_addr * fc_a)61 static void fc_copy_address(FIDO_ADDRESS *a, hs_addr *fc_a)
62 {
63 memset(a, 0, sizeof(FIDO_ADDRESS));
64
65 a->zone = fc_a->zone;
66 a->net = fc_a->net;
67 a->node = fc_a->node;
68 a->point = fc_a->point;
69
70 a->fidonet = 1;
71
72 if (fc_a->domain != NULL && *(fc_a->domain))
73 {
74 a->domain = xstrdup(fc_a->domain);
75 }
76 else
77 {
78 a->domain = NULL;
79 }
80 }
81
fc_add_area(s_area * fc_area,int netmail,int local)82 static void fc_add_area(s_area *fc_area, int netmail, int local)
83 {
84 static AREA a;
85
86 memset(&a, 0, sizeof a);
87
88 if (fc_area->msgbType != MSGTYPE_SDM
89 #ifdef USE_MSGAPI
90 && fc_area->msgbType != MSGTYPE_SQUISH
91 && fc_area->msgbType != MSGTYPE_JAM
92 #endif
93 )
94 {
95 return;
96 }
97
98 fc_copy_address(&(a.addr), fc_area->useAka);
99
100 a.tag = xstrdup(fc_area->areaName);
101 a.description=makeareadesc(fc_area->areaName, fc_area->description);
102
103 a.path = xstrdup(fc_area->fileName);
104
105 if ((fc_area->group != NULL) && (SW->areafilegroups) &&
106 (strcmp(fc_area->group, "\060") != 0))
107 {
108 a.group = group_gethandle(fc_area->group, 1);
109 }
110 else
111 {
112 a.group = 0;
113 }
114
115 if (netmail)
116 {
117 a.netmail = 1; a.priv = 1;
118 }
119 else if (local)
120 {
121 a.local = 1;
122 }
123 else
124 {
125 a.echomail = 1;
126 }
127
128 switch (fc_area->msgbType)
129 {
130 case MSGTYPE_SDM:
131 a.msgtype = FIDO;
132 break;
133 #ifdef USE_MSGAPI
134 case MSGTYPE_SQUISH:
135 a.msgtype = SQUISH;
136 break;
137 case MSGTYPE_JAM:
138 a.msgtype = JAM;
139 break;
140 #endif
141 default: /* should never get here */
142 abort();
143 }
144
145 applyflags(&a, areafileflags);
146 AddArea(&a);
147 }
148
check_fidoconfig(char * option_string)149 void check_fidoconfig(char *option_string)
150 {
151 #ifndef USE_FIDOCONFIG
152 printf("\r\aError! This version of "PROG" has been compiled\n"
153 "without support for the FIDOCONFIG standard.\n");
154 exit(-1);
155 #else
156
157 s_fidoconfig *fc_config = readConfig(NULL);
158 s_area *fc_area;
159 int i;
160 int check_type;
161
162 if (option_string != NULL && !stricmp(option_string, "settings"))
163 {
164 check_type = 1;
165 }
166 else if (option_string != NULL && !stricmp(option_string, "both"))
167 {
168 check_type = 3;
169 }
170 else /* Default: Load areas only */
171 {
172 check_type = 2;
173 }
174
175 if (fc_config != NULL)
176 {
177 if (check_type & 1) /* load settings */
178 {
179 /* sysop name */
180 for (i = 0; i < MAXUSERS; i++)
181 {
182 if (user_list[i].name == NULL)
183 {
184 break;
185 }
186 }
187 if (i < MAXUSERS)
188 {
189 user_list[i].name = xstrdup(fc_config->sysop);
190 if (i == 0)
191 {
192 release(ST->username);
193 ST->username = xstrdup(user_list[i].name);
194 SW->useroffset = user_list[i].offset;
195 }
196 }
197
198 /* addresses */
199 if (fc_config->addrCount)
200 {
201 alias = xrealloc(alias,
202 (SW->aliascount + fc_config->addrCount) *
203 sizeof (FIDO_ADDRESS));
204
205 for (i = 0; i < fc_config->addrCount; i++)
206 {
207 fc_copy_address(alias + SW->aliascount + i,
208 fc_config->addr + i);
209 }
210 SW->aliascount += fc_config->addrCount;
211 }
212
213 /* echotoss log */
214 if (fc_config->echotosslog !=NULL)
215 {
216 release(ST->echotoss);
217 ST->echotoss =
218 pathcvt(xstrdup(fc_config->echotosslog));
219 }
220
221 /* area to place file requests in */
222 if (fc_config->netMailAreaCount > 0)
223 {
224 release(ST->freqarea);
225 ST->freqarea = xstrdup(fc_config->netMailAreas[0].areaName);
226 }
227
228 /* fido user list */
229 if (fc_config->nodelistDir != NULL &&
230 fc_config->fidoUserList != NULL)
231 {
232 release(ST->fidolist);
233 ST->fidolist = xmalloc(strlen(fc_config->nodelistDir)+
234 strlen(fc_config->fidoUserList) + 1);
235 strcpy(ST->fidolist, fc_config->nodelistDir);
236 strcat(ST->fidolist, fc_config->fidoUserList);
237 }
238 }
239 if (check_type & 2) /* load areas */
240 {
241 /* netmail, dupe, bad */
242
243 fc_add_area(&(fc_config->dupeArea), 0, 1);
244 fc_add_area(&(fc_config->badArea), 0, 1);
245
246 /* netmail areas */
247 for (i=0; i<fc_config->netMailAreaCount; i++)
248 {
249 fc_area = &(fc_config->netMailAreas[i]);
250 if (fc_area->msgbType != MSGTYPE_PASSTHROUGH)
251 {
252 fc_add_area(fc_area, 1, 0);
253 }
254 }
255
256 /* local areas */
257 for (i=0; i<fc_config->localAreaCount; i++)
258 {
259 fc_area = &(fc_config->localAreas[i]);
260 if (fc_area->msgbType != MSGTYPE_PASSTHROUGH)
261 {
262 fc_add_area(fc_area, 0, 1);
263 }
264 }
265
266 /* echomail areas */
267 for (i=0; i<fc_config->echoAreaCount; i++)
268 {
269 fc_area = &(fc_config->echoAreas[i]);
270 if (fc_area->msgbType != MSGTYPE_PASSTHROUGH)
271 {
272 fc_add_area(fc_area, 0, 0);
273 }
274 }
275 }
276
277 disposeConfig(fc_config);
278 }
279 else
280 {
281 printf ("\r\aError! Cannot open fidoconfig!\n");
282 exit(-1);
283 }
284 #endif
285 }
286 #else
287
288 /* ===================================================================== */
289 /* Part 2: Fidoconfig routines that directly parse the Fidoconfig file */
290 /* ===================================================================== */
291
292 static void read_fidoconfig_file (char *filename, int check_type);
293 static FIDO_ADDRESS fc_default_address;
294 static int fc_default_address_set;
295 static char *fc_config_nodelistDir;
296 static char *fc_config_fidoUserList;
297
check_fidoconfig(char * option_string)298 void check_fidoconfig(char *option_string)
299 {
300 char *filename;
301 int check_type;
302
303 if (option_string != NULL && !stricmp(option_string, "settings"))
304 {
305 check_type = 1;
306 }
307 else if (option_string != NULL && !stricmp(option_string, "both"))
308 {
309 check_type = 3;
310 }
311 else /* Default: Load areas only */
312 {
313 check_type = 2;
314 }
315
316 filename = getenv("FIDOCONFIG");
317
318 if (filename == NULL)
319 {
320 printf ("\r\nError: You must set the FIDOCONFIG environment variable!\n");
321 return;
322 }
323
324 fc_default_address_set = 0;
325 memset(&fc_default_address, 0, sizeof(FIDO_ADDRESS));
326 release (fc_default_address.domain);
327
328 fc_config_nodelistDir = NULL;
329 fc_config_fidoUserList = NULL;
330
331 read_fidoconfig_file(filename, check_type);
332
333 if (fc_config_nodelistDir != NULL &&
334 fc_config_fidoUserList != NULL)
335 {
336 release(ST->userlist);
337 ST->userlist = xmalloc(strlen(fc_config_nodelistDir) +
338 strlen(fc_config_fidoUserList) + 1);
339 strcpy(ST->userlist, fc_config_nodelistDir);
340 strcat(ST->userlist, fc_config_fidoUserList);
341 }
342 release(fc_config_nodelistDir);
343 release(fc_config_fidoUserList);
344 }
345
get_rest_of_line(void)346 static char *get_rest_of_line(void)
347 {
348 static char *rest;
349 char *ptr;
350 int len=0;
351
352 if ((rest = strtok(NULL, "")) == NULL)
353 {
354 return NULL;
355 }
356
357 for (ptr = rest; *ptr == ' ' || *ptr == '\t'; ptr ++);
358
359 if ((len = strlen(ptr)) == 0)
360 {
361 return NULL;
362 }
363
364 len --;
365
366 while (len >= 0 && (ptr[len] == ' ' || ptr[len] =='\t'))
367 {
368 len--;
369 }
370 ptr[len + 1] = '\0';
371
372 return ptr;
373 }
374
375
parse_fc_sysop(void)376 static void parse_fc_sysop(void)
377 {
378 int i;
379 char *sysop = get_rest_of_line();
380
381 if (sysop)
382 {
383 for (i = 0; i < MAXUSERS; i++)
384 {
385 if (user_list[i].name == NULL)
386 {
387 break;
388 }
389 }
390
391 if (i < MAXUSERS)
392 {
393 user_list[i].name = xstrdup(sysop);
394 if (i == 0)
395 {
396 release(ST->username);
397 ST->username = xstrdup(user_list[i].name);
398 SW->useroffset = user_list[i].offset;
399 }
400 }
401 }
402 }
403
404
parse_fc_address(int check_type)405 static void parse_fc_address(int check_type)
406 {
407 char *token = strtok(NULL, " \t");
408 FIDO_ADDRESS tmp;
409 tmp = parsenode(token);
410
411 if (token == NULL)
412 {
413 printf ("\r\nFidoconfig address statement missing argument.\n");
414 return;
415 }
416
417 if (!fc_default_address_set)
418 {
419 fc_default_address_set = 1;
420 copy_addr(&fc_default_address, &tmp);
421 }
422
423 if (check_type & 1) /* load settings */
424 {
425 alias = xrealloc(alias, (++SW->aliascount) * sizeof(FIDO_ADDRESS));
426 memset(alias + SW->aliascount - 1, 0, sizeof(FIDO_ADDRESS));
427 copy_addr(alias + SW->aliascount - 1, &tmp);
428 }
429 release(tmp.domain);
430 }
431
parse_fc_tosslog(void)432 static void parse_fc_tosslog(void)
433 {
434 char *tosslog = get_rest_of_line();
435
436 if (tosslog)
437 {
438 release(ST->echotoss);
439 ST->echotoss = pathcvt(xstrdup(tosslog));
440 }
441 }
442
parse_fc_fidouserlist()443 static void parse_fc_fidouserlist()
444 {
445 fc_config_fidoUserList = xstrdup(get_rest_of_line());
446 }
447
parse_fc_nodelistdir()448 static void parse_fc_nodelistdir()
449 {
450 fc_config_nodelistDir = xstrdup(get_rest_of_line());
451 }
452
parse_fc_include(int check_type)453 static void parse_fc_include(int check_type)
454 {
455 char *token = strtok(NULL, " \t");
456 char *fn;
457 char *duptoken;
458
459 if (token != NULL)
460 {
461 duptoken = xstrdup(token);
462 fn = pathcvt(duptoken);
463 read_fidoconfig_file(fn, check_type);
464 xfree(fn);
465 }
466 else
467 {
468 printf ("\r\nFidoconfig include statement missing argument.\n");
469 }
470 }
471
fc_get_description(char * firsttoken)472 static char *fc_get_description(char *firsttoken)
473 {
474
475 static char desc[257];
476 char *token = firsttoken;
477 int len = 0;
478
479 *desc = '\0';
480 while(token != NULL)
481 {
482 if (len + 1 >= sizeof(desc))
483 {
484 return NULL;
485 }
486 if (*desc)
487 {
488 desc[len++] = ' '; desc[len] = '\0';
489 }
490 else
491 {
492 if (*token=='"')
493 {
494 token++;
495 }
496 }
497 if (len + strlen(token) >= sizeof(desc))
498 {
499 return NULL;
500 }
501 strcpy(desc + len, token);
502 len += strlen(token);
503
504 if (!len || desc[len - 1]!='"')
505 {
506 token=strtok(NULL, " \t");
507 }
508 else
509 {
510 token = NULL;
511 if (len)
512 {
513 desc[len - 1] = '\0';
514 }
515 }
516 }
517
518 return desc;
519 }
520
521
522
parse_fc_area(int type)523 static void parse_fc_area(int type)
524 {
525 static AREA a;
526 char *area_description = NULL;
527 char *token;
528 int option;
529
530 memset(&a, 0, sizeof(AREA));
531
532 token = strtok(NULL, " \t");
533 if (token == NULL)
534 {
535 printf ("\r\nFidoconfig *area statement missing argument.\n");
536 return;
537 }
538
539 a.tag = xstrdup(token);
540
541 token = strtok(NULL, " \t");
542 if (token == NULL)
543 {
544 xfree(a.tag);
545 printf ("\r\nFidoconfig *area statement missing argument.\n");
546 return;
547 }
548 else if (!stricmp(token, "passthrough"))
549 {
550 xfree(a.tag);
551 return;
552 }
553
554 a.path = pathcvt(xstrdup(token));
555
556 copy_addr(&(a.addr), &(fc_default_address));
557
558 switch(type)
559 {
560 case 1:
561 a.netmail = 1;
562 a.priv = 1;
563 break;
564 case 2:
565 a.local = 1;
566 break;
567 case 3:
568 a.echomail = 1;
569 break;
570 }
571
572 a.msgtype = FIDO;
573
574 token = strtok(NULL, " \t");
575 while (token != NULL)
576 {
577 if (token[0] == '-')
578 {
579 option = 0;
580 if (!stricmp(token + 1, "b"))
581 {
582 option = 1;
583 }
584 else if (!stricmp(token + 1, "a"))
585 {
586 option = 2;
587 }
588 else if (!stricmp(token + 1, "g"))
589 {
590 option = 3;
591 }
592 else if (!stricmp(token + 1, "d"))
593 {
594 option = 4;
595 }
596
597 if (option)
598 {
599 token = strtok(NULL, " \t");
600 if (token != NULL)
601 {
602 switch(option)
603 {
604 case 1:
605 if (!stricmp(token, "msg"))
606 {
607 a.msgtype = FIDO;
608 }
609 #ifdef USE_MSGAPI
610 else if (!stricmp(token, "squish"))
611 {
612 a.msgtype = SQUISH;
613 }
614 else if (!stricmp(token, "jam"))
615 {
616 a.msgtype = JAM;
617 }
618 #endif
619 else
620 {
621 release(a.tag);
622 release(a.path);
623 release(a.addr.domain);
624 return;
625 }
626 break;
627
628 case 2:
629 release(a.addr.domain);
630 a.addr = parsenode(token);
631 break;
632
633 case 3:
634 a.group = group_gethandle(token, 1);
635 break;
636
637 case 4:
638 area_description = fc_get_description(token);
639 break;
640 }
641 }
642 }
643 }
644 token = strtok(NULL, " \t");
645 }
646
647 a.description=makeareadesc(a.tag, area_description);
648 applyflags(&a, areafileflags);
649 AddArea(&a);
650 }
651
parse_fc_line(char * line,int check_type)652 static void parse_fc_line(char *line, int check_type)
653 {
654 char *token;
655
656 if (!(*line))
657 {
658 return;
659 }
660
661 token = strtok(line, " \t");
662
663 if (token == NULL)
664 {
665 return;
666 }
667
668 if ((check_type & 2) &&
669 ((!stricmp(token, "netmailarea")) ||
670 (!stricmp(token, "netarea"))))
671 {
672 parse_fc_area(1); /* netmail folders */
673 }
674 else if ((check_type && 2) &&
675 ((!stricmp(token, "dupearea")) ||
676 (!stricmp(token, "badarea")) ||
677 (!stricmp(token, "localarea"))))
678 {
679 parse_fc_area(2); /* local folders */
680 }
681 else if ((check_type && 2) &&
682 (!stricmp(token, "echoarea")))
683 {
684 parse_fc_area(3); /* echomail folders */
685 }
686 else if ((!stricmp(token, "include")))
687 {
688 parse_fc_include(check_type);
689 }
690 else if ((!stricmp(token, "address")))
691 {
692 parse_fc_address(check_type);
693 }
694 else if ((check_type && 1) &&
695 (!stricmp(token, "sysop")))
696 {
697 parse_fc_sysop();
698 }
699 else if ((check_type && 1) &&
700 (!stricmp(token, "echotosslog")))
701 {
702 parse_fc_tosslog();
703 }
704 else if ((check_type && 1) &&
705 (!stricmp(token, "fidouserlist")))
706 {
707 parse_fc_fidouserlist();
708 }
709 else if ((check_type && 1) &&
710 (!stricmp(token, "nodelistdir")))
711 {
712 parse_fc_nodelistdir();
713 }
714 else
715 {
716 /* unknown token */
717 ;
718 }
719
720 return;
721 }
722
read_fidoconfig_file(char * filename,int check_type)723 static void read_fidoconfig_file (char *filename, int check_type)
724 {
725 FILE *f = fopen(filename, "r");
726 static char *line = NULL; /* uh, oh, care for reentrance! */
727 char *start;
728 char *expanded_line;
729 size_t l;
730 int c;
731
732 if (line == NULL) line = xmalloc(2048);
733
734 if (f == NULL)
735 {
736 printf ("\r\nError: Can't open %s while parsing fidoconfig file.\n",
737 filename);
738 return;
739 }
740
741 while(fgets(line, 2048, f) != NULL)
742 {
743 l = strlen(line);
744
745 /* handle trailing \n */
746 if (l)
747 {
748 if (line[l-1] != '\n')
749 {
750 /* eat up superfluous characters in extra long line */
751 do
752 {
753 c = fgetc(f);
754 } while (c != '\n' && c != EOF);
755 }
756 else
757 {
758 line[l-1] = '\0';
759 }
760 }
761
762 /* trim spaces at beginning */
763 for (start = line;
764 ((*start == ' ') || (*start == '\t') || (*start == (char)0xFE));
765 start++, l--);
766 memmove(line, start, l+1);
767
768 /* trim trailing spaces */
769 while (l && (line[l - 1] == ' ' || line[l - 1] == '\t'))
770 {
771 line[l - 1] = '\0';
772 l--;
773 }
774
775 /* strip comments */
776 if (*line == '#')
777 {
778 *line='\0';
779 }
780 else
781 {
782 start = strchr(line,'#');
783 if ((start != NULL) && (*(start - 1)==' ' || *(start - 1) == '\t'))
784 {
785 *(start - 1) = '\0';
786 }
787 }
788
789 expanded_line = env_expand(line); /* expand %ENVIRONMENT% variables */
790 parse_fc_line(expanded_line, check_type);
791 xfree(expanded_line);
792 }
793
794 fclose(f);
795 }
796 #endif
797