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