Move DIRECTORY_SEP from lisp.h to config.h
[emacs.git] / lib-src / movemail.c
blob3ea4f4521c112e0d58d6a22dc8fd3ae8d7a3eb27
1 /* movemail foo bar -- move file foo to file bar,
2 locking file foo the way /bin/mail respects.
4 Copyright (C) 1986, 1992-1994, 1996, 1999, 2001-2012
5 Free Software Foundation, Inc.
7 This file is part of GNU Emacs.
9 GNU Emacs is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
14 GNU Emacs is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
23 /* Important notice: defining MAIL_USE_FLOCK or MAIL_USE_LOCKF *will
24 cause loss of mail* if you do it on a system that does not normally
25 use flock as its way of interlocking access to inbox files. The
26 setting of MAIL_USE_FLOCK and MAIL_USE_LOCKF *must agree* with the
27 system's own conventions. It is not a choice that is up to you.
29 So, if your system uses lock files rather than flock, then the only way
30 you can get proper operation is to enable movemail to write lockfiles there.
31 This means you must either give that directory access modes
32 that permit everyone to write lockfiles in it, or you must make movemail
33 a setuid or setgid program. */
36 * Modified January, 1986 by Michael R. Gretzinger (Project Athena)
38 * Added POP (Post Office Protocol) service. When compiled -DMAIL_USE_POP
39 * movemail will accept input filename arguments of the form
40 * "po:username". This will cause movemail to open a connection to
41 * a pop server running on $MAILHOST (environment variable). Movemail
42 * must be setuid to root in order to work with POP.
44 * New module: popmail.c
45 * Modified routines:
46 * main - added code within #ifdef MAIL_USE_POP; added setuid (getuid ())
47 * after POP code.
48 * New routines in movemail.c:
49 * get_errmsg - return pointer to system error message
51 * Modified August, 1993 by Jonathan Kamens (OpenVision Technologies)
53 * Move all of the POP code into a separate file, "pop.c".
54 * Use strerror instead of get_errmsg.
58 #include <config.h>
59 #include <sys/types.h>
60 #include <sys/stat.h>
61 #include <sys/file.h>
62 #include <stdio.h>
63 #include <errno.h>
64 #include <time.h>
66 #include <getopt.h>
67 #include <unistd.h>
68 #ifdef HAVE_FCNTL_H
69 #include <fcntl.h>
70 #endif
71 #include <string.h>
72 #include "syswait.h"
73 #ifdef MAIL_USE_POP
74 #include "pop.h"
75 #endif
77 #ifdef MSDOS
78 #undef access
79 #endif /* MSDOS */
81 #ifdef WINDOWSNT
82 #include "ntlib.h"
83 #undef access
84 #undef unlink
85 #define fork() 0
86 #define wait(var) (*(var) = 0)
87 /* Unfortunately, Samba doesn't seem to properly lock Unix files even
88 though the locking call succeeds (and indeed blocks local access from
89 other NT programs). If you have direct file access using an NFS
90 client or something other than Samba, the locking call might work
91 properly - make sure it does before you enable this!
93 [18-Feb-97 andrewi] I now believe my comment above to be incorrect,
94 since it was based on a misunderstanding of how locking calls are
95 implemented and used on Unix. */
96 //#define DISABLE_DIRECT_ACCESS
98 #include <fcntl.h>
99 #endif /* WINDOWSNT */
101 #ifndef F_OK
102 #define F_OK 0
103 #define X_OK 1
104 #define W_OK 2
105 #define R_OK 4
106 #endif
108 #ifdef WINDOWSNT
109 #include <sys/locking.h>
110 #endif
112 #ifdef MAIL_USE_LOCKF
113 #define MAIL_USE_SYSTEM_LOCK
114 #endif
116 #ifdef MAIL_USE_FLOCK
117 #define MAIL_USE_SYSTEM_LOCK
118 #endif
120 #ifdef MAIL_USE_MMDF
121 extern int lk_open (), lk_close ();
122 #endif
124 #if !defined (MAIL_USE_SYSTEM_LOCK) && !defined (MAIL_USE_MMDF) && \
125 (defined (HAVE_LIBMAIL) || defined (HAVE_LIBLOCKFILE)) && \
126 defined (HAVE_MAILLOCK_H)
127 #include <maillock.h>
128 /* We can't use maillock unless we know what directory system mail
129 files appear in. */
130 #ifdef MAILDIR
131 #define MAIL_USE_MAILLOCK
132 static char *mail_spool_name (char *);
133 #endif
134 #endif
136 static _Noreturn void fatal (const char *s1, const char *s2, const char *s3);
137 static void error (const char *s1, const char *s2, const char *s3);
138 static _Noreturn void pfatal_with_name (char *name);
139 static _Noreturn void pfatal_and_delete (char *name);
140 #ifdef MAIL_USE_POP
141 static int popmail (char *mailbox, char *outfile, int preserve, char *password, int reverse_order);
142 static int pop_retr (popserver server, int msgno, FILE *arg);
143 static int mbx_write (char *line, int len, FILE *mbf);
144 static int mbx_delimit_begin (FILE *mbf);
145 static int mbx_delimit_end (FILE *mbf);
146 #endif
148 #if (defined MAIL_USE_MAILLOCK \
149 || (!defined DISABLE_DIRECT_ACCESS && !defined MAIL_USE_MMDF \
150 && !defined MAIL_USE_SYSTEM_LOCK))
151 /* Like malloc but get fatal error if memory is exhausted. */
153 static void *
154 xmalloc (size_t size)
156 void *result = malloc (size);
157 if (!result)
158 fatal ("virtual memory exhausted", 0, 0);
159 return result;
161 #endif
163 /* Nonzero means this is name of a lock file to delete on fatal error. */
164 static char *delete_lockname;
167 main (int argc, char **argv)
169 char *inname, *outname;
170 int indesc, outdesc;
171 ssize_t nread;
172 int wait_status;
173 int c, preserve_mail = 0;
175 #ifndef MAIL_USE_SYSTEM_LOCK
176 struct stat st;
177 int tem;
178 char *lockname;
179 char *tempname;
180 size_t inname_len, inname_dirlen;
181 int desc;
182 #endif /* not MAIL_USE_SYSTEM_LOCK */
184 #ifdef MAIL_USE_MAILLOCK
185 char *spool_name;
186 #endif
188 #ifdef MAIL_USE_POP
189 int pop_reverse_order = 0;
190 # define ARGSTR "pr"
191 #else /* ! MAIL_USE_POP */
192 # define ARGSTR "p"
193 #endif /* MAIL_USE_POP */
195 uid_t real_gid = getgid ();
196 uid_t priv_gid = getegid ();
198 #ifdef WINDOWSNT
199 /* Ensure all file i/o is in binary mode. */
200 _fmode = _O_BINARY;
201 #endif
203 delete_lockname = 0;
205 while ((c = getopt (argc, argv, ARGSTR)) != EOF)
207 switch (c) {
208 #ifdef MAIL_USE_POP
209 case 'r':
210 pop_reverse_order = 1;
211 break;
212 #endif
213 case 'p':
214 preserve_mail++;
215 break;
216 default:
217 exit (EXIT_FAILURE);
221 if (
222 #ifdef MAIL_USE_POP
223 (argc - optind < 2) || (argc - optind > 3)
224 #else
225 (argc - optind != 2)
226 #endif
229 #ifdef MAIL_USE_POP
230 fprintf (stderr, "Usage: movemail [-p] [-r] inbox destfile%s\n",
231 " [POP-password]");
232 #else
233 fprintf (stderr, "Usage: movemail [-p] inbox destfile%s\n", "");
234 #endif
235 exit (EXIT_FAILURE);
238 inname = argv[optind];
239 outname = argv[optind+1];
241 #ifdef MAIL_USE_MMDF
242 mmdf_init (argv[0]);
243 #endif
245 if (*outname == 0)
246 fatal ("Destination file name is empty", 0, 0);
248 #ifdef MAIL_USE_POP
249 if (!strncmp (inname, "po:", 3))
251 int status;
253 status = popmail (inname + 3, outname, preserve_mail,
254 (argc - optind == 3) ? argv[optind+2] : NULL,
255 pop_reverse_order);
256 exit (status);
259 if (setuid (getuid ()) < 0)
260 fatal ("Failed to drop privileges", 0, 0);
262 #endif /* MAIL_USE_POP */
264 #ifndef DISABLE_DIRECT_ACCESS
265 #ifndef MAIL_USE_MMDF
266 #ifndef MAIL_USE_SYSTEM_LOCK
267 #ifdef MAIL_USE_MAILLOCK
268 spool_name = mail_spool_name (inname);
269 if (spool_name)
271 #ifdef lint
272 lockname = 0;
273 #endif
275 else
276 #endif
278 /* Use a lock file named after our first argument with .lock appended:
279 If it exists, the mail file is locked. */
280 /* Note: this locking mechanism is *required* by the mailer
281 (on systems which use it) to prevent loss of mail.
283 On systems that use a lock file, extracting the mail without locking
284 WILL occasionally cause loss of mail due to timing errors!
286 So, if creation of the lock file fails due to access
287 permission on the mail spool directory, you simply MUST
288 change the permission and/or make movemail a setgid program
289 so it can create lock files properly.
291 You might also wish to verify that your system is one which
292 uses lock files for this purpose. Some systems use other methods.
294 If your system uses the `flock' system call for mail locking,
295 define MAIL_USE_SYSTEM_LOCK in config.h and recompile movemail.
296 If your system type should always define MAIL_USE_SYSTEM_LOCK
297 but does not, send a bug report to bug-gnu-emacs@gnu.org so we
298 can change the default in configure. */
300 inname_len = strlen (inname);
301 lockname = xmalloc (inname_len + sizeof ".lock");
302 strcpy (lockname, inname);
303 strcpy (lockname + inname_len, ".lock");
304 for (inname_dirlen = inname_len;
305 inname_dirlen && !IS_DIRECTORY_SEP (inname[inname_dirlen - 1]);
306 inname_dirlen--)
307 continue;
308 tempname = xmalloc (inname_dirlen + sizeof "EXXXXXX");
310 while (1)
312 /* Create the lock file, but not under the lock file name. */
313 /* Give up if cannot do that. */
315 memcpy (tempname, inname, inname_dirlen);
316 strcpy (tempname + inname_dirlen, "EXXXXXX");
317 #ifdef HAVE_MKSTEMP
318 desc = mkstemp (tempname);
319 #else
320 mktemp (tempname);
321 if (!*tempname)
322 desc = -1;
323 else
325 unlink (tempname);
326 desc = open (tempname, O_WRONLY | O_CREAT | O_EXCL, 0600);
328 #endif
329 if (desc < 0)
331 int mkstemp_errno = errno;
332 error ("error while creating what would become the lock file",
333 0, 0);
334 errno = mkstemp_errno;
335 pfatal_with_name (tempname);
337 close (desc);
339 tem = link (tempname, lockname);
341 #ifdef EPERM
342 if (tem < 0 && errno == EPERM)
343 fatal ("Unable to create hard link between %s and %s",
344 tempname, lockname);
345 #endif
347 unlink (tempname);
348 if (tem >= 0)
349 break;
350 sleep (1);
352 /* If lock file is five minutes old, unlock it.
353 Five minutes should be good enough to cope with crashes
354 and wedgitude, and long enough to avoid being fooled
355 by time differences between machines. */
356 if (stat (lockname, &st) >= 0)
358 time_t now = time (0);
359 if (st.st_ctime < now - 300)
360 unlink (lockname);
364 delete_lockname = lockname;
366 #endif /* not MAIL_USE_SYSTEM_LOCK */
367 #endif /* not MAIL_USE_MMDF */
369 if (fork () == 0)
371 int lockcount = 0;
372 int status = 0;
373 #if defined (MAIL_USE_MAILLOCK) && defined (HAVE_TOUCHLOCK)
374 time_t touched_lock;
375 # ifdef lint
376 touched_lock = 0;
377 # endif
378 #endif
380 if (setuid (getuid ()) < 0 || setregid (-1, real_gid) < 0)
381 fatal ("Failed to drop privileges", 0, 0);
383 #ifndef MAIL_USE_MMDF
384 #ifdef MAIL_USE_SYSTEM_LOCK
385 indesc = open (inname, O_RDWR);
386 #else /* if not MAIL_USE_SYSTEM_LOCK */
387 indesc = open (inname, O_RDONLY);
388 #endif /* not MAIL_USE_SYSTEM_LOCK */
389 #else /* MAIL_USE_MMDF */
390 indesc = lk_open (inname, O_RDONLY, 0, 0, 10);
391 #endif /* MAIL_USE_MMDF */
393 if (indesc < 0)
394 pfatal_with_name (inname);
396 #ifdef BSD_SYSTEM
397 /* In case movemail is setuid to root, make sure the user can
398 read the output file. */
399 /* This is desirable for all systems
400 but I don't want to assume all have the umask system call */
401 umask (umask (0) & 0333);
402 #endif /* BSD_SYSTEM */
403 outdesc = open (outname, O_WRONLY | O_CREAT | O_EXCL, 0666);
404 if (outdesc < 0)
405 pfatal_with_name (outname);
407 if (setregid (-1, priv_gid) < 0)
408 fatal ("Failed to regain privileges", 0, 0);
410 /* This label exists so we can retry locking
411 after a delay, if it got EAGAIN or EBUSY. */
412 retry_lock:
414 /* Try to lock it. */
415 #ifdef MAIL_USE_MAILLOCK
416 if (spool_name)
418 /* The "0 - " is to make it a negative number if maillock returns
419 non-zero. */
420 status = 0 - maillock (spool_name, 1);
421 #ifdef HAVE_TOUCHLOCK
422 touched_lock = time (0);
423 #endif
424 lockcount = 5;
426 else
427 #endif /* MAIL_USE_MAILLOCK */
429 #ifdef MAIL_USE_SYSTEM_LOCK
430 #ifdef MAIL_USE_LOCKF
431 status = lockf (indesc, F_LOCK, 0);
432 #else /* not MAIL_USE_LOCKF */
433 #ifdef WINDOWSNT
434 status = locking (indesc, LK_RLCK, -1L);
435 #else
436 status = flock (indesc, LOCK_EX);
437 #endif
438 #endif /* not MAIL_USE_LOCKF */
439 #endif /* MAIL_USE_SYSTEM_LOCK */
442 /* If it fails, retry up to 5 times
443 for certain failure codes. */
444 if (status < 0)
446 if (++lockcount <= 5)
448 #ifdef EAGAIN
449 if (errno == EAGAIN)
451 sleep (1);
452 goto retry_lock;
454 #endif
455 #ifdef EBUSY
456 if (errno == EBUSY)
458 sleep (1);
459 goto retry_lock;
461 #endif
464 pfatal_with_name (inname);
468 char buf[1024];
470 while (1)
472 nread = read (indesc, buf, sizeof buf);
473 if (nread < 0)
474 pfatal_with_name (inname);
475 if (nread != write (outdesc, buf, nread))
477 int saved_errno = errno;
478 unlink (outname);
479 errno = saved_errno;
480 pfatal_with_name (outname);
482 if (nread < sizeof buf)
483 break;
484 #if defined (MAIL_USE_MAILLOCK) && defined (HAVE_TOUCHLOCK)
485 if (spool_name)
487 time_t now = time (0);
488 if (now - touched_lock > 60)
490 touchlock ();
491 touched_lock = now;
494 #endif /* MAIL_USE_MAILLOCK */
498 #ifdef BSD_SYSTEM
499 if (fsync (outdesc) < 0)
500 pfatal_and_delete (outname);
501 #endif
503 /* Prevent symlink attacks truncating other users' mailboxes */
504 if (setregid (-1, real_gid) < 0)
505 fatal ("Failed to drop privileges", 0, 0);
507 /* Check to make sure no errors before we zap the inbox. */
508 if (close (outdesc) != 0)
509 pfatal_and_delete (outname);
511 #ifdef MAIL_USE_SYSTEM_LOCK
512 if (! preserve_mail)
514 if (ftruncate (indesc, 0L) != 0)
515 pfatal_with_name (inname);
517 #endif /* MAIL_USE_SYSTEM_LOCK */
519 #ifdef MAIL_USE_MMDF
520 lk_close (indesc, 0, 0, 0);
521 #else
522 close (indesc);
523 #endif
525 #ifndef MAIL_USE_SYSTEM_LOCK
526 if (! preserve_mail)
528 /* Delete the input file; if we can't, at least get rid of its
529 contents. */
530 #ifdef MAIL_UNLINK_SPOOL
531 /* This is generally bad to do, because it destroys the permissions
532 that were set on the file. Better to just empty the file. */
533 if (unlink (inname) < 0 && errno != ENOENT)
534 #endif /* MAIL_UNLINK_SPOOL */
535 creat (inname, 0600);
537 #endif /* not MAIL_USE_SYSTEM_LOCK */
539 /* End of mailbox truncation */
540 if (setregid (-1, priv_gid) < 0)
541 fatal ("Failed to regain privileges", 0, 0);
543 #ifdef MAIL_USE_MAILLOCK
544 /* This has to occur in the child, i.e., in the process that
545 acquired the lock! */
546 if (spool_name)
547 mailunlock ();
548 #endif
549 exit (EXIT_SUCCESS);
552 wait (&wait_status);
553 if (!WIFEXITED (wait_status))
554 exit (EXIT_FAILURE);
555 else if (WEXITSTATUS (wait_status) != 0)
556 exit (WEXITSTATUS (wait_status));
558 #if !defined (MAIL_USE_MMDF) && !defined (MAIL_USE_SYSTEM_LOCK)
559 #ifdef MAIL_USE_MAILLOCK
560 if (! spool_name)
561 #endif /* MAIL_USE_MAILLOCK */
562 unlink (lockname);
563 #endif /* not MAIL_USE_MMDF and not MAIL_USE_SYSTEM_LOCK */
565 #endif /* ! DISABLE_DIRECT_ACCESS */
567 return EXIT_SUCCESS;
570 #ifdef MAIL_USE_MAILLOCK
571 /* This function uses stat to confirm that the mail directory is
572 identical to the directory of the input file, rather than just
573 string-comparing the two paths, because one or both of them might
574 be symbolic links pointing to some other directory. */
575 static char *
576 mail_spool_name (char *inname)
578 struct stat stat1, stat2;
579 char *indir, *fname;
580 int status;
582 if (! (fname = strrchr (inname, '/')))
583 return NULL;
585 fname++;
587 if (stat (MAILDIR, &stat1) < 0)
588 return NULL;
590 indir = xmalloc (fname - inname + 1);
591 memcpy (indir, inname, fname - inname);
592 indir[fname-inname] = '\0';
595 status = stat (indir, &stat2);
597 free (indir);
599 if (status < 0)
600 return NULL;
602 if (stat1.st_dev == stat2.st_dev
603 && stat1.st_ino == stat2.st_ino)
604 return fname;
606 return NULL;
608 #endif /* MAIL_USE_MAILLOCK */
610 /* Print error message and exit. */
612 static void
613 fatal (const char *s1, const char *s2, const char *s3)
615 if (delete_lockname)
616 unlink (delete_lockname);
617 error (s1, s2, s3);
618 exit (EXIT_FAILURE);
621 /* Print error message. `s1' is printf control string, `s2' and `s3'
622 are args for it or null. */
624 static void
625 error (const char *s1, const char *s2, const char *s3)
627 fprintf (stderr, "movemail: ");
628 if (s3)
629 fprintf (stderr, s1, s2, s3);
630 else if (s2)
631 fprintf (stderr, s1, s2);
632 else
633 fprintf (stderr, "%s", s1);
634 fprintf (stderr, "\n");
637 static void
638 pfatal_with_name (char *name)
640 fatal ("%s for %s", strerror (errno), name);
643 static void
644 pfatal_and_delete (char *name)
646 char *s = strerror (errno);
647 unlink (name);
648 fatal ("%s for %s", s, name);
651 /* This is the guts of the interface to the Post Office Protocol. */
653 #ifdef MAIL_USE_POP
655 #ifndef WINDOWSNT
656 #include <sys/socket.h>
657 #include <netinet/in.h>
658 #include <netdb.h>
659 #else
660 #undef _WINSOCKAPI_
661 #include <winsock.h>
662 #endif
663 #include <pwd.h>
664 #include <string.h>
666 #define NOTOK (-1)
667 #define OK 0
669 static char Errmsg[200]; /* POP errors, at least, can exceed
670 the original length of 80. */
673 * The full valid syntax for a POP mailbox specification for movemail
674 * is "po:username:hostname". The ":hostname" is optional; if it is
675 * omitted, the MAILHOST environment variable will be consulted. Note
676 * that by the time popmail() is called the "po:" has been stripped
677 * off of the front of the mailbox name.
679 * If the mailbox is in the form "po:username:hostname", then it is
680 * modified by this function -- the second colon is replaced by a
681 * null.
683 * Return a value suitable for passing to `exit'.
686 static int
687 popmail (char *mailbox, char *outfile, int preserve, char *password, int reverse_order)
689 int nmsgs, nbytes;
690 register int i;
691 int mbfi;
692 FILE *mbf;
693 char *getenv (const char *);
694 popserver server;
695 int start, end, increment;
696 char *user, *hostname;
698 user = mailbox;
699 if ((hostname = strchr (mailbox, ':')))
700 *hostname++ = '\0';
702 server = pop_open (hostname, user, password, POP_NO_GETPASS);
703 if (! server)
705 error ("Error connecting to POP server: %s", pop_error, 0);
706 return EXIT_FAILURE;
709 if (pop_stat (server, &nmsgs, &nbytes))
711 error ("Error getting message count from POP server: %s", pop_error, 0);
712 return EXIT_FAILURE;
715 if (!nmsgs)
717 pop_close (server);
718 return EXIT_SUCCESS;
721 mbfi = open (outfile, O_WRONLY | O_CREAT | O_EXCL, 0666);
722 if (mbfi < 0)
724 pop_close (server);
725 error ("Error in open: %s, %s", strerror (errno), outfile);
726 return EXIT_FAILURE;
729 if (fchown (mbfi, getuid (), -1) != 0)
731 int fchown_errno = errno;
732 struct stat st;
733 if (fstat (mbfi, &st) != 0 || st.st_uid != getuid ())
735 pop_close (server);
736 error ("Error in fchown: %s, %s", strerror (fchown_errno), outfile);
737 return EXIT_FAILURE;
741 if ((mbf = fdopen (mbfi, "wb")) == NULL)
743 pop_close (server);
744 error ("Error in fdopen: %s", strerror (errno), 0);
745 close (mbfi);
746 unlink (outfile);
747 return EXIT_FAILURE;
750 if (reverse_order)
752 start = nmsgs;
753 end = 1;
754 increment = -1;
756 else
758 start = 1;
759 end = nmsgs;
760 increment = 1;
763 for (i = start; i * increment <= end * increment; i += increment)
765 mbx_delimit_begin (mbf);
766 if (pop_retr (server, i, mbf) != OK)
768 error ("%s", Errmsg, 0);
769 close (mbfi);
770 return EXIT_FAILURE;
772 mbx_delimit_end (mbf);
773 fflush (mbf);
774 if (ferror (mbf))
776 error ("Error in fflush: %s", strerror (errno), 0);
777 pop_close (server);
778 close (mbfi);
779 return EXIT_FAILURE;
783 /* On AFS, a call to write only modifies the file in the local
784 * workstation's AFS cache. The changes are not written to the server
785 * until a call to fsync or close is made. Users with AFS home
786 * directories have lost mail when over quota because these checks were
787 * not made in previous versions of movemail. */
789 #ifdef BSD_SYSTEM
790 if (fsync (mbfi) < 0)
792 error ("Error in fsync: %s", strerror (errno), 0);
793 return EXIT_FAILURE;
795 #endif
797 if (close (mbfi) == -1)
799 error ("Error in close: %s", strerror (errno), 0);
800 return EXIT_FAILURE;
803 if (! preserve)
804 for (i = 1; i <= nmsgs; i++)
806 if (pop_delete (server, i))
808 error ("Error from POP server: %s", pop_error, 0);
809 pop_close (server);
810 return EXIT_FAILURE;
814 if (pop_quit (server))
816 error ("Error from POP server: %s", pop_error, 0);
817 return EXIT_FAILURE;
820 return EXIT_SUCCESS;
823 static int
824 pop_retr (popserver server, int msgno, FILE *arg)
826 char *line;
827 int ret;
829 if (pop_retrieve_first (server, msgno, &line))
831 snprintf (Errmsg, sizeof Errmsg, "Error from POP server: %s", pop_error);
832 return (NOTOK);
835 while ((ret = pop_retrieve_next (server, &line)) >= 0)
837 if (! line)
838 break;
840 if (mbx_write (line, ret, arg) != OK)
842 strcpy (Errmsg, strerror (errno));
843 pop_close (server);
844 return (NOTOK);
848 if (ret)
850 snprintf (Errmsg, sizeof Errmsg, "Error from POP server: %s", pop_error);
851 return (NOTOK);
854 return (OK);
857 static int
858 mbx_write (char *line, int len, FILE *mbf)
860 #ifdef MOVEMAIL_QUOTE_POP_FROM_LINES
861 /* Do this as a macro instead of using strcmp to save on execution time. */
862 # define IS_FROM_LINE(a) ((a[0] == 'F') \
863 && (a[1] == 'r') \
864 && (a[2] == 'o') \
865 && (a[3] == 'm') \
866 && (a[4] == ' '))
867 if (IS_FROM_LINE (line))
869 if (fputc ('>', mbf) == EOF)
870 return (NOTOK);
872 #endif
873 if (line[0] == '\037')
875 if (fputs ("^_", mbf) == EOF)
876 return (NOTOK);
877 line++;
878 len--;
880 if (fwrite (line, 1, len, mbf) != len)
881 return (NOTOK);
882 if (fputc (0x0a, mbf) == EOF)
883 return (NOTOK);
884 return (OK);
887 static int
888 mbx_delimit_begin (FILE *mbf)
890 time_t now;
891 struct tm *ltime;
892 char fromline[40] = "From movemail ";
894 now = time (NULL);
895 ltime = localtime (&now);
897 strcat (fromline, asctime (ltime));
899 if (fputs (fromline, mbf) == EOF)
900 return (NOTOK);
901 return (OK);
904 static int
905 mbx_delimit_end (FILE *mbf)
907 if (putc ('\n', mbf) == EOF)
908 return (NOTOK);
909 return (OK);
912 #endif /* MAIL_USE_POP */