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