diff options
| author | Richard M. Stallman | 1994-09-27 19:45:00 +0000 |
|---|---|---|
| committer | Richard M. Stallman | 1994-09-27 19:45:00 +0000 |
| commit | 2e82e3c30a7616dc198336a222defbb9d93a58dd (patch) | |
| tree | 3faf302088b9f06dbe720ec2710a0e24f3112eef /lib-src | |
| parent | 81f940520e99edf76c6f1fd1ed69d5b152277d99 (diff) | |
| download | emacs-2e82e3c30a7616dc198336a222defbb9d93a58dd.tar.gz emacs-2e82e3c30a7616dc198336a222defbb9d93a58dd.zip | |
Improve POP code, move most of it into a separate file.
(mbx_delimit_end, mbx_delimit_begin): Check for errors.
(mbx_write): Check for errors and for From line.
(pop_retr, popmail): Use subroutines in pop.c to do the real work.
(get_errmsg, multiline, getline, putline, pop_stat, pop_command)
(pop_init): Functions deleted.
Diffstat (limited to 'lib-src')
| -rw-r--r-- | lib-src/movemail.c | 354 |
1 files changed, 105 insertions, 249 deletions
diff --git a/lib-src/movemail.c b/lib-src/movemail.c index 9613564f69b..5c5b85ce921 100644 --- a/lib-src/movemail.c +++ b/lib-src/movemail.c | |||
| @@ -46,6 +46,11 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ | |||
| 46 | * New routines in movemail.c: | 46 | * New routines in movemail.c: |
| 47 | * get_errmsg - return pointer to system error message | 47 | * get_errmsg - return pointer to system error message |
| 48 | * | 48 | * |
| 49 | * Modified August, 1993 by Jonathan Kamens (OpenVision Technologies) | ||
| 50 | * | ||
| 51 | * Move all of the POP code into a separate file, "pop.c". | ||
| 52 | * Use strerror instead of get_errmsg. | ||
| 53 | * | ||
| 49 | */ | 54 | */ |
| 50 | 55 | ||
| 51 | #define NO_SHORTNAMES /* Tell config not to load remap.h */ | 56 | #define NO_SHORTNAMES /* Tell config not to load remap.h */ |
| @@ -55,6 +60,9 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ | |||
| 55 | #include <sys/file.h> | 60 | #include <sys/file.h> |
| 56 | #include <errno.h> | 61 | #include <errno.h> |
| 57 | #include <../src/syswait.h> | 62 | #include <../src/syswait.h> |
| 63 | #ifdef MAIL_USE_POP | ||
| 64 | #include "pop.h" | ||
| 65 | #endif | ||
| 58 | 66 | ||
| 59 | #ifdef MSDOS | 67 | #ifdef MSDOS |
| 60 | #undef access | 68 | #undef access |
| @@ -445,346 +453,194 @@ xmalloc (size) | |||
| 445 | char *progname; | 453 | char *progname; |
| 446 | FILE *sfi; | 454 | FILE *sfi; |
| 447 | FILE *sfo; | 455 | FILE *sfo; |
| 456 | char ibuffer[BUFSIZ]; | ||
| 457 | char obuffer[BUFSIZ]; | ||
| 448 | char Errmsg[80]; | 458 | char Errmsg[80]; |
| 449 | 459 | ||
| 450 | static int debug = 0; | ||
| 451 | |||
| 452 | char *get_errmsg (); | ||
| 453 | char *getenv (); | ||
| 454 | int mbx_write (); | ||
| 455 | |||
| 456 | popmail (user, outfile) | 460 | popmail (user, outfile) |
| 457 | char *user; | 461 | char *user; |
| 458 | char *outfile; | 462 | char *outfile; |
| 459 | { | 463 | { |
| 460 | char *host; | ||
| 461 | int nmsgs, nbytes; | 464 | int nmsgs, nbytes; |
| 462 | char response[128]; | ||
| 463 | register int i; | 465 | register int i; |
| 464 | int mbfi; | 466 | int mbfi; |
| 465 | FILE *mbf; | 467 | FILE *mbf; |
| 466 | struct passwd *pw = (struct passwd *) getpwuid (getuid ()); | 468 | char *getenv (); |
| 467 | if (pw == NULL) | 469 | int mbx_write (); |
| 468 | fatal ("cannot determine user name"); | 470 | PopServer server; |
| 469 | 471 | extern char *strerror (); | |
| 470 | host = getenv ("MAILHOST"); | ||
| 471 | if (host == NULL) | ||
| 472 | { | ||
| 473 | fatal ("no MAILHOST defined"); | ||
| 474 | } | ||
| 475 | |||
| 476 | if (pop_init (host) == NOTOK) | ||
| 477 | { | ||
| 478 | fatal (Errmsg); | ||
| 479 | } | ||
| 480 | |||
| 481 | if (getline (response, sizeof response, sfi) != OK) | ||
| 482 | { | ||
| 483 | fatal (response); | ||
| 484 | } | ||
| 485 | 472 | ||
| 486 | if (pop_command ("USER %s", user) == NOTOK | 473 | server = pop_open (0, user, 0, POP_NO_GETPASS); |
| 487 | || pop_command ("RPOP %s", pw->pw_name) == NOTOK) | 474 | if (! server) |
| 488 | { | 475 | { |
| 489 | pop_command ("QUIT"); | 476 | error (pop_error); |
| 490 | fatal (Errmsg); | 477 | return (1); |
| 491 | } | 478 | } |
| 492 | 479 | ||
| 493 | if (pop_stat (&nmsgs, &nbytes) == NOTOK) | 480 | if (pop_stat (server, &nmsgs, &nbytes)) |
| 494 | { | 481 | { |
| 495 | pop_command ("QUIT"); | 482 | error (pop_error); |
| 496 | fatal (Errmsg); | 483 | return (1); |
| 497 | } | 484 | } |
| 498 | 485 | ||
| 499 | if (!nmsgs) | 486 | if (!nmsgs) |
| 500 | { | 487 | { |
| 501 | pop_command ("QUIT"); | 488 | pop_close (server); |
| 502 | return 0; | 489 | return (0); |
| 503 | } | 490 | } |
| 504 | 491 | ||
| 505 | mbfi = open (outfile, O_WRONLY | O_CREAT | O_EXCL, 0666); | 492 | mbfi = open (outfile, O_WRONLY | O_CREAT | O_EXCL, 0666); |
| 506 | if (mbfi < 0) | 493 | if (mbfi < 0) |
| 507 | { | 494 | { |
| 508 | pop_command ("QUIT"); | 495 | pop_close (server); |
| 509 | pfatal_and_delete (outfile); | 496 | error ("Error in open: %s, %s", strerror (errno), outfile); |
| 497 | return (1); | ||
| 510 | } | 498 | } |
| 511 | fchown (mbfi, getuid (), -1); | 499 | fchown (mbfi, getuid (), -1); |
| 512 | 500 | ||
| 513 | if ((mbf = fdopen (mbfi, "w")) == NULL) | 501 | if ((mbf = fdopen (mbfi, "w")) == NULL) |
| 514 | { | 502 | { |
| 515 | pop_command ("QUIT"); | 503 | pop_close (server); |
| 516 | pfatal_and_delete (outfile); | 504 | error ("Error in fdopen: %s", strerror (errno)); |
| 505 | close (mbfi); | ||
| 506 | unlink (outfile); | ||
| 507 | return (1); | ||
| 517 | } | 508 | } |
| 518 | 509 | ||
| 519 | for (i = 1; i <= nmsgs; i++) | 510 | for (i = 1; i <= nmsgs; i++) |
| 520 | { | 511 | { |
| 521 | mbx_delimit_begin (mbf); | 512 | mbx_delimit_begin (mbf); |
| 522 | if (pop_retr (i, mbx_write, mbf) != OK) | 513 | if (pop_retr (server, i, mbx_write, mbf) != OK) |
| 523 | { | 514 | { |
| 524 | pop_command ("QUIT"); | 515 | error (Errmsg); |
| 525 | close (mbfi); | 516 | close (mbfi); |
| 526 | unlink (outfile); | 517 | return (1); |
| 527 | fatal (Errmsg); | ||
| 528 | } | 518 | } |
| 529 | mbx_delimit_end (mbf); | 519 | mbx_delimit_end (mbf); |
| 530 | fflush (mbf); | 520 | fflush (mbf); |
| 521 | if (ferror (mbf)) | ||
| 522 | { | ||
| 523 | error ("Error in fflush: %s", strerror (errno)); | ||
| 524 | pop_close (server); | ||
| 525 | close (mbfi); | ||
| 526 | return (1); | ||
| 527 | } | ||
| 531 | } | 528 | } |
| 532 | 529 | ||
| 530 | /* On AFS, a call to write only modifies the file in the local | ||
| 531 | * workstation's AFS cache. The changes are not written to the server | ||
| 532 | * until a call to fsync or close is made. Users with AFS home | ||
| 533 | * directories have lost mail when over quota because these checks were | ||
| 534 | * not made in previous versions of movemail. */ | ||
| 535 | |||
| 533 | if (fsync (mbfi) < 0) | 536 | if (fsync (mbfi) < 0) |
| 534 | { | 537 | { |
| 535 | pop_command ("QUIT"); | 538 | error ("Error in fsync: %s", strerror (errno)); |
| 536 | pfatal_and_delete (outfile); | 539 | return (1); |
| 537 | } | 540 | } |
| 538 | 541 | ||
| 539 | if (close (mbfi) == -1) | 542 | if (close (mbfi) == -1) |
| 540 | { | 543 | { |
| 541 | pop_command ("QUIT"); | 544 | error ("Error in close: %s", strerror (errno)); |
| 542 | pfatal_and_delete (outfile); | 545 | return (1); |
| 543 | } | 546 | } |
| 544 | 547 | ||
| 545 | for (i = 1; i <= nmsgs; i++) | 548 | for (i = 1; i <= nmsgs; i++) |
| 546 | { | 549 | { |
| 547 | if (pop_command ("DELE %d", i) == NOTOK) | 550 | if (pop_delete (server, i)) |
| 548 | { | 551 | { |
| 549 | /* Better to ignore this failure. */ | 552 | error (pop_error); |
| 553 | pop_close (server); | ||
| 554 | return (1); | ||
| 550 | } | 555 | } |
| 551 | } | 556 | } |
| 552 | 557 | ||
| 553 | pop_command ("QUIT"); | 558 | if (pop_quit (server)) |
| 554 | return (0); | ||
| 555 | } | ||
| 556 | |||
| 557 | pop_init (host) | ||
| 558 | char *host; | ||
| 559 | { | ||
| 560 | register struct hostent *hp; | ||
| 561 | register struct servent *sp; | ||
| 562 | int lport = IPPORT_RESERVED - 1; | ||
| 563 | struct sockaddr_in sin; | ||
| 564 | register int s; | ||
| 565 | |||
| 566 | hp = gethostbyname (host); | ||
| 567 | if (hp == NULL) | ||
| 568 | { | 559 | { |
| 569 | sprintf (Errmsg, "MAILHOST unknown: %s", host); | 560 | error (pop_error); |
| 570 | return NOTOK; | 561 | return (1); |
| 571 | } | 562 | } |
| 572 | |||
| 573 | sp = getservbyname ("pop", "tcp"); | ||
| 574 | if (sp == 0) | ||
| 575 | { | ||
| 576 | strcpy (Errmsg, "tcp/pop: unknown service"); | ||
| 577 | return NOTOK; | ||
| 578 | } | ||
| 579 | |||
| 580 | sin.sin_family = hp->h_addrtype; | ||
| 581 | bcopy (hp->h_addr, (char *)&sin.sin_addr, hp->h_length); | ||
| 582 | sin.sin_port = sp->s_port; | ||
| 583 | s = rresvport (&lport); | ||
| 584 | if (s < 0) | ||
| 585 | { | ||
| 586 | sprintf (Errmsg, "error creating socket: %s", get_errmsg ()); | ||
| 587 | return NOTOK; | ||
| 588 | } | ||
| 589 | |||
| 590 | if (connect (s, (char *)&sin, sizeof sin) < 0) | ||
| 591 | { | ||
| 592 | sprintf (Errmsg, "error during connect: %s", get_errmsg ()); | ||
| 593 | close (s); | ||
| 594 | return NOTOK; | ||
| 595 | } | ||
| 596 | |||
| 597 | sfi = fdopen (s, "r"); | ||
| 598 | sfo = fdopen (s, "w"); | ||
| 599 | if (sfi == NULL || sfo == NULL) | ||
| 600 | { | ||
| 601 | sprintf (Errmsg, "error in fdopen: %s", get_errmsg ()); | ||
| 602 | close (s); | ||
| 603 | return NOTOK; | ||
| 604 | } | ||
| 605 | |||
| 606 | return OK; | ||
| 607 | } | ||
| 608 | |||
| 609 | pop_command (fmt, a, b, c, d) | ||
| 610 | char *fmt; | ||
| 611 | { | ||
| 612 | char buf[128]; | ||
| 613 | char errmsg[64]; | ||
| 614 | |||
| 615 | sprintf (buf, fmt, a, b, c, d); | ||
| 616 | |||
| 617 | if (debug) fprintf (stderr, "---> %s\n", buf); | ||
| 618 | if (putline (buf, Errmsg, sfo) == NOTOK) return NOTOK; | ||
| 619 | |||
| 620 | if (getline (buf, sizeof buf, sfi) != OK) | ||
| 621 | { | ||
| 622 | strcpy (Errmsg, buf); | ||
| 623 | return NOTOK; | ||
| 624 | } | ||
| 625 | |||
| 626 | if (debug) | ||
| 627 | fprintf (stderr, "<--- %s\n", buf); | ||
| 628 | if (*buf != '+') | ||
| 629 | { | ||
| 630 | strcpy (Errmsg, buf); | ||
| 631 | return NOTOK; | ||
| 632 | } | ||
| 633 | else | ||
| 634 | { | ||
| 635 | return OK; | ||
| 636 | } | ||
| 637 | } | ||
| 638 | |||
| 639 | 563 | ||
| 640 | pop_stat (nmsgs, nbytes) | 564 | return (0); |
| 641 | int *nmsgs, *nbytes; | ||
| 642 | { | ||
| 643 | char buf[128]; | ||
| 644 | |||
| 645 | if (debug) | ||
| 646 | fprintf (stderr, "---> STAT\n"); | ||
| 647 | if (putline ("STAT", Errmsg, sfo) == NOTOK) | ||
| 648 | return NOTOK; | ||
| 649 | |||
| 650 | if (getline (buf, sizeof buf, sfi) != OK) | ||
| 651 | { | ||
| 652 | strcpy (Errmsg, buf); | ||
| 653 | return NOTOK; | ||
| 654 | } | ||
| 655 | |||
| 656 | if (debug) fprintf (stderr, "<--- %s\n", buf); | ||
| 657 | if (*buf != '+') | ||
| 658 | { | ||
| 659 | strcpy (Errmsg, buf); | ||
| 660 | return NOTOK; | ||
| 661 | } | ||
| 662 | else | ||
| 663 | { | ||
| 664 | sscanf (buf, "+OK %d %d", nmsgs, nbytes); | ||
| 665 | return OK; | ||
| 666 | } | ||
| 667 | } | 565 | } |
| 668 | 566 | ||
| 669 | pop_retr (msgno, action, arg) | 567 | pop_retr (server, msgno, action, arg) |
| 568 | PopServer server; | ||
| 670 | int (*action)(); | 569 | int (*action)(); |
| 671 | { | 570 | { |
| 672 | char buf[128]; | 571 | extern char *strerror (); |
| 673 | 572 | char *line; | |
| 674 | sprintf (buf, "RETR %d", msgno); | 573 | int ret; |
| 675 | if (debug) fprintf (stderr, "%s\n", buf); | ||
| 676 | if (putline (buf, Errmsg, sfo) == NOTOK) return NOTOK; | ||
| 677 | 574 | ||
| 678 | if (getline (buf, sizeof buf, sfi) != OK) | 575 | if (pop_retrieve_first (server, msgno, &line)) |
| 679 | { | 576 | { |
| 680 | strcpy (Errmsg, buf); | 577 | strncpy (Errmsg, pop_error, sizeof (Errmsg)); |
| 681 | return NOTOK; | 578 | Errmsg[sizeof (Errmsg)-1] = '\0'; |
| 579 | return (NOTOK); | ||
| 682 | } | 580 | } |
| 683 | 581 | ||
| 684 | while (1) | 582 | while (! (ret = pop_retrieve_next (server, &line))) |
| 685 | { | 583 | { |
| 686 | switch (multiline (buf, sizeof buf, sfi)) | 584 | if (! line) |
| 585 | break; | ||
| 586 | |||
| 587 | if ((*action)(line, arg) != OK) | ||
| 687 | { | 588 | { |
| 688 | case OK: | 589 | strcpy (Errmsg, strerror (errno)); |
| 689 | (*action)(buf, arg); | 590 | pop_close (server); |
| 690 | break; | 591 | return (NOTOK); |
| 691 | case DONE: | ||
| 692 | return OK; | ||
| 693 | case NOTOK: | ||
| 694 | strcpy (Errmsg, buf); | ||
| 695 | return NOTOK; | ||
| 696 | } | 592 | } |
| 697 | } | 593 | } |
| 698 | } | ||
| 699 | |||
| 700 | getline (buf, n, f) | ||
| 701 | char *buf; | ||
| 702 | register int n; | ||
| 703 | FILE *f; | ||
| 704 | { | ||
| 705 | register char *p; | ||
| 706 | int c; | ||
| 707 | |||
| 708 | p = buf; | ||
| 709 | while (--n > 0 && (c = fgetc (f)) != EOF) | ||
| 710 | if ((*p++ = c) == '\n') break; | ||
| 711 | |||
| 712 | if (ferror (f)) | ||
| 713 | { | ||
| 714 | strcpy (buf, "error on connection"); | ||
| 715 | return NOTOK; | ||
| 716 | } | ||
| 717 | 594 | ||
| 718 | if (c == EOF && p == buf) | 595 | if (ret) |
| 719 | { | 596 | { |
| 720 | strcpy (buf, "connection closed by foreign host"); | 597 | strncpy (Errmsg, pop_error, sizeof (Errmsg)); |
| 721 | return DONE; | 598 | Errmsg[sizeof (Errmsg)-1] = '\0'; |
| 599 | return (NOTOK); | ||
| 722 | } | 600 | } |
| 723 | 601 | ||
| 724 | *p = NULL; | 602 | return (OK); |
| 725 | if (*--p == '\n') *p = NULL; | ||
| 726 | if (*--p == '\r') *p = NULL; | ||
| 727 | return OK; | ||
| 728 | } | 603 | } |
| 729 | 604 | ||
| 730 | multiline (buf, n, f) | 605 | /* Do this as a macro instead of using strcmp to save on execution time. */ |
| 731 | char *buf; | 606 | #define IS_FROM_LINE(a) ((a[0] == 'F') \ |
| 732 | register int n; | 607 | && (a[1] == 'r') \ |
| 733 | FILE *f; | 608 | && (a[2] == 'o') \ |
| 734 | { | 609 | && (a[3] == 'm') \ |
| 735 | if (getline (buf, n, f) != OK) | 610 | && (a[4] == ' ')) |
| 736 | return NOTOK; | ||
| 737 | if (*buf == '.') | ||
| 738 | { | ||
| 739 | if (*(buf+1) == NULL) | ||
| 740 | return DONE; | ||
| 741 | else | ||
| 742 | strcpy (buf, buf+1); | ||
| 743 | } | ||
| 744 | return OK; | ||
| 745 | } | ||
| 746 | |||
| 747 | char * | ||
| 748 | get_errmsg () | ||
| 749 | { | ||
| 750 | extern int errno; | ||
| 751 | extern char *strerror (); | ||
| 752 | return strerror (errno); | ||
| 753 | } | ||
| 754 | |||
| 755 | putline (buf, err, f) | ||
| 756 | char *buf; | ||
| 757 | char *err; | ||
| 758 | FILE *f; | ||
| 759 | { | ||
| 760 | fprintf (f, "%s\r\n", buf); | ||
| 761 | fflush (f); | ||
| 762 | if (ferror (f)) | ||
| 763 | { | ||
| 764 | strcpy (err, "lost connection"); | ||
| 765 | return NOTOK; | ||
| 766 | } | ||
| 767 | return OK; | ||
| 768 | } | ||
| 769 | 611 | ||
| 612 | int | ||
| 770 | mbx_write (line, mbf) | 613 | mbx_write (line, mbf) |
| 771 | char *line; | 614 | char *line; |
| 772 | FILE *mbf; | 615 | FILE *mbf; |
| 773 | { | 616 | { |
| 774 | fputs (line, mbf); | 617 | if (IS_FROM_LINE (line)) |
| 775 | fputc (0x0a, mbf); | 618 | { |
| 619 | if (fputc ('>', mbf) == EOF) | ||
| 620 | return (NOTOK); | ||
| 621 | } | ||
| 622 | if (fputs (line, mbf) == EOF) | ||
| 623 | return (NOTOK); | ||
| 624 | if (fputc (0x0a, mbf) == EOF) | ||
| 625 | return (NOTOK); | ||
| 626 | return (OK); | ||
| 776 | } | 627 | } |
| 777 | 628 | ||
| 629 | int | ||
| 778 | mbx_delimit_begin (mbf) | 630 | mbx_delimit_begin (mbf) |
| 779 | FILE *mbf; | 631 | FILE *mbf; |
| 780 | { | 632 | { |
| 781 | fputs ("\f\n0, unseen,,\n", mbf); | 633 | if (fputs ("\f\n0, unseen,,\n", mbf) == EOF) |
| 634 | return (NOTOK); | ||
| 635 | return (OK); | ||
| 782 | } | 636 | } |
| 783 | 637 | ||
| 784 | mbx_delimit_end (mbf) | 638 | mbx_delimit_end (mbf) |
| 785 | FILE *mbf; | 639 | FILE *mbf; |
| 786 | { | 640 | { |
| 787 | putc ('\037', mbf); | 641 | if (putc ('\037', mbf) == EOF) |
| 642 | return (NOTOK); | ||
| 643 | return (OK); | ||
| 788 | } | 644 | } |
| 789 | 645 | ||
| 790 | #endif /* MAIL_USE_POP */ | 646 | #endif /* MAIL_USE_POP */ |