]>
Commit | Line | Data |
---|---|---|
c8f4eac4 | 1 | /* |
4ac4a490 | 2 | * Copyright (C) 1996-2017 The Squid Software Foundation and contributors |
c8f4eac4 | 3 | * |
bbc27441 AJ |
4 | * Squid software is distributed under GPLv2+ license and includes |
5 | * contributions from numerous individuals and organizations. | |
6 | * Please see the COPYING and CONTRIBUTORS files for details. | |
c8f4eac4 | 7 | */ |
8 | ||
bbc27441 AJ |
9 | /* DEBUG: section 03 Configuration File Parsing */ |
10 | ||
f7f3304a | 11 | #include "squid.h" |
8a01b99e | 12 | #include "cache_cf.h" |
27bc2077 | 13 | #include "compat/strtoll.h" |
079a8480 | 14 | #include "ConfigParser.h" |
54a063a2 | 15 | #include "Debug.h" |
602d9612 A |
16 | #include "globals.h" |
17 | #include "Parsing.h" | |
c8f4eac4 | 18 | |
19 | /* | |
20 | * These functions is the same as atoi/l/f, except that they check for errors | |
21 | */ | |
22 | ||
0e656b69 | 23 | double |
24 | xatof(const char *token) | |
c8f4eac4 | 25 | { |
54a063a2 | 26 | char *end = NULL; |
0e656b69 | 27 | double ret = strtod(token, &end); |
c8f4eac4 | 28 | |
54a063a2 TX |
29 | if (ret == 0 && end == token) { |
30 | debugs(0, DBG_PARSE_NOTE(DBG_IMPORTANT), "ERROR: No digits were found in the input value '" << token << "'."); | |
c8f4eac4 | 31 | self_destruct(); |
54a063a2 TX |
32 | } |
33 | ||
34 | if (*end) { | |
35 | debugs(0, DBG_PARSE_NOTE(DBG_IMPORTANT), "ERROR: Invalid value: '" << token << "' is supposed to be a number."); | |
36 | self_destruct(); | |
37 | } | |
c8f4eac4 | 38 | |
39 | return ret; | |
40 | } | |
41 | ||
42 | int | |
43 | xatoi(const char *token) | |
44 | { | |
54a063a2 TX |
45 | int64_t input = xatoll(token, 10); |
46 | int ret = (int) input; | |
47 | ||
48 | if (input != static_cast<int64_t>(ret)) { | |
49 | debugs(0, DBG_PARSE_NOTE(DBG_IMPORTANT), "ERROR: The value '" << token << "' is larger than the type 'int'."); | |
50 | self_destruct(); | |
51 | } | |
52 | ||
53 | return ret; | |
54 | } | |
55 | ||
56 | unsigned int | |
e398d16e | 57 | xatoui(const char *token, char eov) |
54a063a2 | 58 | { |
e398d16e | 59 | int64_t input = xatoll(token, 10, eov); |
54a063a2 TX |
60 | if (input < 0) { |
61 | debugs(0, DBG_PARSE_NOTE(DBG_IMPORTANT), "ERROR: The input value '" << token << "' cannot be less than 0."); | |
62 | self_destruct(); | |
63 | } | |
64 | ||
65 | unsigned int ret = (unsigned int) input; | |
66 | if (input != static_cast<int64_t>(ret)) { | |
67 | debugs(0, DBG_PARSE_NOTE(DBG_IMPORTANT), "ERROR: The value '" << token << "' is larger than the type 'unsigned int'."); | |
68 | self_destruct(); | |
69 | } | |
70 | ||
71 | return ret; | |
c8f4eac4 | 72 | } |
73 | ||
0e656b69 | 74 | long |
75 | xatol(const char *token) | |
76 | { | |
54a063a2 TX |
77 | int64_t input = xatoll(token, 10); |
78 | long ret = (long) input; | |
79 | ||
80 | if (input != static_cast<int64_t>(ret)) { | |
81 | debugs(0, DBG_PARSE_NOTE(DBG_IMPORTANT), "ERROR: The value '" << token << "' is larger than the type 'long'."); | |
82 | self_destruct(); | |
83 | } | |
84 | ||
85 | return ret; | |
86 | } | |
87 | ||
88 | int64_t | |
e398d16e | 89 | xatoll(const char *token, int base, char eov) |
54a063a2 TX |
90 | { |
91 | char *end = NULL; | |
92 | int64_t ret = strtoll(token, &end, base); | |
0e656b69 | 93 | |
54a063a2 TX |
94 | if (end == token) { |
95 | debugs(0, DBG_PARSE_NOTE(DBG_IMPORTANT), "ERROR: No digits were found in the input value '" << token << "'."); | |
0e656b69 | 96 | self_destruct(); |
54a063a2 TX |
97 | } |
98 | ||
e398d16e | 99 | if (*end != eov) { |
54a063a2 TX |
100 | debugs(0, DBG_PARSE_NOTE(DBG_IMPORTANT), "ERROR: Invalid value: '" << token << "' is supposed to be a number."); |
101 | self_destruct(); | |
102 | } | |
0e656b69 | 103 | |
104 | return ret; | |
105 | } | |
106 | ||
107 | unsigned short | |
108 | xatos(const char *token) | |
109 | { | |
110 | long port = xatol(token); | |
111 | ||
54a063a2 TX |
112 | if (port < 0) { |
113 | debugs(0, DBG_PARSE_NOTE(DBG_IMPORTANT), "ERROR: The value '" << token << "' cannot be less than 0."); | |
114 | self_destruct(); | |
115 | } | |
116 | ||
117 | if (port & ~0xFFFF) { | |
118 | debugs(0, DBG_PARSE_NOTE(DBG_IMPORTANT), "ERROR: The value '" << token << "' is larger than the type 'short'."); | |
0e656b69 | 119 | self_destruct(); |
54a063a2 | 120 | } |
0e656b69 | 121 | |
122 | return port; | |
123 | } | |
124 | ||
b1fb3348 AJ |
125 | int64_t |
126 | GetInteger64(void) | |
127 | { | |
2eceb328 | 128 | char *token = ConfigParser::NextToken(); |
b9e4cf09 | 129 | if (!token) { |
b1fb3348 | 130 | self_destruct(); |
b9e4cf09 AJ |
131 | return -1; // not reachable |
132 | } | |
b1fb3348 | 133 | |
54a063a2 | 134 | return xatoll(token, 10); |
b1fb3348 AJ |
135 | } |
136 | ||
54a063a2 TX |
137 | /* |
138 | * This function is different from others (e.g., GetInteger64, GetShort) | |
139 | * because it supports octal and hexadecimal numbers | |
140 | */ | |
c8f4eac4 | 141 | int |
142 | GetInteger(void) | |
143 | { | |
2eceb328 | 144 | char *token = ConfigParser::NextToken(); |
c8f4eac4 | 145 | int i; |
146 | ||
b9e4cf09 | 147 | if (!token) { |
c8f4eac4 | 148 | self_destruct(); |
b9e4cf09 AJ |
149 | return -1; // not reachable |
150 | } | |
c8f4eac4 | 151 | |
54a063a2 TX |
152 | // The conversion must honor 0 and 0x prefixes, which are important for things like umask |
153 | int64_t ret = xatoll(token, 0); | |
154 | ||
155 | i = (int) ret; | |
156 | if (ret != static_cast<int64_t>(i)) { | |
157 | debugs(0, DBG_PARSE_NOTE(DBG_IMPORTANT), "ERROR: The value '" << token << "' is larger than the type 'int'."); | |
c8f4eac4 | 158 | self_destruct(); |
54a063a2 | 159 | } |
c8f4eac4 | 160 | |
161 | return i; | |
162 | } | |
163 | ||
54a063a2 TX |
164 | /* |
165 | * This function is similar as GetInteger() but the token might contain | |
166 | * the percentage symbol (%) and we check whether the value is in the range | |
167 | * of [0, 100] | |
168 | * So, we accept two types of input: 1. XX% or 2. XX , 0<=XX<=100 | |
1454480a | 169 | * unless the limit parameter is set to false. |
54a063a2 | 170 | */ |
1454480a AJ |
171 | double |
172 | GetPercentage(bool limit) | |
54a063a2 | 173 | { |
223d18cd | 174 | char *token = ConfigParser::NextToken(); |
54a063a2 | 175 | |
f5bc7b15 | 176 | if (!token) { |
1454480a | 177 | debugs(3, DBG_CRITICAL, "FATAL: A percentage value is missing."); |
f5bc7b15 | 178 | self_destruct(); |
b9e4cf09 | 179 | return 0.0; // not reachable |
f5bc7b15 AJ |
180 | } |
181 | ||
54a063a2 TX |
182 | //if there is a % in the end of the digits, we remove it and go on. |
183 | char* end = &token[strlen(token)-1]; | |
184 | if (*end == '%') { | |
185 | *end = '\0'; | |
186 | } | |
187 | ||
223d18cd | 188 | int p = xatoi(token); |
54a063a2 | 189 | |
1454480a AJ |
190 | if (p < 0 || (limit && p > 100)) { |
191 | debugs(3, DBG_CRITICAL, "FATAL: The value '" << token << "' is out of range. A percentage should be within [0, 100]."); | |
54a063a2 TX |
192 | self_destruct(); |
193 | } | |
194 | ||
1454480a | 195 | return static_cast<double>(p) / 100.0; |
54a063a2 TX |
196 | } |
197 | ||
f45dd259 | 198 | unsigned short |
0e656b69 | 199 | GetShort(void) |
200 | { | |
2eceb328 | 201 | char *token = ConfigParser::NextToken(); |
b9e4cf09 | 202 | if (!token) { |
0e656b69 | 203 | self_destruct(); |
b9e4cf09 AJ |
204 | return 0; // not reachable |
205 | } | |
0e656b69 | 206 | |
207 | return xatos(token); | |
208 | } | |
209 | ||
053b1f59 | 210 | bool |
211 | StringToInt(const char *s, int &result, const char **p, int base) | |
212 | { | |
213 | if (s) { | |
214 | char *ptr = 0; | |
215 | const int h = (int) strtol(s, &ptr, base); | |
216 | ||
217 | if (ptr != s && ptr) { | |
218 | result = h; | |
219 | ||
220 | if (p) | |
221 | *p = ptr; | |
222 | ||
223 | return true; | |
224 | } | |
225 | } | |
226 | ||
227 | return false; | |
228 | } | |
47f6e231 | 229 | |
230 | bool | |
231 | StringToInt64(const char *s, int64_t &result, const char **p, int base) | |
232 | { | |
233 | if (s) { | |
234 | char *ptr = 0; | |
235 | const int64_t h = (int64_t) strtoll(s, &ptr, base); | |
236 | ||
237 | if (ptr != s && ptr) { | |
238 | result = h; | |
239 | ||
240 | if (p) | |
241 | *p = ptr; | |
242 | ||
243 | return true; | |
244 | } | |
245 | } | |
246 | ||
247 | return false; | |
248 | } | |
82b7abe3 AJ |
249 | |
250 | bool | |
b7ac5457 | 251 | GetHostWithPort(char *token, Ip::Address *ipa) |
82b7abe3 AJ |
252 | { |
253 | char *t; | |
254 | char *host; | |
255 | char *tmp; | |
256 | unsigned short port; | |
257 | ||
258 | host = NULL; | |
259 | port = 0; | |
260 | ||
82b7abe3 AJ |
261 | if (*token == '[') { |
262 | /* [host]:port */ | |
263 | host = token + 1; | |
264 | t = strchr(host, ']'); | |
265 | if (!t) | |
266 | return false; | |
f412b2d6 FC |
267 | *t = '\0'; |
268 | ++t; | |
82b7abe3 AJ |
269 | if (*t != ':') |
270 | return false; | |
271 | port = xatos(t + 1); | |
055421ee AJ |
272 | } else if ((t = strchr(token, ':'))) { |
273 | /* host:port */ | |
274 | host = token; | |
275 | *t = '\0'; | |
276 | port = xatos(t + 1); | |
277 | ||
278 | if (0 == port) | |
279 | return false; | |
54a063a2 TX |
280 | } else if (strtol(token, &tmp, 10) && !*tmp) { |
281 | port = xatos(token); | |
055421ee AJ |
282 | } else { |
283 | host = token; | |
284 | port = 0; | |
285 | } | |
82b7abe3 AJ |
286 | |
287 | if (NULL == host) | |
4dd643d5 | 288 | ipa->setAnyAddr(); |
82b7abe3 AJ |
289 | else if ( ipa->GetHostByName(host) ) /* dont use ipcache. Accept either FQDN or IPA. */ |
290 | (void) 0; | |
291 | else | |
292 | return false; | |
293 | ||
294 | /* port MUST be set after the IPA lookup/conversion is performed. */ | |
4dd643d5 | 295 | ipa->port(port); |
82b7abe3 AJ |
296 | |
297 | return true; | |
298 | } | |
f53969cc | 299 |