Mercurial > hg > xemacs-beta
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 |