FreeCalypso > hg > themwi-system-sw
comparison sip-out/readconf.c @ 154:e54b0a9e322f
beginning of themwi-sip-out
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Tue, 11 Oct 2022 23:04:01 -0800 |
parents | sip-in/readconf.c@7e04d28fae8b |
children | 0bacca1f2f7b |
comparison
equal
deleted
inserted
replaced
153:99fd4ae573ae | 154:e54b0a9e322f |
---|---|
1 /* | |
2 * In this module we implement the reading of /var/gsm/themwi-sip-out.cfg: | |
3 * the main settings are bind-ip and bind-port, but we also have some | |
4 * optional config settings. | |
5 */ | |
6 | |
7 #include <sys/types.h> | |
8 #include <sys/socket.h> | |
9 #include <netinet/in.h> | |
10 #include <arpa/inet.h> | |
11 #include <ctype.h> | |
12 #include <stdio.h> | |
13 #include <stdlib.h> | |
14 #include <string.h> | |
15 #include <strings.h> | |
16 | |
17 struct in_addr sip_bind_ip; | |
18 unsigned sip_bind_port; | |
19 unsigned cfg_retrans_timeout = 500; | |
20 unsigned cfg_retrans_count = 10; | |
21 unsigned max_forwards = 70; | |
22 unsigned sip_linger_timeout = 10; | |
23 unsigned sip_linger_invite_err = 10; | |
24 unsigned sip_linger_gotbye = 30; | |
25 unsigned sip_linger_bye_out_ok = 5; | |
26 unsigned sip_linger_bye_out_err = 180; | |
27 int block_1900_numbers = 1; | |
28 | |
29 static char config_file_pathname[] = "/var/gsm/themwi-sip-out.cfg"; | |
30 | |
31 struct parse_state { | |
32 int lineno; | |
33 int set_mask; | |
34 }; | |
35 | |
36 static void | |
37 require_one_arg(st, kw, arg) | |
38 struct parse_state *st; | |
39 char *kw, *arg; | |
40 { | |
41 char *cp; | |
42 | |
43 if (*arg == '\0' || *arg == '#') { | |
44 inv_syntax: fprintf(stderr, | |
45 "%s line %d: %s setting requires one argument\n", | |
46 config_file_pathname, st->lineno, kw); | |
47 exit(1); | |
48 } | |
49 for (cp = arg; *cp && !isspace(*cp); cp++) | |
50 ; | |
51 if (*cp) | |
52 *cp++ = '\0'; | |
53 while (isspace(*cp)) | |
54 cp++; | |
55 if (*cp != '\0' && *cp != '#') | |
56 goto inv_syntax; | |
57 } | |
58 | |
59 static void | |
60 handle_ip(st, kw, arg, var) | |
61 struct parse_state *st; | |
62 char *kw, *arg; | |
63 struct in_addr *var; | |
64 { | |
65 require_one_arg(st, kw, arg); | |
66 var->s_addr = inet_addr(arg); | |
67 if (var->s_addr == INADDR_NONE) { | |
68 fprintf(stderr, | |
69 "%s line %d: invalid IP address argument \"%s\"\n", | |
70 config_file_pathname, st->lineno, arg); | |
71 exit(1); | |
72 } | |
73 } | |
74 | |
75 static void | |
76 handle_num(st, kw, arg, var) | |
77 struct parse_state *st; | |
78 char *kw, *arg; | |
79 unsigned *var; | |
80 { | |
81 char *endp; | |
82 | |
83 require_one_arg(st, kw, arg); | |
84 *var = strtoul(arg, &endp, 10); | |
85 if (*endp) { | |
86 fprintf(stderr, "%s line %d: invalid numeric argument \"%s\"\n", | |
87 config_file_pathname, st->lineno, arg); | |
88 exit(1); | |
89 } | |
90 } | |
91 | |
92 static void | |
93 handle_bool(st, kw, arg, var) | |
94 struct parse_state *st; | |
95 char *kw, *arg; | |
96 int *var; | |
97 { | |
98 require_one_arg(st, kw, arg); | |
99 if (!strcmp(arg, "true") || !strcmp(arg, "on") || !strcmp(arg, "yes") | |
100 || !strcmp(arg, "1")) { | |
101 *var = 1; | |
102 return; | |
103 } | |
104 if (!strcmp(arg, "false") || !strcmp(arg, "off") || !strcmp(arg, "no") | |
105 || !strcmp(arg, "0")) { | |
106 *var = 0; | |
107 return; | |
108 } | |
109 fprintf(stderr, "%s line %d: invalid boolean argument \"%s\"\n", | |
110 config_file_pathname, st->lineno, arg); | |
111 exit(1); | |
112 } | |
113 | |
114 static void | |
115 handle_retrans_conf(st, kw, arg) | |
116 struct parse_state *st; | |
117 char *kw, *arg; | |
118 { | |
119 char *cp = arg; | |
120 | |
121 if (!isdigit(*cp)) { | |
122 inv: fprintf(stderr, | |
123 "%s line %d: %s setting requires two numeric arguments\n", | |
124 config_file_pathname, st->lineno, kw); | |
125 exit(1); | |
126 } | |
127 cfg_retrans_timeout = strtoul(cp, &cp, 10); | |
128 while (isspace(*cp)) | |
129 cp++; | |
130 if (!isdigit(*cp)) | |
131 goto inv; | |
132 cfg_retrans_count = strtoul(cp, &cp, 10); | |
133 while (isspace(*cp)) | |
134 cp++; | |
135 if (*cp != '\0' && *cp != '#') | |
136 goto inv; | |
137 } | |
138 | |
139 static void | |
140 process_line(st, line) | |
141 struct parse_state *st; | |
142 char *line; | |
143 { | |
144 char *cp, *kw; | |
145 void (*handler)(), *var; | |
146 int set_id; | |
147 | |
148 if (!index(line, '\n')) { | |
149 fprintf(stderr, "%s line %d: too long or missing newline\n", | |
150 config_file_pathname, st->lineno); | |
151 exit(1); | |
152 } | |
153 for (cp = line; isspace(*cp); cp++) | |
154 ; | |
155 if (*cp == '\0' || *cp == '#') | |
156 return; | |
157 for (kw = cp; *cp && !isspace(*cp); cp++) | |
158 ; | |
159 if (*cp) | |
160 *cp++ = '\0'; | |
161 if (!strcmp(kw, "bind-ip")) { | |
162 handler = handle_ip; | |
163 var = &sip_bind_ip; | |
164 set_id = 1; | |
165 } else if (!strcmp(kw, "bind-port")) { | |
166 handler = handle_num; | |
167 var = &sip_bind_port; | |
168 set_id = 2; | |
169 } else if (!strcmp(kw, "sip-udp-retrans")) { | |
170 handler = handle_retrans_conf; | |
171 var = (void *) 0; | |
172 set_id = 0; | |
173 } else if (!strcmp(kw, "sip-linger-timeout")) { | |
174 handler = handle_num; | |
175 var = &sip_linger_timeout; | |
176 set_id = 0; | |
177 } else if (!strcmp(kw, "sip-linger-invite-error")) { | |
178 handler = handle_num; | |
179 var = &sip_linger_invite_err; | |
180 set_id = 0; | |
181 } else if (!strcmp(kw, "sip-linger-got-bye")) { | |
182 handler = handle_num; | |
183 var = &sip_linger_gotbye; | |
184 set_id = 0; | |
185 } else if (!strcmp(kw, "sip-linger-bye-out-ok")) { | |
186 handler = handle_num; | |
187 var = &sip_linger_bye_out_ok; | |
188 set_id = 0; | |
189 } else if (!strcmp(kw, "sip-linger-bye-out-error")) { | |
190 handler = handle_num; | |
191 var = &sip_linger_bye_out_err; | |
192 set_id = 0; | |
193 } else if (!strcmp(kw, "max-forwards")) { | |
194 handler = &handle_num; | |
195 var = &max_forwards; | |
196 set_id = 0; | |
197 } else if (!strcmp(kw, "block-1900")) { | |
198 handler = handle_bool; | |
199 var = &block_1900_numbers; | |
200 set_id = 0; | |
201 } else { | |
202 fprintf(stderr, "%s line %d: non-understood keyword \"%s\"\n", | |
203 config_file_pathname, st->lineno, kw); | |
204 exit(1); | |
205 } | |
206 if (st->set_mask & set_id) { | |
207 fprintf(stderr, "%s line %d: duplicate %s setting\n", | |
208 config_file_pathname, st->lineno, kw); | |
209 exit(1); | |
210 } | |
211 while (isspace(*cp)) | |
212 cp++; | |
213 handler(st, kw, cp, var); | |
214 st->set_mask |= set_id; | |
215 } | |
216 | |
217 read_config_file() | |
218 { | |
219 FILE *inf; | |
220 struct parse_state pst; | |
221 char linebuf[256]; | |
222 | |
223 inf = fopen(config_file_pathname, "r"); | |
224 if (!inf) { | |
225 perror(config_file_pathname); | |
226 exit(1); | |
227 } | |
228 pst.set_mask = 0; | |
229 for (pst.lineno = 1; fgets(linebuf, sizeof linebuf, inf); pst.lineno++) | |
230 process_line(&pst, linebuf); | |
231 fclose(inf); | |
232 if (pst.set_mask != 3) { | |
233 fprintf(stderr, "error: %s did not set all required settings\n", | |
234 config_file_pathname); | |
235 exit(1); | |
236 } | |
237 } |