1 /*
2 *
3 * XASTIR, Amateur Station Tracking and Information Reporting
4 * Copyright (C) 1999,2000  Frank Giannandrea
5 * Copyright (C) 2000-2019 The Xastir Group
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
20  *
21  * Look at the README for more information on the program.
22  */
23 
24 //====================================================================
25 //    Canadian Callsign Lookup
26 //    Richard Hagemeyer, VE3UNW
27 //    GNU COPYLEFT applies
28 //    1999-11-08
29 //
30 //    For use with XASTIR by Frank Giannandrea
31 //********************************************************************
32 
33 #ifdef HAVE_CONFIG_H
34   #include "config.h"
35 #endif  // HAVE_CONFIG_H
36 
37 #include <stdio.h>
38 #include <fcntl.h>
39 #include <unistd.h>
40 #include <signal.h>
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <string.h>
44 #include <ctype.h>
45 #include <sys/types.h>
46 
47 #if TIME_WITH_SYS_TIME
48   #include <sys/time.h>
49   #include <time.h>
50 #else   // TIME_WITH_SYS_TIME
51   #if HAVE_SYS_TIME_H
52     #include <sys/time.h>
53   #else  // HAVE_SYS_TIME_H
54     #include <time.h>
55   #endif // HAVE_SYS_TIME_H
56 #endif  // TIME_WITH_SYS_TIME
57 
58 #include <Xm/XmAll.h>
59 
60 #include "xastir.h"
61 #include "rac_data.h"
62 #include "xa_config.h"
63 #include "main.h"
64 #include "snprintf.h"
65 
66 // Must be last include file
67 #include "leak_detection.h"
68 
69 
70 
71 
72 
73 /* ====================================================================    */
74 /*    my version of chomp from perl, removes spaces and dashes    */
75 /*                                    */
76 /* ******************************************************************** */
chomp(char * input,unsigned int i)77 int chomp(char *input, unsigned int i)
78 {
79   unsigned int    x;
80 
81   for (x=i; input[x] == ' ' || input[x] == '-'; x--)
82   {
83     input[x] = '\0';
84   }
85 
86   return ( (int)(i-x) );
87 }
88 
89 
90 
91 
92 
93 /* ====================================================================    */
94 /*    build a new (or newer if I check the file date) index file    */
95 /*    check for current ic index file                    */
96 /*      FG: added a date check in case the RAC file has been updated.   */
97 /*      AMACALL.LST must have a time stamp newer than the index file    */
98 /*      time stamp. Use the touch command on the AMACALL.LST file to    */
99 /*      make the time current if necessary.                             */
100 /* ******************************************************************** */
build_rac_index(void)101 int build_rac_index(void)
102 {
103   FILE *fdb;
104   FILE *fndx;
105   unsigned long call_offset = 0;
106   unsigned long x = 0;
107   char racdata[RAC_DATA_LEN+8];
108   char amacall_path[MAX_VALUE];
109 
110   get_user_base_dir("data/AMACALL.ndx", amacall_path, sizeof(amacall_path));
111 
112   /* ====================================================================    */
113   /*    If the index file is there, exit                */
114   /*                                    */
115   if (filethere(amacall_path))
116   {
117     /* if file is there make sure the index date is newer */
118     if(file_time(amacall_path)<=file_time(amacall_path))
119     {
120       return(1);
121     }
122     else
123     {
124 
125       // RAC index old, rebuilding
126       statusline(langcode("STIFCC0103"), 1);
127 
128       fprintf(stderr,"RAC index is old.  Rebuilding index.\n");
129 //            XmTextFieldSetString(text,"RAC Index old rebuilding");
130 //            XtManageChild(text);
131 //            XmUpdateDisplay(XtParent(text));
132     }
133   }
134   /* ====================================================================    */
135   /*    Open the database and index file                */
136   /*                                    */
137   fdb=fopen(get_data_base_dir("fcc/AMACALL.LST"),"rb");
138   if (fdb==NULL)
139   {
140     fprintf(stderr,"Build:Could not open RAC data base: %s\n", get_data_base_dir("fcc/AMACALL.LST") );
141     return(0);
142   }
143 
144   fndx=fopen(amacall_path,"w");
145   if (fndx==NULL)
146   {
147     fprintf(stderr,"Build:Could not open/create RAC data base index: %s\n", amacall_path );
148     (void)fclose(fdb);
149     return(0);
150   }
151   /* ====================================================================    */
152   /*    Skip past the header to the first callsign (VA2AA)        */
153   /*                                    */
154   memset(racdata, 0, sizeof(racdata));
155   while (!feof(fdb) && strncmp(racdata,"VA",2))
156   {
157     call_offset = (unsigned long)ftell(fdb);
158     if (fgets(racdata, (int)sizeof(racdata), fdb)==NULL)
159     {
160       fprintf(stderr,"Build:header:Unable to read data base\n");
161       (void)fclose(fdb);
162       (void)fclose(fndx);
163       fprintf(stderr,"rc=0\n");
164       return (0);
165     }
166   }
167 
168   /* ====================================================================    */
169   /*    write out the current callsign and RBA of the db file         */
170   /*    skip 100 records and do it again until no more            */
171   /*                                    */
172   while (!feof(fdb))
173   {
174     fprintf(fndx,"%6.6s%li\n",racdata,(long)call_offset);
175     call_offset = (unsigned long)ftell(fdb);
176     for (x=0; x<=100 && !feof(fdb); x++)
177       if (fgets(racdata, (int)sizeof(racdata), fdb)==NULL)
178       {
179         break;
180       }
181   }
182   (void)fclose(fdb);
183   (void)fclose(fndx);
184 
185 //    XmTextFieldSetString(text,"");
186 //    XtManageChild(text);
187 
188   return(1);
189 }
190 
191 
192 
193 
194 
195 /* ====================================================================    */
196 /*    Check for ic data base file                    */
197 /*    Check/build the index                        */
198 /*                                    */
199 /* ******************************************************************** */
check_rac_data(void)200 int check_rac_data(void)
201 {
202   int rac_data_available = 0;
203   if( filethere( get_data_base_dir("fcc/AMACALL.LST") ) )
204   {
205     if (build_rac_index())
206     {
207       rac_data_available=1;
208     }
209     else
210     {
211       fprintf(stderr,"Check:Could not build ic data base index\n");
212       rac_data_available=0;
213     }
214   }
215   return(rac_data_available);
216 }
217 
218 
219 
220 
221 
222 /* ====================================================================    */
223 /*    The real work.  Pass the callsign, get the info            */
224 /*                                    */
225 /* ******************************************************************** */
search_rac_data(char * callsign,rac_record * data)226 int search_rac_data(char *callsign, rac_record *data)
227 {
228   FILE *fdb;
229   FILE *fndx;
230   long call_offset = 0l;
231   char char_offset[16];
232   char index[32];
233   int found = 0;
234   rac_record racdata;
235   /*char        filler[8];*/
236   char amacall_path[MAX_VALUE];
237 
238   get_user_base_dir("data/AMACALL.ndx", amacall_path, sizeof(amacall_path));
239 
240 
241   xastir_snprintf(index, sizeof(index)," ");
242   xastir_snprintf(racdata.callsign, sizeof(racdata.callsign)," ");
243 
244   /* ====================================================================    */
245   /*    Search thru the index, get the RBA                */
246   /*                                    */
247 
248   fndx = fopen(amacall_path, "r");
249   if(fndx != NULL)
250   {
251     if (fgets(index, (int)sizeof(index), fndx) == NULL)
252     {
253       // Error occurred
254       fprintf(stderr,
255               "Search:Could not read RAC data base index: %s\n",
256               amacall_path );
257       return (0);
258     }
259     memcpy(char_offset, &index[6], sizeof(char_offset));
260     char_offset[sizeof(char_offset)-1] = '\0';  // Terminate string
261     while (!feof(fndx) && strncmp(callsign, index, 6) > 0)
262     {
263       memcpy(char_offset, &index[6], sizeof(char_offset));
264       char_offset[sizeof(char_offset)-1] = '\0';  // Terminate string
265       if (fgets(index, (int)sizeof(index), fndx) == NULL)
266       {
267         // Error occurred
268         fprintf(stderr,
269                 "Search:Could not read RAC data base index(2): %s\n",
270                 amacall_path );
271         return (0);
272       }
273     }
274   }
275   else
276   {
277     fprintf(stderr,
278             "Search:Could not open RAC data base index: %s\n",
279             amacall_path );
280     return (0);
281   }
282   call_offset = atol(char_offset);
283 
284   (void)fclose(fndx);
285 
286   /* ====================================================================    */
287   /*    Now we have our pointer into the main database (text) file.    */
288   /*    Start from there and linear search the data.            */
289   /*    This will take an avg of 1/2 of the # skipped making the index    */
290   /*                                    */
291 
292   fdb = fopen(get_data_base_dir("fcc/AMACALL.LST"), "r");
293   if (fdb != NULL)
294   {
295     (void)fseek(fdb, call_offset, SEEK_SET);
296     if (callsign[5] == '-')
297     {
298       (void)chomp(callsign,5);
299     }
300 
301     while (!feof(fdb) && strncmp((char *)&racdata, callsign, 6) < 0)
302 
303 //WE7U
304 // Problem here:  We're sticking 8 bytes too many into racdata!
305       if (fgets((char *)&racdata, sizeof(racdata), fdb) == NULL)
306       {
307         // Error occurred
308         fprintf(stderr,
309                 "Search:Could not read RAC data base: %s\n",
310                 amacall_path );
311         return (0);
312       }
313 
314   }
315   else
316   {
317     fprintf(stderr,"Search:Could not open RAC data base: %s\n", get_data_base_dir("fcc/AMACALL.LST") );
318   }
319 
320   /*  || (callsign[5] == '-' && strncmp((char *)&racdata,callsign,5) < 0)) */
321   (void)chomp(racdata.callsign, 6);
322 
323   if (!strncmp((char *)racdata.callsign, callsign, 6))
324   {
325     found = 1;
326 
327 // Some of these cause problems on 64-bit processors, so commented
328 // them out for now.
329 //        (void)chomp(racdata.first_name, 35);
330 //        (void)chomp(racdata.last_name, 35);
331 //        (void)chomp(racdata.address, 70);
332 //        (void)chomp(racdata.city, 35);
333 //        (void)chomp(racdata.province, 2);
334 //        (void)chomp(racdata.postal_code, 10);
335 //        (void)chomp(racdata.qual_a, 1);
336 //        (void)chomp(racdata.qual_b, 1);
337 //        (void)chomp(racdata.qual_c, 1);
338 //        (void)chomp(racdata.qual_d, 1);
339 //        (void)chomp(racdata.club_name, 141);
340 //        (void)chomp(racdata.club_address, 70);
341 //        (void)chomp(racdata.club_city, 35);
342 //        (void)chomp(racdata.club_province, 2);
343 //        (void)chomp(racdata.club_postal_code, 9);
344 
345     xastir_snprintf(data->callsign,
346                     sizeof(data->callsign),
347                     "%s",
348                     racdata.callsign);
349 
350     xastir_snprintf(data->first_name,
351                     sizeof(data->first_name),
352                     "%s",
353                     racdata.first_name);
354 
355     xastir_snprintf(data->last_name,
356                     sizeof(data->last_name),
357                     "%s",
358                     racdata.last_name);
359 
360     xastir_snprintf(data->address,
361                     sizeof(data->address),
362                     "%s",
363                     racdata.address);
364 
365     xastir_snprintf(data->city,
366                     sizeof(data->city),
367                     "%s",
368                     racdata.city);
369 
370     xastir_snprintf(data->province,
371                     sizeof(data->province),
372                     "%s",
373                     racdata.province);
374 
375     xastir_snprintf(data->postal_code,
376                     sizeof(data->postal_code),
377                     "%s",
378                     racdata.postal_code);
379 
380     xastir_snprintf(data->qual_a,
381                     sizeof(data->qual_a),
382                     "%s",
383                     racdata.qual_a);
384 
385     xastir_snprintf(data->qual_b,
386                     sizeof(data->qual_b),
387                     "%s",
388                     racdata.qual_b);
389 
390     xastir_snprintf(data->qual_c,
391                     sizeof(data->qual_c),
392                     "%s",
393                     racdata.qual_c);
394 
395     xastir_snprintf(data->qual_d,
396                     sizeof(data->qual_d),
397                     "%s",
398                     racdata.qual_d);
399 
400     xastir_snprintf(data->club_name,
401                     sizeof(data->club_name),
402                     "%s",
403                     racdata.club_name);
404 
405     xastir_snprintf(data->club_address,
406                     sizeof(data->club_address),
407                     "%s",
408                     racdata.club_address);
409 
410     xastir_snprintf(data->club_city,
411                     sizeof(data->club_city),
412                     "%s",
413                     racdata.club_city);
414 
415     xastir_snprintf(data->club_province,
416                     sizeof(data->club_province),
417                     "%s",
418                     racdata.club_province);
419 
420     xastir_snprintf(data->club_postal_code,
421                     sizeof(data->club_postal_code),
422                     "%s",
423                     racdata.club_postal_code);
424 
425   }
426   (void)fclose(fdb);
427 
428   if (!found)
429   {
430 
431     // "Callsign Search", "Callsign Not Found!"
432     popup_message_always(langcode("STIFCC0101"),
433                          langcode("STIFCC0102") );
434   }
435 
436   return(found);
437 }
438 
439 
440