1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3  * Author: Jim Faulkner <newspost@sdf.lonestar.org>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  *
19  */
20 
21 #include "../base/newspost.h"
22 
23 #include <signal.h>
24 
25 #include "errors.h"
26 #include "options.h"
27 #include "ui.h"
28 
29 boolean writedefaults = FALSE;
30 boolean temporary_prefix = FALSE;
31 
32 const char *EDITOR = NULL;
33 
34 static void signal_handler();
35 
main(int argc,char ** argv)36 int main(int argc, char **argv) {
37 	newspost_data main_data;
38 	struct sigaction act;
39 	int optind, retval, fd;
40 	FILE *fp;
41 	SList *file_list;
42 	SList *pi;
43 	boolean temporary_message = FALSE;
44 	boolean posting_anything = FALSE;
45 	Buff *command = NULL;
46 	file_entry *file_data = NULL;
47 
48 	retval = NORMAL;
49 
50 	if (argc == 1)
51 		print_help();
52 
53 	/* initialize the data */
54 	main_data.subject = NULL;
55 	main_data.newsgroup = NULL;
56 	main_data.from = NULL;
57 	main_data.organization = NULL;
58 	main_data.address = NULL;
59 	main_data.port = 119;
60 	main_data.user = NULL;
61 	main_data.password = NULL;
62 	main_data.lines = 7500;
63 	main_data.prefix = NULL;
64 	main_data.yenc = FALSE;
65 	main_data.sfv = NULL;
66 	main_data.par = NULL;
67 	main_data.parnum = 0;
68 	main_data.filesperpar = 10;
69 	main_data.reference = NULL;
70 	main_data.filenumber = FALSE;
71 	main_data.tmpdir = NULL;
72 	main_data.noarchive = TRUE;
73 	main_data.followupto = NULL;
74 	main_data.replyto = NULL;
75 	main_data.name = NULL;
76 	main_data.extra_headers = NULL;
77 	main_data.text = FALSE;
78 
79 	/* get all options */
80 	parse_environment(&main_data);
81 	parse_defaults(&main_data);
82 	optind = parse_options(argc, argv, &main_data);
83 
84 	file_list = (SList *) parse_input_files(argc, argv, optind,
85 						&main_data);
86 
87 	if (writedefaults == TRUE) {
88 		printf( (set_defaults(&main_data) == TRUE) ?
89 			"\nDefaults written." :
90 			"\nDefaults NOT written.");
91 		fflush(stdout);
92 	}
93 
94 	check_options(&main_data);
95 
96 	if ((main_data.text == FALSE) && (file_list == NULL)) {
97 		fprintf(stderr, "\nNo files to post!\n");
98 		exit(EXIT_NO_FILES);
99 	}
100 
101 	if ((main_data.text == TRUE) && (slist_length(file_list) > 1)) {
102 		fprintf(stderr, "\nOnly one text file may be posted.\n");
103 		exit(EXIT_TOO_MANY_TEXT_FILES);
104 	}
105 
106 	if(main_data.text == FALSE){
107 		if((main_data.sfv == NULL)
108 		   && (main_data.par == NULL)){
109 			pi = file_list;
110 			while(pi != NULL){
111 				file_data = (file_entry *) pi->data;
112 				if (file_data->parts != NULL) {
113 					if(file_data->parts[0] == FALSE){
114 						posting_anything = TRUE;
115 						break;
116 					}
117 				}
118 				else{
119 					posting_anything = TRUE;
120 					break;
121 				}
122 
123 				pi = slist_next(pi);
124 			}
125 			if(posting_anything == FALSE){
126 				fprintf(stderr, "\nNo files to post!\n");
127 				exit(EXIT_NO_FILES);
128 			}
129 		}
130 	}
131 
132 	/* create the directory for storing temporary files */
133 	/* only create it if we need it */
134 	if ((main_data.sfv != NULL)
135 	   || (main_data.par != NULL)
136 	   || (temporary_prefix == TRUE)
137 	   || ((main_data.text == TRUE) && (file_list == NULL)) ) {
138 		if (main_data.tmpdir == NULL)
139 			main_data.tmpdir = buff_create(main_data.tmpdir, "%s", P_tmpdir);
140 		main_data.tmpdir = buff_add(main_data.tmpdir, "/newspost-XXXXXX");
141 		if((fd = mkstemp(main_data.tmpdir->data)) == -1){
142 			ui_tmpdir_create_failed(main_data.tmpdir->data, errno);
143 			exit(EXIT_FAILED_TO_CREATE_TMPFILES);
144 		}
145 		close(fd);
146 		unlink(main_data.tmpdir->data);
147 		if (mkdir(main_data.tmpdir->data, S_IRWXU) == -1) {
148 			ui_tmpdir_create_failed(main_data.tmpdir->data, errno);
149 			exit(EXIT_FAILED_TO_CREATE_TMPFILES);
150 		}
151 		else {
152 			/* we catch the signal and delete tmpdir */
153 			act.sa_handler = signal_handler;
154 			sigemptyset(&act.sa_mask);
155 			act.sa_flags = 0;
156 			sigaction(SIGHUP, &act, NULL);
157 			sigaction(SIGINT, &act, NULL);
158 			sigaction(SIGTERM, &act, NULL);
159 			tmpdir_ptr = main_data.tmpdir;
160 
161 			if ((main_data.text == TRUE) && (file_list == NULL)) {
162 				file_data = file_entry_alloc(file_data);
163 				file_data->filename = buff_create(file_data->filename,
164 					 "%s/message", main_data.tmpdir->data);
165 				command = buff_create(command, "%s %s",
166 					 (EDITOR != NULL) ? EDITOR : "vi",
167 					 file_data->filename->data);
168 				system(command->data);
169 
170 				fp = fopen(file_data->filename->data, "rb");
171 				if (fp != NULL) {
172 					fclose(fp);
173 					chmod(file_data->filename->data,
174 						S_IRUSR | S_IWUSR);
175 					stat(file_data->filename->data,
176 						&file_data->fileinfo);
177 					file_data->parts = NULL;
178 					file_list = slist_prepend(file_list,
179 								  file_data);
180 					temporary_message = TRUE;
181 				}
182 				else {
183 					buff_free(file_data->filename);
184 					free(file_data);
185 					if (rmdir(main_data.tmpdir->data) == -1) {
186 						command = buff_create(command,
187 							 "rm -rf %s",
188 							 main_data.tmpdir->data);
189 						system(command->data);
190 					}
191 					fprintf(stderr,
192 						"\nCannot open message: %s"
193 						"\nNothing to post!\n",
194 						strerror(errno));
195 					exit(EXIT_NO_FILES);
196 				}
197 			}
198 			else if ((temporary_prefix == TRUE) &&
199 				 (retval == NORMAL) &&
200 				 (main_data.text == FALSE)) {
201 				main_data.prefix = buff_create(main_data.prefix,
202 					 "%s/prefix", main_data.tmpdir->data);
203 
204 				command = buff_create(command, "%s %s",
205 					 (EDITOR != NULL) ? EDITOR : "vi",
206 					 main_data.prefix->data);
207 				system(command->data);
208 
209 				fp = fopen(main_data.prefix->data, "rb");
210 
211 				if (fp != NULL) {
212 					fclose(fp);
213 					chmod(main_data.prefix->data,
214 						S_IRUSR|S_IWUSR);
215 				}
216 				else {
217 					fprintf(stderr,
218 						"\nWARNING: Cannot open"
219 						" prefix: %s - SKIPPING",
220 						strerror(errno));
221 					main_data.prefix = buff_free(main_data.prefix);
222 				}
223 			}
224 		}
225 	}
226 	/* post */
227 	if (NORMAL == retval)
228 		retval = newspost(&main_data, file_list);
229 
230 	/* free all the data */
231 	pi = file_list;
232 	while (pi != NULL) {
233 		file_data = (file_entry *) pi->data;
234 		if (temporary_message == TRUE) {
235 			unlink(file_data->filename->data);
236 			file_entry_free(file_data);
237 			/* if the check for length(file_list) > 1 is
238 			 * ever removed, not all data will be freed */
239 			break;
240 		}
241 		file_entry_free(file_data);
242 		pi = slist_next(pi);
243 	}
244 	slist_free(file_list);
245 	pi = main_data.extra_headers;
246 	while (pi != NULL) {
247 		buff_free(pi->data);
248 		pi = slist_next(pi);
249 	}
250 	if ((TRUE == temporary_prefix) && (main_data.text == FALSE))
251 		unlink(main_data.prefix->data);
252 
253 	/* if we forgot to remove a file in tmpdir, force its removal */
254 	if ((main_data.sfv != NULL)
255 	   || (main_data.par != NULL)
256 	   || (temporary_prefix == TRUE)
257 	   || (temporary_message == TRUE)) {
258 		if (rmdir(main_data.tmpdir->data) == -1) {
259 			command = buff_create(command,
260 				 "rm -rf %s", main_data.tmpdir->data);
261 			system(command->data);
262 		}
263 	}
264 	buff_free(command);
265 
266 	/* free the data */
267 	buff_free(main_data.subject);
268 	buff_free(main_data.newsgroup);
269 	buff_free(main_data.from);
270 	buff_free(main_data.organization);
271 	buff_free(main_data.address);
272 	buff_free(main_data.user);
273 	buff_free(main_data.password);
274 	buff_free(main_data.prefix);
275 	buff_free(main_data.sfv);
276 	buff_free(main_data.par);
277 	buff_free(main_data.reference);
278 	buff_free(main_data.tmpdir);
279 	buff_free(main_data.followupto);
280 	buff_free(main_data.replyto);
281 	buff_free(main_data.name);
282 	if (main_data.extra_headers != NULL)
283 		slist_free(main_data.extra_headers);
284 
285 	switch (retval) {
286 
287 	case NORMAL:
288 		if (main_data.text == TRUE)
289 			printf("\nFile posted as text.\n");
290 		else
291 			ui_post_done();
292 		exit(EXIT_NORMAL);
293 
294 	case FAILED_TO_CREATE_TMPFILES:
295 		fprintf(stderr,
296 			"\nFailed to create temporary directory\n");
297 		exit(EXIT_FAILED_TO_CREATE_TMPFILES);
298 
299 	case FAILED_TO_RESOLVE_HOST:
300 		fprintf(stderr,
301 			"\nFailed to resolve the server name\n");
302 		exit(EXIT_FAILED_TO_RESOLVE_HOST);
303 
304 	case FAILED_TO_CREATE_SOCKET:
305 		fprintf(stderr,
306 			"\nFailed to connect to the server\n");
307 		exit(EXIT_FAILED_TO_CREATE_SOCKET);
308 
309 	case LOGON_FAILED:
310 		fprintf(stderr,
311 			"\nFailed to logon to the server\n");
312 		exit(EXIT_LOGON_FAILED);
313 
314 	case POSTING_NOT_ALLOWED:
315 		fprintf(stderr,
316 			"\nPosting is not allowed\n");
317 		exit(EXIT_POSTING_NOT_ALLOWED);
318 
319 	default:
320 		fprintf(stderr,
321 			"\nInternal error.  "
322 			"Please contact the author.\n");
323 		exit(EXIT_UNKNOWN);
324 	}
325 }
326 
signal_handler()327 static void signal_handler() {
328 	Buff *command = NULL;
329 
330 	fprintf(stderr, "\nSignal received");
331 	if (tmpdir_ptr != NULL) {
332 		fprintf(stderr, "\nDeleting temporary files... ");
333 		if (rmdir(tmpdir_ptr->data) == -1) {
334 			command = buff_create(command,
335 				 "rm -rf %s", tmpdir_ptr->data);
336 			system(command->data);
337 		}
338 		fprintf(stderr, "done.");
339 	}
340 	fprintf(stderr, "\n");
341 	exit(EXIT_SIGNAL);
342 }
343