Merge from trunk
[emacs.git] / lib-src / movemail.c
blob4cf97cbac186cf9ebde583628060faa117fbbb8a
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-2011
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 #ifdef HAVE_STRING_H
72 #include <string.h>
73 #endif
74 #include "syswait.h"
75 #ifdef MAIL_USE_POP
76 #include "pop.h"
77 #endif
79 #ifdef MSDOS
80 #undef access
81 #endif /* MSDOS */
83 #ifdef WINDOWSNT
84 #include "ntlib.h"
85 #undef access
86 #undef unlink
87 #define fork() 0
88 #define wait(var) (*(var) = 0)
89 /* Unfortunately, Samba doesn't seem to properly lock Unix files even
90 though the locking call succeeds (and indeed blocks local access from
91 other NT programs). If you have direct file access using an NFS
92 client or something other than Samba, the locking call might work
93 properly - make sure it does before you enable this!
95 [18-Feb-97 andrewi] I now believe my comment above to be incorrect,
96 since it was based on a misunderstanding of how locking calls are
97 implemented and used on Unix. */
98 //#define DISABLE_DIRECT_ACCESS
100 #include <fcntl.h>
101 #endif /* WINDOWSNT */
103 #ifndef F_OK
104 #define F_OK 0
105 #define X_OK 1
106 #define W_OK 2
107 #define R_OK 4
108 #endif
110 #ifdef WINDOWSNT
111 #include <sys/locking.h>
112 #endif
114 #ifdef MAIL_USE_LOCKF
115 #define MAIL_USE_SYSTEM_LOCK
116 #endif
118 #ifdef MAIL_USE_FLOCK
119 #define MAIL_USE_SYSTEM_LOCK
120 #endif
122 #ifdef MAIL_USE_MMDF
123 extern int lk_open (), lk_close ();
124 #endif
126 #if !defined (MAIL_USE_SYSTEM_LOCK) && !defined (MAIL_USE_MMDF) && \
127 (defined (HAVE_LIBMAIL) || defined (HAVE_LIBLOCKFILE)) && \
128 defined (HAVE_MAILLOCK_H)
129 #include <maillock.h>
130 /* We can't use maillock unless we know what directory system mail
131 files appear in. */
132 #ifdef MAILDIR
133 #define MAIL_USE_MAILLOCK
134 static char *mail_spool_name (char *);
135 #endif
136 #endif
138 #ifndef HAVE_STRERROR
139 char *strerror (int);
140 #endif
142 static void fatal (const char *s1, const char *s2, const char *s3) NO_RETURN;
143 static void error (const char *s1, const char *s2, const char *s3);
144 static void pfatal_with_name (char *name) NO_RETURN;
145 static void pfatal_and_delete (char *name) NO_RETURN;
146 static char *concat (const char *s1, const char *s2, const char *s3);
147 static long *xmalloc (unsigned int size);
148 #ifdef MAIL_USE_POP
149 static int popmail (char *mailbox, char *outfile, int preserve, char *password, int reverse_order);
150 static int pop_retr (popserver server, int msgno, FILE *arg);
151 static int mbx_write (char *line, int len, FILE *mbf);
152 static int mbx_delimit_begin (FILE *mbf);
153 static int mbx_delimit_end (FILE *mbf);
154 #endif
156 /* Nonzero means this is name of a lock file to delete on fatal error. */
157 static char *delete_lockname;
160 main (int argc, char **argv)
162 char *inname, *outname;
163 int indesc, outdesc;
164 ssize_t nread;
165 int wait_status;
166 int c, preserve_mail = 0;
168 #ifndef MAIL_USE_SYSTEM_LOCK
169 struct stat st;
170 int tem;
171 char *lockname, *p;
172 char *tempname;
173 int desc;
174 #endif /* not MAIL_USE_SYSTEM_LOCK */
176 #ifdef MAIL_USE_MAILLOCK
177 char *spool_name;
178 #endif
180 #ifdef MAIL_USE_POP
181 int pop_reverse_order = 0;
182 # define ARGSTR "pr"
183 #else /* ! MAIL_USE_POP */
184 # define ARGSTR "p"
185 #endif /* MAIL_USE_POP */
187 uid_t real_gid = getgid();
188 uid_t priv_gid = getegid();
190 #ifdef WINDOWSNT
191 /* Ensure all file i/o is in binary mode. */
192 _fmode = _O_BINARY;
193 #endif
195 delete_lockname = 0;
197 while ((c = getopt (argc, argv, ARGSTR)) != EOF)
199 switch (c) {
200 #ifdef MAIL_USE_POP
201 case 'r':
202 pop_reverse_order = 1;
203 break;
204 #endif
205 case 'p':
206 preserve_mail++;
207 break;
208 default:
209 exit (EXIT_FAILURE);
213 if (
214 #ifdef MAIL_USE_POP
215 (argc - optind < 2) || (argc - optind > 3)
216 #else
217 (argc - optind != 2)
218 #endif
221 #ifdef MAIL_USE_POP
222 fprintf (stderr, "Usage: movemail [-p] [-r] inbox destfile%s\n",
223 " [POP-password]");
224 #else
225 fprintf (stderr, "Usage: movemail [-p] inbox destfile%s\n", "");
226 #endif
227 exit (EXIT_FAILURE);
230 inname = argv[optind];
231 outname = argv[optind+1];
233 #ifdef MAIL_USE_MMDF
234 mmdf_init (argv[0]);
235 #endif
237 if (*outname == 0)
238 fatal ("Destination file name is empty", 0, 0);
240 #ifdef MAIL_USE_POP
241 if (!strncmp (inname, "po:", 3))
243 int status;
245 status = popmail (inname + 3, outname, preserve_mail,
246 (argc - optind == 3) ? argv[optind+2] : NULL,
247 pop_reverse_order);
248 exit (status);
251 if (setuid (getuid ()) < 0)
252 fatal ("Failed to drop privileges", 0, 0);
254 #endif /* MAIL_USE_POP */
256 #ifndef DISABLE_DIRECT_ACCESS
257 #ifndef MAIL_USE_MMDF
258 #ifndef MAIL_USE_SYSTEM_LOCK
259 #ifdef MAIL_USE_MAILLOCK
260 spool_name = mail_spool_name (inname);
261 if (spool_name)
263 #ifdef lint
264 lockname = 0;
265 #endif
267 else
268 #endif
270 #ifndef DIRECTORY_SEP
271 #define DIRECTORY_SEP '/'
272 #endif
273 #ifndef IS_DIRECTORY_SEP
274 #define IS_DIRECTORY_SEP(_c_) ((_c_) == DIRECTORY_SEP)
275 #endif
277 /* Use a lock file named after our first argument with .lock appended:
278 If it exists, the mail file is locked. */
279 /* Note: this locking mechanism is *required* by the mailer
280 (on systems which use it) to prevent loss of mail.
282 On systems that use a lock file, extracting the mail without locking
283 WILL occasionally cause loss of mail due to timing errors!
285 So, if creation of the lock file fails
286 due to access permission on the mail spool directory,
287 you simply MUST change the permission
288 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
292 which 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 or the s-*.h file
296 and recompile movemail. If the s- file for your system
297 should define MAIL_USE_SYSTEM_LOCK but does not, send a bug report
298 to bug-gnu-emacs@prep.ai.mit.edu so we can fix it. */
300 lockname = concat (inname, ".lock", "");
301 tempname = (char *) xmalloc (strlen (inname) + strlen ("EXXXXXX") + 1);
302 strcpy (tempname, inname);
303 p = tempname + strlen (tempname);
304 while (p != tempname && !IS_DIRECTORY_SEP (p[-1]))
305 p--;
306 *p = 0;
307 strcpy (p, "EXXXXXX");
308 mktemp (tempname);
309 unlink (tempname);
311 while (1)
313 /* Create the lock file, but not under the lock file name. */
314 /* Give up if cannot do that. */
315 desc = open (tempname, O_WRONLY | O_CREAT | O_EXCL, 0666);
316 if (desc < 0)
318 char *message = (char *) xmalloc (strlen (tempname) + 50);
319 sprintf (message, "creating %s, which would become the lock file",
320 tempname);
321 pfatal_with_name (message);
323 close (desc);
325 tem = link (tempname, lockname);
327 #ifdef EPERM
328 if (tem < 0 && errno == EPERM)
329 fatal ("Unable to create hard link between %s and %s",
330 tempname, lockname);
331 #endif
333 unlink (tempname);
334 if (tem >= 0)
335 break;
336 sleep (1);
338 /* If lock file is five minutes old, unlock it.
339 Five minutes should be good enough to cope with crashes
340 and wedgitude, and long enough to avoid being fooled
341 by time differences between machines. */
342 if (stat (lockname, &st) >= 0)
344 time_t now = time (0);
345 if (st.st_ctime < now - 300)
346 unlink (lockname);
350 delete_lockname = lockname;
352 #endif /* not MAIL_USE_SYSTEM_LOCK */
353 #endif /* not MAIL_USE_MMDF */
355 if (fork () == 0)
357 int lockcount = 0;
358 int status = 0;
359 #if defined (MAIL_USE_MAILLOCK) && defined (HAVE_TOUCHLOCK)
360 time_t touched_lock;
361 # ifdef lint
362 touched_lock = 0;
363 # endif
364 #endif
366 if (setuid (getuid ()) < 0 || setregid (-1, real_gid) < 0)
367 fatal ("Failed to drop privileges", 0, 0);
369 #ifndef MAIL_USE_MMDF
370 #ifdef MAIL_USE_SYSTEM_LOCK
371 indesc = open (inname, O_RDWR);
372 #else /* if not MAIL_USE_SYSTEM_LOCK */
373 indesc = open (inname, O_RDONLY);
374 #endif /* not MAIL_USE_SYSTEM_LOCK */
375 #else /* MAIL_USE_MMDF */
376 indesc = lk_open (inname, O_RDONLY, 0, 0, 10);
377 #endif /* MAIL_USE_MMDF */
379 if (indesc < 0)
380 pfatal_with_name (inname);
382 #ifdef BSD_SYSTEM
383 /* In case movemail is setuid to root, make sure the user can
384 read the output file. */
385 /* This is desirable for all systems
386 but I don't want to assume all have the umask system call */
387 umask (umask (0) & 0333);
388 #endif /* BSD_SYSTEM */
389 outdesc = open (outname, O_WRONLY | O_CREAT | O_EXCL, 0666);
390 if (outdesc < 0)
391 pfatal_with_name (outname);
393 if (setregid (-1, priv_gid) < 0)
394 fatal ("Failed to regain privileges", 0, 0);
396 /* This label exists so we can retry locking
397 after a delay, if it got EAGAIN or EBUSY. */
398 retry_lock:
400 /* Try to lock it. */
401 #ifdef MAIL_USE_MAILLOCK
402 if (spool_name)
404 /* The "0 - " is to make it a negative number if maillock returns
405 non-zero. */
406 status = 0 - maillock (spool_name, 1);
407 #ifdef HAVE_TOUCHLOCK
408 touched_lock = time (0);
409 #endif
410 lockcount = 5;
412 else
413 #endif /* MAIL_USE_MAILLOCK */
415 #ifdef MAIL_USE_SYSTEM_LOCK
416 #ifdef MAIL_USE_LOCKF
417 status = lockf (indesc, F_LOCK, 0);
418 #else /* not MAIL_USE_LOCKF */
419 #ifdef WINDOWSNT
420 status = locking (indesc, LK_RLCK, -1L);
421 #else
422 status = flock (indesc, LOCK_EX);
423 #endif
424 #endif /* not MAIL_USE_LOCKF */
425 #endif /* MAIL_USE_SYSTEM_LOCK */
428 /* If it fails, retry up to 5 times
429 for certain failure codes. */
430 if (status < 0)
432 if (++lockcount <= 5)
434 #ifdef EAGAIN
435 if (errno == EAGAIN)
437 sleep (1);
438 goto retry_lock;
440 #endif
441 #ifdef EBUSY
442 if (errno == EBUSY)
444 sleep (1);
445 goto retry_lock;
447 #endif
450 pfatal_with_name (inname);
454 char buf[1024];
456 while (1)
458 nread = read (indesc, buf, sizeof buf);
459 if (nread < 0)
460 pfatal_with_name (inname);
461 if (nread != write (outdesc, buf, nread))
463 int saved_errno = errno;
464 unlink (outname);
465 errno = saved_errno;
466 pfatal_with_name (outname);
468 if (nread < sizeof buf)
469 break;
470 #if defined (MAIL_USE_MAILLOCK) && defined (HAVE_TOUCHLOCK)
471 if (spool_name)
473 time_t now = time (0);
474 if (now - touched_lock > 60)
476 touchlock ();
477 touched_lock = now;
480 #endif /* MAIL_USE_MAILLOCK */
484 #ifdef BSD_SYSTEM
485 if (fsync (outdesc) < 0)
486 pfatal_and_delete (outname);
487 #endif
489 /* Prevent symlink attacks truncating other users' mailboxes */
490 if (setregid (-1, real_gid) < 0)
491 fatal ("Failed to drop privileges", 0, 0);
493 /* Check to make sure no errors before we zap the inbox. */
494 if (close (outdesc) != 0)
495 pfatal_and_delete (outname);
497 #ifdef MAIL_USE_SYSTEM_LOCK
498 if (! preserve_mail)
500 if (ftruncate (indesc, 0L) != 0)
501 pfatal_with_name (inname);
503 #endif /* MAIL_USE_SYSTEM_LOCK */
505 #ifdef MAIL_USE_MMDF
506 lk_close (indesc, 0, 0, 0);
507 #else
508 close (indesc);
509 #endif
511 #ifndef MAIL_USE_SYSTEM_LOCK
512 if (! preserve_mail)
514 /* Delete the input file; if we can't, at least get rid of its
515 contents. */
516 #ifdef MAIL_UNLINK_SPOOL
517 /* This is generally bad to do, because it destroys the permissions
518 that were set on the file. Better to just empty the file. */
519 if (unlink (inname) < 0 && errno != ENOENT)
520 #endif /* MAIL_UNLINK_SPOOL */
521 creat (inname, 0600);
523 #endif /* not MAIL_USE_SYSTEM_LOCK */
525 /* End of mailbox truncation */
526 if (setregid (-1, priv_gid) < 0)
527 fatal ("Failed to regain privileges", 0, 0);
529 #ifdef MAIL_USE_MAILLOCK
530 /* This has to occur in the child, i.e., in the process that
531 acquired the lock! */
532 if (spool_name)
533 mailunlock ();
534 #endif
535 exit (EXIT_SUCCESS);
538 wait (&wait_status);
539 if (!WIFEXITED (wait_status))
540 exit (EXIT_FAILURE);
541 else if (WRETCODE (wait_status) != 0)
542 exit (WRETCODE (wait_status));
544 #if !defined (MAIL_USE_MMDF) && !defined (MAIL_USE_SYSTEM_LOCK)
545 #ifdef MAIL_USE_MAILLOCK
546 if (! spool_name)
547 #endif /* MAIL_USE_MAILLOCK */
548 unlink (lockname);
549 #endif /* not MAIL_USE_MMDF and not MAIL_USE_SYSTEM_LOCK */
551 #endif /* ! DISABLE_DIRECT_ACCESS */
553 return EXIT_SUCCESS;
556 #ifdef MAIL_USE_MAILLOCK
557 /* This function uses stat to confirm that the mail directory is
558 identical to the directory of the input file, rather than just
559 string-comparing the two paths, because one or both of them might
560 be symbolic links pointing to some other directory. */
561 static char *
562 mail_spool_name (char *inname)
564 struct stat stat1, stat2;
565 char *indir, *fname;
566 int status;
568 if (! (fname = strrchr (inname, '/')))
569 return NULL;
571 fname++;
573 if (stat (MAILDIR, &stat1) < 0)
574 return NULL;
576 indir = (char *) xmalloc (fname - inname + 1);
577 strncpy (indir, inname, fname - inname);
578 indir[fname-inname] = '\0';
581 status = stat (indir, &stat2);
583 free (indir);
585 if (status < 0)
586 return NULL;
588 if (stat1.st_dev == stat2.st_dev
589 && stat1.st_ino == stat2.st_ino)
590 return fname;
592 return NULL;
594 #endif /* MAIL_USE_MAILLOCK */
596 /* Print error message and exit. */
598 static void
599 fatal (const char *s1, const char *s2, const char *s3)
601 if (delete_lockname)
602 unlink (delete_lockname);
603 error (s1, s2, s3);
604 exit (EXIT_FAILURE);
607 /* Print error message. `s1' is printf control string, `s2' and `s3'
608 are args for it or null. */
610 static void
611 error (const char *s1, const char *s2, const char *s3)
613 fprintf (stderr, "movemail: ");
614 if (s3)
615 fprintf (stderr, s1, s2, s3);
616 else if (s2)
617 fprintf (stderr, s1, s2);
618 else
619 fprintf (stderr, "%s", s1);
620 fprintf (stderr, "\n");
623 static void
624 pfatal_with_name (char *name)
626 fatal ("%s for %s", strerror (errno), name);
629 static void
630 pfatal_and_delete (char *name)
632 char *s = strerror (errno);
633 unlink (name);
634 fatal ("%s for %s", s, name);
637 /* Return a newly-allocated string whose contents concatenate those of s1, s2, s3. */
639 static char *
640 concat (const char *s1, const char *s2, const char *s3)
642 size_t len1 = strlen (s1), len2 = strlen (s2), len3 = strlen (s3);
643 char *result = (char *) xmalloc (len1 + len2 + len3 + 1);
645 strcpy (result, s1);
646 strcpy (result + len1, s2);
647 strcpy (result + len1 + len2, s3);
648 *(result + len1 + len2 + len3) = 0;
650 return result;
653 /* Like malloc but get fatal error if memory is exhausted. */
655 static long *
656 xmalloc (unsigned int size)
658 long *result = (long *) malloc (size);
659 if (!result)
660 fatal ("virtual memory exhausted", 0, 0);
661 return result;
664 /* This is the guts of the interface to the Post Office Protocol. */
666 #ifdef MAIL_USE_POP
668 #ifndef WINDOWSNT
669 #include <sys/socket.h>
670 #include <netinet/in.h>
671 #include <netdb.h>
672 #else
673 #undef _WINSOCKAPI_
674 #include <winsock.h>
675 #endif
676 #include <pwd.h>
677 #include <string.h>
679 #define NOTOK (-1)
680 #define OK 0
682 static char Errmsg[200]; /* POP errors, at least, can exceed
683 the original length of 80. */
686 * The full valid syntax for a POP mailbox specification for movemail
687 * is "po:username:hostname". The ":hostname" is optional; if it is
688 * omitted, the MAILHOST environment variable will be consulted. Note
689 * that by the time popmail() is called the "po:" has been stripped
690 * off of the front of the mailbox name.
692 * If the mailbox is in the form "po:username:hostname", then it is
693 * modified by this function -- the second colon is replaced by a
694 * null.
696 * Return a value suitable for passing to `exit'.
699 static int
700 popmail (char *mailbox, char *outfile, int preserve, char *password, int reverse_order)
702 int nmsgs, nbytes;
703 register int i;
704 int mbfi;
705 FILE *mbf;
706 char *getenv (const char *);
707 popserver server;
708 int start, end, increment;
709 char *user, *hostname;
711 user = mailbox;
712 if ((hostname = strchr (mailbox, ':')))
713 *hostname++ = '\0';
715 server = pop_open (hostname, user, password, POP_NO_GETPASS);
716 if (! server)
718 error ("Error connecting to POP server: %s", pop_error, 0);
719 return EXIT_FAILURE;
722 if (pop_stat (server, &nmsgs, &nbytes))
724 error ("Error getting message count from POP server: %s", pop_error, 0);
725 return EXIT_FAILURE;
728 if (!nmsgs)
730 pop_close (server);
731 return EXIT_SUCCESS;
734 mbfi = open (outfile, O_WRONLY | O_CREAT | O_EXCL, 0666);
735 if (mbfi < 0)
737 pop_close (server);
738 error ("Error in open: %s, %s", strerror (errno), outfile);
739 return EXIT_FAILURE;
742 if (fchown (mbfi, getuid (), -1) != 0)
744 int fchown_errno = errno;
745 struct stat st;
746 if (fstat (mbfi, &st) != 0 || st.st_uid != getuid ())
748 pop_close (server);
749 error ("Error in fchown: %s, %s", strerror (fchown_errno), outfile);
750 return EXIT_FAILURE;
754 if ((mbf = fdopen (mbfi, "wb")) == NULL)
756 pop_close (server);
757 error ("Error in fdopen: %s", strerror (errno), 0);
758 close (mbfi);
759 unlink (outfile);
760 return EXIT_FAILURE;
763 if (reverse_order)
765 start = nmsgs;
766 end = 1;
767 increment = -1;
769 else
771 start = 1;
772 end = nmsgs;
773 increment = 1;
776 for (i = start; i * increment <= end * increment; i += increment)
778 mbx_delimit_begin (mbf);
779 if (pop_retr (server, i, mbf) != OK)
781 error ("%s", Errmsg, 0);
782 close (mbfi);
783 return EXIT_FAILURE;
785 mbx_delimit_end (mbf);
786 fflush (mbf);
787 if (ferror (mbf))
789 error ("Error in fflush: %s", strerror (errno), 0);
790 pop_close (server);
791 close (mbfi);
792 return EXIT_FAILURE;
796 /* On AFS, a call to write only modifies the file in the local
797 * workstation's AFS cache. The changes are not written to the server
798 * until a call to fsync or close is made. Users with AFS home
799 * directories have lost mail when over quota because these checks were
800 * not made in previous versions of movemail. */
802 #ifdef BSD_SYSTEM
803 if (fsync (mbfi) < 0)
805 error ("Error in fsync: %s", strerror (errno), 0);
806 return EXIT_FAILURE;
808 #endif
810 if (close (mbfi) == -1)
812 error ("Error in close: %s", strerror (errno), 0);
813 return EXIT_FAILURE;
816 if (! preserve)
817 for (i = 1; i <= nmsgs; i++)
819 if (pop_delete (server, i))
821 error ("Error from POP server: %s", pop_error, 0);
822 pop_close (server);
823 return EXIT_FAILURE;
827 if (pop_quit (server))
829 error ("Error from POP server: %s", pop_error, 0);
830 return EXIT_FAILURE;
833 return EXIT_SUCCESS;
836 static int
837 pop_retr (popserver server, int msgno, FILE *arg)
839 char *line;
840 int ret;
842 if (pop_retrieve_first (server, msgno, &line))
844 char *msg = concat ("Error from POP server: ", pop_error, "");
845 strncpy (Errmsg, msg, sizeof (Errmsg));
846 Errmsg[sizeof (Errmsg)-1] = '\0';
847 free (msg);
848 return (NOTOK);
851 while ((ret = pop_retrieve_next (server, &line)) >= 0)
853 if (! line)
854 break;
856 if (mbx_write (line, ret, arg) != OK)
858 strcpy (Errmsg, strerror (errno));
859 pop_close (server);
860 return (NOTOK);
864 if (ret)
866 char *msg = concat ("Error from POP server: ", pop_error, "");
867 strncpy (Errmsg, msg, sizeof (Errmsg));
868 Errmsg[sizeof (Errmsg)-1] = '\0';
869 free (msg);
870 return (NOTOK);
873 return (OK);
876 static int
877 mbx_write (char *line, int len, FILE *mbf)
879 #ifdef MOVEMAIL_QUOTE_POP_FROM_LINES
880 /* Do this as a macro instead of using strcmp to save on execution time. */
881 # define IS_FROM_LINE(a) ((a[0] == 'F') \
882 && (a[1] == 'r') \
883 && (a[2] == 'o') \
884 && (a[3] == 'm') \
885 && (a[4] == ' '))
886 if (IS_FROM_LINE (line))
888 if (fputc ('>', mbf) == EOF)
889 return (NOTOK);
891 #endif
892 if (line[0] == '\037')
894 if (fputs ("^_", mbf) == EOF)
895 return (NOTOK);
896 line++;
897 len--;
899 if (fwrite (line, 1, len, mbf) != len)
900 return (NOTOK);
901 if (fputc (0x0a, mbf) == EOF)
902 return (NOTOK);
903 return (OK);
906 static int
907 mbx_delimit_begin (FILE *mbf)
909 time_t now;
910 struct tm *ltime;
911 char fromline[40] = "From movemail ";
913 now = time (NULL);
914 ltime = localtime (&now);
916 strcat (fromline, asctime (ltime));
918 if (fputs (fromline, mbf) == EOF)
919 return (NOTOK);
920 return (OK);
923 static int
924 mbx_delimit_end (FILE *mbf)
926 if (putc ('\n', mbf) == EOF)
927 return (NOTOK);
928 return (OK);
931 #endif /* MAIL_USE_POP */
933 #ifndef HAVE_STRERROR
934 char *
935 strerror (errnum)
936 int errnum;
938 extern char *sys_errlist[];
939 extern int sys_nerr;
941 if (errnum >= 0 && errnum < sys_nerr)
942 return sys_errlist[errnum];
943 return (char *) "Unknown error";
946 #endif /* ! HAVE_STRERROR */
949 /* movemail.c ends here */