aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Eggert2015-03-06 15:41:09 -0800
committerPaul Eggert2015-03-06 15:41:45 -0800
commite1acc3c7efb805d659f9edf345fc18a4647df538 (patch)
tree2127bc1ad49856a87a39c7af2b31e33dd605b6b3
parent20c6b227ea69b9cd47f92d1a7e0935312e8ce83c (diff)
downloademacs-e1acc3c7efb805d659f9edf345fc18a4647df538.tar.gz
emacs-e1acc3c7efb805d659f9edf345fc18a4647df538.zip
Random minor fixes for movemail
* movemail.c: Include <stdbool.h> and <signal.h>. (waitpid) [WINDOWSNT]: New macro. (wait) [WINDOWSNT]: Remove. (main, popmail, pop_retr, mbx_write, mbx_delimit_begin) (mbx_delimit_end): Use bool for boolean. (main): Simplify #if usage a bit. (main): Don't assume EOF == -1. Prefer 'return' to 'exit'. Don't possibly unlink lockname twice, as that's a race condition. Set SIGCHLD to SIG_DFL to work around SysV misfeature. Check for fork failure. Use waitpid, not wait, to avoid a race condition in the unlikely case where we start up with a child. (NOTOK, OK): Remove, in favor of plain boolean. (popmail, pop_retr): Don't get confused about errno, e.g., ferror need not set errno. (popmail): Use fclose (mbf), not close (fileno (mbf)), to also detect any stream-related errors (e.g., memory exhaustion). (pop_retr): Report pop errors separately, since caller now does errno reporting. (mbx_write, mbx_delimit_begin, mbx_delimit_end): Check < 0, not == EOF, as it's a bit faster and (in theory) pickier.
-rw-r--r--lib-src/ChangeLog24
-rw-r--r--lib-src/movemail.c197
2 files changed, 117 insertions, 104 deletions
diff --git a/lib-src/ChangeLog b/lib-src/ChangeLog
index 83855afa675..97868094bda 100644
--- a/lib-src/ChangeLog
+++ b/lib-src/ChangeLog
@@ -1,3 +1,27 @@
12015-03-06 Paul Eggert <eggert@cs.ucla.edu>
2
3 Random minor fixes for movemail
4 * movemail.c: Include <stdbool.h> and <signal.h>.
5 (waitpid) [WINDOWSNT]: New macro.
6 (wait) [WINDOWSNT]: Remove.
7 (main, popmail, pop_retr, mbx_write, mbx_delimit_begin)
8 (mbx_delimit_end): Use bool for boolean.
9 (main): Simplify #if usage a bit.
10 (main): Don't assume EOF == -1. Prefer 'return' to 'exit'. Don't
11 possibly unlink lockname twice, as that's a race condition. Set
12 SIGCHLD to SIG_DFL to work around SysV misfeature. Check for fork
13 failure. Use waitpid, not wait, to avoid a race condition in the
14 unlikely case where we start up with a child.
15 (NOTOK, OK): Remove, in favor of plain boolean.
16 (popmail, pop_retr): Don't get confused about errno, e.g., ferror
17 need not set errno.
18 (popmail): Use fclose (mbf), not close (fileno (mbf)), to also
19 detect any stream-related errors (e.g., memory exhaustion).
20 (pop_retr): Report pop errors separately, since caller now does
21 errno reporting.
22 (mbx_write, mbx_delimit_begin, mbx_delimit_end): Check < 0, not ==
23 EOF, as it's a bit faster and (in theory) pickier.
24
12015-02-27 Mark Laws <mdl@60hz.org> 252015-02-27 Mark Laws <mdl@60hz.org>
2 26
3 Support daemon mode on MS-Windows (bug#19688) 27 Support daemon mode on MS-Windows (bug#19688)
diff --git a/lib-src/movemail.c b/lib-src/movemail.c
index 5008c9b15f7..1618a6980e9 100644
--- a/lib-src/movemail.c
+++ b/lib-src/movemail.c
@@ -59,6 +59,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
59#include <sys/types.h> 59#include <sys/types.h>
60#include <sys/stat.h> 60#include <sys/stat.h>
61#include <sys/file.h> 61#include <sys/file.h>
62#include <stdbool.h>
62#include <stdio.h> 63#include <stdio.h>
63#include <errno.h> 64#include <errno.h>
64#include <time.h> 65#include <time.h>
@@ -66,6 +67,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
66#include <getopt.h> 67#include <getopt.h>
67#include <unistd.h> 68#include <unistd.h>
68#include <fcntl.h> 69#include <fcntl.h>
70#include <signal.h>
69#include <string.h> 71#include <string.h>
70#include "syswait.h" 72#include "syswait.h"
71#ifdef MAIL_USE_POP 73#ifdef MAIL_USE_POP
@@ -81,7 +83,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
81#undef access 83#undef access
82#undef unlink 84#undef unlink
83#define fork() 0 85#define fork() 0
84#define wait(var) (*(var) = 0) 86#define waitpid(child, var, flags) (*(var) = 0)
85/* Unfortunately, Samba doesn't seem to properly lock Unix files even 87/* Unfortunately, Samba doesn't seem to properly lock Unix files even
86 though the locking call succeeds (and indeed blocks local access from 88 though the locking call succeeds (and indeed blocks local access from
87 other NT programs). If you have direct file access using an NFS 89 other NT programs). If you have direct file access using an NFS
@@ -134,11 +136,11 @@ static void error (const char *s1, const char *s2, const char *s3);
134static _Noreturn void pfatal_with_name (char *name); 136static _Noreturn void pfatal_with_name (char *name);
135static _Noreturn void pfatal_and_delete (char *name); 137static _Noreturn void pfatal_and_delete (char *name);
136#ifdef MAIL_USE_POP 138#ifdef MAIL_USE_POP
137static int popmail (char *mailbox, char *outfile, int preserve, char *password, int reverse_order); 139static int popmail (char *, char *, bool, char *, bool);
138static int pop_retr (popserver server, int msgno, FILE *arg); 140static bool pop_retr (popserver, int, FILE *);
139static int mbx_write (char *line, int len, FILE *mbf); 141static bool mbx_write (char *, int, FILE *);
140static int mbx_delimit_begin (FILE *mbf); 142static bool mbx_delimit_begin (FILE *);
141static int mbx_delimit_end (FILE *mbf); 143static bool mbx_delimit_end (FILE *);
142#endif 144#endif
143 145
144#if (defined MAIL_USE_MAILLOCK \ 146#if (defined MAIL_USE_MAILLOCK \
@@ -166,23 +168,21 @@ main (int argc, char **argv)
166 int indesc, outdesc; 168 int indesc, outdesc;
167 ssize_t nread; 169 ssize_t nread;
168 int wait_status; 170 int wait_status;
169 int c, preserve_mail = 0; 171 int c;
172 bool preserve_mail = false;
170 173
171#ifndef MAIL_USE_SYSTEM_LOCK 174#ifndef MAIL_USE_SYSTEM_LOCK
172 struct stat st; 175 struct stat st;
173 int tem; 176 int tem;
174 char *lockname;
175 char *tempname; 177 char *tempname;
176 size_t inname_len, inname_dirlen; 178 size_t inname_len, inname_dirlen;
177 int desc; 179 int desc;
178#endif /* not MAIL_USE_SYSTEM_LOCK */ 180#endif /* not MAIL_USE_SYSTEM_LOCK */
179 181
180#ifdef MAIL_USE_MAILLOCK 182 char *spool_name = 0;
181 char *spool_name;
182#endif
183 183
184#ifdef MAIL_USE_POP 184#ifdef MAIL_USE_POP
185 int pop_reverse_order = 0; 185 bool pop_reverse_order = false;
186# define ARGSTR "pr" 186# define ARGSTR "pr"
187#else /* ! MAIL_USE_POP */ 187#else /* ! MAIL_USE_POP */
188# define ARGSTR "p" 188# define ARGSTR "p"
@@ -193,19 +193,19 @@ main (int argc, char **argv)
193 193
194 delete_lockname = 0; 194 delete_lockname = 0;
195 195
196 while ((c = getopt (argc, argv, ARGSTR)) != EOF) 196 while (0 <= (c = getopt (argc, argv, ARGSTR)))
197 { 197 {
198 switch (c) { 198 switch (c) {
199#ifdef MAIL_USE_POP 199#ifdef MAIL_USE_POP
200 case 'r': 200 case 'r':
201 pop_reverse_order = 1; 201 pop_reverse_order = true;
202 break; 202 break;
203#endif 203#endif
204 case 'p': 204 case 'p':
205 preserve_mail++; 205 preserve_mail = true;
206 break; 206 break;
207 default: 207 default:
208 exit (EXIT_FAILURE); 208 return EXIT_FAILURE;
209 } 209 }
210 } 210 }
211 211
@@ -223,7 +223,7 @@ main (int argc, char **argv)
223#else 223#else
224 fprintf (stderr, "Usage: movemail [-p] inbox destfile%s\n", ""); 224 fprintf (stderr, "Usage: movemail [-p] inbox destfile%s\n", "");
225#endif 225#endif
226 exit (EXIT_FAILURE); 226 return EXIT_FAILURE;
227 } 227 }
228 228
229 inname = argv[optind]; 229 inname = argv[optind];
@@ -244,7 +244,7 @@ main (int argc, char **argv)
244 status = popmail (inname + 3, outname, preserve_mail, 244 status = popmail (inname + 3, outname, preserve_mail,
245 (argc - optind == 3) ? argv[optind+2] : NULL, 245 (argc - optind == 3) ? argv[optind+2] : NULL,
246 pop_reverse_order); 246 pop_reverse_order);
247 exit (status); 247 return status;
248 } 248 }
249 249
250 if (setuid (getuid ()) < 0) 250 if (setuid (getuid ()) < 0)
@@ -253,18 +253,15 @@ main (int argc, char **argv)
253#endif /* MAIL_USE_POP */ 253#endif /* MAIL_USE_POP */
254 254
255#ifndef DISABLE_DIRECT_ACCESS 255#ifndef DISABLE_DIRECT_ACCESS
256
257 char *lockname = 0;
258
256#ifndef MAIL_USE_MMDF 259#ifndef MAIL_USE_MMDF
257#ifndef MAIL_USE_SYSTEM_LOCK 260#ifndef MAIL_USE_SYSTEM_LOCK
258#ifdef MAIL_USE_MAILLOCK 261#ifdef MAIL_USE_MAILLOCK
259 spool_name = mail_spool_name (inname); 262 spool_name = mail_spool_name (inname);
260 if (spool_name)
261 {
262#ifdef lint
263 lockname = 0;
264#endif
265 }
266 else
267#endif 263#endif
264 if (! spool_name)
268 { 265 {
269 /* Use a lock file named after our first argument with .lock appended: 266 /* Use a lock file named after our first argument with .lock appended:
270 If it exists, the mail file is locked. */ 267 If it exists, the mail file is locked. */
@@ -292,7 +289,7 @@ main (int argc, char **argv)
292 continue; 289 continue;
293 tempname = xmalloc (inname_dirlen + sizeof "EXXXXXX"); 290 tempname = xmalloc (inname_dirlen + sizeof "EXXXXXX");
294 291
295 while (1) 292 while (true)
296 { 293 {
297 /* Create the lock file, but not under the lock file name. */ 294 /* Create the lock file, but not under the lock file name. */
298 /* Give up if cannot do that. */ 295 /* Give up if cannot do that. */
@@ -328,7 +325,10 @@ main (int argc, char **argv)
328 { 325 {
329 time_t now = time (0); 326 time_t now = time (0);
330 if (st.st_ctime < now - 300) 327 if (st.st_ctime < now - 300)
331 unlink (lockname); 328 {
329 unlink (lockname);
330 lockname = 0;
331 }
332 } 332 }
333 } 333 }
334 334
@@ -337,15 +337,20 @@ main (int argc, char **argv)
337#endif /* not MAIL_USE_SYSTEM_LOCK */ 337#endif /* not MAIL_USE_SYSTEM_LOCK */
338#endif /* not MAIL_USE_MMDF */ 338#endif /* not MAIL_USE_MMDF */
339 339
340 if (fork () == 0) 340#ifdef SIGCHLD
341 signal (SIGCHLD, SIG_DFL);
342#endif
343
344 pid_t child = fork ();
345 if (child < 0)
346 fatal ("Error in fork; %s", strerror (errno), 0);
347
348 if (child == 0)
341 { 349 {
342 int lockcount = 0; 350 int lockcount = 0;
343 int status = 0; 351 int status = 0;
344#if defined (MAIL_USE_MAILLOCK) && defined (HAVE_TOUCHLOCK) 352#if defined (MAIL_USE_MAILLOCK) && defined (HAVE_TOUCHLOCK)
345 time_t touched_lock; 353 time_t touched_lock IF_LINT (= 0);
346# ifdef lint
347 touched_lock = 0;
348# endif
349#endif 354#endif
350 355
351 if (setuid (getuid ()) < 0 || setregid (-1, real_gid) < 0) 356 if (setuid (getuid ()) < 0 || setregid (-1, real_gid) < 0)
@@ -382,9 +387,9 @@ main (int argc, char **argv)
382#ifdef MAIL_USE_MAILLOCK 387#ifdef MAIL_USE_MAILLOCK
383 if (spool_name) 388 if (spool_name)
384 { 389 {
385 /* The "0 - " is to make it a negative number if maillock returns 390 /* The "-" is to make it a negative number if maillock returns
386 non-zero. */ 391 non-zero. */
387 status = 0 - maillock (spool_name, 1); 392 status = - maillock (spool_name, 1);
388#ifdef HAVE_TOUCHLOCK 393#ifdef HAVE_TOUCHLOCK
389 touched_lock = time (0); 394 touched_lock = time (0);
390#endif 395#endif
@@ -422,7 +427,7 @@ main (int argc, char **argv)
422 { 427 {
423 char buf[1024]; 428 char buf[1024];
424 429
425 while (1) 430 while (true)
426 { 431 {
427 nread = read (indesc, buf, sizeof buf); 432 nread = read (indesc, buf, sizeof buf);
428 if (nread < 0) 433 if (nread < 0)
@@ -464,7 +469,7 @@ main (int argc, char **argv)
464#ifdef MAIL_USE_SYSTEM_LOCK 469#ifdef MAIL_USE_SYSTEM_LOCK
465 if (! preserve_mail) 470 if (! preserve_mail)
466 { 471 {
467 if (ftruncate (indesc, 0L) != 0) 472 if (ftruncate (indesc, 0) != 0)
468 pfatal_with_name (inname); 473 pfatal_with_name (inname);
469 } 474 }
470#endif /* MAIL_USE_SYSTEM_LOCK */ 475#endif /* MAIL_USE_SYSTEM_LOCK */
@@ -499,21 +504,18 @@ main (int argc, char **argv)
499 if (spool_name) 504 if (spool_name)
500 mailunlock (); 505 mailunlock ();
501#endif 506#endif
502 exit (EXIT_SUCCESS); 507 return EXIT_SUCCESS;
503 } 508 }
504 509
505 wait (&wait_status); 510 if (waitpid (child, &wait_status, 0) < 0)
511 fatal ("Error in waitpid; %s", strerror (errno), 0);
506 if (!WIFEXITED (wait_status)) 512 if (!WIFEXITED (wait_status))
507 exit (EXIT_FAILURE); 513 return EXIT_FAILURE;
508 else if (WEXITSTATUS (wait_status) != 0) 514 else if (WEXITSTATUS (wait_status) != 0)
509 exit (WEXITSTATUS (wait_status)); 515 return WEXITSTATUS (wait_status);
510 516
511#if !defined (MAIL_USE_MMDF) && !defined (MAIL_USE_SYSTEM_LOCK) 517 if (lockname)
512#ifdef MAIL_USE_MAILLOCK
513 if (! spool_name)
514#endif /* MAIL_USE_MAILLOCK */
515 unlink (lockname); 518 unlink (lockname);
516#endif /* not MAIL_USE_MMDF and not MAIL_USE_SYSTEM_LOCK */
517 519
518#endif /* ! DISABLE_DIRECT_ACCESS */ 520#endif /* ! DISABLE_DIRECT_ACCESS */
519 521
@@ -616,12 +618,6 @@ pfatal_and_delete (char *name)
616#include <pwd.h> 618#include <pwd.h>
617#include <string.h> 619#include <string.h>
618 620
619#define NOTOK (-1)
620#define OK 0
621
622static char Errmsg[200]; /* POP errors, at least, can exceed
623 the original length of 80. */
624
625/* 621/*
626 * The full valid syntax for a POP mailbox specification for movemail 622 * The full valid syntax for a POP mailbox specification for movemail
627 * is "po:username:hostname". The ":hostname" is optional; if it is 623 * is "po:username:hostname". The ":hostname" is optional; if it is
@@ -637,10 +633,11 @@ static char Errmsg[200]; /* POP errors, at least, can exceed
637 */ 633 */
638 634
639static int 635static int
640popmail (char *mailbox, char *outfile, int preserve, char *password, int reverse_order) 636popmail (char *mailbox, char *outfile, bool preserve, char *password,
637 bool reverse_order)
641{ 638{
642 int nmsgs, nbytes; 639 int nmsgs, nbytes;
643 register int i; 640 int i;
644 int mbfi; 641 int mbfi;
645 FILE *mbf; 642 FILE *mbf;
646 popserver server; 643 popserver server;
@@ -690,7 +687,8 @@ popmail (char *mailbox, char *outfile, int preserve, char *password, int reverse
690 } 687 }
691 } 688 }
692 689
693 if ((mbf = fdopen (mbfi, "wb")) == NULL) 690 mbf = fdopen (mbfi, "wb");
691 if (!mbf)
694 { 692 {
695 pop_close (server); 693 pop_close (server);
696 error ("Error in fdopen: %s", strerror (errno), 0); 694 error ("Error in fdopen: %s", strerror (errno), 0);
@@ -713,35 +711,28 @@ popmail (char *mailbox, char *outfile, int preserve, char *password, int reverse
713 } 711 }
714 712
715 for (i = start; i * increment <= end * increment; i += increment) 713 for (i = start; i * increment <= end * increment; i += increment)
716 { 714 if (! (mbx_delimit_begin (mbf)
717 if (mbx_delimit_begin (mbf) != OK 715 && pop_retr (server, i, mbf)
718 || pop_retr (server, i, mbf) != OK) 716 && mbx_delimit_end (mbf)
719 { 717 && fflush (mbf) == 0))
720 error ("%s", Errmsg, 0); 718 {
721 close (mbfi); 719 if (errno)
722 return EXIT_FAILURE; 720 error ("Error in POP retrieving: %s", strerror (errno), 0);
723 } 721 pop_close (server);
724 mbx_delimit_end (mbf); 722 fclose (mbf);
725 fflush (mbf); 723 return EXIT_FAILURE;
726 if (ferror (mbf)) 724 }
727 {
728 error ("Error in fflush: %s", strerror (errno), 0);
729 pop_close (server);
730 close (mbfi);
731 return EXIT_FAILURE;
732 }
733 }
734 725
735 if (fsync (mbfi) != 0 && errno != EINVAL) 726 if (fsync (mbfi) != 0 && errno != EINVAL)
736 { 727 {
737 error ("Error in fsync: %s", strerror (errno), 0); 728 error ("Error in fsync: %s", strerror (errno), 0);
738 close (mbfi); 729 fclose (mbf);
739 return EXIT_FAILURE; 730 return EXIT_FAILURE;
740 } 731 }
741 732
742 if (close (mbfi) != 0) 733 if (fclose (mbf) != 0)
743 { 734 {
744 error ("Error in close: %s", strerror (errno), 0); 735 error ("Error in fclose: %s", strerror (errno), 0);
745 return EXIT_FAILURE; 736 return EXIT_FAILURE;
746 } 737 }
747 738
@@ -765,7 +756,7 @@ popmail (char *mailbox, char *outfile, int preserve, char *password, int reverse
765 return EXIT_SUCCESS; 756 return EXIT_SUCCESS;
766} 757}
767 758
768static int 759static bool
769pop_retr (popserver server, int msgno, FILE *arg) 760pop_retr (popserver server, int msgno, FILE *arg)
770{ 761{
771 char *line; 762 char *line;
@@ -773,8 +764,9 @@ pop_retr (popserver server, int msgno, FILE *arg)
773 764
774 if (pop_retrieve_first (server, msgno, &line)) 765 if (pop_retrieve_first (server, msgno, &line))
775 { 766 {
776 snprintf (Errmsg, sizeof Errmsg, "Error from POP server: %s", pop_error); 767 error ("Error from POP server: %s", pop_error, 0);
777 return (NOTOK); 768 errno = 0;
769 return false;
778 } 770 }
779 771
780 while ((ret = pop_retrieve_next (server, &line)) >= 0) 772 while ((ret = pop_retrieve_next (server, &line)) >= 0)
@@ -782,24 +774,26 @@ pop_retr (popserver server, int msgno, FILE *arg)
782 if (! line) 774 if (! line)
783 break; 775 break;
784 776
785 if (mbx_write (line, ret, arg) != OK) 777 if (! mbx_write (line, ret, arg))
786 { 778 {
787 strcpy (Errmsg, strerror (errno)); 779 int write_errno = errno;
788 pop_close (server); 780 pop_close (server);
789 return (NOTOK); 781 errno = write_errno;
782 return false;
790 } 783 }
791 } 784 }
792 785
793 if (ret) 786 if (ret)
794 { 787 {
795 snprintf (Errmsg, sizeof Errmsg, "Error from POP server: %s", pop_error); 788 error ("Error from POP server: %s", pop_error, 0);
796 return (NOTOK); 789 errno = 0;
790 return false;
797 } 791 }
798 792
799 return (OK); 793 return true;
800} 794}
801 795
802static int 796static bool
803mbx_write (char *line, int len, FILE *mbf) 797mbx_write (char *line, int len, FILE *mbf)
804{ 798{
805#ifdef MOVEMAIL_QUOTE_POP_FROM_LINES 799#ifdef MOVEMAIL_QUOTE_POP_FROM_LINES
@@ -811,47 +805,42 @@ mbx_write (char *line, int len, FILE *mbf)
811 && (a[4] == ' ')) 805 && (a[4] == ' '))
812 if (IS_FROM_LINE (line)) 806 if (IS_FROM_LINE (line))
813 { 807 {
814 if (fputc ('>', mbf) == EOF) 808 if (fputc ('>', mbf) < 0)
815 return (NOTOK); 809 return false;
816 } 810 }
817#endif 811#endif
818 if (line[0] == '\037') 812 if (line[0] == '\037')
819 { 813 {
820 if (fputs ("^_", mbf) == EOF) 814 if (fputs ("^_", mbf) < 0)
821 return (NOTOK); 815 return false;
822 line++; 816 line++;
823 len--; 817 len--;
824 } 818 }
825 if (fwrite (line, 1, len, mbf) != len) 819 return fwrite (line, 1, len, mbf) == len && 0 <= fputc ('\n', mbf);
826 return (NOTOK);
827 if (fputc (0x0a, mbf) == EOF)
828 return (NOTOK);
829 return (OK);
830} 820}
831 821
832static int 822static bool
833mbx_delimit_begin (FILE *mbf) 823mbx_delimit_begin (FILE *mbf)
834{ 824{
835 time_t now = time (NULL); 825 time_t now = time (NULL);
836 struct tm *ltime = localtime (&now); 826 struct tm *ltime = localtime (&now);
837 if (!ltime) 827 if (!ltime)
838 return NOTOK; 828 return false;
839 829
840 char fromline[100]; 830 char fromline[100];
841 if (! strftime (fromline, sizeof fromline, 831 if (! strftime (fromline, sizeof fromline,
842 "From movemail %a %b %e %T %Y\n", ltime)) 832 "From movemail %a %b %e %T %Y\n", ltime))
843 return NOTOK; 833 {
844 if (fputs (fromline, mbf) == EOF) 834 errno = EOVERFLOW;
845 return (NOTOK); 835 return false;
846 return (OK); 836 }
837 return 0 <= fputs (fromline, mbf);
847} 838}
848 839
849static int 840static bool
850mbx_delimit_end (FILE *mbf) 841mbx_delimit_end (FILE *mbf)
851{ 842{
852 if (putc ('\n', mbf) == EOF) 843 return 0 <= putc ('\n', mbf);
853 return (NOTOK);
854 return (OK);
855} 844}
856 845
857#endif /* MAIL_USE_POP */ 846#endif /* MAIL_USE_POP */