1 #include <config.h>
2 
3 #include <stdlib.h>
4 #include <stdio.h>
5 
6 #ifdef HAVE_UNISTD_H
7 #include <unistd.h>
8 #endif
9 
10 #ifdef HAVE_SYS_WAIT_H
11 #include <sys/wait.h>
12 #endif
13 
14 #include <string.h>
15 #include <sys/types.h>
16 #include <sys/stat.h>
17 
18 #ifdef HAVE_DIRENT_H
19 # include <dirent.h>
20 #else
21 # ifdef HAVE_SYS_NDIR_H
22 #  include <sys/ndir.h>
23 # endif
24 # ifdef HAVE_SYS_DIR_H
25 #  include <sys/dir.h>
26 # endif
27 #endif
28 
29 #ifdef DMALLOC
30 #include <dmalloc.h>
31 #endif
32 
33 #include "suck_config.h"
34 #include "suck.h"
35 #include "both.h"
36 #include "batch.h"
37 #include "suckutils.h"
38 #include "phrases.h"
39 #include "active.h"
40 #include "timer.h"
41 
42 /*--------------------------------------------------------*/
43 /* function prototypes */
44 int post_one_msg(PMaster, int, char *);
45 
46 /*----------------------------------------------------------*/
do_innbatch(PMaster master)47 int do_innbatch(PMaster master) {
48 	/* build batch file that contains article listing */
49 	/* needed by innxmit */
50 	/* this is done by searching thru MSGDIR to find files */
51 	/* which match our naming convention */
52 
53 	int i, retval = RETVAL_OK;
54 	FILE *fptr;
55 	const char *tmp;
56 	DIR *dptr;
57 	struct dirent *entry;
58 
59 	print_phrases(master->msgs, batch_phrases[3], NULL);
60 
61 	if((fptr = fopen(master->batchfile, "w")) == NULL) {
62 		MyPerror(master->batchfile);
63 		retval = RETVAL_ERROR;
64 	}
65 	else if((dptr = opendir(full_path(FP_GET, FP_MSGDIR, ""))) == NULL) {
66 		MyPerror(full_path(FP_GET, FP_MSGDIR, ""));
67 		retval = RETVAL_ERROR;
68 		fclose(fptr);
69 	}
70 	else {
71 		tmp = full_path(FP_GET_POSTFIX, 0, "");		/* this will be string we search for */
72 		/* look for entries which have our postfix */
73 		while((entry = readdir(dptr)) != NULL && retval == RETVAL_OK) {
74 			/* ignore hidden files */
75 			if(entry->d_name[0] != '.' && strstr(entry->d_name, tmp) != NULL) {
76 				i = fprintf(fptr, "%s\n", full_path(FP_GET_NOPOSTFIX, FP_MSGDIR, entry->d_name));
77 				if(i <= 0) {
78 					retval = RETVAL_ERROR;
79 					MyPerror(master->batchfile);
80 				}
81 			}
82 		}
83 		fclose(fptr);
84 		closedir(dptr);
85 	}
86 	return retval;
87 }
88 /*----------------------------------------------------------*/
do_rnewsbatch(PMaster master)89 int do_rnewsbatch(PMaster master) {
90 
91 	/* build rnews formated file of articles */
92 	/* this is done by searching thru MSGDIR to find files */
93 	/* which match our naming convention */
94 
95 	/* if max_file_size > 0, then create multiple files up to  max file size */
96 
97 	int i, x, batchnr = 0, retval = RETVAL_OK;
98 	FILE *fptr = NULL, *fpin;
99 	const char *tptr, *tmp;
100 	char buf[MAXLINLEN];
101 	DIR *dptr;
102 	struct dirent *entry;
103 	struct stat sbuf, tbuf;
104 	long cursize = 0L;
105 
106 	print_phrases(master->msgs, batch_phrases[4], NULL);
107 
108 	if((dptr = opendir(full_path(FP_GET, FP_MSGDIR, ""))) == NULL) {
109 		MyPerror(full_path(FP_GET, FP_MSGDIR, ""));
110 		retval = RETVAL_ERROR;
111 	}
112 	else {
113 		tmp = full_path(FP_GET_POSTFIX, 0, "");	/* this will be string we search for */
114 		/* look for entries which have our postfix */
115 		while(retval == RETVAL_OK && (entry = readdir(dptr))) {
116 			/* ignore hidden files */
117 			if(entry->d_name[0] != '.' && strstr(entry->d_name, tmp) != NULL) {
118 				tptr = full_path(FP_GET_NOPOSTFIX, FP_MSGDIR, entry->d_name);
119 				if(stat(tptr, &sbuf) != 0 || (fpin = fopen(tptr, "r")) == NULL) {
120 					MyPerror(tptr);
121 					retval = RETVAL_ERROR;
122 				}
123 				else {
124 					if( cursize == 0 ) {
125 						if(fptr != NULL) {
126 							/* close old file */
127 							fclose(fptr);
128 							batchnr++;
129 						}
130 						/* have to open file */
131 						if(batchnr == 0) {
132 							strcpy(buf, master->batchfile);
133 						}
134 						else {
135 							sprintf(buf, "%s%d", master->batchfile, batchnr);
136 						}
137 						if(master->debug == TRUE) {
138 							do_debug("BATCH FILE: %s\n", buf);
139 						}
140 						if(stat(buf, &tbuf) == 0) {
141 							/* whoops file already exists */
142 							MyPerror(buf);
143 							retval = RETVAL_ERROR;
144 						}
145 						else if((fptr = fopen(buf, "w")) == NULL) {
146 							MyPerror(buf);
147 							retval = RETVAL_ERROR;
148 						}
149 					}
150 					if(retval == RETVAL_OK) {
151 						/* first put #! rnews size */
152 						fprintf(fptr, "#! rnews %ld\n", (long) sbuf.st_size);
153 						/* use fread/fwrite in case lines are longer than MAXLINLEN */
154 						while((i = fread(buf, 1, MAXLINLEN, fpin)) > 0 && retval == RETVAL_OK) {
155 							x = fwrite(buf, 1, i, fptr);
156 							if(x != i) {
157 								/* error writing file */
158 								retval = RETVAL_ERROR;
159 								MyPerror(buf);
160 							}
161 						}
162 						if(retval == RETVAL_OK ) {
163 							unlink(tptr);	/* we are done with it, nuke it */
164 							cursize += sbuf.st_size;
165 							/* keep track of current file size, we can ignore the #! rnews */
166 							/* size, since it adds so little to the overall size */
167 
168 							if(master->rnews_size > 0L && cursize > master->rnews_size) {
169 								/* reached file size length */
170 								cursize = 0L;	/* this will force a close and open on next article */
171 							}
172 						}
173 					}
174 					fclose(fpin);
175 				}
176 			}
177 		}
178 		if(fptr != NULL) {
179 			fclose(fptr);
180 		}
181 
182 		closedir(dptr);
183 	}
184 	return retval;
185 }
186 /*----------------------------------------------------------------------------------*/
do_lmovebatch(PMaster master)187 void do_lmovebatch(PMaster master) {
188 	/* fork lmove */
189 	const char *args[LMOVE_MAX_ARGS];
190 	int i, x;
191 	pid_t pid;
192 
193 	print_phrases(master->msgs, batch_phrases[0], NULL);
194 
195 	/* first build command */
196 	args[0] = "lmove";
197 	args[1] = "-c";
198 	args[2] = master->batchfile;
199 	args[3] = "-d";
200 	args[4] = full_path(FP_GET, FP_MSGDIR, "");
201 	i = 5;
202 	if(master->errlog != NULL) {
203 		args[i++ ] = "-E";
204 		args[i++ ] = master->errlog;
205 	}
206 	if(master->phrases != NULL) {
207 		args[i++] = "-l";
208 		args[i++] = master->phrases;
209 	}
210 
211 	if(master->debug == TRUE) {
212 		args[i++] = "-D";
213 	}
214 	args[i] = NULL;
215 
216 	if(master->debug == TRUE) {
217 		do_debug("Calling lmove with args:");
218 		for(x = 0; x < i; x++) {
219 			do_debug(" %s", args[x]);
220 		}
221 		do_debug("\n");
222 	}
223 
224 	/* now fork and execl */
225 	pid = fork();
226 	if(pid == 0) {
227 		/* in child */
228 		execvp(args[0], (char *const *) args);
229 		MyPerror(batch_phrases[2]);	/* only get here on errors */
230 		exit(-1); /* so we aren't running two sucks */
231 	}
232 	else if(pid < 0) {
233 		/* whoops */
234 		MyPerror(batch_phrases[1]);
235 	}
236 	else {
237 		/* in parent let the child finish */
238 		wait(NULL);
239 	}
240 }
241 /*---------------------------------------------------------------------------*/
do_localpost(PMaster master)242 int do_localpost(PMaster master) {
243 
244 	/* post articles to local server using IHAVE */
245 	int sockfd, count = 0, retval = RETVAL_OK;
246 	FILE *fp_list;
247 	char msg[MAXLINLEN+1];
248 	const char *fname;
249 
250 	TimerFunc(TIMER_START, 0, NULL);
251 
252 	print_phrases(master->msgs, batch_phrases[5], master->localhost, NULL);
253 
254 	if(master->batchfile == NULL) {
255 		error_log(ERRLOG_REPORT, batch_phrases[6], NULL);
256 		retval = RETVAL_ERROR;
257 	}
258 	else {
259 		fname = full_path(FP_GET, FP_TMPDIR, master->batchfile);
260 		if((fp_list = fopen(fname, "r")) == NULL ) {
261 			MyPerror(fname);
262 			retval = RETVAL_ERROR;
263 		}
264 		else {
265 			if((sockfd = connect_local(master)) < 0) {
266 				retval = RETVAL_ERROR;
267 			}
268 			else {
269 				while(retval == RETVAL_OK && fgets(msg, MAXLINLEN, fp_list) != NULL) {
270 					retval = post_one_msg(master, sockfd, msg);
271 					if(retval == RETVAL_OK) {
272 						count++;
273 					}
274 				}
275 				disconnect_from_nntphost(sockfd, master->local_ssl, &master->local_ssl_struct);
276 			}
277 			fclose(fp_list);
278 		}
279 		if(retval == RETVAL_OK) {
280 			if(master->debug == TRUE) {
281 				do_debug("deleting %s\n", fname);
282 			}
283 			unlink(fname);
284 		}
285 	}
286 
287 	print_phrases(master->msgs, batch_phrases[10], str_int(count), NULL);
288 	TimerFunc(TIMER_TIMEONLY, 0,master->msgs);
289 
290 	return retval;
291 
292 }
293 /*------------------------------------------------------------------------------------------------*/
post_one_msg(PMaster master,int sockfd,char * msg)294 int post_one_msg(PMaster master, int sockfd, char *msg) {
295 
296 	int len, nr, longline, do_unlink = FALSE, retval = RETVAL_OK;
297 	char *msgid, *resp, linein[MAXLINLEN+4]; /* the extra in case of . in first pos */
298 	FILE *fpi;
299 
300 	/* msg contains the path and msgid */
301 	msgid = strstr(msg, " <"); /* find the start of the msgid */
302 	if(msgid == NULL) {
303 		error_log(ERRLOG_REPORT, batch_phrases[7], msg, NULL);
304 	}
305 	else {
306 		*msgid = '\0';	/* end the path name */
307 		msgid++;	/* so we point to the < */
308 
309 		len = strlen(msgid);
310 		/* strip a nl */
311 		if(msgid[len-1] == '\n') {
312 			msgid[len-1] = '\0';
313 		}
314 		if(master->debug == TRUE) {
315 			do_debug("File Name = \"%s\"\n", msg);
316 		}
317 
318 		if((fpi = fopen(msg, "r")) == NULL) {
319 			MyPerror(msg);
320 		}
321 		else {
322 			sprintf(linein, "IHAVE %s\r\n", msgid);
323 			if(master->debug == TRUE) {
324 				do_debug("sending command %s", linein);
325 			}
326 			sputline(sockfd, linein, master->local_ssl, master->local_ssl_struct);
327 			if(sgetline(sockfd, &resp, master->local_ssl, master->local_ssl_struct) < 0) {
328 				retval = RETVAL_ERROR;
329 			}
330 			else {
331 				if(master->debug == TRUE) {
332 					do_debug("got answer: %s", resp);
333 				}
334 				number(resp, &nr);
335 				/* added for prob */
336 				if(master->debug == TRUE) {
337 					do_debug("Answer=%d\n", nr);
338 				}
339 				if(nr == 435) {
340 					error_log(ERRLOG_REPORT, batch_phrases[11], msgid, resp, NULL);
341 					do_unlink = TRUE;
342 				}
343 				else if(nr != 335) {
344 					error_log(ERRLOG_REPORT, batch_phrases[8], msgid, resp, NULL);
345 				}
346 				else {
347                                         /* send the article */
348 					longline = FALSE;
349 					while(fgets(linein, MAXLINLEN, fpi) != NULL) {
350 						/* added for prob */
351 						if(master->debug == TRUE) {
352 							do_debug("sending line-%s--\n", linein);
353 						}
354 
355 						len = strlen(linein);
356 						if(longline == FALSE && linein[0] == '.') {
357 							/* double the . at beginning of line */
358 							memmove(linein+1,linein,++len);
359 							linein[0] = '.';
360 						}
361 
362 						longline = ( linein[len - 1] == '\n' ) ? FALSE : TRUE ;
363 						if(longline == FALSE) {
364 							/* replace nl with cr nl */
365 							strcpy(&linein[len-1], "\r\n");
366 						}
367 						sputline(sockfd, linein, master->local_ssl, master->local_ssl_struct);
368 					}
369 					if(longline == TRUE) {
370 						/* end the last line */
371 						sputline(sockfd, "\r\n", master->local_ssl, master->local_ssl_struct);
372 					}
373 					/* end the article */
374 					sputline(sockfd, ".\r\n", master->local_ssl, master->local_ssl_struct);
375 					/* put in for prob */
376 					if(master->debug == TRUE) {
377 						do_debug("Finished sending article\n");
378 					}
379 					if(sgetline(sockfd, &resp, master->local_ssl, master->local_ssl_struct) < 0 ) {
380 						retval = RETVAL_ERROR;
381 					}
382 					else {
383 						if(master->debug == TRUE) {
384 							do_debug("Got response: %s", resp);
385 						}
386 						number(resp, &nr);
387 						if(nr == 437) {
388 							error_log(ERRLOG_REPORT, batch_phrases[12], msgid, resp, NULL);
389 							do_unlink = TRUE;
390 						}
391 						else if(nr == 235) {
392 							/* successfully posted, nuke it */
393 							do_unlink = TRUE;
394 						}
395 						else {
396 							error_log(ERRLOG_REPORT, batch_phrases[9], msgid, resp, NULL);
397 						}
398 					}
399 				}
400 			}
401 			fclose(fpi);
402 			if(do_unlink == TRUE) {
403 				unlink(msg);
404 			}
405 
406 		}
407 	}
408 
409 	return retval;
410 
411 }
412 /*--------------------------------------------------------------------------*/
do_post_filter(PMaster master)413 void do_post_filter(PMaster master) {
414 	/* call lpost filter prgm with batchfile as argument */
415 	const char *msgdir;
416 	pid_t pid;
417 
418 	if(master->post_filter != NULL) {
419 		msgdir = full_path(FP_GET, FP_MSGDIR, "");
420 		if(master->debug == TRUE) {
421 			do_debug("Running %s with %s as args\n", master->post_filter, msgdir);
422 		}
423 
424 		pid = fork();
425 		if(pid == 0) {
426 			/* in child */
427 			if(execlp(master->post_filter, master->post_filter, msgdir, NULL) == -1) {
428 				/* big error */
429 				MyPerror(master->post_filter);
430 				exit(-1); /* so we aren't running two sucks */
431 			}
432 		}
433 		else if(pid == -1) {
434 			/* whoops */
435 			MyPerror(master->post_filter);
436 		}
437 		else {
438 			/* parent, wait on child */
439 			wait(NULL);
440 		}
441 	}
442 }
443