1 /* Copyright (C) 2002 GFRN systems
2
3 This program is free software; you can redistribute it and/or
4 modify it under the terms of the GNU General Public License as
5 published by the Free Software Foundation; either version 2 of the
6 License, or (at your option) any later version.
7
8 This program is distributed in the hope that it will be useful, but
9 WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11 See the GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License
14 along with this program; if not, write to the Free Software
15 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
16 02111-1307, USA.
17
18 The latest version of this program may be found at
19 http://CQiNet.sourceforge.net
20
21 $Log: configvars.c,v $
22 Revision 1.37 2012/12/09 19:32:13 wb6ymh
23 1. Removed old chan_rptdir style Asterisk support variables AsteriskIP,
24 AsteriskBind2IP, AsteriskDesc, AsteriskPort, and AsteriskEnable.
25 Asterisk is now supported by G.726 and Ulaw RTP connections.
26 2. Added ConfTextEnable and ConfCmdEnable.
27
28 Revision 1.36 2012/12/09 18:52:40 wb6ymh
29 Corrected bug in LoadFile which caused odd crashes and general bad behavor
30 when the configuration variables HelpFile or InfoFile where used.
31
32 Revision 1.35 2011/11/06 14:34:06 wb6ymh
33 Added RTP_Port. NB: not tested in thebridge build, added to fix
34 compile error. Tested on thelinkbox build, probably works here too.
35
36 Revision 1.34 2009/09/14 21:45:32 wb6ymh
37 1. Added TempDir.
38 2. Added new argument to the StartCmdHandler call.
39
40 Revision 1.33 2009/04/04 20:17:39 wb6ymh
41 Added LogIPAddresses.
42
43 Revision 1.32 2008/07/23 14:47:12 wb6ymh
44 Added AsteriskEnable, CompressionType, and FullDuplex configuration variables.
45
46 Revision 1.31 2008/07/16 22:40:23 wb6ymh
47 Added AsteriskBind2IP, AsteriskIP, AsteriskDesc, EnableRemoteDTMF,
48 FullDuplex, and AsteriskPort.
49
50 Revision 1.30 2008/04/11 14:08:24 wb6ymh
51 Added missing argument to error logging in CheckEmailAdr. Fixes segfault
52 when email address lacks '@' or '.' characters.
53
54 Revision 1.29 2008/02/26 17:35:47 wb6ymh
55 1. Added dmalloc support.
56 2. Added AllowADPCM, EchoLinkEnable, and Debug config variables.
57
58 Revision 1.28 2008/02/09 16:53:26 wb6ymh
59 Added ShowStatusInInfo.
60
61 Revision 1.27 2008/01/03 16:07:15 wb6ymh
62 1. Added SFBind2IP.
63 2. Restored default AppName to "tbd".
64
65 Revision 1.26 2007/12/27 18:36:05 wb6ymh
66 Added FullName.
67
68 Revision 1.25 2007/12/22 18:58:13 wb6ymh
69 Changed calling convention of all SetFuncs (now called AccessFunc).
70
71 Revision 1.24 2007/12/07 22:41:08 wb6ymh
72 1. Removed thelinkbox variables, they are now elsewhere.
73 2. Added ConfigGetVarPtr() stub.
74
75 Revision 1.23 2007/11/26 15:03:27 wb6ymh
76 Undeleted. Converting to C++ was a bad idea because it would have required
77 a C++ compiler to build thebrige as well as thelinkbox. This file is now
78 used for thebrige only. Configuration variables for thelinkbox are defined
79 in ../linkbox/configvars.cpp.
80
81 Revision 1.21 2007/11/21 17:29:43 wb6ymh
82 1. Added configuration variables AudioDongleSN, COS_KeyCode, and ShareIRLP_Port.
83 2. Added bMonitor so it's accessable to the set command.
84
85 Revision 1.20 2007/06/29 18:16:15 wb6ymh
86 Added QthInHostsFile configuration variable to allow Qth information to
87 be optionally included in the host file. NB: As of today the inclusion
88 of Qth information breaks the EchoIRLP scripts.
89
90 Revision 1.19 2007/06/29 17:14:55 wb6ymh
91 Edit, COMPILE, then commit!
92
93 Revision 1.18 2007/06/29 17:11:28 wb6ymh
94 Corrected CONFIG_FILE_PATH, thelinkbox and thebridge version were swapped.
95
96 Revision 1.17 2007/06/13 00:05:08 wb6ymh
97 1. Added ChatPort.
98 2. Added thelinkbox configuration variables.
99 3. Changed LoadHelp file to LoadFile and made it more generic so it can
100 be used to load command files as well as help files.
101
102 Revision 1.16 2004/11/27 22:12:45 wb6ymh
103 Added new configuration variables UserName, ConfEnable, AvrsEnable,
104 AvrsInterval, bEchoIrlpMode, Latitude, Longitude, TxPower, Hatt, AntGain,
105 Frequency and CTCSS. Added AVRS_Validate() to check entered values.
106
107 Revision 1.15 2004/11/22 00:42:20 wb6ymh
108 1. "%f" -> "%F" so we can support floating point numbers in the
109 configuration file.
110 2. Added configuration variable IncludeAllHosts.
111 3. Warn about needing a "-L", "-R", or conference callsign for all
112 configurations, not just EchoIRLP.
113
114 Revision 1.14 2004/05/29 17:22:47 wb6ymh
115 Add warning about "conference" callsign needing to be a "-R" or "-L" when
116 thebridge is configured for use with EchoIRLP.
117
118 Revision 1.13 2003/09/06 19:05:16 wb6ymh
119 Added MaxDups.
120 Changed default value for StationListInterval to 600 (10 minutes).
121
122 Revision 1.12 2003/09/01 15:15:01 wb6ymh
123 1. Added configuration variables EmailAdr, CmdPort, IdleTimeout, SF_ReplyPort,
124 DirCompression, EventScript, StartupCmd, HelpFile and WelcomeDelay.
125 2. Modified for multipass initialization, primarily to support StartupCmd.
126
127 Revision 1.11 2003/04/30 21:35:58 wb6ymh
128 1. Added configuration varibles Bind2IP, AppName, RunDir, AutoLurkTimeout,
129 DefaultAutoLurk, BlabOffTimer, and LogLevel.
130 2. Added SetQth() to verify that the default Qth has been edited (sigh).
131
132 Revision 1.10 2002/12/21 18:17:24 wb6ymh
133 Added configuration variables MaxPlayWithoutPause, SaveInfoFiles,
134 ShowStationInfo and WriteHostFile.
135
136 Revision 1.9 2002/12/18 00:56:59 wb6ymh
137 Added WelcomeFile, MaxPlayBackPause, MinPlayBackPause, LogFileRolloverType,
138 and AudioTestConf.
139
140 Revision 1.8 2002/11/02 18:15:23 wb6ymh
141 1. Added config variables RTP_Pass, PrivateConference, EnableDiskCommands,
142 iLinkDirServer, DnsUpdateInterval, BelchTime, InactiveDirTimeout and
143 bQuickStart.
144 2. Added routine to set ConferenceCall so we can check for an unedited
145 config file earlier in the game. (Otherwise a bad working directory
146 is reported before the default conference call is detected confusing
147 lusers).
148
149 Revision 1.7 2002/10/25 14:27:30 wb6ymh
150 Added iLinkDirServer config variable.
151
152 Revision 1.6 2002/09/29 16:32:55 wb6ymh
153 Added configuration variables SysopPass and PauseTime.
154
155 Revision 1.5 2002/09/14 16:49:21 wb6ymh
156 Added WorkingDir, RunAsUser, Banner, UserCountEnable, MaxCountEnable, and
157 UserCountInLocation variables. Deleted BannerEable and ConnectTo variables.
158
159 Revision 1.4 2002/09/01 04:55:40 wb6ymh
160 Fixed yet another more pointer to pointer bug.... sigh.
161
162 Revision 1.3 2002/09/01 03:05:16 wb6ymh
163 Pointers to pointers make my head hurt! Fixed bug in SetConfigDefaults().
164 GCC V 2.95.3 under FreeBSD didn't issue a warning, but GCC V 2.95.3 on
165 Linux and Visual C++ did. Weird!
166
167 Revision 1.2 2002/08/31 23:42:36 wb6ymh
168 Added configuration variables DirServerHost1 ...3, AdminPass, BannerEnable,
169 SF_Port, SF_Enable, SF_SWL_Only, LinkConferences. Modified SetConfigDefaults()
170 to free all "%s" type variables. Changed DirServerHost to be an array of
171 NUM_DIRECTORY_SERVERS strings. Changed ConfAudioTimeout default to 800
172 milliseconds.
173
174 Revision 1.1.1.1 2002/08/10 20:33:41 wb6ymh
175 initial import
176
177 */
178
179 #include "common.h"
180 #include <stdio.h>
181 #include <stdlib.h>
182 #include <string.h>
183 #include <errno.h>
184 #ifndef _WIN32
185 #include <unistd.h>
186 #include <sys/socket.h>
187 #include <netinet/in.h>
188 #include <arpa/inet.h>
189 #include <sys/types.h>
190 #ifdef TIME_WITH_SYS_TIME
191 #include <sys/time.h>
192 #include <time.h>
193 #else
194 #ifdef HAVE_SYS_TIME_H
195 #include <sys/time.h>
196 #else
197 #include <time.h>
198 #endif
199 #endif
200 #include <sys/stat.h>
201 #define CONFIG_FILE_PATH SYSCON_DIR "/tbd.conf"
202
203 #include <netdb.h>
204 #else
205 #include <direct.h>
206 #include <time.h>
207 #include <sys\timeb.h>
208 #include <winsock2.h>
209 #include <sys\stat.h>
210 #define CONFIG_FILE_PATH "tbd.conf"
211 #endif
212
213 #include "configfile.h"
214 #include "configvars.h"
215 #include "main.h"
216 #include "conference.h"
217 #include "sf.h"
218 #include "hostfile.h"
219 #include "rtp.h"
220
221 #ifdef USE_DMALLOC
222 #include "dmalloc.h"
223 #endif
224
225 // Configuration variables
226
227 // String variables: Dynamically allocated
228 char *ConferenceCall;
229 char *ConferencePass;
230 char *ConferenceQth;
231 char *EmailAdr;
232 char *ConferenceID;
233 char *DirServerHost[NUM_DIRECTORY_SERVERS];
234 char *AdminPass;
235 char *SysopPass;
236 char *Banner;
237 char *WorkingDir;
238 char *RunAsUser;
239 char *RTP_Pass;
240 char *WelcomeFile;
241 char *Bind2IP;
242 char *SFBind2IP;
243 char *AppName;
244 char *RunDir;
245 char *EventScript;
246 char *CustomHelp;
247 char *AntType;
248 char *UserName;
249 char *FullName;
250 char *TempDir;
251 char *RTP_Port;
252
253 // Integer variables
254 int ConfAudioTimeout = 800; // in milliseconds (> 8 frames)
255 int ConfMemberTimeout = 40; // in seconds (>= 4 missed frames)
256 int LoginInterval = 360; // in seconds
257 int StationListInterval = 600; // in seconds
258 int SDES_Interval = 10; // in seconds
259 int MaxConferenceClients= 8;
260 int SF_Port = SF_AUDIO_PORT;
261 int SF_Enable = 0;
262 int bAllowADPCM = 0;
263 int bEchoLinkEnabled = 1;
264 int LinkConferences = 1;
265 int SF_SWL_Only = 0;
266 int SB_Enable = 0;
267 int UserCountEnable = 1;
268 int MaxCountEnable = 1;
269 int UserCountInLocation = 1;
270 int PauseTime = 0;
271 int iLinkDirServer = 0;
272 int PrivateConference = 0;
273 int EnableDiskCommands = 1;
274 int DnsUpdateInterval = 15 * 60;
275 int BelchTime = 0;
276 int InactiveDirTimeout = 60 * 60 * 24; // one day
277 int EnableRemoteDTMF = 0;
278 int CompressionType = RTP_PT_GSM;
279 int FullDuplex = 0;
280 int LogIPAddresses = 0;
281
282 extern int LogFileRolloverType;
283
284 int MaxPlayBackPause = 5;
285 int MinPlayBackPause = 0;
286 int AudioTestConf = 0;
287 int MaxPlayWithoutPause = (10 * 60); // 10 minutes
288 int SaveInfoFiles = 0;
289 int ShowStationInfo = 0;
290 int WriteHostFile = 0;
291 int AutoLurkTimeout = (15 * 60); // 15 minutes
292 int DefaultAutoLurk = 0;
293 int BlabOffTimer = 0;
294 int LogLevel = 0;
295 int CmdPort = 0;
296 int ChatPort = 0;
297 int IdleTimeout = 3 * 60;
298 int SF_ReplyPort = SF_AUDIO_PORT;
299 int DirCompression = 1;
300 int WelcomeDelay = 0;
301 int MaxDups = 100;
302 int IncludeAllHosts = 0;
303 int QthInHostsFile = 0;
304 int AvrsEnable = 0;
305 int AvrsInterval = (10 * 60); // 10 minutes
306 int bEchoIrlpMode = 0;
307 int ConfEnable = 1;
308 int ConfTextEnable = 1;
309 int ConfCmdEnable = 1;
310 int ShowStatusInInfo = 0; // Default to disabled
311
312 float Latitude = 200.0;
313 float Longitude = 200.0;
314 float TxPower = 0.0;
315 float Haat = 0.0;
316 float AntGain = 0.0;
317 float AntDir = 0.0; // 0.0 = omni, heading of zero encoded as 360.0
318 float Frequency = 0.0;
319 float CTCSS = 0.0;
320
321 int AddBannerLine(struct config_entry *p, char *Arg, AfCmd Cmd, int x);
322 int SetWorkingDir(struct config_entry *p, char *Arg, AfCmd Cmd, int x);
323 int SetConferenceCall(struct config_entry *p, char *Arg, AfCmd Cmd, int x);
324 int SetQth(struct config_entry *p, char *Arg, AfCmd Cmd, int x);
325 int CheckEmailAdr(struct config_entry *p, char *Arg, AfCmd Cmd, int x);
326 int StartupCommand(struct config_entry *p, char *Arg, AfCmd Cmd, int x);
327 int LoadFile(struct config_entry *p, char *Arg, AfCmd Cmd, int x);
328 int AVRS_Validate(void);
329 int AccessRtpPort(struct config_entry *p, char *Arg, AfCmd Cmd, int x);
330
331 // Pass 1 variables: processed before initialization
332 // Pass 2 variables: processed immediately after initialization
333 // Pass 3 variables: processed after first station list has been downloaded
334 // Pass 4 variables: processed after second successful directory server login
335 // (approximately one minute after pass 3)
336 // Pass 5: Manual set command
337 #define NUM_CONFIG_PASSES 4
338
339 struct config_entry ConfigVars[] = {
340 // Required parameters
341 { "ConferenceCall", "%F", &ConferenceCall, CON_FLG_REQUIRED, SetConferenceCall},
342 { "ConferencePass", "%s", &ConferencePass, CON_FLG_REQUIRED},
343 { "ConferenceQth", "%s", &ConferenceQth, CON_FLG_REQUIRED},
344 { "WorkingDir", "%F", &WorkingDir, CON_FLG_REQUIRED | CON_FLG_ONCE_ONLY, SetWorkingDir},
345 { "EmailAdr", "%F", &EmailAdr, CON_FLG_REQUIRED, CheckEmailAdr },
346 // Optional parameters
347 { "TempDir", "%s", &TempDir, 0},
348 { "ConferenceID", "%s", &ConferenceID, 0},
349 { "DirServerHost", "%s", &DirServerHost[0], 0},
350 { "DirServerHost1", "%s", &DirServerHost[1], 0},
351 { "DirServerHost2", "%s", &DirServerHost[2], 0},
352 { "DirServerHost3", "%s", &DirServerHost[3], 0},
353 { "RunAsUser", "%s", &RunAsUser, 0},
354 { "AdminPass", "%s", &AdminPass, 0},
355 { "SysopPass", "%s", &SysopPass, 0},
356 { "RTP_Pass", "%s", &RTP_Pass, 0},
357 { "WelcomeFile", "%s", &WelcomeFile, 0},
358 { "Bind2IP", "%s", &Bind2IP, 0},
359 { "SFBind2IP", "%s", &SFBind2IP, 0},
360 { "AppName", "%s", &AppName, 0},
361 { "RunDir", "%s", &RunDir, 0},
362 { "Banner", "%F", &Banner, 0, AddBannerLine},
363 { "ConfMemberTimeout", "%d", &ConfMemberTimeout, 0},
364 { "ConfAudioTimeout", "%d", &ConfAudioTimeout, 0},
365 { "LoginInterval", "%d", &LoginInterval, 0},
366 { "StationListInterval", "%d", &StationListInterval, 0},
367 { "SDES_Interval", "%d", &SDES_Interval, 0},
368 { "MaxConferenceClients", "%d", &MaxConferenceClients, 0},
369 { "SF_Port", "%d", &SF_Port, 0},
370 { "SF_Enable", "%d", &SF_Enable, 0},
371 { "SF_SWL_Only", "%d", &SF_SWL_Only, 0},
372 { "SB_Enable", "%d", &SB_Enable, 0},
373 { "UserCountEnable", "%d", &UserCountEnable, 0},
374 { "MaxCountEnable", "%d", &MaxCountEnable, 0},
375 { "UserCountInLocation", "%d", &UserCountInLocation, 0},
376 { "LinkConferences", "%d", &LinkConferences, 0},
377 { "PauseTime", "%d", &PauseTime, 0},
378 { "iLinkDirServer", "%d", &iLinkDirServer, 0},
379 { "PrivateConference", "%d", &PrivateConference, 0},
380 { "EnableDiskCommands", "%d", &EnableDiskCommands, 0},
381 { "DnsUpdateInterval", "%d", &DnsUpdateInterval, 0},
382 { "BelchTime", "%d", &BelchTime, 0},
383 { "InactiveDirTimeout", "%d", &InactiveDirTimeout, 0},
384 { "LogFileRolloverType", "%d", &LogFileRolloverType, 0},
385 { "MaxPlayBackPause", "%d", &MaxPlayBackPause, 0},
386 { "MinPlayBackPause", "%d", &MinPlayBackPause, 0},
387 { "AudioTestConf", "%d", &AudioTestConf, 0},
388 { "MaxPlayWithoutPause", "%d", &MaxPlayWithoutPause, 0},
389 { "SaveInfoFiles", "%d", &SaveInfoFiles, 0},
390 { "ShowStationInfo", "%d", &ShowStationInfo, 0},
391 { "WriteHostFile", "%d", &WriteHostFile, 0},
392 { "AutoLurkTimeout", "%d", &AutoLurkTimeout, 0},
393 { "DefaultAutoLurk", "%d", &DefaultAutoLurk, 0},
394 { "BlabOffTimer", "%d", &BlabOffTimer, 0},
395 { "LogLevel", "%d", &LogLevel, 0},
396 { "CmdPort", "%d", &CmdPort, 0},
397 { "ChatPort", "%d", &ChatPort, 0},
398 { "IdleTimeout", "%d", &IdleTimeout, 0},
399 { "SF_ReplyPort", "%d", &SF_ReplyPort, 0},
400 { "DirCompression", "%d", &DirCompression, 0},
401 { "EventScript", "%s", &EventScript, 0},
402 { "StartupCmd", "%F", NULL, CON_FLG_PASS4, StartupCommand},
403 { "HelpFile", "%F", &CustomHelp, 0, LoadFile},
404 { "WelcomeDelay", "%d", &WelcomeDelay, 0},
405 { "MaxDups", "%d", &MaxDups, 0},
406 { "ConfEnable", "%d", &ConfEnable, 0},
407 { "UserName", "%s", &UserName, 0},
408 { "IncludeAllHosts", "%d", &IncludeAllHosts, 0},
409 { "QthInHostsFile", "%d", &QthInHostsFile, 0},
410 { "Latitude", "%f", &Latitude, 0},
411 { "Longitude", "%f", &Longitude, 0},
412 { "TxPower", "%f", &TxPower, 0},
413 { "Haat", "%f", &Haat, 0},
414 { "AntGain", "%f", &AntGain, 0},
415 { "Frequency", "%f", &Frequency, 0},
416 { "CTCSS", "%f", &CTCSS, 0},
417 { "AntType", "%s", &AntType, 0},
418 { "AntDir", "%f", &AntDir, 0},
419 { "AvrsEnable", "%d", &AvrsEnable, 0},
420 { "AvrsInterval", "%d", &AvrsInterval, 0},
421 { "ShowStatusInInfo", "%d", &ShowStatusInInfo},
422 { "AllowADPCM", "%d", &bAllowADPCM, 0},
423 { "EchoLinkEnable", "%d", &bEchoLinkEnabled, 0},
424 { "Debug", "%d", &Debug, 0},
425 { "EnableRemoteDTMF", "%d", &EnableRemoteDTMF, 0},
426 { "CompressionType", "%d", &CompressionType, 0},
427 { "FullDuplex", "%d", &FullDuplex, 0},
428 { "LogIPAddresses", "%d", &LogIPAddresses, 0},
429 { "RTP_Port", "%F", NULL, 0, AccessRtpPort},
430 { "" } /* end of table marker */
431 };
432
SetConfigDefaults(int bSet)433 void SetConfigDefaults(int bSet)
434 {
435 int i;
436 void *var_ptr = NULL;
437
438 for(i = 0; ConfigVars[i].var_name[0] != 0; i++) {
439 if(strcmp(ConfigVars[i].var_type,"%s") == 0) {
440 if(ConfigVars[i].Flags & CON_FLG_BASED_VAR) {
441 if(ConfigPass == 0) {
442 // Prior to first pass, class variables haven't been created yet
443 continue;
444 }
445 }
446 else {
447 var_ptr = ConfigVars[i].var_ptr;
448 }
449
450 if(*((char **) var_ptr) != NULL)
451 {
452 free(*((char **) var_ptr));
453 *((char **) var_ptr) = NULL;
454 }
455 }
456 else if(strcmp(ConfigVars[i].var_type,"%F") == 0) {
457 ConfigVars[i].AccessFunc(&ConfigVars[i],NULL,AF_SET_DEFAULT,0);
458 }
459 }
460
461 if(bSet) {
462 ConferenceID = strdup(PACKAGE " V " VERSION);
463 DirServerHost[0] = strdup("server1.echolink.org");
464 AppName = strdup("tbd");
465 RunDir = strdup("/var/run/");
466 }
467 }
468
AddBannerLine(struct config_entry * p,char * Arg,AfCmd Cmd,int x)469 int AddBannerLine(struct config_entry *p, char *Arg, AfCmd Cmd, int x)
470 {
471 char *Temp;
472
473 switch(Cmd) {
474 case AF_SET_VAR:
475 if(Banner != NULL) {
476 // Banner already has line(s)
477 Temp = Banner;
478 Banner = (char *) malloc(strlen(Temp)+strlen(Arg)+2);
479 if(Banner != NULL) {
480 strcpy(Banner,Temp);
481 strcat(Banner,"\r");
482 strcat(Banner,Arg);
483 }
484 free(Temp);
485 }
486 else {
487 // First banner line
488 Banner = strdup(Arg);
489 }
490 break;
491
492 case AF_SET_DEFAULT:
493 if(Banner != NULL) {
494 free(Banner);
495 Banner = NULL;
496 }
497 break;
498
499 case AF_DISPLAY_VAR:
500 break;
501 }
502
503 return 0;
504 }
505
SetConferenceCall(struct config_entry * p,char * Arg,AfCmd Cmd,int x)506 int SetConferenceCall(struct config_entry *p, char *Arg, AfCmd Cmd, int x)
507 {
508 int Ret = 0;
509
510 switch(Cmd) {
511 case AF_SET_VAR:
512 if(ConferenceCall != NULL) {
513 free(ConferenceCall);
514 }
515
516 ConferenceCall = strdup(Arg);
517
518 if(strcmp(ConferenceCall,"W1AW") == 0) {
519 LOG_ERROR(("Come on now, your call isn't really W1AW is it!\n"));
520 LOG_ERROR(("Please read the documentation, edit tbd.conf and try again.\n"));
521 Ret = ERR_CONFIG_FILE;
522 }
523 p->Flags |= CON_FLG_SET;
524 break;
525
526 case AF_SET_DEFAULT:
527 if(ConferenceCall != NULL) {
528 free(ConferenceCall);
529 ConferenceCall = NULL;
530 }
531 break;
532
533 case AF_DISPLAY_VAR:
534 strncpy(Arg,ConferenceCall,x);
535 break;
536 }
537 return Ret;
538 }
539
SetQth(struct config_entry * p,char * Arg,AfCmd Cmd,int x)540 int SetQth(struct config_entry *p, char *Arg, AfCmd Cmd, int x)
541 {
542 int Ret = 0;
543
544 switch(Cmd) {
545 case AF_SET_VAR:
546 if(ConferenceQth!= NULL) {
547 free(ConferenceQth);
548 }
549
550 ConferenceQth = strdup(Arg);
551
552 if(strcmp(ConferenceQth,"Newington, Ct.") == 0) {
553 LOG_ERROR(("Come on now, you don't live in \"Newington, Ct.\" do you!\n"));
554 LOG_ERROR(("Please read the documentation, edit tbd.conf and try again.\n"));
555 Ret = ERR_CONFIG_FILE;
556 }
557 p->Flags |= CON_FLG_SET;
558 break;
559
560 case AF_SET_DEFAULT:
561 if(ConferenceQth != NULL) {
562 free(ConferenceQth);
563 ConferenceQth = NULL;
564 }
565 break;
566
567 case AF_DISPLAY_VAR:
568 strncpy(Arg,ConferenceQth,x);
569 break;
570 }
571
572 return Ret;
573 }
574
SetWorkingDir(struct config_entry * p,char * Arg,AfCmd Cmd,int x)575 int SetWorkingDir(struct config_entry *p, char *Arg, AfCmd Cmd, int x)
576 {
577 int Ret = 0;
578
579 switch(Cmd) {
580 case AF_SET_VAR:
581 if(WorkingDir != NULL) {
582 free(WorkingDir);
583 }
584 WorkingDir = strdup(Arg);
585 if(WorkingDir != NULL) {
586 if(chdir(WorkingDir)) {
587 LOG_ERROR(("Unable to change to working directory \"%s\", %s",
588 WorkingDir,Err2String(errno)));
589 free(WorkingDir);
590 WorkingDir = NULL;
591 Ret = ERR_WORKING_DIR;
592 }
593 p->Flags |= CON_FLG_SET;
594 }
595 break;
596
597 case AF_SET_DEFAULT:
598 if(WorkingDir != NULL) {
599 free(WorkingDir);
600 WorkingDir = NULL;
601 }
602 break;
603
604 case AF_DISPLAY_VAR:
605 strncpy(Arg,WorkingDir,x);
606 break;
607 }
608
609 return Ret;
610 }
611
CheckEmailAdr(struct config_entry * p,char * Arg,AfCmd Cmd,int x)612 int CheckEmailAdr(struct config_entry *p, char *Arg, AfCmd Cmd, int x)
613 {
614 int Ret = 0;
615
616 switch(Cmd) {
617 case AF_SET_VAR:
618 if(EmailAdr != NULL) {
619 free(EmailAdr);
620 }
621
622 EmailAdr = strdup(Arg);
623
624 if(strcmp(EmailAdr,"w1aw@arrl.net") == 0) {
625 LOG_ERROR(("Come on now, your email address isn't \"w1aw@arrl.net\" "
626 "is it?\n"));
627 Ret = ERR_CONFIG_FILE;
628 }
629 else if(!strchr(EmailAdr,'@') || !strchr(EmailAdr,'.')) {
630 LOG_ERROR(("Error: Invalid email address \"%s\".\n",EmailAdr));
631 Ret = ERR_CONFIG_FILE;
632 }
633
634 if(Ret != 0) {
635 LOG_ERROR(("The email address is optional, please either delete the "
636 "entry\n"));
637 LOG_ERROR(("or provide a valid email address.\n"));
638 }
639 p->Flags |= CON_FLG_SET;
640 break;
641
642 case AF_SET_DEFAULT:
643 if(EmailAdr != NULL) {
644 free(EmailAdr);
645 EmailAdr = NULL;
646 }
647 break;
648
649 case AF_DISPLAY_VAR:
650 break;
651 }
652 return Ret;
653 }
654
StartupCommand(struct config_entry * p,char * Arg,AfCmd Cmd,int x)655 int StartupCommand(struct config_entry *p, char *Arg, AfCmd Cmd, int x)
656 {
657 switch(Cmd) {
658 case AF_SET_VAR:
659 StartCmdHandler(Arg,"StartupCmd");
660 break;
661
662 case AF_SET_DEFAULT:
663 break;
664
665 case AF_DISPLAY_VAR:
666 break;
667 }
668 return 0;
669 }
670
LoadFile(struct config_entry * p,char * Arg,AfCmd Cmd,int x)671 int LoadFile(struct config_entry *p, char *Arg, AfCmd Cmd, int x)
672 {
673 struct stat FileStats;
674 FILE *fp;
675 char *cp;
676 char **pBuf;
677 int Ret = 0;
678
679 pBuf = (char **) p->var_ptr;
680 if(p->var_ptr != NULL && *pBuf != NULL) {
681 free(*pBuf);
682 *pBuf = NULL;
683 }
684
685 switch(Cmd) {
686 case AF_SET_VAR:
687 if(stat(Arg,&FileStats) != 0 || (fp = fopen(Arg,"r")) == NULL) {
688 LOG_ERROR(("Error: unable to open %s \"%s\" %s",p->var_name,Arg,
689 Err2String(errno)));
690 Ret = ERR_CONFIG_FILE;
691 }
692 else if((*pBuf = (char *) malloc(FileStats.st_size)) != NULL) {
693 if(fread(*pBuf,FileStats.st_size,1,fp) != 1) {
694 LOG_ERROR(("Error reading help file \"%s\", %s",Arg,
695 Err2String(errno)));
696 free(*pBuf);
697 *pBuf = NULL;
698 Ret = ERR_CONFIG_FILE;
699 }
700 else {
701 // Convert the '\n' end of line convention to '\r' used by EchoLink
702 cp = (char *) p->var_ptr;
703 while((cp = strchr(cp,'\n')) != NULL) {
704 *cp++ = '\r';
705 }
706 }
707 fclose(fp);
708 }
709 break;
710
711 case AF_SET_DEFAULT:
712 break;
713
714 case AF_DISPLAY_VAR:
715 break;
716 }
717 return Ret;
718 }
719
720
721 // Configuration passes:
722 // 1 - first pass (duh!)
723 // 2 - Initialization complete.
724 // 3 - Station list downloaded from EchoLink directory server.
725 // 4 - Station list downloaded a second time from EchoLink directory server.
726 // 5 - Manual variable set
DoConfigPass(int Pass)727 int DoConfigPass(int Pass)
728 {
729 char *ConfigFile = ConfigFilePath;
730 static FILE *fp = NULL;
731 int Ret = 0;
732
733 ConfigPass = Pass;
734 if(ConfigFile == NULL) {
735 ConfigFile = CONFIG_FILE_PATH;
736 }
737
738 if(Pass == 1 && (fp = fopen(ConfigFile,"r")) == NULL) {
739 LOG_ERROR(("Fatal error opening configuration file, \"%s\".\n",
740 ConfigFile));
741 Ret = CONFIG_OPEN_ERROR;
742 }
743 else {
744 fseek(fp,0,SEEK_SET);
745 Ret = read_config(fp,ConfigVars,Pass);
746 if(Pass == NUM_CONFIG_PASSES) {
747 fclose(fp);
748 fp = NULL;
749 }
750 }
751
752 if(Pass == 1 && Ret == 0) do {
753 // Require that the callsign be a link, repeater or conference callsign
754 if(ConferenceCall != NULL &&
755 ConferenceCall[0] != '*' &&
756 strstr(ConferenceCall,"-R") == NULL &&
757 strstr(ConferenceCall,"-L") == NULL)
758 { // Must be a bare callsign ... not allowed.
759 LOG_ERROR(("Error: Invalid ConferenceCall \"%s\".\n"
760 "ConferenceCall must be a callsign folllowed by \"-R\", "
761 "or \"-L\" or \n"
762 "be an assigned conference name.\n",
763 ConferenceCall));
764 Ret = ERR_CONFIG_FILE;
765 break;
766 }
767
768 if(AvrsEnable && !AVRS_Validate()) {
769 Ret = ERR_CONFIG_FILE;
770 break;
771 }
772
773 if(SF_Port != SF_ReplyPort) {
774 bEchoIrlpMode = TRUE;
775 }
776 } while(FALSE);
777
778 return Ret;
779 }
780
781
782 // We're connected to the EchoLink network see if we have any AVRS
783 // info to send
AVRS_Validate()784 int AVRS_Validate()
785 {
786 struct hostent *pHost;
787 int Ret = FALSE;
788
789 // We require Longitude, Latitude, and Frequency to be set
790 if(ConferenceCall[0] == '*') {
791 LOG_ERROR(("Error: AVRS reporting not available for conferences, "
792 "AVRS disabled.\n"));
793 }
794 else if(Longitude > 180.0 || Longitude < -180.0) {
795 LOG_ERROR(("Error: Invalid Longitude, AVRS disabled.\n"));
796 }
797 else if(Latitude > 90.0 || Latitude < -90.0) {
798 LOG_ERROR(("Error: Invalid Latitude, AVRS disabled.\n"));
799 }
800 else if(AntDir > 360.0 || AntDir < 0.0) {
801 LOG_ERROR(("Error: Invalid Antenna direction, AVRS disabled.\n"));
802 }
803 else if(CTCSS < 0.0 || CTCSS > 229.1) {
804 LOG_ERROR(("Error: Invalid CTCSS frequency, AVRS disabled.\n"));
805 }
806 else {
807 Ret = TRUE;
808
809 // Prime the DNS cache so we'll have the IP address later when we need it
810 pHost = GetHostByName("aprs.echolink.org");
811 }
812
813 AvrsEnable = Ret;
814
815 return Ret;
816 }
817
ConfigGetVarPtr(struct config_entry * pConfig)818 void *ConfigGetVarPtr(struct config_entry *pConfig)
819 {
820 return NULL;
821 }
822
CheckRTP_PortSpec(char * Spec)823 int CheckRTP_PortSpec(char *Spec)
824 {
825 int Ret = ERR_CONFIG_FILE; // assume the worse
826 char *cp = strchr(Spec,'-');
827 int FirstPort;
828 int LastPort;
829
830 do {
831 if(sscanf(Spec,"%d",&FirstPort) != 1) {
832 LOG_ERROR(("Error: Invalid RTP_Port \"%s\"\n",Spec));
833 break;
834 }
835 else if(FirstPort & 1) {
836 LOG_ERROR(("Error: First RTP port must be even\n"));
837 break;
838 }
839
840 if(cp != NULL) {
841 // Range
842 if(sscanf(&cp[1],"%d",&LastPort) != 1) {
843 LOG_ERROR(("Error: Invalid RTP_Port \"%s\"\n",Spec));
844 break;
845 }
846 else if(!(LastPort & 1)) {
847 LOG_ERROR(("Error: Last RTP port must be odd\n"));
848 break;
849 }
850 else if(LastPort <= FirstPort) {
851 LOG_ERROR(("Error: The last port must larger the first port\n"));
852 break;
853 }
854 }
855 Ret = 0;
856 } while(FALSE);
857
858
859 return Ret;
860 }
861
862
863 // Rtp_port = 0 // disable
864 // Rtp_port = <evenport>
865 // Rtp_port = <evenport>-<oddport> for a range
AccessRtpPort(struct config_entry * p,char * Arg,AfCmd Cmd,int x)866 int AccessRtpPort(struct config_entry *p, char *Arg, AfCmd Cmd, int x)
867 {
868 int Ret = ERR_CONFIG_FILE; // assume the worse
869
870 switch(Cmd) {
871 case AF_SET_VAR:
872 if((Ret = CheckRTP_PortSpec(Arg)) != 0) {
873 break;
874 }
875 if(RTP_Port != NULL) {
876 free(RTP_Port);
877 }
878 RTP_Port = strdup(Arg);
879
880 printf("ConfigPass: %d\n",ConfigPass);
881 if(ConfigPass == MANUAL_SET) {
882 RtpInit();
883 }
884 break;
885
886 case AF_SET_DEFAULT:
887 Ret = 0;
888 break;
889
890 case AF_DISPLAY_VAR:
891 snprintf(Arg,x,"%s",RTP_Port != NULL ? RTP_Port : "not set");
892 Ret = 0;
893 break;
894 }
895
896 return Ret;
897 }
898
899