Add new VC methods: vc-log-incoming and vc-log-outgoing.
[emacs.git] / lib-src / movemail.c
blobea30724135135913fd90b72406e05f3df3e2f2c3
1 /* movemail foo bar -- move file foo to file bar,
2 locking file foo the way /bin/mail respects.
3 Copyright (C) 1986, 1992, 1993, 1994, 1996, 1999, 2001, 2002, 2003, 2004,
4 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
6 This file is part of GNU Emacs.
8 GNU Emacs is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
13 GNU Emacs is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
22 /* Important notice: defining MAIL_USE_FLOCK or MAIL_USE_LOCKF *will
23 cause loss of mail* if you do it on a system that does not normally
24 use flock as its way of interlocking access to inbox files. The
25 setting of MAIL_USE_FLOCK and MAIL_USE_LOCKF *must agree* with the
26 system's own conventions. It is not a choice that is up to you.
28 So, if your system uses lock files rather than flock, then the only way
29 you can get proper operation is to enable movemail to write lockfiles there.
30 This means you must either give that directory access modes
31 that permit everyone to write lockfiles in it, or you must make movemail
32 a setuid or setgid program. */
35 * Modified January, 1986 by Michael R. Gretzinger (Project Athena)
37 * Added POP (Post Office Protocol) service. When compiled -DMAIL_USE_POP
38 * movemail will accept input filename arguments of the form
39 * "po:username". This will cause movemail to open a connection to
40 * a pop server running on $MAILHOST (environment variable). Movemail
41 * must be setuid to root in order to work with POP.
43 * New module: popmail.c
44 * Modified routines:
45 * main - added code within #ifdef MAIL_USE_POP; added setuid (getuid ())
46 * after POP code.
47 * New routines in movemail.c:
48 * get_errmsg - return pointer to system error message
50 * Modified August, 1993 by Jonathan Kamens (OpenVision Technologies)
52 * Move all of the POP code into a separate file, "pop.c".
53 * Use strerror instead of get_errmsg.
57 #include <config.h>
58 #include <sys/types.h>
59 #include <sys/stat.h>
60 #include <sys/file.h>
61 #include <stdio.h>
62 #include <errno.h>
63 #include <time.h>
65 #include <getopt.h>
66 #ifdef HAVE_UNISTD_H
67 #include <unistd.h>
68 #endif
69 #ifdef HAVE_FCNTL_H
70 #include <fcntl.h>
71 #endif
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 #ifndef DIRECTORY_SEP
82 #define DIRECTORY_SEP '/'
83 #endif
84 #ifndef IS_DIRECTORY_SEP
85 #define IS_DIRECTORY_SEP(_c_) ((_c_) == DIRECTORY_SEP)
86 #endif
88 #ifdef WINDOWSNT
89 #include "ntlib.h"
90 #undef access
91 #undef unlink
92 #define fork() 0
93 #define wait(var) (*(var) = 0)
94 /* Unfortunately, Samba doesn't seem to properly lock Unix files even
95 though the locking call succeeds (and indeed blocks local access from
96 other NT programs). If you have direct file access using an NFS
97 client or something other than Samba, the locking call might work
98 properly - make sure it does before you enable this!
100 [18-Feb-97 andrewi] I now believe my comment above to be incorrect,
101 since it was based on a misunderstanding of how locking calls are
102 implemented and used on Unix. */
103 //#define DISABLE_DIRECT_ACCESS
105 #include <fcntl.h>
106 #endif /* WINDOWSNT */
108 #ifndef F_OK
109 #define F_OK 0
110 #define X_OK 1
111 #define W_OK 2
112 #define R_OK 4
113 #endif
115 #ifdef WINDOWSNT
116 #include <sys/locking.h>
117 #endif
119 #ifdef MAIL_USE_LOCKF
120 #define MAIL_USE_SYSTEM_LOCK
121 #endif
123 #ifdef MAIL_USE_FLOCK
124 #define MAIL_USE_SYSTEM_LOCK
125 #endif
127 #ifdef MAIL_USE_MMDF
128 extern int lk_open (), lk_close ();
129 #endif
131 #if !defined (MAIL_USE_SYSTEM_LOCK) && !defined (MAIL_USE_MMDF) && \
132 (defined (HAVE_LIBMAIL) || defined (HAVE_LIBLOCKFILE)) && \
133 defined (HAVE_MAILLOCK_H)
134 #include <maillock.h>
135 /* We can't use maillock unless we know what directory system mail
136 files appear in. */
137 #ifdef MAILDIR
138 #define MAIL_USE_MAILLOCK
139 static char *mail_spool_name ();
140 #endif
141 #endif
143 char *strerror ();
144 #ifdef HAVE_INDEX
145 extern char *index __P ((const char *, int));
146 #endif
147 #ifdef HAVE_RINDEX
148 extern char *rindex __P((const char *, int));
149 #endif
151 void fatal ();
152 void error ();
153 void pfatal_with_name ();
154 void pfatal_and_delete ();
155 char *concat ();
156 long *xmalloc ();
157 int popmail ();
158 int pop_retr ();
159 int mbx_write ();
160 int mbx_delimit_begin ();
161 int mbx_delimit_end ();
163 /* Nonzero means this is name of a lock file to delete on fatal error. */
164 char *delete_lockname;
167 main (argc, argv)
168 int argc;
169 char **argv;
171 char *inname, *outname;
172 int indesc, outdesc;
173 int nread;
174 int status;
175 int c, preserve_mail = 0;
177 #ifndef MAIL_USE_SYSTEM_LOCK
178 struct stat st;
179 long now;
180 int tem;
181 char *lockname, *p;
182 char *tempname;
183 int desc;
184 #endif /* not MAIL_USE_SYSTEM_LOCK */
186 #ifdef MAIL_USE_MAILLOCK
187 char *spool_name;
188 #endif
190 #ifdef MAIL_USE_POP
191 int pop_reverse_order = 0;
192 # define ARGSTR "pr"
193 #else /* ! MAIL_USE_POP */
194 # define ARGSTR "p"
195 #endif /* MAIL_USE_POP */
197 uid_t real_gid = getgid();
198 uid_t priv_gid = getegid();
200 #ifdef WINDOWSNT
201 /* Ensure all file i/o is in binary mode. */
202 _fmode = _O_BINARY;
203 #endif
205 delete_lockname = 0;
207 while ((c = getopt (argc, argv, ARGSTR)) != EOF)
209 switch (c) {
210 #ifdef MAIL_USE_POP
211 case 'r':
212 pop_reverse_order = 1;
213 break;
214 #endif
215 case 'p':
216 preserve_mail++;
217 break;
218 default:
219 exit (EXIT_FAILURE);
223 if (
224 #ifdef MAIL_USE_POP
225 (argc - optind < 2) || (argc - optind > 3)
226 #else
227 (argc - optind != 2)
228 #endif
231 #ifdef MAIL_USE_POP
232 fprintf (stderr, "Usage: movemail [-p] [-r] inbox destfile%s\n",
233 " [POP-password]");
234 #else
235 fprintf (stderr, "Usage: movemail [-p] inbox destfile%s\n", "");
236 #endif
237 exit (EXIT_FAILURE);
240 inname = argv[optind];
241 outname = argv[optind+1];
243 #ifdef MAIL_USE_MMDF
244 mmdf_init (argv[0]);
245 #endif
247 if (*outname == 0)
248 fatal ("Destination file name is empty", 0, 0);
250 #ifdef MAIL_USE_POP
251 if (!strncmp (inname, "po:", 3))
253 int status;
255 status = popmail (inname + 3, outname, preserve_mail,
256 (argc - optind == 3) ? argv[optind+2] : NULL,
257 pop_reverse_order);
258 exit (status);
261 if (setuid (getuid ()) < 0)
262 fatal ("Failed to drop privileges", 0, 0);
264 #endif /* MAIL_USE_POP */
266 #ifndef DISABLE_DIRECT_ACCESS
267 #ifndef MAIL_USE_MMDF
268 #ifndef MAIL_USE_SYSTEM_LOCK
269 #ifdef MAIL_USE_MAILLOCK
270 spool_name = mail_spool_name (inname);
271 if (! spool_name)
272 #endif
274 /* Use a lock file named after our first argument with .lock appended:
275 If it exists, the mail file is locked. */
276 /* Note: this locking mechanism is *required* by the mailer
277 (on systems which use it) to prevent loss of mail.
279 On systems that use a lock file, extracting the mail without locking
280 WILL occasionally cause loss of mail due to timing errors!
282 So, if creation of the lock file fails
283 due to access permission on the mail spool directory,
284 you simply MUST change the permission
285 and/or make movemail a setgid program
286 so it can create lock files properly.
288 You might also wish to verify that your system is one
289 which uses lock files for this purpose. Some systems use other methods.
291 If your system uses the `flock' system call for mail locking,
292 define MAIL_USE_SYSTEM_LOCK in config.h or the s-*.h file
293 and recompile movemail. If the s- file for your system
294 should define MAIL_USE_SYSTEM_LOCK but does not, send a bug report
295 to bug-gnu-emacs@prep.ai.mit.edu so we can fix it. */
297 lockname = concat (inname, ".lock", "");
298 tempname = (char *) xmalloc (strlen (inname) + strlen ("EXXXXXX") + 1);
299 strcpy (tempname, inname);
300 p = tempname + strlen (tempname);
301 while (p != tempname && !IS_DIRECTORY_SEP (p[-1]))
302 p--;
303 *p = 0;
304 strcpy (p, "EXXXXXX");
305 mktemp (tempname);
306 unlink (tempname);
308 while (1)
310 /* Create the lock file, but not under the lock file name. */
311 /* Give up if cannot do that. */
312 desc = open (tempname, O_WRONLY | O_CREAT | O_EXCL, 0666);
313 if (desc < 0)
315 char *message = (char *) xmalloc (strlen (tempname) + 50);
316 sprintf (message, "creating %s, which would become the lock file",
317 tempname);
318 pfatal_with_name (message);
320 close (desc);
322 tem = link (tempname, lockname);
324 #ifdef EPERM
325 if (tem < 0 && errno == EPERM)
326 fatal ("Unable to create hard link between %s and %s",
327 tempname, lockname);
328 #endif
330 unlink (tempname);
331 if (tem >= 0)
332 break;
333 sleep (1);
335 /* If lock file is five minutes old, unlock it.
336 Five minutes should be good enough to cope with crashes
337 and wedgitude, and long enough to avoid being fooled
338 by time differences between machines. */
339 if (stat (lockname, &st) >= 0)
341 now = time (0);
342 if (st.st_ctime < now - 300)
343 unlink (lockname);
347 delete_lockname = lockname;
349 #endif /* not MAIL_USE_SYSTEM_LOCK */
350 #endif /* not MAIL_USE_MMDF */
352 if (fork () == 0)
354 int lockcount = 0;
355 int status = 0;
356 #if defined (MAIL_USE_MAILLOCK) && defined (HAVE_TOUCHLOCK)
357 time_t touched_lock, now;
358 #endif
360 if (setuid (getuid ()) < 0 || setegid (real_gid) < 0)
361 fatal ("Failed to drop privileges", 0, 0);
363 #ifndef MAIL_USE_MMDF
364 #ifdef MAIL_USE_SYSTEM_LOCK
365 indesc = open (inname, O_RDWR);
366 #else /* if not MAIL_USE_SYSTEM_LOCK */
367 indesc = open (inname, O_RDONLY);
368 #endif /* not MAIL_USE_SYSTEM_LOCK */
369 #else /* MAIL_USE_MMDF */
370 indesc = lk_open (inname, O_RDONLY, 0, 0, 10);
371 #endif /* MAIL_USE_MMDF */
373 if (indesc < 0)
374 pfatal_with_name (inname);
376 #ifdef BSD_SYSTEM
377 /* In case movemail is setuid to root, make sure the user can
378 read the output file. */
379 /* This is desirable for all systems
380 but I don't want to assume all have the umask system call */
381 umask (umask (0) & 0333);
382 #endif /* BSD_SYSTEM */
383 outdesc = open (outname, O_WRONLY | O_CREAT | O_EXCL, 0666);
384 if (outdesc < 0)
385 pfatal_with_name (outname);
387 if (setegid (priv_gid) < 0)
388 fatal ("Failed to regain privileges", 0, 0);
390 /* This label exists so we can retry locking
391 after a delay, if it got EAGAIN or EBUSY. */
392 retry_lock:
394 /* Try to lock it. */
395 #ifdef MAIL_USE_MAILLOCK
396 if (spool_name)
398 /* The "0 - " is to make it a negative number if maillock returns
399 non-zero. */
400 status = 0 - maillock (spool_name, 1);
401 #ifdef HAVE_TOUCHLOCK
402 touched_lock = time (0);
403 #endif
404 lockcount = 5;
406 else
407 #endif /* MAIL_USE_MAILLOCK */
409 #ifdef MAIL_USE_SYSTEM_LOCK
410 #ifdef MAIL_USE_LOCKF
411 status = lockf (indesc, F_LOCK, 0);
412 #else /* not MAIL_USE_LOCKF */
413 #ifdef WINDOWSNT
414 status = locking (indesc, LK_RLCK, -1L);
415 #else
416 status = flock (indesc, LOCK_EX);
417 #endif
418 #endif /* not MAIL_USE_LOCKF */
419 #endif /* MAIL_USE_SYSTEM_LOCK */
422 /* If it fails, retry up to 5 times
423 for certain failure codes. */
424 if (status < 0)
426 if (++lockcount <= 5)
428 #ifdef EAGAIN
429 if (errno == EAGAIN)
431 sleep (1);
432 goto retry_lock;
434 #endif
435 #ifdef EBUSY
436 if (errno == EBUSY)
438 sleep (1);
439 goto retry_lock;
441 #endif
444 pfatal_with_name (inname);
448 char buf[1024];
450 while (1)
452 nread = read (indesc, buf, sizeof buf);
453 if (nread < 0)
454 pfatal_with_name (inname);
455 if (nread != write (outdesc, buf, nread))
457 int saved_errno = errno;
458 unlink (outname);
459 errno = saved_errno;
460 pfatal_with_name (outname);
462 if (nread < sizeof buf)
463 break;
464 #if defined (MAIL_USE_MAILLOCK) && defined (HAVE_TOUCHLOCK)
465 if (spool_name)
467 now = time (0);
468 if (now - touched_lock > 60)
470 touchlock ();
471 touched_lock = now;
474 #endif /* MAIL_USE_MAILLOCK */
478 #ifdef BSD_SYSTEM
479 if (fsync (outdesc) < 0)
480 pfatal_and_delete (outname);
481 #endif
483 /* Prevent symlink attacks truncating other users' mailboxes */
484 if (setegid (real_gid) < 0)
485 fatal ("Failed to drop privileges", 0, 0);
487 /* Check to make sure no errors before we zap the inbox. */
488 if (close (outdesc) != 0)
489 pfatal_and_delete (outname);
491 #ifdef MAIL_USE_SYSTEM_LOCK
492 if (! preserve_mail)
494 ftruncate (indesc, 0L);
496 #endif /* MAIL_USE_SYSTEM_LOCK */
498 #ifdef MAIL_USE_MMDF
499 lk_close (indesc, 0, 0, 0);
500 #else
501 close (indesc);
502 #endif
504 #ifndef MAIL_USE_SYSTEM_LOCK
505 if (! preserve_mail)
507 /* Delete the input file; if we can't, at least get rid of its
508 contents. */
509 #ifdef MAIL_UNLINK_SPOOL
510 /* This is generally bad to do, because it destroys the permissions
511 that were set on the file. Better to just empty the file. */
512 if (unlink (inname) < 0 && errno != ENOENT)
513 #endif /* MAIL_UNLINK_SPOOL */
514 creat (inname, 0600);
516 #endif /* not MAIL_USE_SYSTEM_LOCK */
518 /* End of mailbox truncation */
519 if (setegid (priv_gid) < 0)
520 fatal ("Failed to regain privileges", 0, 0);
522 #ifdef MAIL_USE_MAILLOCK
523 /* This has to occur in the child, i.e., in the process that
524 acquired the lock! */
525 if (spool_name)
526 mailunlock ();
527 #endif
528 exit (EXIT_SUCCESS);
531 wait (&status);
532 if (!WIFEXITED (status))
533 exit (EXIT_FAILURE);
534 else if (WRETCODE (status) != 0)
535 exit (WRETCODE (status));
537 #if !defined (MAIL_USE_MMDF) && !defined (MAIL_USE_SYSTEM_LOCK)
538 #ifdef MAIL_USE_MAILLOCK
539 if (! spool_name)
540 #endif /* MAIL_USE_MAILLOCK */
541 unlink (lockname);
542 #endif /* not MAIL_USE_MMDF and not MAIL_USE_SYSTEM_LOCK */
544 #endif /* ! DISABLE_DIRECT_ACCESS */
546 return EXIT_SUCCESS;
549 #ifdef MAIL_USE_MAILLOCK
550 /* This function uses stat to confirm that the mail directory is
551 identical to the directory of the input file, rather than just
552 string-comparing the two paths, because one or both of them might
553 be symbolic links pointing to some other directory. */
554 static char *
555 mail_spool_name (inname)
556 char *inname;
558 struct stat stat1, stat2;
559 char *indir, *fname;
560 int status;
562 if (! (fname = rindex (inname, '/')))
563 return NULL;
565 fname++;
567 if (stat (MAILDIR, &stat1) < 0)
568 return NULL;
570 indir = (char *) xmalloc (fname - inname + 1);
571 strncpy (indir, inname, fname - inname);
572 indir[fname-inname] = '\0';
575 status = stat (indir, &stat2);
577 free (indir);
579 if (status < 0)
580 return NULL;
582 if (stat1.st_dev == stat2.st_dev
583 && stat1.st_ino == stat2.st_ino)
584 return fname;
586 return NULL;
588 #endif /* MAIL_USE_MAILLOCK */
590 /* Print error message and exit. */
592 void
593 fatal (s1, s2, s3)
594 char *s1, *s2, *s3;
596 if (delete_lockname)
597 unlink (delete_lockname);
598 error (s1, s2, s3);
599 exit (EXIT_FAILURE);
602 /* Print error message. `s1' is printf control string, `s2' and `s3'
603 are args for it or null. */
605 void
606 error (s1, s2, s3)
607 char *s1, *s2, *s3;
609 fprintf (stderr, "movemail: ");
610 if (s3)
611 fprintf (stderr, s1, s2, s3);
612 else if (s2)
613 fprintf (stderr, s1, s2);
614 else
615 fprintf (stderr, s1);
616 fprintf (stderr, "\n");
619 void
620 pfatal_with_name (name)
621 char *name;
623 fatal ("%s for %s", strerror (errno), name);
626 void
627 pfatal_and_delete (name)
628 char *name;
630 char *s = strerror (errno);
631 unlink (name);
632 fatal ("%s for %s", s, name);
635 /* Return a newly-allocated string whose contents concatenate those of s1, s2, s3. */
637 char *
638 concat (s1, s2, s3)
639 char *s1, *s2, *s3;
641 int len1 = strlen (s1), len2 = strlen (s2), len3 = strlen (s3);
642 char *result = (char *) xmalloc (len1 + len2 + len3 + 1);
644 strcpy (result, s1);
645 strcpy (result + len1, s2);
646 strcpy (result + len1 + len2, s3);
647 *(result + len1 + len2 + len3) = 0;
649 return result;
652 /* Like malloc but get fatal error if memory is exhausted. */
654 long *
655 xmalloc (size)
656 unsigned 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
681 #define DONE 1
683 char *progname;
684 FILE *sfi;
685 FILE *sfo;
686 char ibuffer[BUFSIZ];
687 char obuffer[BUFSIZ];
688 char Errmsg[200]; /* POP errors, at least, can exceed
689 the original length of 80. */
692 * The full valid syntax for a POP mailbox specification for movemail
693 * is "po:username:hostname". The ":hostname" is optional; if it is
694 * omitted, the MAILHOST environment variable will be consulted. Note
695 * that by the time popmail() is called the "po:" has been stripped
696 * off of the front of the mailbox name.
698 * If the mailbox is in the form "po:username:hostname", then it is
699 * modified by this function -- the second colon is replaced by a
700 * null.
702 * Return a value suitable for passing to `exit'.
706 popmail (mailbox, outfile, preserve, password, reverse_order)
707 char *mailbox;
708 char *outfile;
709 int preserve;
710 char *password;
711 int reverse_order;
713 int nmsgs, nbytes;
714 register int i;
715 int mbfi;
716 FILE *mbf;
717 char *getenv ();
718 popserver server;
719 int start, end, increment;
720 char *user, *hostname;
722 user = mailbox;
723 if ((hostname = index(mailbox, ':')))
724 *hostname++ = '\0';
726 server = pop_open (hostname, user, password, POP_NO_GETPASS);
727 if (! server)
729 error ("Error connecting to POP server: %s", pop_error, 0);
730 return EXIT_FAILURE;
733 if (pop_stat (server, &nmsgs, &nbytes))
735 error ("Error getting message count from POP server: %s", pop_error, 0);
736 return EXIT_FAILURE;
739 if (!nmsgs)
741 pop_close (server);
742 return EXIT_SUCCESS;
745 mbfi = open (outfile, O_WRONLY | O_CREAT | O_EXCL, 0666);
746 if (mbfi < 0)
748 pop_close (server);
749 error ("Error in open: %s, %s", strerror (errno), outfile);
750 return EXIT_FAILURE;
752 fchown (mbfi, getuid (), -1);
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;
837 pop_retr (server, msgno, arg)
838 popserver server;
839 int msgno;
840 FILE *arg;
842 extern char *strerror ();
843 char *line;
844 int ret;
846 if (pop_retrieve_first (server, msgno, &line))
848 char *error = concat ("Error from POP server: ", pop_error, "");
849 strncpy (Errmsg, error, sizeof (Errmsg));
850 Errmsg[sizeof (Errmsg)-1] = '\0';
851 free(error);
852 return (NOTOK);
855 while ((ret = pop_retrieve_next (server, &line)) >= 0)
857 if (! line)
858 break;
860 if (mbx_write (line, ret, arg) != OK)
862 strcpy (Errmsg, strerror (errno));
863 pop_close (server);
864 return (NOTOK);
868 if (ret)
870 char *error = concat ("Error from POP server: ", pop_error, "");
871 strncpy (Errmsg, error, sizeof (Errmsg));
872 Errmsg[sizeof (Errmsg)-1] = '\0';
873 free(error);
874 return (NOTOK);
877 return (OK);
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] == ' '))
888 mbx_write (line, len, mbf)
889 char *line;
890 int len;
891 FILE *mbf;
893 #ifdef MOVEMAIL_QUOTE_POP_FROM_LINES
894 if (IS_FROM_LINE (line))
896 if (fputc ('>', mbf) == EOF)
897 return (NOTOK);
899 #endif
900 if (line[0] == '\037')
902 if (fputs ("^_", mbf) == EOF)
903 return (NOTOK);
904 line++;
905 len--;
907 if (fwrite (line, 1, len, mbf) != len)
908 return (NOTOK);
909 if (fputc (0x0a, mbf) == EOF)
910 return (NOTOK);
911 return (OK);
915 mbx_delimit_begin (mbf)
916 FILE *mbf;
918 time_t now;
919 struct tm *ltime;
920 char fromline[40] = "From movemail ";
922 now = time (NULL);
923 ltime = localtime (&now);
925 strcat (fromline, asctime (ltime));
927 if (fputs (fromline, mbf) == EOF)
928 return (NOTOK);
929 return (OK);
933 mbx_delimit_end (mbf)
934 FILE *mbf;
936 if (putc ('\n', mbf) == EOF)
937 return (NOTOK);
938 return (OK);
941 #endif /* MAIL_USE_POP */
943 #ifndef HAVE_STRERROR
944 char *
945 strerror (errnum)
946 int errnum;
948 extern char *sys_errlist[];
949 extern int sys_nerr;
951 if (errnum >= 0 && errnum < sys_nerr)
952 return sys_errlist[errnum];
953 return (char *) "Unknown error";
956 #endif /* ! HAVE_STRERROR */
958 /* arch-tag: 1c323112-41fe-4fe5-8de9-494de631f73f
959 (do not change this comment) */
961 /* movemail.c ends here */