aboutsummaryrefslogtreecommitdiffstats
path: root/lib-src
diff options
context:
space:
mode:
authorRichard M. Stallman1994-09-27 19:45:00 +0000
committerRichard M. Stallman1994-09-27 19:45:00 +0000
commit2e82e3c30a7616dc198336a222defbb9d93a58dd (patch)
tree3faf302088b9f06dbe720ec2710a0e24f3112eef /lib-src
parent81f940520e99edf76c6f1fd1ed69d5b152277d99 (diff)
downloademacs-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.c354
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)
445char *progname; 453char *progname;
446FILE *sfi; 454FILE *sfi;
447FILE *sfo; 455FILE *sfo;
456char ibuffer[BUFSIZ];
457char obuffer[BUFSIZ];
448char Errmsg[80]; 458char Errmsg[80];
449 459
450static int debug = 0;
451
452char *get_errmsg ();
453char *getenv ();
454int mbx_write ();
455
456popmail (user, outfile) 460popmail (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
557pop_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
609pop_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
640pop_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
669pop_retr (msgno, action, arg) 567pop_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
700getline (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
730multiline (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
747char *
748get_errmsg ()
749{
750 extern int errno;
751 extern char *strerror ();
752 return strerror (errno);
753}
754
755putline (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
612int
770mbx_write (line, mbf) 613mbx_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
629int
778mbx_delimit_begin (mbf) 630mbx_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
784mbx_delimit_end (mbf) 638mbx_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 */