1 /*
2  *	binkleyforce -- unix FTN mailer project
3  *
4  *	Copyright (c) 1998-2000 Alexander Belkin, 2:5020/1398.11
5  *
6  *	This program is free software; you can redistribute it and/or modify
7  *	it under the terms of the GNU General Public License as published by
8  *	the Free Software Foundation; either version 2 of the License, or
9  *	(at your option) any later version.
10  *
11  *	$Id: outb_bsy.c,v 1.1.1.1 2004/09/09 09:52:38 kstepanenkov Exp $
12  */
13 
14 #include "includes.h"
15 #include "confread.h"
16 #include "logger.h"
17 #include "util.h"
18 #include "outbound.h"
19 
20 typedef struct bsylist {
21 	s_faddr addr;
22 	char *name_4d;
23 	char *name_domain;
24 	char *name_amiga;
25 	struct bsylist *next;
26 #ifdef BFORCE_USE_CSY
27 	bool is_csy;
28 #endif
29 } s_bsylist;
30 
31 s_bsylist *bsylist = NULL;
32 
33 static int out_bsy_convert_csy_to_bsy(s_bsylist *ptrl);
34 
35 /* ========================================================================= */
36 /* PRIVATE part                                                              */
37 /* ========================================================================= */
38 
out_bsy_file_check(const char * name,const char * ext)39 static int out_bsy_file_check(const char *name, const char *ext)
40 {
41 	char lockname[BFORCE_MAX_PATH+1];
42 
43 	ASSERT(name != NULL && ext != NULL);
44 
45 	strnxcpy(lockname, name, sizeof(lockname));
46 	strnxcat(lockname, ext, sizeof(lockname));
47 
48 	return plock_check(lockname);
49 }
50 
out_bsy_file_create(const char * name,const char * ext)51 static int out_bsy_file_create(const char *name, const char *ext)
52 {
53 	char lockname[BFORCE_MAX_PATH+1];
54 
55 	ASSERT(name != NULL && ext != NULL);
56 
57 	strnxcpy(lockname, name, sizeof(lockname));
58 	strnxcat(lockname, ext, sizeof(lockname));
59 
60 	return plock_create(lockname);
61 }
62 
out_bsy_file_link(const char * oldname,const char * oldext,const char * newname,const char * newext)63 static int out_bsy_file_link(const char *oldname, const char *oldext,
64                              const char *newname, const char *newext)
65 {
66 	char old_lockname[BFORCE_MAX_PATH+1];
67 	char new_lockname[BFORCE_MAX_PATH+1];
68 
69 	ASSERT(oldname != NULL && oldext != NULL);
70 	ASSERT(newname != NULL && newext != NULL);
71 
72 	strnxcpy(old_lockname, oldname, sizeof(old_lockname));
73 	strnxcat(old_lockname, oldext, sizeof(old_lockname));
74 	strnxcpy(new_lockname, newname, sizeof(new_lockname));
75 	strnxcat(new_lockname, newext, sizeof(new_lockname));
76 
77 	return plock_link(new_lockname, old_lockname);
78 }
79 
out_bsy_file_unlink(const char * name,const char * ext)80 static int out_bsy_file_unlink(const char *name, const char *ext)
81 {
82 	char lockname[BFORCE_MAX_PATH+1];
83 
84 	ASSERT(name != NULL && ext != NULL);
85 
86 	strnxcpy(lockname, name, sizeof(lockname));
87 	strnxcat(lockname, ext, sizeof(lockname));
88 
89 	return plock_remove(lockname);
90 }
91 
92 /* ========================================================================= */
93 /* PUBLIC part                                                               */
94 /* ========================================================================= */
95 
out_bsy_check(s_faddr addr)96 int out_bsy_check(s_faddr addr)
97 {
98 	bool isfailed = FALSE;
99 	char *name_4d = NULL;
100 	char *name_domain = NULL;
101 	char *name_amiga = NULL;
102 
103 	name_4d     = out_getname_4d(addr);
104 	name_domain = out_getname_domain(addr);
105 	name_amiga  = out_getname_amiga(addr);
106 
107 	DEB((D_OUTBOUND, "out_bsy_check: name_4d = \"%s\"", name_4d));
108 	DEB((D_OUTBOUND, "out_bsy_check: name_domain = \"%s\"", name_domain));
109 	DEB((D_OUTBOUND, "out_bsy_check: name_amiga = \"%s\"", name_amiga));
110 
111 	/* Check for BSY files in all outbounds */
112 	if( (name_4d     && out_bsy_file_check(name_4d, ".bsy") == PLOCK_EXIST)
113 	 || (name_domain && out_bsy_file_check(name_domain, ".bsy") == PLOCK_EXIST)
114 	 || (name_amiga  && out_bsy_file_check(name_amiga, ".bsy") == PLOCK_EXIST) )
115 		isfailed = TRUE;
116 
117 #ifdef BFORCE_USE_CSY
118 	if( !isfailed )
119 	{
120 		/* Check for CSY files in all outbounds */
121 		if( (name_4d     && out_bsy_file_check(name_4d, ".csy") == PLOCK_EXIST)
122 		 || (name_domain && out_bsy_file_check(name_domain, ".csy") == PLOCK_EXIST)
123 		 || (name_amiga  && out_bsy_file_check(name_amiga, ".csy") == PLOCK_EXIST) )
124 			isfailed = TRUE;
125 	}
126 #endif
127 
128 	if( name_4d )
129 		free(name_4d);
130 	if( name_domain )
131 		free(name_domain);
132 	if( name_amiga )
133 		free(name_amiga);
134 
135 	return isfailed ? -1 : 0;
136 }
137 
138 #ifdef BFORCE_USE_CSY
out_bsy_lock(s_faddr addr,bool csy_locks)139 int out_bsy_lock(s_faddr addr, bool csy_locks)
140 #else
141 int out_bsy_lock(s_faddr addr)
142 #endif
143 {
144 	char *name_4d = NULL;
145 	char *name_domain = NULL;
146 	char *name_amiga = NULL;
147 	bool locked_4d = FALSE;
148 	bool locked_domain = FALSE;
149 	bool locked_amiga = FALSE;
150 	s_bsylist bsytmp, **bsylst;
151 	bool isfailed = FALSE;
152 #ifdef DEBUG
153 	char abuf[BF_MAXADDRSTR+1];
154 #endif
155 #ifdef BFORCE_USE_CSY
156 	const char *lockext = csy_locks ? ".csy" : ".bsy";
157 #else
158 	const char *lockext = ".bsy";
159 #endif
160 
161 	DEB((D_OUTBOUND, "out_bsy_lock: lock address %s",
162 		ftn_addrstr(abuf, addr)));
163 
164 	/*
165 	 * Check, may be we've allready locked this address.
166 	 */
167 	for( bsylst = &bsylist; *bsylst; bsylst = &(*bsylst)->next )
168 	{
169 		if( !ftn_addrcomp((*bsylst)->addr, addr) )
170 		{
171 			DEB((D_OUTBOUND, "out_bsy_lock: address is allready locked"));
172 #ifdef BFORCE_USE_CSY
173 			if( (*bsylst)->is_csy && !csy_locks )
174 				return out_bsy_convert_csy_to_bsy(*bsylst);
175 #else
176 			return 0;
177 #endif
178 		}
179 	}
180 
181 	name_4d     = out_getname_4d(addr);
182 	name_domain = out_getname_domain(addr);
183 	name_amiga  = out_getname_amiga(addr);
184 
185 	DEB((D_OUTBOUND, "out_bsy_lock: name_4d = \"%s\"", name_4d));
186 	DEB((D_OUTBOUND, "out_bsy_lock: name_domain = \"%s\"", name_domain));
187 	DEB((D_OUTBOUND, "out_bsy_lock: name_amiga = \"%s\"", name_amiga));
188 
189 	/* Check for BSY files in all outbounds */
190 	if( (name_4d     && out_bsy_file_check(name_4d, ".bsy") == PLOCK_EXIST)
191 	 || (name_domain && out_bsy_file_check(name_domain, ".bsy") == PLOCK_EXIST)
192 	 || (name_amiga  && out_bsy_file_check(name_amiga, ".bsy") == PLOCK_EXIST) )
193 		isfailed = TRUE;
194 
195 #ifdef BFORCE_USE_CSY
196 	if( !isfailed )
197 	{
198 		/* Check for CSY files in all outbounds */
199 		if( (name_4d     && out_bsy_file_check(name_4d, ".csy") == PLOCK_EXIST)
200 		 || (name_domain && out_bsy_file_check(name_domain, ".csy") == PLOCK_EXIST)
201 		 || (name_amiga  && out_bsy_file_check(name_amiga, ".csy") == PLOCK_EXIST) )
202 			isfailed = TRUE;
203 	}
204 #endif
205 
206 	DEB((D_OUTBOUND, "out_bsy_lock: lock check result: %s",
207 		isfailed ? "Locked" : "Not locked"));
208 
209 	/* Create ?SY file in 4D outbound */
210 	if( !isfailed && name_4d )
211 	{
212 		switch( out_bsy_file_create(name_4d, lockext) ) {
213 		case PLOCK_OK:	locked_4d = TRUE; break;
214 		case PLOCK_EXIST:	isfailed = TRUE; break;
215 		case PLOCK_ERROR:	locked_4d = FALSE; break;
216 		}
217 	}
218 
219 	/* Create ?SY file in domain outbound */
220 	if( !isfailed && name_domain )
221 	{
222 		switch( out_bsy_file_create(name_domain, lockext) ) {
223 		case PLOCK_OK:	locked_domain = TRUE; break;
224 		case PLOCK_EXIST:	isfailed = TRUE; break;
225 		case PLOCK_ERROR:	locked_domain = FALSE; break;
226 		}
227 	}
228 
229 	/* Create ?SY file in "AmigaDos" outbound */
230 	if( !isfailed && name_amiga )
231 	{
232 		switch( out_bsy_file_create(name_amiga, lockext) ) {
233 		case PLOCK_OK:	locked_amiga = TRUE; break;
234 		case PLOCK_EXIST:	isfailed = TRUE; break;
235 		case PLOCK_ERROR:	locked_amiga = FALSE; break;
236 		}
237 	}
238 
239 #ifdef BFORCE_USE_CSY
240 	if( !isfailed )
241 	{
242 		/* Check for BSY files in all outbounds */
243 		if( (name_4d     && out_bsy_file_check(name_4d, ".bsy") == PLOCK_EXIST)
244 		 || (name_domain && out_bsy_file_check(name_domain, ".bsy") == PLOCK_EXIST)
245 		 || (name_amiga  && out_bsy_file_check(name_amiga, ".bsy") == PLOCK_EXIST) )
246 			isfailed = TRUE;
247 	}
248 #endif
249 
250 	DEB((D_OUTBOUND, "out_bsy_lock: lock create result: %s",
251 		isfailed ? "Failed" : "Successful"));
252 
253 	/* Somebody else create BSY before us?! */
254 	if( isfailed )
255 	{
256 		if( locked_4d )
257 			out_bsy_file_unlink(name_4d, lockext);
258 		if( locked_domain )
259 			out_bsy_file_unlink(name_domain, lockext);
260 		if( locked_amiga )
261 			out_bsy_file_unlink(name_amiga, lockext);
262 
263 		if( name_4d )
264 			free(name_4d);
265 		if( name_domain )
266 			free(name_domain);
267 		if( name_amiga )
268 			free(name_amiga);
269 
270 		return -1;
271 	}
272 
273 	/*
274 	 * Successful locking. Add new entry to the ``bsylist''.
275 	 */
276 
277 	memset(&bsytmp, '\0', sizeof(s_bsylist));
278 
279 	bsytmp.addr = addr;
280 
281 #ifdef BFORCE_USE_CSY
282 	bsytmp.is_csy = csy_locks;
283 #endif
284 
285 	if( locked_4d )
286 		bsytmp.name_4d = name_4d;
287 	if( locked_domain )
288 		bsytmp.name_domain = name_domain;
289 	if( locked_amiga )
290 		bsytmp.name_amiga = name_amiga;
291 
292 	for( bsylst = &bsylist; *bsylst; bsylst = &(*bsylst)->next )
293 	{
294 		/* EMPTY LOOP */
295 	}
296 
297 	(*bsylst) = (s_bsylist*)xmalloc(sizeof(s_bsylist));
298 	**bsylst = bsytmp;
299 
300 	return 0;
301 }
302 
out_bsy_unlockall(void)303 int out_bsy_unlockall(void)
304 {
305 	s_bsylist *ptrl, *next;
306 #ifdef DEBUG
307 	char abuf[BFORCE_MAX_ADDRSTR+1];
308 #endif
309 
310 	for( ptrl = bsylist; ptrl; ptrl = next )
311 	{
312 #ifdef BFORCE_USE_CSY
313 		const char *lockext = ptrl->is_csy ? ".csy" : ".bsy";
314 #else
315 		const char *lockext = ".bsy";
316 #endif
317 		next = ptrl->next;
318 
319 		DEB((D_OUTBOUND, "out_bsy_unlockall: unlock address %s",
320 			ftn_addrstr(abuf, ptrl->addr)));
321 
322 		if( ptrl->name_4d )
323 		{
324 			out_bsy_file_unlink(ptrl->name_4d, lockext);
325 			free(ptrl->name_4d);
326 		}
327 
328 		if( ptrl->name_domain )
329 		{
330 			out_bsy_file_unlink(ptrl->name_domain, lockext);
331 			free(ptrl->name_domain);
332 		}
333 
334 		if( ptrl->name_amiga )
335 		{
336 			out_bsy_file_unlink(ptrl->name_amiga, lockext);
337 			free(ptrl->name_amiga);
338 		}
339 
340 		free(ptrl);
341 	}
342 
343 	bsylist = NULL;
344 
345 	return 0;
346 }
347 
348 #ifdef BFORCE_USE_CSY
out_bsy_convert_csy_to_bsy(s_bsylist * ptrl)349 static int out_bsy_convert_csy_to_bsy(s_bsylist *ptrl)
350 {
351 	bool locked_4d = FALSE;
352 	bool locked_domain = FALSE;
353 	bool locked_amiga = FALSE;
354 	bool isfailed = FALSE;
355 #ifdef DEBUG
356 	char abuf[BF_MAXADDRSTR+1];
357 #endif
358 
359 	DEB((D_OUTBOUND, "out_bsy_convert_csy_to_bsy: process address %s",
360 		ftn_addrstr(abuf, ptrl->addr)));
361 
362 	if( !ptrl->is_csy )
363 	{
364 		DEB((D_OUTBOUND, "out_bsy_convert_csy_to_bsy: skip (no csy locks)"));
365 		return 0;
366 	}
367 
368 #define LINK_CSY_TO_BSY(lockname) \
369 	out_bsy_file_link(lockname, ".csy", lockname, ".bsy")
370 
371 	/* Create BSY file in 4D outbound */
372 	if( !isfailed && ptrl->name_4d )
373 	{
374 		switch( LINK_CSY_TO_BSY(ptrl->name_4d) ) {
375 		case PLOCK_OK:	locked_4d = TRUE; break;
376 		case PLOCK_EXIST:	isfailed = TRUE; break;
377 		case PLOCK_ERROR:	locked_4d = FALSE; break;
378 		}
379 	}
380 
381 	/* Create BSY file in domain outbound */
382 	if( !isfailed && ptrl->name_domain )
383 	{
384 		switch( LINK_CSY_TO_BSY(ptrl->name_domain) ) {
385 		case PLOCK_OK:	locked_domain = TRUE; break;
386 		case PLOCK_EXIST:	isfailed = TRUE; break;
387 		case PLOCK_ERROR:	locked_domain = FALSE; break;
388 		}
389 	}
390 
391 	/* Create BSY file in "AmigaDos" outbound */
392 	if( !isfailed && ptrl->name_amiga )
393 	{
394 		switch( LINK_CSY_TO_BSY(ptrl->name_amiga) ) {
395 		case PLOCK_OK:	locked_amiga = TRUE; break;
396 		case PLOCK_EXIST:	isfailed = TRUE; break;
397 		case PLOCK_ERROR:	locked_amiga = FALSE; break;
398 		}
399 	}
400 
401 	DEB((D_OUTBOUND, "out_csy_to_bsy: lock create result: %s",
402 		isfailed ? "Failed" : "Successful"));
403 
404 	/* Somebody else create BSY before us?! */
405 	if( isfailed )
406 	{
407 		if( locked_4d )
408 			out_bsy_file_unlink(ptrl->name_4d, ".bsy");
409 		if( locked_domain )
410 			out_bsy_file_unlink(ptrl->name_domain, ".bsy");
411 		if( locked_amiga )
412 			out_bsy_file_unlink(ptrl->name_amiga, ".bsy");
413 
414 		/* Leave ``.csy'' files untouched! */
415 
416 		return 1;
417 	}
418 
419 	ptrl->is_csy = FALSE;
420 
421 	return 0;
422 }
423 #endif /* BFORCE_USE_CSY */
424 
425