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 Fido Userlist Compiler routines
7 */
8 #include <stdio.h>
9 #include <string.h>
10 #include <assert.h>
11 #include <stdlib.h>
12 #include <ctype.h>
13 #include "nlstring.h"
14 #include "ulc.h"
15
16 enum
17 { T_ZONE, T_REGION, T_HOST, T_HUB, T_NODE };
18
19 /* A node or point has been parsed in a node list. Write it in Fidouser.Lst
20 format to the output file. The output file is not yet sorted. The
21 "username" parameter should contain underscores instead of spaces. */
22
23 #define ENTRYLENGTH 60 /* without trailing \r\n! */
24
parsednode(FILE * fout,unsigned zone,unsigned net,unsigned node,unsigned point,char * username)25 static int parsednode( FILE * fout, unsigned zone, unsigned net, unsigned node,
26 unsigned point, char *username )
27 {
28 char rev_username[ENTRYLENGTH + 3], *cp, *cp2;
29 char nodenr[24];
30
31 cp = strrchr( username, '_' );
32
33 if( cp == NULL )
34 {
35 strncpy( rev_username, username, ENTRYLENGTH );
36 rev_username[ENTRYLENGTH] = '\0';
37 }
38 else
39 {
40 strncpy( rev_username, cp + 1, ENTRYLENGTH - 2 );
41 strcat( rev_username, ", " );
42 *cp = 0;
43
44 for( cp = username, cp2 = rev_username + strlen( rev_username );
45 *cp && cp2 - rev_username < ENTRYLENGTH; cp++, cp2++ )
46 {
47 if( *cp == '_' )
48 {
49 *cp2 = ' ';
50 }
51 else
52 {
53 *cp2 = *cp;
54 }
55 }
56 *cp2 = '\0';
57 }
58
59 sprintf( nodenr, "%u:%u/%u.%u", zone % 65536, net % 65536, node % 65536, point % 65536 );
60
61 if( strlen( rev_username ) > ENTRYLENGTH - strlen( nodenr ) - 1 )
62 {
63 rev_username[ENTRYLENGTH - strlen( nodenr ) - 1] = '\0';
64 }
65 else
66 {
67 for( cp = rev_username + strlen( rev_username );
68 cp - rev_username < ENTRYLENGTH - ( signed ) strlen( nodenr ) - 1; cp++ )
69 {
70 *cp = ' ';
71 }
72 }
73
74 strcat( rev_username, " " );
75 strcat( rev_username, nodenr );
76 strcat( rev_username, "\r\n" );
77
78 return ( fwrite( rev_username, ENTRYLENGTH + 2, 1, fout ) == 1 );
79 }
80
81 /* Process a line from a nodelist file */
82
parse2d(char * ptr,unsigned int * net,unsigned int * node)83 static void parse2d( char *ptr, unsigned int *net, unsigned int *node )
84 {
85 *net = 0;
86 *node = 0;
87 while( isdigit( *ptr ) )
88 {
89 *net = 10 * ( *net ) + ( *ptr ) - '0';
90 ptr++;
91 }
92 if( ( *( ptr ) ) != '/' )
93 {
94 *net = *node = 0;
95 }
96 else
97 {
98 ptr++;
99 while( isdigit( *ptr ) )
100 {
101 *node = 10 * ( *node ) + ( *ptr ) - '0';
102 ptr++;
103 }
104 if( *ptr )
105 {
106 *net = *node = 0;
107 }
108 }
109 }
110
parse3d(char * ptr,unsigned int * zone,unsigned int * net,unsigned int * node)111 static void parse3d( char *ptr, unsigned int *zone, unsigned int *net, unsigned int *node )
112 {
113 *zone = 0;
114 while( isdigit( *ptr ) )
115 {
116 *zone = 10 * ( *zone ) + ( *ptr ) - '0';
117 ptr++;
118 }
119 if( ( *( ptr ) ) != ':' )
120 {
121 *zone = *net = *node = 0;
122 }
123 else
124 {
125 ptr++;
126 parse2d( ptr, net, node );
127 }
128 }
129
ulc_line(FILE * fin,FILE * fout,unsigned format,unsigned * zone,unsigned * net,unsigned * node)130 static int ulc_line( FILE * fin, FILE * fout, unsigned format,
131 unsigned *zone, unsigned *net, unsigned *node )
132 {
133 char linebuf[128], *ptr = NULL, *sptr = NULL;
134 size_t l;
135 int incomplete;
136 int k, rv = 1;
137 char *username = NULL;
138 unsigned point = 0;
139 int type = 0;
140
141 if( fgets( linebuf, sizeof( linebuf ), fin ) != NULL )
142 {
143 l = strlen( linebuf );
144 incomplete = ( l && linebuf[l - 1] != '\n' );
145
146 /* analyze the string */
147
148 switch ( *linebuf )
149 {
150 case ';':
151 break; /* ignore the comment */
152
153 case ',':
154 ptr = "";
155 sptr = linebuf + 1;
156 break;
157
158 default:
159 ptr = strtok( linebuf, ",\r\n" );
160 break;
161
162 }
163
164 for( k = 0; ptr != NULL && k <= 4; k++ )
165 {
166
167 switch ( format )
168 {
169
170 case F_POINTS4D:
171 switch ( k )
172 {
173 case 0:
174 if( !casecmp( ptr, "BOSS" ) )
175 {
176 type = T_HOST;
177 }
178 else if( ( !*ptr ) || ( !casecmp( ptr, "POINT" ) ) )
179 {
180 type = T_NODE;
181 }
182 else
183 {
184 k = 4; /* ignore this one */
185 }
186 break;
187
188 case 1:
189 if( type == T_HOST )
190 {
191 parse3d( ptr, zone, net, node );
192 }
193 else
194 {
195 point = atoi( ptr );
196 }
197 break;
198
199 case 2:
200 break;
201
202 case 3:
203 break;
204
205 case 4:
206 if( type == T_NODE )
207 {
208 username = ptr;
209 rv = parsednode( fout, *zone, *net, *node, point, username );
210 }
211 break;
212 }
213 break;
214
215 case F_POINTS24:
216
217 switch ( k )
218 {
219 case 0:
220 if( !strcmp( ptr, "Host" ) )
221 {
222 type = T_HOST;
223 }
224 else if( !*ptr )
225 {
226 type = T_NODE;
227 }
228 else
229 {
230 k = 4; /* ignore this one */
231 }
232 break;
233
234 case 1:
235 if( type == T_NODE )
236 {
237 point = atoi( ptr );
238 }
239 break;
240
241 case 2:
242 if( type == T_HOST )
243 {
244 parse2d( ptr, net, node );
245 }
246 break;
247
248 case 3: /* Country */
249 break;
250
251 case 4: /* Sysop Name */
252 if( type == T_NODE )
253 {
254
255 username = ptr;
256 rv = parsednode( fout, *zone, *net, *node, point, username );
257 }
258 break;
259 }
260 break;
261
262 default:
263
264 switch ( k )
265 {
266 case 0:
267 if( !strcmp( ptr, "Zone" ) )
268 {
269 type = T_ZONE;
270 }
271 else if( !strcmp( ptr, "Region" ) )
272 {
273 type = T_REGION;
274 }
275 else if( !strcmp( ptr, "Host" ) )
276 {
277 type = T_HOST;
278 }
279 else if( !strcmp( ptr, "Hub" ) )
280 {
281 type = T_HUB;
282 }
283 else /* Pvt, or empty */
284 {
285 type = T_NODE;
286 }
287 break;
288
289 case 1:
290 switch ( type )
291 {
292 case T_ZONE:
293 *zone = *net = atoi( ptr );
294 *node = 0;
295 break;
296 case T_REGION:
297 case T_HOST:
298 *net = atoi( ptr );
299 *node = 0;
300 break;
301 case T_HUB:
302 case T_NODE:
303 *node = atoi( ptr );
304 break;
305 }
306 break;
307
308 case 2: /* System Name */
309 break;
310
311 case 3: /* Country */
312 break;
313
314 case 4: /* Sysop Name */
315 username = ptr;
316 rv = parsednode( fout, *zone, *net, *node, 0, username );
317 break;
318 }
319 }
320
321
322 ptr = strtok( sptr, ",\r\n" );
323 sptr = NULL;
324 }
325
326
327 /* if the string is longer than 128 characters, ignore the rest */
328
329 while( incomplete && fgets( linebuf, sizeof( linebuf ), fin ) != NULL )
330 {
331 l = strlen( linebuf );
332 incomplete = ( l && linebuf[l - 1] != '\n' );
333 }
334
335 return rv;
336 }
337 if( feof( fin ) )
338 return 2; /* EOF is a normal situation */
339
340 return 0; /* everything else is an error */
341 }
342
ul_compile(FILE * fin,FILE * fout,int type,int defzone)343 int ul_compile( FILE * fin, FILE * fout, int type, int defzone )
344 {
345 unsigned int zone, net, code, node;
346
347 zone = net = defzone;
348 node = 0;
349
350 while( ( code = ulc_line( fin, fout, type, &zone, &net, &node ) ) == 1 );
351
352 return code == 2;
353 }
354