1 /*
2 ** Copyright 2002-2009 Double Precision, Inc.
3 ** See COPYING for distribution information.
4 */
5
6 #if HAVE_CONFIG_H
7 #include "config.h"
8 #endif
9
10 #include "courier.h"
11 #include "moduledel.h"
12 #include "comqueuename.h"
13 #include "comfax.h"
14 #include "rfc822/rfc822.h"
15 #include "waitlib/waitlib.h"
16 #include "unicode/unicode.h"
17 #include "numlib/numlib.h"
18 #include <stdlib.h>
19 #include <locale.h>
20 #include <langinfo.h>
21 #include <string.h>
22 #include <ctype.h>
23 #include <signal.h>
24 #include <errno.h>
25 #if HAVE_UNISTD_H
26 #include <unistd.h>
27 #endif
28 #if HAVE_FCNTL_H
29 #include <fcntl.h>
30 #endif
31 #include <pwd.h>
32 #include <sys/wait.h>
33 #include <sys/time.h>
34 #include "comctlfile.h"
35 #include "comqueuename.h"
36 #include "comstrtotime.h"
37 #include "comstrtimestamp.h"
38 #include "comverp.h"
39 #include <sys/stat.h>
40 #include <sys/types.h>
41 #if HAVE_SYS_WAIT_H
42 #include <sys/wait.h>
43 #endif
44 #ifndef WEXITSTATUS
45 #define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)
46 #endif
47 #ifndef WIFEXITED
48 #define WIFEXITED(stat_val) (((stat_val) & 255) == 0)
49 #endif
50 #include "faxconvert.h"
51 #include "sendfax.h"
52 #include "faxtmpdir.h"
53
54 static const char rcsid[]="$Id: courierfax.c,v 1.8 2009/11/08 18:14:47 mrsam Exp $";
55
56 static void fax(struct moduledel *);
57
58 const struct unicode_info *default_charset;
59
60 /*
61 ** Kill the child process.
62 */
63
killit(int n)64 static RETSIGTYPE killit(int n)
65 {
66 module_signal(SIGKILL);
67 exit(0);
68 #if RETSIGTYPE != void
69 return (0);
70 #endif
71 }
72
73 /*
74 ** Main loop. Receive a message to deliver. Fork off a child process. Yawn.
75 */
76
main(int argc,char ** argv)77 int main(int argc, char **argv)
78 {
79 struct moduledel *p;
80 int waitstat;
81 const char *cp;
82
83 setlocale(LC_ALL, "");
84 default_charset=unicode_find(nl_langinfo(CODESET));
85 setlocale(LC_ALL, "C");
86
87 if (!default_charset)
88 default_charset= &unicode_ISO8859_1;
89
90 clog_open_syslog("courierfax");
91 if (chdir(getenv("COURIER_HOME")))
92 clog_msg_errno();
93
94 cp=getenv("MAXDELS");
95 if (!cp || atoi(cp) != 1)
96 {
97 clog_msg_start_err();
98 clog_msg_str("FATAL: courierfax module misconfiguration, MAXDELS must be 1");
99 clog_msg_send();
100 exit(0);
101 }
102
103 cp=getenv("MAXRCPT");
104 if (!cp || atoi(cp) != 1)
105 {
106 clog_msg_start_err();
107 clog_msg_str("FATAL: courierfax module misconfiguration, MAXRCPT must be 1");
108 clog_msg_send();
109 exit(0);
110 }
111
112 module_init(0);
113 while ((p=module_getdel()) != NULL)
114 {
115 pid_t pid;
116 unsigned delid;
117
118 delid=atol(p->delid);
119
120 if ((pid=module_fork(delid, 0)) == -1)
121 {
122 clog_msg_prerrno();
123 module_completed(delid, delid);
124 continue;
125 }
126
127 if (pid == 0)
128 {
129 fax(p);
130 exit(0);
131 }
132 }
133
134 module_signal(SIGTERM);
135 signal(SIGCHLD, SIG_DFL);
136 signal(SIGALRM, killit);
137 alarm(5);
138 wait(&waitstat);
139 alarm(0);
140 return (0);
141 }
142
143 /*
144 ** All righty - pick up a message to deliver.
145 */
146
faxabort(int n)147 static RETSIGTYPE faxabort(int n)
148 {
149 signal(SIGTERM, SIG_IGN);
150 kill(-getpid(), SIGTERM);
151 #if RETSIGTYPE != void
152 return (0);
153 #endif
154 }
155
read_childerrmsg(pid_t child_proc,int errfd,int (* errhandler)(int,char *,void *),void * errhandler_arg)156 static int read_childerrmsg(pid_t child_proc,
157 int errfd,
158 int (*errhandler)(int, char *, void *),
159 void *errhandler_arg)
160 {
161 char errbuf[BUFSIZ];
162 int errptr=0;
163 int waitstat;
164 pid_t p;
165
166 for (;;)
167 {
168 int n, i;
169
170 if (errptr >= BUFSIZ/4 * 3)
171 {
172 /* Read errmsg too big, strip it */
173
174 i=BUFSIZ/2;
175
176 for (n=BUFSIZ/2; n<errptr; n++)
177 if (errbuf[n] == '\n')
178 {
179 i= n+1;
180 break;
181 }
182
183 strcpy(errbuf, "...\n");
184 n=4;
185 while (i < errptr)
186 errbuf[n++] = errbuf[i++];
187 errptr=n;
188 }
189
190 n=read(errfd, errbuf+errptr, BUFSIZ-1-errptr);
191 if (n <= 0)
192 break;
193 errptr += n;
194 }
195 errbuf[errptr]=0;
196 close(errfd);
197
198 while ((p=wait(&waitstat)) != child_proc)
199 {
200 if (p < 0 && errno != EINTR)
201 break;
202 }
203
204 if (p == child_proc && WIFEXITED(waitstat) &&
205 WEXITSTATUS(waitstat) == 0)
206 return (0);
207
208 if (errptr == 0)
209 strcpy(errbuf, "courierfax: child process crashed.");
210
211 return (*errhandler)(p == child_proc && WIFEXITED(waitstat)
212 ? WEXITSTATUS(waitstat):1,
213 errbuf, errhandler_arg);
214 }
215
216 struct faxconv_err_args {
217 struct ctlfile *ctf;
218 unsigned nreceip;
219
220 struct sort_file_list *file_list;
221 int is_locked;
222 int n_cover_pages;
223 } ;
224
225
faxconvert_cleanup(int dummy,char * errmsg,void * vp)226 static int faxconvert_cleanup(int dummy, char *errmsg, void *vp)
227 {
228 struct faxconv_err_args *args=(struct faxconv_err_args *)vp;
229
230 ctlfile_append_reply(args->ctf, args->nreceip,
231 errmsg,
232 COMCTLFILE_DELFAIL_NOTRACK, 0);
233 return (-1);
234 }
235
236 extern int faxconvert(const char *, int, int *);
237
238 static int faxsend_cleanup(int, char *, void *);
239
fax(struct moduledel * p)240 static void fax(struct moduledel *p)
241 {
242 struct ctlfile ctf;
243 unsigned nreceipients=p->nreceipients;
244 const char *host=p->host;
245 const char *receipient;
246 unsigned nrecipient=(unsigned)atol(p->receipients[0]);
247 int pipefd[2];
248 pid_t child_proc;
249 int faxopts;
250 int n_cover_pages;
251 FILE *fp;
252
253 struct faxconv_err_args err_args;
254
255 struct sort_file_list *page_list, *pp;
256
257
258 #if HAVE_SETPGRP
259 #if SETPGRP_VOID
260 setpgrp();
261 #else
262 setpgrp(0, 0);
263 #endif
264 #else
265 #if HAVE_SETPGID
266 setpgid(0, 0);
267 #endif
268 #endif
269
270 if (comgetfaxopts(host, &faxopts))
271 {
272 clog_msg_start_err();
273 clog_msg_str("courierfax: FATAL: invalid host");
274 clog_msg_send();
275 exit(1);
276 }
277
278 putenv(faxopts & FAX_LOWRES ? "FAXRES=lo":"FAXRES=hi");
279
280 if (nreceipients != 1)
281 {
282 clog_msg_start_err();
283 clog_msg_str("courierfax: FATAL: # receipients must be 1");
284 clog_msg_send();
285 exit(1);
286 }
287
288 receipient=p->receipients[1];
289 nrecipient=(unsigned)atol(p->receipients[0]);
290
291 if (ctlfile_openi(p->inum, &ctf, 0))
292 clog_msg_errno();
293
294 /* Convert message to fax format, use a child process */
295
296 signal(SIGTERM, faxabort);
297
298 if (pipe(pipefd) < 0)
299 {
300 clog_msg_errno();
301 }
302
303 child_proc=fork();
304 if (child_proc < 0)
305 {
306 clog_msg_errno();
307 return;
308 }
309
310 if (child_proc == 0)
311 {
312 const char *fn;
313
314 close(0);
315 if (open("/dev/null", O_RDONLY) != 0)
316 clog_msg_errno();
317
318 close(pipefd[0]);
319 close(1);
320 if (dup(pipefd[1]) != 1)
321 {
322 perror("dup");
323 exit(1);
324 }
325 close(2);
326 if (dup(pipefd[1]) != 2)
327 {
328 fprintf(stderr, "ERROR: dup failed\n");
329 exit(1);
330 }
331 close(pipefd[1]);
332
333 libmail_changeuidgid(MAILUID, MAILGID);
334
335 fn=qmsgsdatname(p->inum);
336
337 if (faxconvert(fn, faxopts, &n_cover_pages))
338 exit (1);
339
340 if ((fp=fopen(FAXTMPDIR "/.ncoverpages", "w")) == NULL ||
341 fprintf(fp, "%d\n", n_cover_pages) < 0 ||
342 fflush(fp) < 0)
343 exit(1);
344 fclose(fp);
345 exit(0);
346 }
347
348 close(pipefd[1]);
349
350 err_args.ctf= &ctf;
351 err_args.nreceip=nrecipient;
352
353 if (read_childerrmsg(child_proc, pipefd[0],
354 &faxconvert_cleanup, &err_args))
355 {
356 ctlfile_close(&ctf);
357 return;
358 }
359
360 /* Hit it */
361
362 if ((fp=fopen(FAXTMPDIR "/.ncoverpages", "r")) == NULL ||
363 fscanf(fp, "%d", &n_cover_pages) != 1)
364 {
365 if (fp)
366 fclose(fp);
367
368 ctlfile_append_reply(err_args.ctf,
369 err_args.nreceip,
370 "Internal error: cannot read number of cover pages",
371 COMCTLFILE_DELFAIL, 0);
372 ctlfile_close(&ctf);
373 exit(0);
374 }
375
376 page_list=read_dir_sort_filenames(FAXTMPDIR, FAXTMPDIR "/");
377
378 if (!page_list)
379 {
380 clog_msg_start_err();
381 clog_msg_str("courierfax: INTERNAL ERROR - no pages to xmit.");
382 clog_msg_send();
383 exit(1);
384 }
385
386 /* Keep trying until the modem line is unlocked */
387
388 do
389 {
390 if (pipe(pipefd) < 0)
391 {
392 clog_msg_errno();
393 }
394
395 child_proc=fork();
396 if (child_proc < 0)
397 {
398 clog_msg_errno();
399 return;
400 }
401
402 if (child_proc == 0)
403 {
404 unsigned page_cnt=0;
405 char **argvec;
406
407 close(pipefd[0]);
408 close(0);
409 if (open("/dev/null", O_RDONLY) != 0)
410 {
411 perror("/dev/null");
412 exit(1);
413 }
414 close(1);
415 if (dup(pipefd[1]) != 1)
416 {
417 perror("dup");
418 exit(1);
419 }
420 close(2);
421 if (dup(pipefd[1]) != 2)
422 {
423 fprintf(stderr, "ERROR: dup failed\n");
424 exit(1);
425 }
426 close(pipefd[1]);
427
428 for (pp=page_list; pp; pp=pp->next)
429 ++page_cnt;
430
431 #if 0
432 while (page_list)
433 {
434 unlink(page_list->filename);
435 page_list=page_list->next;
436 }
437
438 exit(0);
439 #endif
440
441 argvec=(char **)courier_malloc(sizeof(char *)*
442 (page_cnt+10));
443
444 argvec[0]=SENDFAX;
445 argvec[1]="-v";
446 argvec[2]="-r";
447
448 page_cnt=3;
449
450 if (faxopts & FAX_LOWRES)
451 argvec[page_cnt++]="-n";
452
453 argvec[page_cnt++]=(char *)receipient;
454
455 while (page_list)
456 {
457 argvec[page_cnt++]=page_list->filename;
458 page_list=page_list->next;
459 }
460 argvec[page_cnt]=0;
461 execv(SENDFAX, argvec);
462 perror(SENDFAX);
463 exit(1);
464 }
465 close(pipefd[1]);
466
467 err_args.ctf= &ctf;
468 err_args.nreceip=nrecipient;
469 err_args.file_list=page_list;
470 err_args.is_locked=0;
471 err_args.n_cover_pages=n_cover_pages;
472
473 if (read_childerrmsg(child_proc, pipefd[0],
474 &faxsend_cleanup, &err_args) == 0)
475 {
476 size_t npages=0;
477 char fmtbuf[NUMBUFSIZE];
478 char fmtbuf1[NUMBUFSIZE];
479 char fmtbuf2[NUMBUFSIZE+100];
480
481 for (pp=page_list; pp; pp=pp->next)
482 ++npages;
483
484 libmail_str_size_t(npages, fmtbuf);
485 libmail_str_size_t(n_cover_pages, fmtbuf1);
486
487 sprintf(fmtbuf2,
488 "%s pages - including %s cover page(s)"
489 " - sent by fax.", fmtbuf, fmtbuf1);
490
491 ctlfile_append_reply(&ctf, (unsigned)
492 nrecipient,
493 fmtbuf2,
494 COMCTLFILE_DELSUCCESS, " l");
495 break;
496 }
497 } while (err_args.is_locked);
498
499 ctlfile_close(&ctf);
500 rmdir_contents(FAXTMPDIR);
501 }
502
faxsend_cleanup(int errcode,char * errmsg,void * vp)503 static int faxsend_cleanup(int errcode, char *errmsg, void *vp)
504 {
505 struct faxconv_err_args *args=(struct faxconv_err_args *)vp;
506 unsigned pages_sent=0;
507 char *p, *q;
508
509 int i;
510 time_t now_time;
511
512 unsigned coverpage_cnt=0;
513 unsigned page_cnt=0;
514
515 /* Check how many files sendfax renamed (were succesfully sent) */
516
517 while (args->file_list)
518 {
519 if (access(args->file_list->filename, 0) == 0)
520 break;
521
522 if (coverpage_cnt < args->n_cover_pages)
523 ++coverpage_cnt;
524 else
525 ++pages_sent;
526 args->file_list=args->file_list->next;
527 }
528
529 /* Strip out any blank lines in captured output from sendfax */
530
531 for (p=q=errmsg; *p; p++)
532 {
533 if (*p == '\n' && (p[1] == '\n' || p[1] == 0))
534 continue;
535
536 *q++=*p;
537 }
538 *q=0;
539
540 /* Find the last message from sendfax */
541
542 for (p=q=errmsg; *p; p++)
543 {
544 if (*p != '\n')
545 continue;
546
547 *p=0;
548
549 /* Dump sendfax's output to the log */
550
551 if (*q)
552 {
553 clog_msg_start_info();
554 clog_msg_str("courierfax: " SENDFAX ": ");
555 clog_msg_str(q);
556 clog_msg_send();
557 }
558 q=p+1;
559 }
560
561 if (*q) /* Last line of the error message */
562 {
563 clog_msg_start_info();
564 clog_msg_str("courierfax: " SENDFAX ": ");
565 clog_msg_str(q);
566 clog_msg_send();
567 }
568 else /* Default message */
569 {
570 q=SENDFAX ": completed.";
571 }
572
573 /*
574 ** Ugly hack: capture the following message from sendfax:
575 **
576 ** /usr/sbin/sendfax: cannot access fax device(s) (locked?)
577 */
578
579 #if 0
580 lockflag=0;
581 p=strchr(q, ':');
582 if (p)
583 {
584 static const char msg1[]="cannot access fax device";
585 static const char msg2[]="locked";
586
587 ++p;
588 while (*p && isspace((int)(unsigned char)*p))
589 p++;
590
591 if (*p && strncasecmp(p, msg1, sizeof(msg1)-1) == 0)
592 {
593 p += sizeof(msg1);
594 while (*p && !isspace((int)(unsigned char)*p))
595 ++p;
596
597 p=strchr(p, '(');
598
599 if (p && strncmp(p+1, msg2, sizeof(msg2)-1) == 0)
600 {
601 args->is_locked=1;
602 clog_msg_start_info();
603 clog_msg_str("courierfax: detected locked"
604 " modem line, sleeping...");
605 clog_msg_send();
606 sleep(60);
607 return (-1);
608 }
609 }
610 }
611 #else
612
613 if (errcode == 2)
614 {
615 args->is_locked=1;
616 clog_msg_start_info();
617 clog_msg_str("courierfax: detected locked"
618 " modem line, sleeping...");
619 clog_msg_send();
620 sleep(60);
621 return (-1);
622 }
623 #endif
624
625 ctlfile_append_connectioninfo(args->ctf, args->nreceip,
626 COMCTLFILE_DELINFO_REPLY, q);
627
628 sprintf(errmsg, "%u cover pages, %u document pages sent.",
629 coverpage_cnt, page_cnt);
630
631 i=ctlfile_searchfirst(args->ctf, COMCTLFILE_FAXEXPIRES);
632
633 time(&now_time);
634 ctlfile_append_reply(args->ctf, args->nreceip,
635 errmsg,
636 (pages_sent == 0 &&
637 i >= 0 &&
638 errcode < 10 &&
639 now_time < strtotime(args->ctf->lines[i]+1)
640 ? COMCTLFILE_DELDEFERRED:
641 COMCTLFILE_DELFAIL_NOTRACK), 0);
642 return (-1);
643 }
644
645