1 /**********************************************************
2  * Outbound management.
3  **********************************************************/
4 /*
5  * $Id: outbound.c,v 1.21 2005/08/10 19:45:50 mitry Exp $
6  *
7  * $Log: outbound.c,v $
8  * Revision 1.21  2005/08/10 19:45:50  mitry
9  * Added param to qscandir() to return full path with file name
10  *
11  * Revision 1.20  2005/05/17 18:17:42  mitry
12  * Removed system basename() usage.
13  * Added qbasename() implementation.
14  *
15  * Revision 1.19  2005/05/16 20:33:46  mitry
16  * Code cleaning
17  *
18  * Revision 1.18  2005/05/11 20:17:36  mitry
19  * Changed int var; to size_t var; for strlen()
20  *
21  * Revision 1.17  2005/05/11 16:37:41  mitry
22  * Set initial values to static variables explicitly
23  *
24  * Revision 1.16  2005/05/06 20:36:45  mitry
25  * Major rewrite again
26  *
27  * Revision 1.15  2005/04/14 18:04:26  mitry
28  * Changed scandir() to qscandir()
29  *
30  * Revision 1.14  2005/04/05 09:31:12  mitry
31  * New xstrcpy() and xstrcat()
32  *
33  * Revision 1.13  2005/03/28 16:37:26  mitry
34  * Moved some code to mappath() function (see tools.c)
35  *
36  * Revision 1.12  2005/02/16 21:42:47  mitry
37  * Check the value returned from scandir (n <= 0) for out_aso_rescan(), out_bso_scan_zone(), out_bso_rescan().
38  *
39  * Revision 1.11  2005/02/16 11:25:29  mitry
40  * Next fix for out_bso_scan_zone()
41  *
42  * Revision 1.10  2005/02/15 22:12:26  mitry
43  * Fix for out_bso_scan_zone()
44  *
45  * Revision 1.9  2005/02/15 11:17:39  mitry
46  * Another fix for out_bso_rescan()
47  *
48  * Revision 1.8  2005/02/09 12:44:23  mitry
49  * Changed free() to xfree()
50  * Changed out_bso_rescan() code
51  *
52  * Revision 1.7  2005/02/08 19:57:28  mitry
53  * Added outbound_addr_busy().
54  * Wiped out old outbound_rescan code.
55  * Cleaned code a bit.
56  *
57  */
58 
59 #include "headers.h"
60 
61 static int bso_defzone = 2;
62 static char *bso_base = NULL;
63 static char *aso_base = NULL;
64 static char *p_domain = NULL;
65 static char *sts_base = NULL;
66 static size_t pd_len = 0;
67 static char out_internal_tmp[MAX_PATH + 5];
68 
69 static qeach_t _each = NULL;
70 static int _rslow;
71 
72 
73 static char *ext_lo[] = {
74     ".pnt", ".req",
75     ".ilo", ".clo", ".dlo", ".flo", ".hlo",
76     NULL
77 };
78 
79 static char *ext_ut[] = {
80     ".iut", ".cut", ".dut", ".out", ".hut",
81     NULL
82 };
83 
84 
outbound_init(const char * asopath,const char * bsopath,const char * stspath,int def_zone)85 int outbound_init(const char *asopath, const char *bsopath,
86 	const char *stspath, int def_zone)
87 {
88     int		rc = 0;
89     size_t	len = 0;
90 
91     outbound_done();
92 
93     if ( bsopath && *bsopath ) {
94         char *p;
95 
96         len = strlen( bsopath ) - 1;
97         xstrcpy( out_internal_tmp, bsopath, MAX_PATH );
98         len = chopc( out_internal_tmp, '/' );
99 
100         if ( len ) {
101             p = strrchr( out_internal_tmp, '/' );
102 
103             if ( p ) {
104                 p_domain = xstrdup( p + 1 );
105                 pd_len = strlen( p_domain );
106 
107                 if ( p == out_internal_tmp )
108                     *(p + 1) = '\0';
109                 else
110                     *p = '\0';
111                 bso_base = xstrdup( out_internal_tmp );
112                 bso_defzone = def_zone;
113                 rc |= BSO;
114             } else
115                 len = 0;
116         }
117     }
118 
119     if ( !len ) {
120         xfree( bso_base );
121         xfree( p_domain );
122     }
123 
124     len = 0;
125 
126     if ( asopath && *asopath ) {
127         len = strlen( asopath ) - 1;
128         xstrcpy( out_internal_tmp, asopath, MAX_PATH );
129         len = chopc( out_internal_tmp, '/' );
130 
131         if ( !len )
132             aso_base = xstrdup( "/" );
133         else
134             aso_base = xstrdup( out_internal_tmp );
135         rc |= ASO;
136     }
137 
138     if ( !rc )
139         return 0;
140 
141     if ( stspath && *stspath ) {
142         xstrcpy( out_internal_tmp, stspath, MAX_PATH );
143         len = chopc( out_internal_tmp, '/' );
144         if ( !len )
145             sts_base = xstrdup( "/" );
146         else
147             sts_base = xstrdup( stspath );
148     } else if ( bsopath )
149         sts_base = xstrdup( bsopath );
150     else if ( asopath )
151         sts_base = xstrdup( asopath );
152 
153     return rc;
154 }
155 
156 
outbound_done(void)157 void outbound_done(void)
158 {
159     xfree( bso_base );
160     xfree( p_domain );
161     xfree( aso_base );
162     xfree( sts_base );
163     pd_len = 0;
164 }
165 
166 
get_outbound_name(int type,const ftnaddr_t * fa)167 static char *get_outbound_name(int type, const ftnaddr_t *fa)
168 {
169     out_internal_tmp[0] = '\0';
170 
171     switch( type ) {
172     case ASO:
173         if ( aso_base )
174             snprintf( out_internal_tmp, MAX_PATH, "%s/%d.%d.%d.%d.", aso_base, fa->z, fa->n, fa->f, fa->p) ;
175         break;
176 
177     case BSO:
178         if ( bso_base ) {
179             char t[30];
180 
181             snprintf( out_internal_tmp, MAX_PATH, "%s/%s", bso_base, p_domain );
182             if ( fa->z != bso_defzone ) {
183                 snprintf( t, 30, ".%03x", fa->z );
184                 xstrcat( out_internal_tmp, t, MAX_PATH );
185             }
186             snprintf( t, 30, "/%04x%04x.", fa->n, fa->f );
187             xstrcat( out_internal_tmp, t, MAX_PATH );
188             if( fa->p ) {
189                 snprintf( t, 30, "pnt/%08x.", fa->p );
190                 xstrcat( out_internal_tmp, t, MAX_PATH );
191             }
192         }
193         break;
194 
195     default:
196         return NULL;
197     }
198 
199     if ( *out_internal_tmp )
200         return out_internal_tmp;
201 
202     return NULL;
203 }
204 
205 
get_pkt_name(int type,const ftnaddr_t * fa,int fl)206 static char *get_pkt_name(int type, const ftnaddr_t *fa, int fl)
207 {
208     char e[] = "eut";
209     char *name = get_outbound_name( type, fa );
210 
211     if ( name ) {
212         switch( fl ) {
213             case F_NORM:
214             case F_REQ:  *e = 'o'; break;
215             case F_DIR:  *e = 'd'; break;
216             case F_CRSH: *e = 'c'; break;
217             case F_HOLD: *e = 'h'; break;
218             case F_IMM:  *e = 'i'; break;
219         }
220         xstrcat( name, e, MAX_PATH );
221     }
222 
223     return name;
224 }
225 
226 
get_flo_name(int type,const ftnaddr_t * fa,int fl)227 static char *get_flo_name(int type, const ftnaddr_t *fa, int fl)
228 {
229     char e[] = "elo";
230     char *name = get_outbound_name( type, fa );
231 
232     if ( name ) {
233         switch( fl ) {
234             case F_NORM:
235             case F_REQ:  *e = 'f'; break;
236             case F_DIR:  *e = 'd'; break;
237             case F_CRSH: *e = 'c'; break;
238             case F_HOLD: *e = 'h'; break;
239             case F_IMM:  *e = 'i'; break;
240         }
241         xstrcat( name, e, MAX_PATH );
242     }
243 
244     return name;
245 }
246 
247 
get_req_name(int type,const ftnaddr_t * fa)248 static char *get_req_name(int type, const ftnaddr_t *fa)
249 {
250     char *name = get_outbound_name( type, fa );
251 
252     if ( name )
253         xstrcat( name, "req", MAX_PATH );
254 
255     return name;
256 }
257 
258 
get_busy_name(int type,const ftnaddr_t * fa,char b)259 static char *get_busy_name(int type, const ftnaddr_t *fa, char b)
260 {
261     char bn[] = "esy";
262     char *name = get_outbound_name( type, fa );
263 
264     if ( name ) {
265         *bn = b;
266         xstrcat( name, bn, MAX_PATH );
267     }
268 
269     return name;
270 }
271 
272 
get_status_name(const ftnaddr_t * fa)273 static char *get_status_name(const ftnaddr_t *fa)
274 {
275     if ( sts_base ) {
276         snprintf( out_internal_tmp, MAX_PATH, "%s/%d.%d.%d.%d.qst", sts_base, fa->z, fa->n, fa->f, fa->p);
277         return out_internal_tmp;
278     }
279     return NULL;
280 }
281 
282 
out_scan_flo(const char * flo_name,const ftnaddr_t * addr)283 static void out_scan_flo(const char *flo_name, const ftnaddr_t *addr)
284 {
285 	size_t len = strlen( flo_name );
286 
287 	DEBUG(('S',3,"out_scan_flo: flo_name == '%s'", flo_name));
288 	if ( !strcasecmp( (char *) (flo_name + len - 2), "lo" ))
289 		(*_each)( flo_name, addr, T_ARCMAIL, outbound_flavor( flo_name[len - 3] ), _rslow );
290 	else if ( !strcasecmp( (char *) (flo_name + len - 2), "ut" ))
291 		(*_each)( flo_name, addr, T_NETMAIL, outbound_flavor( flo_name[len - 3] ), _rslow );
292 	else if ( !strcasecmp( (char *) (flo_name + len - 3), "req" ))
293 		(*_each)( flo_name, addr, T_REQ, F_REQ, _rslow );
294 }
295 
296 
297 /*
298  * Returns whether the directory entry is an ASO file.
299  */
aso_select(const char * d_name)300 static int aso_select(const char *d_name)
301 {
302 	size_t	len;
303 	char	**p;
304 
305 	DEBUG(('S',3,"aso_select: '%s'",d_name));
306 
307 	if ( *d_name == '.' )
308 		return 0;
309 
310 	if ( strrchr( d_name, '.' ) == NULL )
311 		return 0;
312 
313 	if ( sscanf( d_name, "%u.%u.%u.%u", &len, &len, &len, &len ) != 4 )
314 		return 0;
315 
316 	len = strlen( d_name ) - 4;
317 	for( p = ext_lo; *p; p++ )
318 		if ( !strcasecmp( *p, d_name + len )) {
319 			DEBUG(('S',3,"aso_select: '%s' OK",d_name));
320 			return 1;
321 		}
322 
323 	for( p = ext_ut; *p; p++ )
324 		if ( !strcasecmp( *p, d_name + len )) {
325 			DEBUG(('S',3,"aso_select: '%s' OK",d_name));
326 			return 1;
327 		}
328 
329 	return 0;
330 }
331 
332 
out_aso_rescan(void)333 static int out_aso_rescan(void)
334 {
335 	char	**namelist = NULL;
336 	int	i, n;
337 
338 	if ( aso_base == NULL )
339 		return 0;
340 
341 	DEBUG(('S',4,"out_aso_rescan: aso_base == '%s'", aso_base));
342 
343 	n = qscandir( aso_base, &namelist, 0, aso_select, NULL );
344 	DEBUG(('S',4,"out_aso_rescan: n == %d", n));
345 
346 	if ( n < 0 ) /* Error */
347 		return 0;
348 
349 	for( i = 0; i < n; i++ ) {
350 		char	*f = qbasename( namelist[i] );
351 		int	az, an, af, ap;
352 
353 		if ( sscanf( f, "%u.%u.%u.%u", &az, &an, &af, &ap ) == 4 ) {
354 
355 			FTNADDR_T( a );
356 			a.z = (short) az;
357 			a.n = (short) an;
358 			a.f = (short) af;
359 			a.p = (short) ap;
360 
361 			DEBUG(('S',4,"out_aso_rescan: flo_name == '%s'", namelist[i]));
362 			out_scan_flo( namelist[i], &a );
363 		}
364 		xfree( namelist[i] );
365 	}
366 
367 	xfree( namelist );
368 	return ASO;
369 }
370 
371 
372 /*
373  * Returns whether the directory entry is a BSO file.
374  */
bso_select(const char * d_name)375 static int bso_select(const char *d_name)
376 {
377 	size_t	len;
378 	char	**p;
379 
380 	DEBUG(('S',3,"bso_select: '%s'",d_name));
381 
382 	if ( *d_name == '.' )
383 		return 0;
384 
385 	len = strlen( d_name );
386 	if ( len != 12 )
387 		return 0;
388 
389 	if ( strspn( d_name, "0123456789abcdefABCDEF" ) != 8 )
390 		return 0;
391 
392 	for( p = ext_lo; *p; p++ )
393 		if ( !strcasecmp( *p, &d_name[len - 4] )) {
394 			DEBUG(('S',3,"bso_select: '%s' OK",d_name));
395 			return 1;
396 		}
397 
398 	for( p = ext_ut; *p; p++ )
399 		if ( !strcasecmp( *p, &d_name[len - 4] )) {
400 			DEBUG(('S',3,"bso_select: '%s' OK",d_name));
401 			return 1;
402 		}
403 
404 	return 0;
405 }
406 
407 
408 /*
409  * Returns whether the directory entry is a BSO zone.
410  */
bso_root_select(const char * d_name)411 static int bso_root_select(const char *d_name)
412 {
413 	size_t len = strlen( d_name );
414 
415 	DEBUG(('S',3,"bso_root_select: '%s'",d_name));
416 
417 	if ( *d_name == '.' )
418 		return 0;
419 
420 	if ( strncasecmp( p_domain, d_name, pd_len ) != 0 )
421 		return 0;
422 
423 	if ( len == pd_len ||
424 		( len - 4 == pd_len && strspn( d_name + len - 3, "0123456789abcdefABCDEF" ) == 3 ))
425 	{
426 		DEBUG(('S',3,"bso_root_select: '%s' OK",d_name));
427 		return 1;
428 	}
429 
430 	return 0;
431 }
432 
433 
out_bso_scan_zone(char * zonehold)434 static int out_bso_scan_zone(char *zonehold)
435 {
436 	int		i, j, n;
437 	char		*p = NULL, **namelist = NULL;
438 	FTNADDR_T	( a );
439 
440 	DEBUG(('S',3,"out_bso_scan_zone: %s", zonehold));
441 
442 	n = qscandir( zonehold, &namelist, 0, bso_select, qalphasort );
443 	DEBUG(('S',4,"out_bso_scan_zone: n == %d", n));
444 
445 	if ( n <= 0 ) /* Error */
446 		return 0;
447 
448 	p = strrchr( zonehold, '.' );
449 	if ( p != NULL) {
450 		sscanf( p, ".%03x", &i );
451 		a.z = (short) i;
452 	} else
453 		a.z = bso_defzone;
454 
455 	for( i = 0; i < n; i++ ) {
456 		int	an, af;
457 
458 		p = qbasename( namelist[i] );
459 		sscanf( p, "%04x%04x", &an, &af );
460 
461 		a.n = (short) an;
462 		a.f = (short) af;
463 		a.p = 0;
464 
465 		DEBUG(('S',4,"out_bso_scan_zone: i == %d, lo == '%s'", i, namelist[i]));
466 		DEBUG(('S',4,"out_bso_scan_zone: %d:%d/%d.%d", a.z, a.n, a.f, a.p));
467 
468 		if ( !strcasecmp( p + 8, ".pnt" )) {
469 			char	**namelist_pnt = NULL;
470 			int	points;
471 
472 			points = qscandir( namelist[i], &namelist_pnt, 0, bso_select, qalphasort );
473 			DEBUG(('S',4,"out_bso_scan_zone: points %d", points));
474 
475 			if ( points >= 0 ) {
476 				if ( points == 0 ) {
477 					DEBUG(('S',4,"out_bso_scan_zone: remove empty points dir'%s'", namelist[i]));
478 					rmdir( namelist[i] );
479 				} else {
480 					for( j = 0; j < points; j++ ) {
481 						int	ap;
482 
483 						p = qbasename( namelist_pnt[j] );
484 
485 						sscanf( p + 4, "%04x", &ap );
486 						a.p = (short) ap;
487 						DEBUG(('S',4,"out_bso_scan_zone: point %d:%d/%d.%d", a.z, a.n, a.f, a.p));
488 						DEBUG(('S',4,"out_bso_scan_zone: flo '%s'", namelist_pnt[j]));
489 						out_scan_flo( namelist_pnt[j], &a );
490 						xfree( namelist_pnt[j] );
491 					}
492 					xfree( namelist_pnt );
493 				}
494 			}
495 		} else {
496 			out_scan_flo( namelist[i], &a );
497 		}
498 
499 		xfree( namelist[i] );
500 	}
501 
502 	xfree( namelist );
503 	return 1;
504 }
505 
506 
out_bso_rescan(void)507 static int out_bso_rescan(void)
508 {
509 	int	i, n;
510 	char	**namelist = NULL;
511 
512 	if ( bso_base == NULL )
513 		return 0;
514 
515 	DEBUG(('S',4,"out_bso_rescan: bso_base == '%s', p_domain == '%s'", bso_base, p_domain));
516 
517 	/* Scan the root and find all outbound directory */
518 	n = qscandir( bso_base, &namelist, 0, bso_root_select, qalphasort );
519 	DEBUG(('S',4,"out_bso_rescan: n == %d", n));
520 
521 	if ( n < 0 )
522 		return 0;
523 
524 	/* For each directory found do recursive rescan */
525 	for( i = 0; i < n; i++ ) {
526 		DEBUG(('S',4,"out_bso_rescan: namelist[%d] == '%s'", i, namelist[i]));
527 		out_bso_scan_zone( namelist[i] );
528 		xfree( namelist[i] );
529 	}
530 
531 	xfree( namelist );
532 	return BSO;
533 }
534 
535 
outbound_rescan(qeach_t each,int rslow)536 int outbound_rescan(qeach_t each, int rslow)
537 {
538 	int rc = 0;
539 
540 	_each = each;
541 	_rslow = rslow;
542 
543 	rc |= out_aso_rescan();
544 	rc |= out_bso_rescan();
545 
546 	return rc;
547 }
548 
549 
out_lock(int type,const ftnaddr_t * adr,int l)550 static int out_lock(int type, const ftnaddr_t *adr, int l)
551 {
552 	char *obn = get_busy_name( type, adr, 'b' );
553 
554 	if ( !obn )
555 		return 0;
556 
557 	mkdirs( obn );
558 
559 	if ( islocked( obn ))
560 		return 0;
561 
562 	if ( l == LCK_s )
563 		return lockpid( obn );
564 
565 	if ( l == LCK_t )
566 		return getpid();
567 
568 	if ( islocked( get_busy_name( type, adr, 'c' )))
569 		return 0;
570 
571 	return lockpid( out_internal_tmp );
572 }
573 
574 
575 /*
576  * Returns whether the address is busy. 0 == free, 1 == busy.
577  */
outbound_addr_busy(const ftnaddr_t * addr)578 int outbound_addr_busy(const ftnaddr_t *addr)
579 {
580 	if ( islocked( get_busy_name( ASO, addr, 'b' )))
581 		return 1;
582 
583 	if ( islocked( get_busy_name( ASO, addr, 'c' )))
584 		return 1;
585 
586 	if ( islocked( get_busy_name( BSO, addr, 'b' )))
587 		return 1;
588 
589 	if ( islocked( get_busy_name( BSO, addr, 'c' ) ))
590 		return 1;
591 
592 	return 0;
593 }
594 
595 
outbound_locknode(const ftnaddr_t * addr,int l)596 int outbound_locknode(const ftnaddr_t *addr, int l)
597 {
598 	int rc = 0;
599 
600 	if ( aso_base && out_lock( ASO, addr, l ))
601 		rc |= ASO;
602 
603 	if ( bso_base && out_lock( BSO, addr, l ))
604 		rc |= BSO;
605 
606 	return rc;
607 }
608 
609 
outbound_unlocknode(const ftnaddr_t * addr,int l)610 int outbound_unlocknode(const ftnaddr_t *addr, int l)
611 {
612 	if ( l == LCK_t )
613 		return 1;
614 
615 	if ( aso_base ) {
616 		if ( get_busy_name( ASO, addr, 'b' ))
617 			lunlink( out_internal_tmp );
618 
619 		if ( get_busy_name( ASO, addr, 'c' ))
620 			lunlink( out_internal_tmp );
621 	}
622 
623 	if ( bso_base ) {
624 		if ( get_busy_name( BSO, addr, 'b' ))
625 			lunlink( out_internal_tmp );
626 
627 		if ( get_busy_name( BSO, addr, 'c' ))
628 			lunlink( out_internal_tmp );
629 
630 		if ( addr->z != bso_defzone )
631 			rmdirs( out_internal_tmp );
632 		else if ( addr->p ) {
633 			rmdir( out_internal_tmp );
634 		}
635 	}
636 
637 	return 1;
638 }
639 
640 
outbound_flavor(char fl)641 int outbound_flavor(char fl)
642 {
643 	switch( tolower( fl )) {
644 	case 'h': return F_HOLD;
645 	case 'f':
646 	case 'n':
647 	case 'o': return F_NORM;
648 	case 'd': return F_DIR;
649 	case 'c': return F_CRSH;
650 	case 'i': return F_IMM;
651 	case 'r': return F_REQ;
652 	}
653 	return F_ERR;
654 }
655 
656 
outbound_attach(const ftnaddr_t * addr,int flv,slist_t * files)657 int outbound_attach(const ftnaddr_t *addr, int flv, slist_t *files)
658 {
659 	FILE *f = NULL;
660 
661 	if ( bso_base )
662 		f = mdfopen( get_flo_name( BSO, addr, flv ), "at" );
663 	if ( !f && aso_base )
664 		f = mdfopen( get_flo_name( ASO, addr, flv ), "at" );
665 	if ( f ) {
666 		slist_t *fl;
667 
668 		for( fl = files; fl; fl = fl->next )
669 			fprintf( f, "%s\n", fl->str );
670 		fclose( f );
671 		return 1;
672 	}
673 	return 0;
674 }
675 
676 
outbound_request(const ftnaddr_t * addr,slist_t * files)677 int outbound_request(const ftnaddr_t *addr, slist_t *files)
678 {
679 	FILE *f = NULL;
680 
681 	if ( bso_base )
682 		f = mdfopen( get_req_name( BSO, addr ), "at" );
683 	if ( !f && aso_base )
684 		f = mdfopen( get_req_name( ASO, addr ), "at" );
685 	if ( f ) {
686 		slist_t *fl;
687 
688 		for( fl = files; fl; fl = fl->next )
689 			fprintf( f, "%s\r\n", fl->str );
690 		fclose( f );
691 		return 1;
692 	}
693 	return 0;
694 }
695 
696 
outbound_poll(const ftnaddr_t * fa,int flavor)697 int outbound_poll(const ftnaddr_t *fa, int flavor)
698 {
699 	if ( flavor == F_ERR ) {
700 		char *pf = cfgs( CFG_POLLFLAVOR );
701 		flavor = outbound_flavor( *pf );
702 	}
703 	return outbound_attach( fa, flavor, NULL );
704 }
705 
706 
outbound_setstatus(const ftnaddr_t * fa,sts_t * st)707 int outbound_setstatus(const ftnaddr_t *fa, sts_t *st)
708 {
709 	FILE *f;
710 	char *name = get_status_name( fa );
711 
712 	if((f = mdfopen( name, "wt" ))) {
713 		fprintf( f, "%d %d %lu %lu", st->try, st->flags, st->htime, st->utime );
714 		if ( st->bp.name && st->bp.flags )
715 			fprintf( f, " %d %d %lu %s", st->bp.flags, st->bp.size, st->bp.time, st->bp.name );
716 		fclose( f );
717 		return 1;
718 	}
719 	return 0;
720 }
721 
722 
outbound_getstatus(const ftnaddr_t * fa,sts_t * st)723 int outbound_getstatus(const ftnaddr_t *fa, sts_t *st)
724 {
725 	int rc;
726 	FILE *f;
727 	char *name = get_status_name( fa );
728 	char tmp[MAX_PATH + 5];
729 
730 	tmp[0] = '\0';
731 
732 	if ( name ) {
733 		if ((f = fopen( name, "rt" ))) {
734 			rc = fscanf( f, "%d %d %lu %lu %d %d %lu %s",
735 				&st->try, &st->flags,
736 				(unsigned long*) &st->htime,
737 				(unsigned long*) &st->utime,
738 				&st->bp.flags, (int*) &st->bp.size,
739 				(unsigned long*) &st->bp.time,
740 				tmp );
741 			fclose( f );
742 
743 			if ( rc < 8 )
744 				memset( &st->bp, 0, sizeof( st->bp ));
745 			else if ( *tmp )
746 				st->bp.name = xstrdup( tmp );
747 
748 			if ( rc == 4 || rc == 8 )
749 				return 1;
750 			write_log( "status file %s corrupted", name );
751         		xfree( st->bp.name );
752 		}
753 	}
754 	memset( st, 0, sizeof( sts_t ));
755 	return 0;
756 }
757 
758 
floflist(flist_t ** fl,char * flon)759 static void floflist(flist_t **fl, char *flon)
760 {
761     FILE *f;
762     off_t off;
763     char *p, str[MAX_PATH + 5], *m, *map = cfgs(CFG_MAPOUT), *fp, *fn;
764     struct stat sb;
765 
766     DEBUG(('S',2,"Add LO '%s'",flon));
767     if(!stat(flon, &sb))if((f=fopen(flon,"r+b"))) {
768         off = ftello( f );
769         while(fgets(str,MAX_PATH,f)) {
770             p=strrchr(str,'\r');
771             if(!p)p=strrchr(str,'\n');
772             if(p)*p=0;
773             if(!*str)continue;
774             p=str;
775             switch(*p) {
776                 case '~':
777                     break;
778 
779                 case '^': /* kill */
780                 case '#': /* trunc */
781                 case ' ': /* filename starting with directive */
782                     p++;
783 
784                 default:
785                     if (( m = mappath( p )) && *m )
786                         p = m;
787                     fp = xstrdup( p );
788                     m = qbasename( fp );
789                     if ( map && strchr( map, 'L' ))
790                         strlwr( m );
791                     else if( map && strchr( map, 'U' ))
792                         strupr( m );
793                     fn = qbasename( p );
794                     mapname( fn, map, MAX_PATH - ( fn - str ) - 1 );
795                     addflist( fl, fp, xstrdup( fn ), str[0], off, f, 1 );
796                     if( !stat( fp, &sb )) {
797                         totalf += sb.st_size;
798                         totaln++;
799                     }
800             }
801             off = ftello( f );
802         }
803         addflist( fl, xstrdup( flon ), NULL, '^', -1, f, 1 );
804     }
805 }
806 
807 
asoflist(flist_t ** fl,const ftnaddr_t * fa,int mode)808 int asoflist(flist_t **fl, const ftnaddr_t *fa, int mode)
809 {
810 	struct stat	sb;
811 	char		str[MAX_PATH + 5];
812 	int		fls[] = { F_IMM, F_CRSH, F_DIR, F_NORM, F_HOLD }, i;
813 
814 #if 0
815 	unsigned long	_tm = totalm, _tn = totaln, _tf = totalf;
816 
817 	DEBUG(('S',2,"asoflist exp in: m %ld, n %ld, f %ld",totalm,totaln,totalf));
818 	{
819 	char *name = NULL, **flolist = NULL;
820 	int t;
821 
822 	if ( bso_base && ( name = get_outbound_name( BSO, fa ))) {
823 		int flo_count = fmatchcase( name, &flolist ), i;
824 
825 		DEBUG(('S',3,"asoflist: bso name '%s",name));
826 		DEBUG(('S',3,"asoflist: bso count %d",flo_count));
827 		for( i = 0; flo_count && i < flo_count; i++ ) {
828 			t = whattype( flolist[i] );
829 			DEBUG(('S',4,"asoflist: type %d, flo '%s'",t,flolist[i]));
830 			switch( t ) {
831 			case IS_PKT:
832 				snprintf( str, MAX_PATH, "%08lx.pkt", sequencer());
833 				totalm += sb.st_size;
834 				break;
835 
836 			case IS_REQ:
837 				snprintf( str, MAX_PATH, "%04x%04x.req", fa->n, fa->f );
838 				totalf += sb.st_size;
839 				break;
840 
841 			case IS_FLO:
842 				floflist( fl, flolist[i] );
843                                 /* Fall through */
844 
845 			default:
846 				t = IS_ERR;
847 			}
848 
849 			if ( t != IS_ERR ) {
850 				addflist( fl, xstrdup( flolist[i] ), xstrdup( str ), '^', 0, NULL, 0 );
851 				totaln++;
852 			}
853 			xfree( flolist[i] );
854 		}
855 		if ( flo_count > 0 )
856 			xfree( flolist );
857 	}
858         }
859 	DEBUG(('S',2,"asoflist exp out: m %ld, n %ld, f %ld",totalm,totaln,totalf));
860 
861         totalm = _tm;
862         totaln = _tn;
863         totalf = _tf;
864 #endif
865 
866 	/* pkt files */
867 	for ( i = 0; i < 5; i++ ) {
868 		char *name = NULL;
869 
870 		if ( bso_base && ( name = get_pkt_name( BSO, fa, fls[i] ))) {
871 			if ( !stat( name, &sb )) {
872 				snprintf( str, MAX_PATH, "%08lx.pkt", sequencer() );
873 				addflist( fl, xstrdup( name ), xstrdup( str ), '^', 0, NULL, 0 );
874 				totalm += sb.st_size;
875 				totaln++;
876 			}
877 		}
878 
879 		if ( aso_base && ( name = get_pkt_name( ASO, fa, fls[i] ))) {
880 			if ( !stat( name, &sb )) {
881 				snprintf( str, MAX_PATH, "%08lx.pkt", sequencer() );
882 				addflist( fl, xstrdup( name ), xstrdup( str ), '^', 0, NULL, 0);
883 				totalm += sb.st_size;
884 				totaln++;
885 			}
886 		}
887 	}
888 
889 	/* file requests */
890 	snprintf( str, MAX_PATH, "%04x%04x.req", fa->n, fa->f );
891 	{
892 		char *name = get_req_name( BSO, fa );
893 
894 		if ( bso_base && name && !stat( name, &sb )) {
895 			addflist( fl, xstrdup( name ), xstrdup( str ), ' ', 0, NULL, 1);
896 			totalf += sb.st_size;
897 			totaln++;
898 		}
899 
900 		name = get_req_name( ASO, fa );
901 
902 		if ( aso_base && name && !stat( name, &sb )) {
903 			addflist( fl, xstrdup( name ), xstrdup( str ), ' ', 0, NULL, 1);
904 			totalf += sb.st_size;
905 			totaln++;
906 		}
907 	}
908 
909 	/* flow files */
910 	for( i = 0; i < ( 5 - (( cfgi( CFG_HOLDOUT ) == 1) && mode )); i++) {
911 		char *name = NULL;
912 
913 		if ( bso_base && (name = get_flo_name( BSO, fa, fls[i] )))
914 			floflist( fl, name );
915 		if ( aso_base && (name = get_flo_name( ASO, fa, fls[i] )))
916 			floflist( fl, name );
917 	}
918 	return 0;
919 }
920