comparison lib-src/movemail.c @ 371:cc15677e0335 r21-2b1

Import from CVS: tag r21-2b1
author cvs
date Mon, 13 Aug 2007 11:03:08 +0200
parents c9ae480b1fff
children d883f39b8495
comparison
equal deleted inserted replaced
370:bd866891f083 371:cc15677e0335
63 #include <errno.h> 63 #include <errno.h>
64 #include "../src/syswait.h" 64 #include "../src/syswait.h"
65 #include "../src/systime.h" 65 #include "../src/systime.h"
66 #include <stdlib.h> 66 #include <stdlib.h>
67 #include <string.h> 67 #include <string.h>
68 #include "getopt.h"
69 #ifdef MAIL_USE_POP 68 #ifdef MAIL_USE_POP
70 #include "pop.h" 69 #include "pop.h"
71 #include "../src/regex.h" 70 #endif
72 #endif
73
74 extern char *optarg;
75 extern int optind, opterr;
76 71
77 #ifndef HAVE_STRERROR 72 #ifndef HAVE_STRERROR
78 char * strerror (int errnum); 73 static char * strerror (int errnum);
79 #endif /* HAVE_STRERROR */ 74 #endif /* HAVE_STRERROR */
80 75
81 #ifdef MSDOS 76 #ifdef MSDOS
82 #undef access 77 #undef access
83 #endif /* MSDOS */ 78 #endif /* MSDOS */
149 static int popmail (char *, char *, char *); 144 static int popmail (char *, char *, char *);
150 static int pop_retr (popserver server, int msgno, int (*action)(), void *arg); 145 static int pop_retr (popserver server, int msgno, int (*action)(), void *arg);
151 static int mbx_write (char *, FILE *); 146 static int mbx_write (char *, FILE *);
152 static int mbx_delimit_begin (FILE *); 147 static int mbx_delimit_begin (FILE *);
153 static int mbx_delimit_end (FILE *); 148 static int mbx_delimit_end (FILE *);
154 static struct re_pattern_buffer* compile_regex (char* regexp_pattern);
155 static int pop_search_top (popserver server, int msgno, int lines,
156 struct re_pattern_buffer* regexp);
157 #endif 149 #endif
158 150
159 /* Nonzero means this is name of a lock file to delete on fatal error. */ 151 /* Nonzero means this is name of a lock file to delete on fatal error. */
160 char *delete_lockname; 152 char *delete_lockname;
161 153
162 int verbose=0;
163 #ifdef MAIL_USE_POP
164 int reverse=0;
165 int keep_messages=0;
166 struct re_pattern_buffer* regexp_pattern=0;
167 int match_lines=10;
168 #endif
169
170 #define VERBOSE(x) if (verbose) { printf x; fflush(stdout); }
171
172 struct option longopts[] =
173 {
174 { "inbox", required_argument, NULL, 'i' },
175 { "outfile", required_argument, NULL, 'o' },
176 #ifdef MAIL_USE_POP
177 { "password", required_argument, NULL, 'p' },
178 { "reverse-pop-order", no_argument, NULL, 'x' },
179 { "keep-messages", no_argument, NULL, 'k' },
180 { "regex", required_argument, NULL, 'r' },
181 { "match-lines", required_argument, NULL, 'l' },
182 #endif
183 { "verbose", no_argument, NULL, 'v' },
184 { 0 }
185 };
186
187 int 154 int
188 main (int argc, char *argv[]) 155 main (int argc, char *argv[])
189 { 156 {
190 char *inname=0, *outname=0, *poppass=0; 157 char *inname, *outname;
191 #ifndef DISABLE_DIRECT_ACCESS 158 #ifndef DISABLE_DIRECT_ACCESS
192 int indesc, outdesc; 159 int indesc, outdesc;
193 int nread; 160 int nread;
194 int status; 161 int status;
195 #endif 162 #endif
203 int desc; 170 int desc;
204 #endif /* not MAIL_USE_SYSTEM_LOCK */ 171 #endif /* not MAIL_USE_SYSTEM_LOCK */
205 172
206 delete_lockname = 0; 173 delete_lockname = 0;
207 174
208 while (1) 175 if (argc < 3)
209 { 176 {
210 #ifdef MAIL_USE_POP 177 fprintf (stderr, "Usage: movemail inbox destfile [POP-password]\n");
211 char* optstring = "i:o:p:l:r:xvk";
212 #else
213 char* optstring = "i:o:v";
214 #endif
215 int opt = getopt_long (argc, argv, optstring, longopts, 0);
216
217 if (opt == EOF)
218 break;
219
220 switch (opt)
221 {
222 case 0:
223 break;
224 case 1: /* one of the standard arguments seen */
225 if (!inname)
226 inname = optarg;
227 else if (!outname)
228 outname = optarg;
229 else
230 poppass = optarg;
231 break;
232
233 case 'i': /* infile */
234 inname = optarg;
235 break;
236
237 case 'o': /* outfile */
238 outname = optarg;
239 break;
240 #ifdef MAIL_USE_POP
241 case 'p': /* pop password */
242 poppass = optarg;
243 break;
244 case 'k': keep_messages=1; break;
245 case 'x': reverse = 1; break;
246 case 'l': /* lines to match */
247 match_lines = atoi (optarg);
248 break;
249
250 case 'r': /* regular expression */
251 regexp_pattern = compile_regex (optarg);
252 break;
253 #endif
254 case 'v': verbose = 1; break;
255 }
256 }
257
258 while (optind < argc)
259 {
260 if (!inname)
261 inname = argv[optind];
262 else if (!outname)
263 outname = argv[optind];
264 else
265 poppass = argv[optind];
266 optind++;
267 }
268
269 if (!inname || !outname)
270 {
271 fprintf (stderr, "Usage: movemail [-rvxk] [-l lines ] [-i] inbox [-o] destfile [[-p] POP-password]\n");
272 exit(1); 178 exit(1);
273 } 179 }
180
181 inname = argv[1];
182 outname = argv[2];
274 183
275 #ifdef MAIL_USE_MMDF 184 #ifdef MAIL_USE_MMDF
276 mmdf_init (argv[0]); 185 mmdf_init (argv[0]);
277 #endif 186 #endif
278 187
299 } 208 }
300 209
301 #ifdef MAIL_USE_POP 210 #ifdef MAIL_USE_POP
302 if (!strncmp (inname, "po:", 3)) 211 if (!strncmp (inname, "po:", 3))
303 { 212 {
304 int retcode = popmail (inname + 3, outname, poppass); 213 int retcode = popmail (inname + 3, outname, argc > 3 ? argv[3] : NULL);
305 exit (retcode); 214 exit (retcode);
306 } 215 }
307 216
308 setuid (getuid ()); 217 setuid (getuid ());
309 #endif /* MAIL_USE_POP */ 218 #endif /* MAIL_USE_POP */
576 #include <winsock.h> 485 #include <winsock.h>
577 #endif 486 #endif
578 #include <stdio.h> 487 #include <stdio.h>
579 #include <pwd.h> 488 #include <pwd.h>
580 489
581 #define POP_ERROR (-1) 490 #define NOTOK (-1)
582 #define POP_RETRIEVED (0) 491 #define OK 0
583 #define POP_DONE (1) 492 #define DONE 1
584 493
585 char *progname; 494 char *progname;
586 FILE *sfi; 495 FILE *sfi;
587 FILE *sfo; 496 FILE *sfo;
588 char ibuffer[BUFSIZ]; 497 char ibuffer[BUFSIZ];
591 500
592 static int 501 static int
593 popmail (char *user, char *outfile, char *password) 502 popmail (char *user, char *outfile, char *password)
594 { 503 {
595 int nmsgs, nbytes; 504 int nmsgs, nbytes;
596 register int i, idx; 505 register int i;
597 int mbfi; 506 int mbfi;
598 short* retrieved_list;
599 FILE *mbf; 507 FILE *mbf;
600 popserver server; 508 popserver server;
601 509
602 VERBOSE(("opening server\r"));
603 server = pop_open (0, user, password, POP_NO_GETPASS); 510 server = pop_open (0, user, password, POP_NO_GETPASS);
604 if (! server) 511 if (! server)
605 { 512 {
606 error (pop_error, NULL, NULL); 513 error (pop_error, NULL, NULL);
607 return (1); 514 return (1);
608 } 515 }
609 516
610 VERBOSE(("stat'ing messages\r"));
611 if (pop_stat (server, &nmsgs, &nbytes)) 517 if (pop_stat (server, &nmsgs, &nbytes))
612 { 518 {
613 error (pop_error, NULL, NULL); 519 error (pop_error, NULL, NULL);
614 return (1); 520 return (1);
615 } 521 }
616 522
617 if (!nmsgs) 523 if (!nmsgs)
618 { 524 {
619 VERBOSE(("closing server\n"));
620 pop_close (server); 525 pop_close (server);
621 return (0); 526 return (0);
622 } 527 }
623
624 /* build a retrieved table */
625 retrieved_list = (short*) xmalloc (sizeof (short) * (nmsgs+1));
626 memset (retrieved_list, 0, sizeof (short) * (nmsgs+1));
627 528
628 mbfi = open (outfile, O_WRONLY | O_CREAT | O_EXCL, 0666); 529 mbfi = open (outfile, O_WRONLY | O_CREAT | O_EXCL, 0666);
629 if (mbfi < 0) 530 if (mbfi < 0)
630 { 531 {
631 pop_close (server); 532 pop_close (server);
643 close (mbfi); 544 close (mbfi);
644 unlink (outfile); 545 unlink (outfile);
645 return (1); 546 return (1);
646 } 547 }
647 548
648 for (idx = 0; idx < nmsgs; idx++) 549 for (i = 1; i <= nmsgs; i++)
649 { 550 {
650 i = reverse ? nmsgs - idx : idx + 1; 551 mbx_delimit_begin (mbf);
651 VERBOSE(("checking message %d \r", i)); 552 if (pop_retr (server, i, mbx_write, mbf) != OK)
652
653 if (!regexp_pattern
654 ||
655 pop_search_top (server, i, match_lines, regexp_pattern) == POP_RETRIEVED)
656 { 553 {
657 VERBOSE(("retrieving message %d \r", i)); 554 error (Errmsg, NULL, NULL);
658 mbx_delimit_begin (mbf); 555 close (mbfi);
659 if (pop_retr (server, i, mbx_write, mbf) != POP_RETRIEVED) 556 return (1);
660 { 557 }
661 error (Errmsg, NULL, NULL); 558 mbx_delimit_end (mbf);
662 close (mbfi); 559 fflush (mbf);
663 return (1); 560 if (ferror (mbf))
664 } 561 {
665 562 error ("Error in fflush: %s", strerror (errno), NULL);
666 retrieved_list[i]=1; 563 pop_close (server);
667 564 close (mbfi);
668 mbx_delimit_end (mbf); 565 return (1);
669 fflush (mbf);
670 if (ferror (mbf))
671 {
672 error ("Error in fflush: %s", strerror (errno), NULL);
673 pop_close (server);
674 close (mbfi);
675 return (1);
676 }
677 } 566 }
678 } 567 }
679 568
680 /* On AFS, a call to write only modifies the file in the local 569 /* On AFS, a call to write only modifies the file in the local
681 * workstation's AFS cache. The changes are not written to the server 570 * workstation's AFS cache. The changes are not written to the server
695 { 584 {
696 error ("Error in close: %s", strerror (errno), NULL); 585 error ("Error in close: %s", strerror (errno), NULL);
697 return (1); 586 return (1);
698 } 587 }
699 588
700 if (!keep_messages) 589 for (i = 1; i <= nmsgs; i++)
701 { 590 {
702 for (i = 1; i <= nmsgs; i++) 591 if (pop_delete (server, i))
703 { 592 {
704 if (retrieved_list[i] == 1) 593 error (pop_error, NULL, NULL);
705 { 594 pop_close (server);
706 VERBOSE(("deleting message %d \r", i)); 595 return (1);
707 if (pop_delete (server, i))
708 {
709 error (pop_error, NULL, NULL);
710 pop_close (server);
711 return (1);
712 }
713 }
714 } 596 }
715 } 597 }
716 598
717 VERBOSE(("closing server \n"));
718 if (pop_quit (server)) 599 if (pop_quit (server))
719 { 600 {
720 error (pop_error, NULL, NULL); 601 error (pop_error, NULL, NULL);
721 return (1); 602 return (1);
722 } 603 }
732 613
733 if (pop_retrieve_first (server, msgno, &line)) 614 if (pop_retrieve_first (server, msgno, &line))
734 { 615 {
735 strncpy (Errmsg, pop_error, sizeof (Errmsg)); 616 strncpy (Errmsg, pop_error, sizeof (Errmsg));
736 Errmsg[sizeof (Errmsg)-1] = '\0'; 617 Errmsg[sizeof (Errmsg)-1] = '\0';
737 return (POP_ERROR); 618 return (NOTOK);
738 } 619 }
739 620
740 while (! (ret = pop_retrieve_next (server, &line))) 621 while (! (ret = pop_retrieve_next (server, &line)))
741 { 622 {
742 if (! line) 623 if (! line)
743 break; 624 break;
744 625
745 if ((*action)(line, arg) != POP_RETRIEVED) 626 if ((*action)(line, arg) != OK)
746 { 627 {
747 strcpy (Errmsg, strerror (errno)); 628 strcpy (Errmsg, strerror (errno));
748 pop_close (server); 629 pop_close (server);
749 return (POP_ERROR); 630 return (NOTOK);
750 } 631 }
751 } 632 }
752 633
753 if (ret) 634 if (ret)
754 { 635 {
755 strncpy (Errmsg, pop_error, sizeof (Errmsg)); 636 strncpy (Errmsg, pop_error, sizeof (Errmsg));
756 Errmsg[sizeof (Errmsg)-1] = '\0'; 637 Errmsg[sizeof (Errmsg)-1] = '\0';
757 return (POP_ERROR); 638 return (NOTOK);
758 } 639 }
759 640
760 return (POP_RETRIEVED); 641 return (OK);
761 }
762
763 /* search the top lines of each message looking for a match */
764 static int
765 pop_search_top (popserver server, int msgno, int lines, struct re_pattern_buffer* regexp)
766 {
767 char *line;
768 int ret;
769 int match = POP_DONE;
770
771 if (pop_top_first (server, msgno, lines, &line))
772 {
773 strncpy (Errmsg, pop_error, sizeof (Errmsg));
774 Errmsg[sizeof (Errmsg)-1] = '\0';
775 return (POP_ERROR);
776 }
777
778 while (! (ret = pop_top_next (server, &line)))
779 {
780 if (! line)
781 break;
782
783 /* VERBOSE (("checking %s\n", line));*/
784 if (match != POP_RETRIEVED)
785 {
786 if ((ret = re_match (regexp, line, strlen (line), 0, 0)) == -2 )
787 {
788 strcpy (Errmsg, "error in regular expression");
789 pop_close (server);
790 return (POP_ERROR);
791 }
792 else if (ret >=0)
793 {
794 match = POP_RETRIEVED;
795 }
796 }
797 }
798
799 if (ret)
800 {
801 strncpy (Errmsg, pop_error, sizeof (Errmsg));
802 Errmsg[sizeof (Errmsg)-1] = '\0';
803 return (POP_ERROR);
804 }
805
806 return match;
807 } 642 }
808 643
809 /* Do this as a macro instead of using strcmp to save on execution time. */ 644 /* Do this as a macro instead of using strcmp to save on execution time. */
810 #define IS_FROM_LINE(a) ((a[0] == 'F') \ 645 #define IS_FROM_LINE(a) ((a[0] == 'F') \
811 && (a[1] == 'r') \ 646 && (a[1] == 'r') \
817 mbx_write (char *line, FILE *mbf) 652 mbx_write (char *line, FILE *mbf)
818 { 653 {
819 if (IS_FROM_LINE (line)) 654 if (IS_FROM_LINE (line))
820 { 655 {
821 if (fputc ('>', mbf) == EOF) 656 if (fputc ('>', mbf) == EOF)
822 return (POP_ERROR); 657 return (NOTOK);
823 } 658 }
824 if (fputs (line, mbf) == EOF) 659 if (fputs (line, mbf) == EOF)
825 return (POP_ERROR); 660 return (NOTOK);
826 if (fputc (0x0a, mbf) == EOF) 661 if (fputc (0x0a, mbf) == EOF)
827 return (POP_ERROR); 662 return (NOTOK);
828 return (POP_RETRIEVED); 663 return (OK);
829 } 664 }
830 665
831 static int 666 static int
832 mbx_delimit_begin (FILE *mbf) 667 mbx_delimit_begin (FILE *mbf)
833 { 668 {
834 if (fputs ("\f\n0, unseen,,\n", mbf) == EOF) 669 if (fputs ("\f\n0, unseen,,\n", mbf) == EOF)
835 return (POP_ERROR); 670 return (NOTOK);
836 return (POP_RETRIEVED); 671 return (OK);
837 } 672 }
838 673
839 static int 674 static int
840 mbx_delimit_end (FILE *mbf) 675 mbx_delimit_end (FILE *mbf)
841 { 676 {
842 if (putc ('\037', mbf) == EOF) 677 if (putc ('\037', mbf) == EOF)
843 return (POP_ERROR); 678 return (NOTOK);
844 return (POP_RETRIEVED); 679 return (OK);
845 } 680 }
846
847 /* Turn a name, which is an ed-style (but Emacs syntax) regular
848 expression, into a real regular expression by compiling it. */
849 static struct re_pattern_buffer*
850 compile_regex (char* pattern)
851 {
852 char *err;
853 struct re_pattern_buffer *patbuf=0;
854
855 patbuf = (struct re_pattern_buffer*) xmalloc (sizeof (struct re_pattern_buffer));
856 patbuf->translate = NULL;
857 patbuf->fastmap = NULL;
858 patbuf->buffer = NULL;
859 patbuf->allocated = 0;
860
861 err = (char*) re_compile_pattern (pattern, strlen (pattern), patbuf);
862 if (err != NULL)
863 {
864 error ("%s while compiling pattern", err, NULL);
865 return 0;
866 }
867
868 return patbuf;
869 }
870
871
872 681
873 #endif /* MAIL_USE_POP */ 682 #endif /* MAIL_USE_POP */
874 683
875 #ifndef HAVE_STRERROR 684 #ifndef HAVE_STRERROR
876 char * 685 static char *
877 strerror (int errnum) 686 strerror (int errnum)
878 { 687 {
879 extern char *sys_errlist[]; 688 extern char *sys_errlist[];
880 extern int sys_nerr; 689 extern int sys_nerr;
881 690