1 /*:ts=8*/
2 /*****************************************************************************
3 * FIDOGATE --- Gateway UNIX Mail/News <-> FTN NetMail/EchoMail
4 *
5 * $Id: flo.c,v 4.14 2004/08/22 20:19:11 n0ll Exp $
6 *
7 * Functions for handling BinkleyTerm-style FLO files
8 *
9 *****************************************************************************
10 * Copyright (C) 1990-2004
11 * _____ _____
12 * | |___ | Martin Junius <mj.at.n0ll.dot.net>
13 * | | | | | | Radiumstr. 18
14 * |_|_|_|@home| D-51069 Koeln, Germany
15 *
16 * This file is part of FIDOGATE.
17 *
18 * FIDOGATE is free software; you can redistribute it and/or modify it
19 * under the terms of the GNU General Public License as published by the
20 * Free Software Foundation; either version 2, or (at your option) any
21 * later version.
22 *
23 * FIDOGATE is distributed in the hope that it will be useful, but
24 * WITHOUT ANY WARRANTY; without even the implied warranty of
25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
26 * General Public License for more details.
27 *
28 * You should have received a copy of the GNU General Public License
29 * along with FIDOGATE; see the file COPYING. If not, write to the Free
30 * Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
31 *****************************************************************************/
32
33 #include "fidogate.h"
34
35
36 /*
37 * Static vars holding data for flo_xxxx() functions
38 */
39 static char flo_name[MAXPATH]; /* File name */
40 static FILE *flo_fp = NULL; /* File stream */
41 static long flo_off_cur = -1; /* Offset beginning of current line
42 * (last one read by flo_gets()) */
43 static long flo_off_next = -1; /* Offset beginning of next line */
44
45
46
47 /*
48 * Return FLO file pointer
49 */
flo_file(void)50 FILE *flo_file(void)
51 {
52 return flo_fp;
53 }
54
55
56
57 /*
58 * Open FLO file for read/write, complete with BSY files and locking
59 */
flo_open(Node * node,int bsy)60 int flo_open(Node *node, int bsy)
61 {
62 return flo_openx(node, bsy, NULL, FALSE);
63 }
64
65
flo_openx(Node * node,int bsy,char * flav,int apmode)66 int flo_openx(Node *node, int bsy, char *flav, int apmode)
67 {
68 char *flo;
69 char *mode;
70
71 mode = apmode ? AP_MODE : RP_MODE;
72
73 /* Find existing or new FLO file */
74 flo = bink_find_flo(node, flav);
75 if(!flo)
76 return ERROR;
77 BUF_COPY(flo_name, flo);
78
79 /* Create directory if necessary */
80 if(bink_mkdir(node) == ERROR)
81 return ERROR;
82
83 /* Create BSY file */
84 if(bsy)
85 if(bink_bsy_create(node, WAIT) == ERROR)
86 return ERROR;
87
88 again:
89 /* Open FLO file for read/write */
90 debug(4, "Opening FLO file, mode=%s", mode);
91 flo_fp = fopen(flo_name, mode);
92 if(flo_fp == NULL)
93 {
94 logit("$opening FLO file %s mode %s failed", flo_name, mode);
95 if(bsy)
96 bink_bsy_delete(node);
97 return ERROR;
98 }
99 chmod(flo_name, FLO_MODE);
100
101 /* Lock it, waiting for lock to be granted */
102 debug(4, "Locking FLO file");
103 if(lock_file(flo_fp))
104 {
105 /* Lock error ... */
106 logit("$locking FLO file %s failed", flo_name);
107 if(bsy)
108 bink_bsy_delete(node);
109 fclose(flo_fp);
110 return ERROR;
111 }
112
113 /* Lock succeeded, but the FLO file may have been deleted */
114 if(access(flo_name, F_OK) == ERROR)
115 {
116 debug(4, "FLO file %s deleted after locking", flo_name);
117 fclose(flo_fp);
118 if(apmode)
119 {
120 if(bsy)
121 bink_bsy_delete(node);
122 goto again;
123 }
124 else
125 return ERROR;
126 }
127
128 debug(4, "FLO file %s open and locking succeeded", flo_name);
129
130 flo_off_cur = -1; /* Nothing read yet */
131 flo_off_next = 0; /* Next line will be the 1st one */
132
133 return OK;
134 }
135
136
137
138 /*
139 * Read entry line from FLO file
140 */
flo_gets(char * s,size_t len)141 char *flo_gets(char *s, size_t len)
142 {
143 long off;
144 char *ret;
145
146 /* Current offset */
147 if( (off = ftell(flo_fp)) == -1 )
148 {
149 logit("$ftell FLO file %s failed", flo_name);
150 return NULL;
151 }
152 flo_off_cur = off;
153
154 /* Read next line */
155 if( ! (ret = fgets(s, len, flo_fp)) )
156 {
157 /* EOF or error */
158 if(ferror(flo_fp))
159 {
160 logit("$reading FLO file %s failed", flo_name);
161 return NULL;
162 }
163 }
164
165 /* New offset == offset of next entry line */
166 if( (off = ftell(flo_fp)) == -1 )
167 {
168 logit("$ftell FLO file %s failed", flo_name);
169 return NULL;
170 }
171 flo_off_next = off;
172
173 /* Remove CR/LF */
174 strip_crlf(s);
175
176 return ret;
177 }
178
179
180
181 /*
182 * Close FLO file
183 */
flo_close(Node * node,int bsy,int del)184 int flo_close(Node *node, int bsy, int del)
185 {
186 int ret = OK;
187
188 if(flo_fp)
189 {
190 if(del)
191 if(unlink(flo_name) == -1)
192 {
193 logit("$removing FLO file %s failed", flo_name);
194 ret = ERROR;
195 }
196 fclose(flo_fp);
197 flo_fp = NULL;
198 }
199
200 if(bsy)
201 bink_bsy_delete(node);
202
203 return ret;
204 }
205
206
207
208 /*
209 * Mark entry line in FLO file as sent
210 */
flo_mark(void)211 int flo_mark(void)
212 {
213 char tilde = '~';
214
215 if(flo_fp==NULL || flo_off_cur==-1 || flo_off_next==-1)
216 return ERROR;
217
218 /* Seek to beginning of line last read */
219 if(fseek(flo_fp, flo_off_cur, SEEK_SET) == -1)
220 {
221 logit("$seeking to offset %ld in FLO file %s failed",
222 flo_off_cur, flo_name);
223 return ERROR;
224 }
225
226 /* Write ~ char */
227 if( fwrite(&tilde, 1, 1, flo_fp) != 1 )
228 {
229 logit("$writing ~ to FLO file %s failed", flo_name);
230 return ERROR;
231 }
232
233 /* Seek to beginning of next line */
234 if(fseek(flo_fp, flo_off_next, SEEK_SET) == -1)
235 {
236 logit("$seeking to offset %ld in FLO file %s failed",
237 flo_off_next, flo_name);
238 return ERROR;
239 }
240
241 return OK;
242 }
243
244
245
246 /*****************************************************************************/
247 #ifdef TEST
248
249 #include "getopt.h"
250
251
252 #define CONFIG DEFAULT_CONFIG_MAIN
253
254
main(int argc,char * argv[])255 int main(int argc, char *argv[])
256 {
257 Node node;
258 int c;
259 char *c_flag=NULL;
260 char *S_flag=NULL, *L_flag=NULL;
261 char mode[] = "-";
262 char *line;
263
264 int option_index;
265 static struct option long_options[] =
266 {
267 { "verbose", 0, 0, 'v'}, /* More verbose */
268 { "config", 1, 0, 'c'}, /* Config file */
269 { "spool-dir", 1, 0, 'S'}, /* Set FIDOGATE spool directory */
270 { "lib-dir", 1, 0, 'L'}, /* Set FIDOGATE lib directory */
271 { 0, 0, 0, 0 }
272 };
273
274 /* Init configuration */
275 cf_initialize();
276
277 while ((c = getopt_long(argc, argv, "vc:S:L:",
278 long_options, &option_index )) != EOF)
279 switch (c) {
280 /***** Common options *****/
281 case 'v':
282 verbose++;
283 break;
284 case 'c':
285 c_flag = optarg;
286 break;
287 case 'S':
288 S_flag = optarg;
289 break;
290 case 'L':
291 L_flag = optarg;
292 break;
293 }
294
295 /*
296 * Read config file
297 */
298 if(L_flag) /* Must set libdir beforehand */
299 cf_s_libdir(L_flag);
300 cf_read_config_file(c_flag ? c_flag : CONFIG);
301
302 /*
303 * Process config options
304 */
305 if(L_flag)
306 cf_s_libdir(L_flag);
307 if(S_flag)
308 cf_s_spooldir(S_flag);
309
310 /***** Test **************************************************************/
311 if(optind >= argc)
312 {
313 fprintf(stderr,
314 "usage: testflo [-v] [-c CONFIG] "
315 "[-L LIBDIR] [-S SPOOLDIR] Z:N/F.P\n");
316 exit(1);
317 }
318
319 if(asc_to_node(argv[optind], &node, FALSE) == ERROR)
320 {
321 fprintf(stderr, "testflo: %s is not an FTN address\n", argv[optind]);
322 exit(1);
323 }
324
325 if(flo_open(&node, TRUE) == ERROR)
326 {
327 printf("No FLO file for %s\n", znfp1(&node));
328 exit(0);
329 }
330
331 printf("Contents of FLO file:\n");
332 str_printf(buffer, sizeof(buffer), "cat -v %s", flo_name);
333 system(buffer);
334
335 while( (line = flo_gets(buffer, sizeof(buffer))) )
336 {
337 mode[0] = '-';
338 printf("Line : %s\n", line);
339 if(*line=='^' || *line=='#')
340 mode[0] = *line++;
341 printf(" DOS : %s %s\n", mode, line);
342 if(cf_dos())
343 printf(" UNIX: %s %s\n", mode, cf_unix_xlate(line));
344 flo_mark();
345 }
346
347 printf("Modified contents of FLO file:\n");
348 str_printf(buffer, sizeof(buffer), "cat -v %s", flo_name);
349 system(buffer);
350
351 flo_close(&node, TRUE, TRUE);
352
353 exit(0);
354
355 /**NOT REACHED**/
356 return 0;
357 }
358
359 #endif /**TEST**/
360