1 /*
2
3 G N O K I I
4
5 A Linux/Unix toolset and driver for the mobile phones.
6
7 This file is part of gnokii.
8
9 Gnokii is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
13
14 Gnokii is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with gnokii; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22
23 Copyright (C) 1999-2000 Hugh Blemings & Pavel Jan�k ml.
24 Copyright (C) 2000 Jan Derfinak
25 Copyright (C) 2000-2011 Pawel Kot
26 Copyright (C) 2001 Jan Kratochvil, Ladis Michl, Chris Kemp
27 Copyright (C) 2002-2004 BORBELY Zoltan
28 Copyright (C) 2002 Manfred Jonsson, Markus Plail
29
30 Some parts of the gn_lock_device() function are derived from minicom
31 communications package, main.c file written by Miquel van Smoorenburg.
32 These parts are copyrighted under GNU GPL version 2.
33
34 Copyright 1991-1995 Miquel van Smoorenburg.
35
36 */
37
38 #include "config.h"
39 #include <string.h>
40 #include <stdlib.h>
41 #include <errno.h>
42 #include <sys/types.h>
43 #include <sys/stat.h>
44 #include <fcntl.h>
45 #include <signal.h>
46
47 #include "compat.h"
48
49 #include "misc.h"
50 #include "gnokii.h"
51 #include "gnokii-internal.h"
52
53 GNOKII_API gn_log_target gn_log_debug_mask = GN_LOG_T_NONE;
54 GNOKII_API gn_log_target gn_log_rlpdebug_mask = GN_LOG_T_NONE;
55 GNOKII_API gn_log_target gn_log_xdebug_mask = GN_LOG_T_NONE;
56 GNOKII_API void (*gn_elog_handler)(const char *fmt, va_list ap) = NULL;
57
gn_line_get(FILE * file,char * line,int count)58 GNOKII_API int gn_line_get(FILE *file, char *line, int count)
59 {
60 char *ptr;
61
62 if (fgets(line, count, file)) {
63 ptr = line + strlen(line) - 1;
64
65 while ((*ptr == '\n' || *ptr == '\r') && ptr >= line)
66 *ptr-- = '\0';
67
68 return strlen(line);
69 } else {
70 return 0;
71 }
72 }
73
74 static gn_phone_model models[] = {
75 /* model, product_name, ... */
76 {"2711", "?????", PM_OLD_DEFAULT }, /* Dancall */
77 {"2731", "?????", PM_OLD_DEFAULT },
78 {"11", "TFF-3", PM_OLD_DEFAULT },
79 {"12", "RX-2", PM_OLD_DEFAULT },
80 {"20", "TME-2", PM_OLD_DEFAULT },
81 {"22", "TME-1", PM_OLD_DEFAULT },
82 {"30", "TME-3", PM_OLD_DEFAULT },
83 {"100", "THX-9L", PM_OLD_DEFAULT },
84 {"450", "THF-9", PM_OLD_DEFAULT },
85 {"505", "NHX-8", PM_OLD_DEFAULT },
86 {"540", "THF-11", PM_OLD_DEFAULT },
87 {"550", "THF-10", PM_OLD_DEFAULT },
88 {"640", "THF-13", PM_OLD_DEFAULT },
89 {"650", "THF-12", PM_OLD_DEFAULT },
90 {"810", "TFE-4R", PM_OLD_DEFAULT },
91 {"1011", "NHE-2", PM_OLD_DEFAULT },
92 {"1100", "RH-18", PM_OLD_DEFAULT },
93 {"1100", "RH-38", PM_OLD_DEFAULT },
94 {"1100b", "RH-36", PM_OLD_DEFAULT },
95 {"1101", "RH-75", PM_OLD_DEFAULT }, /* Yet another 1100 variant, untested */
96 {"1110", "RH-93", PM_DEFAULT_S30 },
97 {"1209", "RH-105", PM_DEFAULT_S30 },
98 {"1220", "NKC-1", PM_OLD_DEFAULT },
99 {"1260", "NKW-1", PM_OLD_DEFAULT },
100 {"1261", "NKW-1C", PM_OLD_DEFAULT },
101 {"1280", "RM-647", PM_DEFAULT_S30 },
102 {"1610", "NHE-5", PM_OLD_DEFAULT },
103 {"1610", "NHE-5NX", PM_OLD_DEFAULT },
104 {"1611", "NHE-5", PM_OLD_DEFAULT },
105 {"1630", "NHE-5NA", PM_OLD_DEFAULT },
106 {"1630", "NHE-5NX", PM_OLD_DEFAULT },
107 {"1631", "NHE-5SA", PM_OLD_DEFAULT },
108 {"2010", "NHE-3", PM_OLD_DEFAULT },
109 {"2100", "NAM-2", PM_OLD_DEFAULT },
110 {"2110", "NHE-1", PM_OLD_DEFAULT },
111 {"2110i", "NHE-4", PM_OLD_DEFAULT },
112 {"2118", "NHE-4", PM_OLD_DEFAULT },
113 {"2140", "NHK-1XA", PM_OLD_DEFAULT },
114 {"2148", "NHK-1", PM_OLD_DEFAULT },
115 {"2148i", "NHK-4", PM_OLD_DEFAULT },
116 {"2160", "NHC-4NE/HE", PM_OLD_DEFAULT },
117 {"2160i", "NHC-4NE/HE", PM_OLD_DEFAULT },
118 {"2170", "NHP-4", PM_OLD_DEFAULT },
119 {"2180", "NHD-4X", PM_OLD_DEFAULT },
120 {"2190", "NHB-3NB", PM_OLD_DEFAULT },
121 {"2220", "RH-40", PM_OLD_DEFAULT },
122 {"2220", "RH-42", PM_OLD_DEFAULT },
123 {"2260", "RH-39", PM_OLD_DEFAULT },
124 {"2260", "RH-41", PM_OLD_DEFAULT },
125 {"2270", "RH-3P", PM_OLD_DEFAULT },
126 {"2275", "RH-3DNG", PM_OLD_DEFAULT },
127 {"2280", "RH-17", PM_OLD_DEFAULT },
128 {"2285", "RH-3", PM_OLD_DEFAULT },
129 {"2300", "RM-4", PM_OLD_DEFAULT },
130 {"2300b", "RM-5", PM_OLD_DEFAULT },
131 {"2330 classic", "RM-512", PM_DEFAULT_S40_3RD }, /* Series 40 5th Edition FP 1 Lite */
132 {"2600", "RH-59", PM_DEFAULT | PM_XGNOKIIBREAKAGE },
133 {"2630", "RM-298", PM_DEFAULT },
134 {"2650", "RH-53", PM_DEFAULT | PM_XGNOKIIBREAKAGE },
135 {"2700 classic", "RM-561", PM_DEFAULT_S40_3RD },
136 {"2730 classic", "RM-578", PM_DEFAULT_S40_3RD }, /* Series 40 5th Edition FP 1 */
137 {"2760", "RM-258", PM_DEFAULT_S40_3RD }, /* Series 40 5th Edition */
138 {"3100", "RH-19", PM_DEFAULT | PM_XGNOKIIBREAKAGE },
139 {"3100b", "RH-50", PM_DEFAULT },
140 {"3105", "RH-48", PM_OLD_DEFAULT },
141 {"3108", "RH-6", PM_OLD_DEFAULT },
142 {"3109c", "RM-274", PM_DEFAULT_S40_3RD }, /* Nokia 3109 classic */
143 {"3110", "NHE-8", PM_OLD_DEFAULT | PM_DATA },
144 {"3110", "0310" , PM_OLD_DEFAULT | PM_DATA }, /* NHE-8 */
145 {"3110c", "RM-237", PM_DEFAULT_S40_3RD }, /* Nokia 3110 classic */
146 {"3120", "RH-19", PM_DEFAULT },
147 {"3120b", "RH-50", PM_DEFAULT },
148 {"3200", "RH-30", PM_DEFAULT | PM_XGNOKIIBREAKAGE },
149 {"3200", "RH-30/31", PM_DEFAULT },
150 {"3200b", "RH-31", PM_DEFAULT },
151 {"3210", "NSE-8", PM_OLD_DEFAULT | PM_NETMONITOR },
152 {"3210", "NSE-9", PM_OLD_DEFAULT },
153 {"3220", "RH-37", PM_DEFAULT },
154 {"3285", "NSD-1A", PM_OLD_DEFAULT },
155 {"3300", "NEM-1", PM_OLD_DEFAULT | PM_XGNOKIIBREAKAGE },
156 {"3300", "NEM-2", PM_OLD_DEFAULT | PM_XGNOKIIBREAKAGE },
157 {"3310", "NHM-5", PM_OLD_DEFAULT | PM_NETMONITOR },
158 {"3310", "NHM-5NX", PM_OLD_DEFAULT },
159 {"3315", "NHM-5NY", PM_OLD_DEFAULT },
160 {"3320", "NPC-1", PM_OLD_DEFAULT },
161 {"3330", "NHM-6", PM_OLD_DEFAULT | PM_NETMONITOR },
162 {"3350", "NHM-9", PM_OLD_DEFAULT },
163 {"3360", "NPW-6", PM_OLD_DEFAULT },
164 {"3360", "NPW-1", PM_OLD_DEFAULT },
165 {"3361", "NPW-1", PM_OLD_DEFAULT },
166 {"3390", "NPB-1", PM_OLD_DEFAULT },
167 {"3395", "NPB-1B", PM_OLD_DEFAULT },
168 {"3410", "NHM-2", PM_OLD_DEFAULT | PM_NETMONITOR },
169 {"3500c", "RM-272", PM_DEFAULT },
170 {"3510", "NHM-8", PM_DEFAULT },
171 {"3510i", "RH-9", PM_DEFAULT },
172 {"3520", "RH-21", PM_DEFAULT },
173 {"3530", "RH-9", PM_DEFAULT },
174 {"3560", "RH-14", PM_DEFAULT },
175 {"3570", "NPD-1FW", PM_OLD_DEFAULT },
176 {"3585", "NPD-1AW", PM_OLD_DEFAULT },
177 {"3585i", "NPD-4AW", PM_OLD_DEFAULT },
178 {"3586i", "RH-44", PM_OLD_DEFAULT },
179 {"3590", "NPM-8", PM_OLD_DEFAULT },
180 {"3595", "NPM-10", PM_OLD_DEFAULT },
181 {"3600", "NHM-10", PM_OLD_DEFAULT },
182 {"3610", "NAM-1", PM_OLD_DEFAULT },
183 {"3620", "NHM-10X", PM_OLD_DEFAULT },
184 {"3650", "NHL-8", PM_DEFAULT | PM_NETMONITOR },
185 {"3660", "NHL-8X", PM_DEFAULT | PM_NETMONITOR },
186 {"3810", "0305" , PM_OLD_DEFAULT | PM_DATA }, /* NHE-9 */
187 {"3810", "NHE-9", PM_OLD_DEFAULT | PM_DATA },
188 {"5100", "NPM-6", PM_DEFAULT },
189 {"5100", "NPM-6X", PM_DEFAULT | PM_XGNOKIIBREAKAGE },
190 {"5100", "NMP-6", PM_DEFAULT | PM_XGNOKIIBREAKAGE },
191 {"5110", "NSE-1", PM_OLD_DEFAULT | PM_NETMONITOR | PM_DATA | PM_AUTHENTICATION },
192 {"5110", "NSE-1NX", PM_OLD_DEFAULT | PM_NETMONITOR | PM_DATA | PM_AUTHENTICATION },
193 {"5110i", "NSE-1NY", PM_OLD_DEFAULT | PM_NETMONITOR | PM_DATA | PM_AUTHENTICATION },
194 {"5110i", "NSE-2NY", PM_OLD_DEFAULT | PM_NETMONITOR | PM_DATA | PM_AUTHENTICATION },
195 {"5120", "NSC-1", PM_OLD_DEFAULT },
196 {"5125", "NSC-1", PM_OLD_DEFAULT },
197 {"5130", "NSK-1", PM_OLD_DEFAULT | PM_NETMONITOR | PM_DATA | PM_AUTHENTICATION },
198 {"5130 XpressMusic", "RM-495", PM_DEFAULT_S40_3RD },
199 {"5140", "NPL-5", PM_DEFAULT | PM_XGNOKIIBREAKAGE },
200 {"5140i", "RM-104", PM_DEFAULT },
201 {"5160", "NSW-1", PM_OLD_DEFAULT | PM_NETMONITOR | PM_DATA | PM_AUTHENTICATION },
202 {"5170", "NSD-1F", PM_OLD_DEFAULT },
203 {"5180", "NSD-1G", PM_OLD_DEFAULT },
204 {"5185", "NSD-1A", PM_OLD_DEFAULT },
205 {"5190", "NSB-1", PM_OLD_DEFAULT | PM_NETMONITOR | PM_DATA | PM_AUTHENTICATION },
206 {"5210", "NSM-5", PM_DEFAULT },
207 {"5300 XpressMusic", "RM-146", PM_DEFAULT_S40_3RD },
208 {"5310 XpressMusic", "RM-303", PM_DEFAULT_S40_3RD },
209 {"5510", "NPM-5", PM_OLD_DEFAULT },
210 {"6010", "NPM-10", PM_OLD_DEFAULT },
211 {"6010", "NPM-10X", PM_OLD_DEFAULT },
212 {"6011", "RTE-2RH", PM_OLD_DEFAULT },
213 {"6015i", "RH-55", PM_DEFAULT },
214 {"6020", "RM-30", PM_DEFAULT },
215 {"6021", "RM-94", PM_DEFAULT | PM_XGNOKIIBREAKAGE},
216 {"6030", "RM-74", PM_DEFAULT },
217 {"6050", "NME-1", PM_OLD_DEFAULT },
218 {"6070", "RM-166", PM_DEFAULT },
219 {"6080", "NME-2", PM_OLD_DEFAULT },
220 {"6081", "NME-2A", PM_OLD_DEFAULT },
221 {"6081", "NME-2E", PM_OLD_DEFAULT },
222 {"6085", "RM-260", PM_DEFAULT },
223 {"6090", "NME-3", PM_OLD_DEFAULT },
224 {"6100", "NPL-2", PM_DEFAULT | PM_XGNOKIIBREAKAGE },
225 {"6108", "RH-4", PM_OLD_DEFAULT },
226 {"6110", "NSE-3", PM_OLD_DEFAULT | PM_NETMONITOR | PM_DATA | PM_AUTHENTICATION },
227 {"6120", "NSC-3", PM_OLD_DEFAULT | PM_NETMONITOR | PM_DATA | PM_AUTHENTICATION },
228 {"6130", "NSK-3", PM_OLD_DEFAULT | PM_NETMONITOR | PM_DATA | PM_AUTHENTICATION },
229 {"6133", "RM-126", PM_DEFAULT_S40_3RD },
230 {"6136", "RM-199", PM_DEFAULT | PM_FULLPBK },
231 {"6138", "NSK-3", PM_OLD_DEFAULT },
232 {"6150", "NSM-1", PM_OLD_DEFAULT | PM_NETMONITOR | PM_DATA | PM_AUTHENTICATION },
233 {"616x", "NSW-3", PM_OLD_DEFAULT | PM_NETMONITOR | PM_DATA | PM_AUTHENTICATION },
234 {"6160", "NSW-3AX", PM_OLD_DEFAULT },
235 {"6161", "NSW-3ND", PM_OLD_DEFAULT },
236 {"6162", "NSW-3AF", PM_OLD_DEFAULT },
237 {"6170", "RM47_-48", PM_DEFAULT },
238 {"6185", "NSD-3", PM_OLD_DEFAULT | PM_NETMONITOR | PM_DATA | PM_AUTHENTICATION },
239 {"6185i", "NSD-3AW", PM_OLD_DEFAULT },
240 {"6188", "NSD-3AX", PM_OLD_DEFAULT },
241 {"6190", "NSB-3", PM_OLD_DEFAULT | PM_NETMONITOR | PM_DATA | PM_AUTHENTICATION },
242 {"6200", "NPL-3", PM_DEFAULT | PM_XGNOKIIBREAKAGE },
243 {"6210", "NPE-3", PM_DEFAULT | PM_NETMONITOR },
244 {"6220", "RH-20", PM_DEFAULT | PM_XGNOKIIBREAKAGE },
245 {"6225", "RH-27", PM_OLD_DEFAULT },
246 {"6230", "RH-12_28_-", PM_DEFAULT },
247 {"6230", "RH12_28_-", PM_DEFAULT },
248 {"6230i", "RM72_73_-", PM_DEFAULT },
249 {"6233", "RM123_145_-", PM_DEFAULT },
250 {"6250", "NHM-3", PM_DEFAULT | PM_NETMONITOR },
251 {"6280", "RH-78", PM_DEFAULT },
252 {"6300", "RM-217", PM_DEFAULT_S40_3RD | PM_FULLPBK },
253 {"6303", "RM-443", PM_DEFAULT_S40_3RD | PM_FULLPBK }, /* Nokia 6303 classic */
254 {"6310", "NPE-4", PM_DEFAULT },
255 {"6310i", "NPL-1", PM_DEFAULT },
256 {"6340", "NPM-2", PM_OLD_DEFAULT },
257 {"6340i", "RH-13", PM_OLD_DEFAULT },
258 {"6360", "NPW-2", PM_DEFAULT },
259 {"6370", "NHP-2FX", PM_OLD_DEFAULT },
260 {"6385", "NHP-2AX", PM_OLD_DEFAULT },
261 {"6500", "NHM-7", PM_DEFAULT },
262 {"6500c", "RM-265", PM_DEFAULT_S40_3RD | PM_FULLPBK }, /* Series 40 5th Edition */
263 {"6510", "NPM-9", PM_DEFAULT },
264 {"6560", "RH-25", PM_OLD_DEFAULT },
265 {"6585", "RH-34", PM_OLD_DEFAULT },
266 {"6590", "NSM-9", PM_OLD_DEFAULT },
267 {"6590i", "NSM-9", PM_OLD_DEFAULT },
268 {"6600", "NHL-10", PM_DEFAULT | PM_NETMONITOR },
269 {"6610", "NHL-4U", PM_DEFAULT | PM_XGNOKIIBREAKAGE },
270 {"6610i", "RM-37", PM_DEFAULT | PM_XGNOKIIBREAKAGE },
271 {"6650", "NHM-1", PM_DEFAULT | PM_XGNOKIIBREAKAGE },
272 {"6680", "RM-36", PM_DEFAULT },
273 {"6700 classic", "RM-470", PM_DEFAULT_S40_3RD }, /* Series 40 6th Edition */
274 {"6800", "NHL-6", PM_DEFAULT | PM_XGNOKIIBREAKAGE },
275 {"6800", "NSB-9", PM_DEFAULT | PM_XGNOKIIBREAKAGE },
276 {"6810", "RM-2", PM_DEFAULT | PM_XGNOKIIBREAKAGE },
277 {"6820", "NHL-9", PM_DEFAULT | PM_XGNOKIIBREAKAGE },
278 {"6820b", "RH-26", PM_DEFAULT | PM_XGNOKIIBREAKAGE },
279 {"6822", "RM-69", PM_DEFAULT },
280 {"7110", "NSE-5", PM_DEFAULT | PM_NETMONITOR },
281 {"7160", "NSW-5", PM_OLD_DEFAULT },
282 {"7190", "NSB-5", PM_DEFAULT | PM_NETMONITOR },
283 {"7200", "RH-23", PM_DEFAULT | PM_XGNOKIIBREAKAGE },
284 {"7210", "NHL-4", PM_DEFAULT | PM_XGNOKIIBREAKAGE },
285 {"7250", "NHL-4J", PM_DEFAULT | PM_XGNOKIIBREAKAGE },
286 {"7250i", "NHL-4JX", PM_DEFAULT | PM_XGNOKIIBREAKAGE },
287 {"7260", "RM-17", PM_DEFAULT | PM_XGNOKIIBREAKAGE },
288 {"7270", "RM-8", PM_DEFAULT | PM_XGNOKIIBREAKAGE },
289 {"7280", "RM-14", PM_DEFAULT | PM_XGNOKIIBREAKAGE },
290 {"7373", "RM-209", PM_DEFAULT },
291 {"7600", "NMM-3", PM_DEFAULT | PM_XGNOKIIBREAKAGE },
292 {"7650", "NHL-2NA", PM_DEFAULT },
293 {"8110", "0423" , PM_OLD_DEFAULT | PM_DATA }, /* NHE-6BX */
294 {"8110", "2501", PM_OLD_DEFAULT | PM_DATA },
295 {"8110", "NHE-6", PM_OLD_DEFAULT | PM_DATA },
296 {"8110", "NHE-6BX", PM_OLD_DEFAULT | PM_DATA },
297 {"8110i", "0423", PM_OLD_DEFAULT | PM_DATA }, /* Guess for NHE-6 */
298 {"8110i", "NHE-6", PM_OLD_DEFAULT | PM_DATA },
299 {"8110i", "NHE-6BM", PM_OLD_DEFAULT | PM_DATA },
300 {"8146", "NHK-6", PM_OLD_DEFAULT | PM_DATA },
301 {"8148", "NHK-6", PM_OLD_DEFAULT | PM_DATA },
302 {"8148i", "NHK-6V", PM_OLD_DEFAULT | PM_DATA },
303 {"8210", "NSM-3", PM_OLD_DEFAULT | PM_NETMONITOR | PM_DATA },
304 {"8250", "NSM-3D", PM_OLD_DEFAULT | PM_NETMONITOR | PM_DATA },
305 {"8260", "NSW-4", PM_OLD_DEFAULT },
306 {"8265", "NPW-3", PM_OLD_DEFAULT },
307 {"8270", "NSD-5FX", PM_OLD_DEFAULT },
308 {"8280", "RH-10", PM_OLD_DEFAULT },
309 {"8290", "NSB-7", PM_OLD_DEFAULT | PM_NETMONITOR | PM_DATA },
310 {"8310", "NHM-7", PM_DEFAULT },
311 {"8390", "NSB-8", PM_OLD_DEFAULT },
312 {"8810", "NSE-6", PM_OLD_DEFAULT | PM_DATA },
313 {"8850", "NSM-2", PM_OLD_DEFAULT | PM_NETMONITOR | PM_DATA },
314 {"8855", "NSM-4", PM_OLD_DEFAULT },
315 {"8860", "NSW-6", PM_OLD_DEFAULT },
316 {"8890", "NSB-6", PM_OLD_DEFAULT },
317 {"8910", "NHM-4NX", PM_OLD_DEFAULT },
318 {"8910i", "NHM-4NX", PM_OLD_DEFAULT },
319 {"9000", "RAE-1", PM_OLD_DEFAULT },
320 {"9000i", "RAE-4", PM_OLD_DEFAULT },
321 {"9110", "RAE-2", PM_OLD_DEFAULT },
322 {"9110i", "RAE-2i", PM_OLD_DEFAULT },
323 {"9210", "RAE-2", PM_OLD_DEFAULT },
324 {"9210c", "RAE-3", PM_OLD_DEFAULT },
325 {"9210i", "RAE-5N", PM_OLD_DEFAULT },
326 {"9290", "RAE-3N", PM_OLD_DEFAULT },
327 {"N70", "RM-84", PM_DEFAULT },
328 {"N73", "RM-133", PM_DEFAULT },
329 {"RPM-1", "RPM-1", PM_OLD_DEFAULT | PM_DATA },
330 {"C1-01", "RM-607", PM_DEFAULT_S40_3RD }, /* Series 40 6th Edition Lite */
331 {"C2-03", "RM-70", PM_DEFAULT_S40_3RD },
332 {"Card Phone 1.0", "RPE-1", PM_OLD_DEFAULT | PM_DATA },
333 {"Card Phone 2.0", "RPM-1", PM_OLD_DEFAULT | PM_DATA },
334 {"C110 Wireless LAN Card", "DTN-10", PM_OLD_DEFAULT },
335 {"C111 Wireless LAN Card", "DTN-11", PM_OLD_DEFAULT },
336 {"D211", "DTE-1", PM_OLD_DEFAULT },
337 {"N-Gage", "NEM-4", PM_OLD_DEFAULT },
338 {"RinGo", "NHX-7", PM_OLD_DEFAULT },
339 {"sx1", "SX1", PM_DEFAULT },
340 {"SIM/USIM", "APDU", 0 },
341 {NULL, NULL, 0 } /* keep last one as NULL */
342 };
343
344 #define MODELS_NUM_ENTRIES (sizeof(models)/sizeof(models[0]))
345
346 /* this should be in libfunctions - will move it there with next version of libgnokii */
gn_lib_get_supported_phone_model(const int num)347 GNOKII_API const char *gn_lib_get_supported_phone_model( const int num )
348 {
349 if (num < 0 || num >= MODELS_NUM_ENTRIES)
350 return NULL;
351 return models[num].model;
352 }
353
354
gn_phone_model_get(const char * product_name)355 GNOKII_API gn_phone_model *gn_phone_model_get(const char *product_name)
356 {
357 int i = 0;
358
359 while (models[i].product_name != NULL) {
360 if (strcmp(product_name, models[i].product_name) == 0) {
361 dprintf("Found model \"%s\"\n", product_name);
362 return (&models[i]);
363 }
364 i++;
365 }
366
367 return (&models[MODELS_NUM_ENTRIES-1]); /* NULL entry */
368 }
369
gn_model_get(const char * product_name)370 GNOKII_API const char *gn_model_get(const char *product_name)
371 {
372 return gn_cfg_get_phone_model(gn_cfg_info, product_name)->model;
373 }
374
log_printf(gn_log_target mask,const char * fmt,va_list ap)375 static void log_printf(gn_log_target mask, const char *fmt, va_list ap)
376 {
377 if (mask & GN_LOG_T_STDERR) {
378 vfprintf(stderr, fmt, ap);
379 fflush(stderr);
380 }
381 }
382
gn_log_debug(const char * fmt,...)383 GNOKII_API void gn_log_debug(const char *fmt, ...)
384 {
385 #ifdef DEBUG
386 va_list ap;
387
388 va_start(ap, fmt);
389
390 log_printf(gn_log_debug_mask, fmt, ap);
391
392 va_end(ap);
393 #endif
394 }
395
gn_log_rlpdebug(const char * fmt,...)396 GNOKII_API void gn_log_rlpdebug(const char *fmt, ...)
397 {
398 #ifdef RLP_DEBUG
399 va_list ap;
400
401 va_start(ap, fmt);
402
403 log_printf(gn_log_rlpdebug_mask, fmt, ap);
404
405 va_end(ap);
406 #endif
407 }
408
gn_log_xdebug(const char * fmt,...)409 GNOKII_API void gn_log_xdebug(const char *fmt, ...)
410 {
411 #ifdef XDEBUG
412 va_list ap;
413
414 va_start(ap, fmt);
415
416 log_printf(gn_log_xdebug_mask, fmt, ap);
417
418 va_end(ap);
419 #endif
420 }
421
gn_elog_write(const char * fmt,...)422 GNOKII_API void gn_elog_write(const char *fmt, ...)
423 {
424 va_list ap, ap1;
425
426 va_start(ap, fmt);
427
428 va_copy(ap1, ap);
429 log_printf(gn_log_debug_mask, fmt, ap1);
430 va_end(ap1);
431
432 if (gn_elog_handler) {
433 va_copy(ap1, ap);
434 gn_elog_handler(fmt, ap1);
435 va_end(ap1);
436 } else {
437 #ifndef DEBUG
438 if (!(gn_log_debug_mask & GN_LOG_T_STDERR)) {
439 va_copy(ap1, ap);
440 log_printf(GN_LOG_T_STDERR, fmt, ap1);
441 va_end(ap1);
442 }
443 #endif
444 }
445
446 va_end(ap);
447 }
448
449 #define BUFFER_MAX_LENGTH 128
450 #if defined (__svr4__)
451 # define lock_path "/var/run/LCK.."
452 #else
453 # define lock_path "/var/lock/LCK.."
454 #endif
455
456 /* Lock the device. Return allocated string with a lock name */
gn_device_lock(const char * port)457 GNOKII_API char *gn_device_lock(const char* port)
458 {
459 #ifndef WIN32
460 char *lock_file = NULL;
461 char buffer[BUFFER_MAX_LENGTH];
462 const char *aux = strrchr(port, '/');
463 int fd, len;
464
465 if (!port) {
466 fprintf(stderr, _("Cannot lock NULL device. Set port config parameter correctly.\n"));
467 return NULL;
468 }
469
470 /* Remove leading '/' */
471 if (aux)
472 aux++;
473 else
474 aux = port;
475
476 len = strlen(aux) + strlen(lock_path);
477
478 memset(buffer, 0, sizeof(buffer));
479 lock_file = calloc(len + 1, 1);
480 if (!lock_file) {
481 fprintf(stderr, _("Out of memory error while locking device.\n"));
482 return NULL;
483 }
484 /*
485 * I think we don't need to use strncpy, as we should have enough
486 * buffer due to strlen results, but it's safer to do so...
487 */
488 strncpy(lock_file, lock_path, len);
489 strncat(lock_file, aux, len - strlen(lock_file));
490
491 /* Check for the stale lockfile.
492 * The code taken from minicom by Miquel van Smoorenburg */
493 if ((fd = open(lock_file, O_RDONLY)) >= 0) {
494 char buf[BUFFER_MAX_LENGTH];
495 int pid, n = 0;
496
497 n = read(fd, buf, sizeof(buf) - 1);
498 close(fd);
499 if (n > 0) {
500 pid = -1;
501 if (n == 4)
502 /* Kermit-style lockfile. */
503 pid = *(int *)buf;
504 else {
505 /* Ascii lockfile. */
506 buf[n] = 0;
507 sscanf(buf, "%d", &pid);
508 }
509 if (pid > 0 && kill((pid_t)pid, 0) < 0 && errno == ESRCH) {
510 fprintf(stderr, _("Lockfile %s is stale. Overriding it...\n"), lock_file);
511 sleep(1);
512 if (unlink(lock_file) == -1) {
513 fprintf(stderr, _("Overriding file %s failed, please check the permissions.\n"), lock_file);
514 fprintf(stderr, _("Cannot lock device.\n"));
515 goto failed;
516 }
517 } else {
518 fprintf(stderr, _("Device already locked with %s.\n"), lock_file);
519 goto failed;
520 }
521 }
522 /* This must not happen. Because we could open the file */
523 /* no wrong permissions are set. Only reason could be */
524 /* flock/lockf or an empty lockfile due to a broken binary */
525 /* which is more likely (like gnokii 0.4.0pre11 ;-). */
526 if (n == 0) {
527 fprintf(stderr, _("Unable to read lockfile %s.\n"), lock_file);
528 fprintf(stderr, _("Please check for reason and remove the lockfile by hand.\n"));
529 fprintf(stderr, _("Cannot lock device.\n"));
530 goto failed;
531 }
532 }
533
534 /* Try to create a new file, with 0644 mode */
535 fd = open(lock_file, O_CREAT | O_EXCL | O_WRONLY, 0644);
536 if (fd == -1) {
537 if (errno == EEXIST)
538 fprintf(stderr, _("Device seems to be locked by unknown process.\n"));
539 else if (errno == EACCES)
540 fprintf(stderr, _("Please check permission on lock directory.\n"));
541 else if (errno == ENOENT)
542 fprintf(stderr, _("Cannot create lockfile %s. Please check for existence of the path.\n"), lock_file);
543 goto failed;
544 }
545 snprintf(buffer, sizeof(buffer), "%10ld gnokii\n", (long)getpid());
546 if (write(fd, buffer, strlen(buffer)) < 0) {
547 fprintf(stderr, _("Failed to write to the lockfile %s.\n"), lock_file);
548 goto failed;
549 }
550 close(fd);
551 return lock_file;
552 failed:
553 if (fd > -1)
554 close(fd);
555 free(lock_file);
556 return NULL;
557 #else
558 return (char *)1;
559 #endif /* WIN32 */
560 }
561
562 /* Removes lock and frees memory */
gn_device_unlock(char * lock_file)563 GNOKII_API int gn_device_unlock(char *lock_file)
564 {
565 #ifndef WIN32
566 int err;
567
568 if (lock_file) {
569 err = unlink(lock_file);
570 free(lock_file);
571 if (err) {
572 fprintf(stderr, _("Cannot unlock device: %s\n"), strerror(errno));
573 return false;
574 }
575 }
576 return true;
577 #else
578 return true;
579 #endif /* WIN32 */
580 }
581
582 /*
583 * Splits string into NULL-terminated string array
584 */
gnokii_strsplit(const char * string,const char * delimiter,int tokens)585 char **gnokii_strsplit(const char *string, const char *delimiter, int tokens)
586 {
587 const char *left = string;
588 char *tmp, *str;
589 int count = 0;
590 char **strings;
591
592 if (!string || !delimiter || !tokens)
593 return NULL;
594
595 /*
596 * Last two elements are:
597 * - leftover from the input line
598 * - NULL (required by gnokii_strfreev())
599 */
600 strings = calloc(tokens + 2, sizeof(char *));
601
602 while ((tmp = strstr(left, delimiter)) != NULL && (count < tokens)) {
603 str = malloc((tmp - left) + 1);
604 memset(str, 0, (tmp - left) + 1);
605 memcpy(str, left, tmp - left);
606 strings[count] = str;
607 left = tmp + strlen(delimiter);
608 count++;
609 }
610
611 strings[count] = strdup(left);
612 /*
613 * Make NULL termination explicit even if it is done via calloc().
614 * gnokii_strfreev() requires it to be NULL-terminated.
615 */
616 strings[count + 1] = NULL;
617
618 for (count = 0; count < tokens; count++) {
619 dprintf("strings[%d] = %s\n", count, strings[count]);
620 }
621
622 return strings;
623 }
624
625 /*
626 * frees NULL-terminated array of strings
627 */
gnokii_strfreev(char ** str_array)628 void gnokii_strfreev(char **str_array)
629 {
630 char **tmp = str_array;
631
632 if (!str_array)
633 return;
634
635 while (*tmp) {
636 free(*tmp);
637 tmp++;
638 }
639 free(str_array);
640 }
641
642 /**
643 * gnokii_strcmpsep:
644 * @s1: a string, NUL terminated, may NOT contain @sep
645 * @s2: a string, NUL terminated, may contain @sep
646 * @sep: comparison stops if this char is found in @s2
647 *
648 * Returns: < 0 if @s1 < @s2
649 * 0 if @s1 == @s2
650 * > 0 if @s1 > @s2
651 *
652 * Compares two strings up to a NUL terminator or a separator char.
653 * Leading and trailing white space in @s2 is ignored.
654 */
gnokii_strcmpsep(const char * s1,const char * s2,char sep)655 int gnokii_strcmpsep(const char *s1, const char *s2, char sep)
656 {
657 while (isspace(*s2))
658 s2++;
659 while (*s1 && *s1 == *s2) {
660 s1++;
661 s2++;
662 }
663 while (isspace(*s2))
664 s2++;
665 if (!*s1 && *s2 == sep)
666 return 0;
667
668 return *s1 - *s2;
669 }
670
671 /*
672 * check if the timestamp in dt has valid date and time
673 */
gn_timestamp_isvalid(const gn_timestamp dt)674 GNOKII_API int gn_timestamp_isvalid(const gn_timestamp dt)
675 {
676 #define BETWEEN(a, x, y) ((a >= x) && (a <= y))
677 int daynum;
678
679 /* assume that year is OK */
680 switch (dt.month) {
681 case 2:
682 if (((dt.year % 4) == 0) &&
683 (((dt.year % 100) != 0) ||
684 ((dt.year % 1000) == 0)))
685 daynum = 29;
686 else
687 daynum = 28;
688 break;
689 case 1:
690 case 3:
691 case 5:
692 case 7:
693 case 8:
694 case 10:
695 case 12:
696 daynum = 31;
697 break;
698 default:
699 daynum = 30;
700 break;
701 }
702 return (BETWEEN(dt.month, 1, 12) && BETWEEN(dt.day, 1, daynum) &&
703 BETWEEN(dt.hour, 0, 24) && BETWEEN(dt.minute, 0, 59) &&
704 BETWEEN(dt.second, 0, 59));
705 }
706