1 /* $Id$
2    Written 1999 by Tobias Ernst and released do the Public Domain.
3    This file is part of NLTOOLS, the nodelist processor of the Husky fidonet
4    software project.
5 
6    Seek nodelist matching a mask
7 */
8 #include <stdlib.h>
9 #include <ctype.h>
10 #include <string.h>
11 #include <errno.h>
12 
13 #include <huskylib/compiler.h>
14 
15 #include <huskylib/dirlayer.h>
16 
17 #include <fidoconf/fidoconf.h>
18 #include <huskylib/log.h>
19 #include "nlstring.h"
20 #include "julian.h"
21 #include "nlfind.h"
22 #include "nldate.h"
23 
free_nlist(nlist * pnl)24 void free_nlist( nlist * pnl )
25 {
26   int i;
27 
28   if( pnl )
29   {
30     for( i = 0; i < pnl->n; i++ )
31     {
32       free( pnl->matches[i] );
33     }
34     if( pnl->matches != NULL )
35     {
36       free( pnl->matches );
37     }
38     if( pnl->julians != NULL )
39     {
40       free( pnl->julians );
41     }
42     if( pnl->applied != NULL )
43     {
44       free( pnl->applied );
45     }
46     free( pnl );
47   }
48 }
49 
make_nlist(void)50 static nlist *make_nlist( void )
51 {
52   nlist *res = malloc( sizeof( nlist ) );
53 
54   if( res == NULL )
55   {
56     w_log( LL_CRIT, "Out of memory." );
57     return NULL;
58   }
59 
60   res->n = 0;
61   res->nmax = 5;
62   res->matches = malloc( res->nmax * sizeof( char * ) );
63   res->julians = malloc( res->nmax * sizeof( long ) );
64   res->applied = malloc( res->nmax * sizeof( int ) );
65 
66   if( res->matches == NULL || res->julians == NULL || res->applied == NULL )
67   {
68     w_log( LL_CRIT, "Out of memory." );
69     if( res->julians )
70       free( res->julians );
71     if( res->matches )
72       free( res->matches );
73     if( res->applied )
74       free( res->applied );
75     free( res );
76     return NULL;
77   }
78 
79   return res;
80 }
81 
add_match(nlist * pnl,char * match)82 int add_match( nlist * pnl, char *match )
83 {
84   char *cp = malloc( strlen( match ) + 1 );
85   char **newm;
86   int *newa;
87   long *newj;
88 
89 /*    w_log( 'X', "add_match()" ); */
90 
91   if( cp == NULL )
92   {
93     w_log( LL_CRIT, "Out of memory." );
94     return 0;
95   }
96   if( pnl == NULL && ( pnl = make_nlist(  ) ) == NULL )
97     return 0;
98 
99   if( pnl->n == pnl->nmax )
100   {
101     newm = realloc( pnl->matches, ( ( pnl->nmax + 1 ) * 2 ) * sizeof( char * ) );
102     newj = realloc( pnl->julians, ( ( pnl->nmax + 1 ) * 2 ) * sizeof( long ) );
103     newa = realloc( pnl->applied, ( ( pnl->nmax + 1 ) * 2 ) * sizeof( int ) );
104 
105     if( newm == NULL || newj == NULL )
106     {
107       w_log( LL_CRIT, "Out of memory." );
108       return 0;
109     }
110     pnl->matches = newm;
111     pnl->julians = newj;
112     pnl->applied = newa;
113     pnl->nmax = ( ( pnl->nmax + 1 ) * 2 );
114   }
115 
116   strcpy( cp, match );
117   pnl->matches[pnl->n] = cp;
118   pnl->julians[pnl->n] = 0;     /* 0 means: not yet known */
119   pnl->applied[pnl->n] = 0;
120   pnl->n++;
121   return 1;
122 }
123 
find_nodelistfiles(char * path,char * base,int allowarc)124 nlist *find_nodelistfiles( char *path, char *base, int allowarc )
125 {
126   char *dfile;
127   husky_DIR *hdir;
128   nlist *pnl = make_nlist(  );
129   size_t l, l2;
130 
131   w_log( LL_FUNC, "find_nodelistfiles()" );
132 
133   if( pnl == NULL )
134   {
135     w_log( LL_FUNC, "find_nodelistfiles() failed " );
136     return NULL;
137   }
138 
139   hdir = husky_opendir( path );
140 
141   if( hdir == NULL )
142   {
143     w_log( LL_ERROR, "Cannot read directory '%s': %s", path, strerror( errno ) );
144     free_nlist( pnl );
145     w_log( LL_FUNC, "find_nodelistfiles() failed " );
146     return NULL;
147   }
148 
149   w_log( LL_DIR, "Scan directory %s for %s", path, base );
150 
151   l = strlen( base );
152 
153   while( ( dfile = husky_readdir( hdir ) ) != NULL )
154   {
155     l2 = strlen( dfile );
156     if( l2 == l + 4 &&
157         !ncasecmp( base, dfile, l ) &&
158         dfile[l] == '.' &&
159         ( allowarc || isdigit( dfile[l + 1] ) ) &&
160         isdigit( dfile[l + 2] ) && isdigit( dfile[l + 3] ) )
161     {
162       if( !add_match( pnl, dfile ) )
163       {
164         free_nlist( pnl );
165         husky_closedir( hdir );
166         w_log( LL_FUNC, "find_nodelistfiles() failed (not found)" );
167         return NULL;
168       }
169       else
170         w_log( LL_DEBUG, "Found: %s", dfile );
171 
172     }
173   }
174 
175   husky_closedir( hdir );
176 
177   if( !pnl->n )
178   {
179     free_nlist( pnl );
180     w_log( LL_FUNC, "find_nodelistfiles() failed" );
181     return NULL;
182   }
183 
184   w_log( LL_FUNC, "find_nodelistfiles() OK" );
185   return pnl;
186 }
187 
findNodelist(s_fidoconfig * config,unsigned int i)188 char *findNodelist( s_fidoconfig * config, unsigned int i )
189 {
190   char *nl;
191   nlist *pnl;
192   int j;
193   long lastjul = -1, tmp;
194   int lastmatch = -1;
195   int l;
196 
197   w_log( LL_FUNC, "findNodelist()" );
198 
199   pnl = find_nodelistfiles( config->nodelistDir, config->nodelists[i].nodelistName, 0 );
200 
201   if( pnl == NULL )
202   {
203     w_log( LL_FUNC, "findNodelist() failed (not found)" );
204     return NULL;
205   }
206   nl = malloc( ( l = strlen( config->nodelistDir ) ) +
207                strlen( config->nodelists[i].nodelistName ) + 5 );
208 
209   if( nl == NULL )
210   {
211     w_log( LL_CRIT, "Out of memory." );
212     free_nlist( pnl );
213     w_log( LL_FUNC, "findNodelist() failed" );
214     return NULL;
215   }
216 
217   memcpy( nl, config->nodelistDir, l );
218 
219   for( j = 0; j < pnl->n; j++ )
220   {
221     strcpy( nl + l, pnl->matches[j] );
222 
223     tmp = parse_nodelist_date( nl );
224 
225     if( tmp > lastjul )
226     {
227       lastjul = tmp;
228       lastmatch = j;
229     }
230   }
231 
232   if( lastmatch == -1 )
233   {
234     free_nlist( pnl );
235     free( nl );
236     w_log( LL_FUNC, "findNodelist() failed (don't match)" );
237     return NULL;
238   }
239 
240   strcpy( nl + l, pnl->matches[lastmatch] );
241 
242   free_nlist( pnl );
243   w_log( LL_FUNC, "findNodelist() OK" );
244   return nl;
245 }
246