comparison lib-src/movemail.c @ 428:3ecd8885ac67 r21-2-22

Import from CVS: tag r21-2-22
author cvs
date Mon, 13 Aug 2007 11:28:15 +0200
parents
children 84b14dcb0985
comparison
equal deleted inserted replaced
427:0a0253eac470 428:3ecd8885ac67
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 Free Software Foundation, Inc.
4
5 This file is part of GNU Emacs.
6
7 GNU Emacs is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
11
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
21
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.
27
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. */
33
34 /*
35 * Modified January, 1986 by Michael R. Gretzinger (Project Athena)
36 *
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.
42 *
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
49 *
50 * Modified August, 1993 by Jonathan Kamens (OpenVision Technologies)
51 *
52 * Move all of the POP code into a separate file, "pop.c".
53 * Use strerror instead of get_errmsg.
54 *
55 */
56
57 #define NO_SHORTNAMES /* Tell config not to load remap.h */
58 #define DONT_ENCAPSULATE
59 #include <../src/config.h>
60 #include <sys/types.h>
61 #include <sys/stat.h>
62 #include <stdio.h>
63 #include <errno.h>
64 #include "../src/sysfile.h"
65 #include "../src/syswait.h"
66 #ifndef WINDOWSNT
67 #include "../src/systime.h"
68 #endif
69 #include <stdlib.h>
70 #include <string.h>
71 #include "getopt.h"
72 #ifdef MAIL_USE_POP
73 #include "pop.h"
74 #include "../src/regex.h"
75 #endif
76
77 extern char *optarg;
78 extern int optind, opterr;
79
80 #ifndef HAVE_STRERROR
81 char * strerror (int errnum);
82 #endif /* HAVE_STRERROR */
83
84 #ifdef MSDOS
85 #undef access
86 #endif /* MSDOS */
87
88 #ifndef DIRECTORY_SEP
89 #define DIRECTORY_SEP '/'
90 #endif
91 #ifndef IS_DIRECTORY_SEP
92 #define IS_DIRECTORY_SEP(_c_) ((_c_) == DIRECTORY_SEP)
93 #endif
94
95 #ifdef WINDOWSNT
96 #undef access
97 #undef unlink
98 #define fork() 0
99 #define sys_wait(var) (*(var) = 0)
100 /* Unfortunately, Samba doesn't seem to properly lock Unix files even
101 though the locking call succeeds (and indeed blocks local access from
102 other NT programs). If you have direct file access using an NFS
103 client or something other than Samba, the locking call might work
104 properly - make sure it does before you enable this! */
105 #define DISABLE_DIRECT_ACCESS
106 #include <io.h>
107 #endif /* WINDOWSNT */
108
109 #if defined (HAVE_UNISTD_H) || defined (USG)
110 #include <unistd.h>
111 #endif /* unistd.h */
112 #ifndef F_OK
113 #define F_OK 0
114 #define X_OK 1
115 #define W_OK 2
116 #define R_OK 4
117 #endif /* No F_OK */
118
119 #if defined (HAVE_FCNTL_H) || defined (USG)
120 #include <fcntl.h>
121 #endif /* fcntl.h */
122
123 #if defined (XENIX) || defined (WINDOWSNT)
124 #include <sys/locking.h>
125 #endif
126
127 #ifdef MAIL_USE_LOCKF
128 #define MAIL_USE_SYSTEM_LOCK
129 #endif
130
131 #ifdef MAIL_USE_FLOCK
132 #define MAIL_USE_SYSTEM_LOCK
133 #endif
134
135 #ifdef MAIL_USE_MMDF
136 extern int lk_open (), lk_close ();
137 #endif
138
139 /* Cancel substitutions made by config.h for Emacs. */
140 #undef open
141 #undef read
142 #undef write
143 #undef close
144
145 static void fatal (char *, char*);
146 static void error (char *, char *, char *);
147 static void pfatal_with_name (char *);
148 static void pfatal_and_delete (char *);
149 static char *concat (char *, char *, char *);
150 static long *xmalloc (unsigned int);
151 #ifdef MAIL_USE_POP
152 static int popmail (char *, char *, char *);
153 static int pop_retr (popserver server, int msgno,
154 int (*action)(char *, FILE *), void *arg);
155 static int mbx_write (char *, FILE *);
156 static int mbx_delimit_begin (FILE *);
157 static int mbx_delimit_end (FILE *);
158 static struct re_pattern_buffer* compile_regex (char* regexp_pattern);
159 static int pop_search_top (popserver server, int msgno, int lines,
160 struct re_pattern_buffer* regexp);
161 #endif
162
163 /* Nonzero means this is name of a lock file to delete on fatal error. */
164 char *delete_lockname;
165
166 int verbose=0;
167 #ifdef MAIL_USE_POP
168 int reverse=0;
169 int keep_messages=0;
170 struct re_pattern_buffer* regexp_pattern=0;
171 int match_lines=10;
172 #endif
173
174 #define VERBOSE(x) if (verbose) { printf x; fflush(stdout); }
175
176 struct option longopts[] =
177 {
178 { "inbox", required_argument, NULL, 'i' },
179 { "outfile", required_argument, NULL, 'o' },
180 #ifdef MAIL_USE_POP
181 { "password", required_argument, NULL, 'p' },
182 { "reverse-pop-order", no_argument, NULL, 'x' },
183 { "keep-messages", no_argument, NULL, 'k' },
184 { "regex", required_argument, NULL, 'r' },
185 { "match-lines", required_argument, NULL, 'l' },
186 #endif
187 { "verbose", no_argument, NULL, 'v' },
188 { 0 }
189 };
190
191 int
192 main (int argc, char *argv[])
193 {
194 char *inname=0, *outname=0, *poppass=0;
195 #ifndef DISABLE_DIRECT_ACCESS
196 int indesc, outdesc;
197 int nread;
198 int status;
199 #endif
200
201 #ifndef MAIL_USE_SYSTEM_LOCK
202 struct stat st;
203 long now;
204 int tem;
205 char *lockname, *p;
206 char *tempname;
207 int desc;
208 #endif /* not MAIL_USE_SYSTEM_LOCK */
209
210 delete_lockname = 0;
211
212 while (1)
213 {
214 #ifdef MAIL_USE_POP
215 char* optstring = "i:o:p:l:r:xvk";
216 #else
217 char* optstring = "i:o:v";
218 #endif
219 int opt = getopt_long (argc, argv, optstring, longopts, 0);
220
221 if (opt == EOF)
222 break;
223
224 switch (opt)
225 {
226 case 0:
227 break;
228 case 1: /* one of the standard arguments seen */
229 if (!inname)
230 inname = optarg;
231 else if (!outname)
232 outname = optarg;
233 else
234 poppass = optarg;
235 break;
236
237 case 'i': /* infile */
238 inname = optarg;
239 break;
240
241 case 'o': /* outfile */
242 outname = optarg;
243 break;
244 #ifdef MAIL_USE_POP
245 case 'p': /* pop password */
246 poppass = optarg;
247 break;
248 case 'k': keep_messages=1; break;
249 case 'x': reverse = 1; break;
250 case 'l': /* lines to match */
251 match_lines = atoi (optarg);
252 break;
253
254 case 'r': /* regular expression */
255 regexp_pattern = compile_regex (optarg);
256 break;
257 #endif
258 case 'v': verbose = 1; break;
259 }
260 }
261
262 while (optind < argc)
263 {
264 if (!inname)
265 inname = argv[optind];
266 else if (!outname)
267 outname = argv[optind];
268 else
269 poppass = argv[optind];
270 optind++;
271 }
272
273 if (!inname || !outname)
274 {
275 fprintf (stderr, "Usage: movemail [-rvxk] [-l lines ] [-i] inbox [-o] destfile [[-p] POP-password]\n");
276 exit(1);
277 }
278
279 #ifdef MAIL_USE_MMDF
280 mmdf_init (argv[0]);
281 #endif
282
283 if (*outname == 0)
284 fatal ("Destination file name is empty", 0);
285
286 /* Check access to output file. */
287 if (access (outname, F_OK) == 0 && access (outname, W_OK) != 0)
288 pfatal_with_name (outname);
289
290 /* Also check that outname's directory is writable to the real uid. */
291 {
292 char *buf = (char *) xmalloc (strlen (outname) + 1);
293 char *cp;
294 strcpy (buf, outname);
295 cp = buf + strlen (buf);
296 while (cp > buf && !IS_DIRECTORY_SEP (cp[-1]))
297 *--cp = 0;
298 if (cp == buf)
299 *cp++ = '.';
300 if (access (buf, W_OK) != 0)
301 pfatal_with_name (buf);
302 free (buf);
303 }
304
305 #ifdef MAIL_USE_POP
306 if (!strncmp (inname, "po:", 3))
307 {
308 int retcode = popmail (inname + 3, outname, poppass);
309 exit (retcode);
310 }
311
312 #ifndef WINDOWSNT
313 setuid (getuid ());
314 #endif
315 #endif /* MAIL_USE_POP */
316
317 #ifndef DISABLE_DIRECT_ACCESS
318
319 /* Check access to input file. */
320 if (access (inname, R_OK | W_OK) != 0)
321 pfatal_with_name (inname);
322
323 #ifndef MAIL_USE_MMDF
324 #ifndef MAIL_USE_SYSTEM_LOCK
325 /* Use a lock file named after our first argument with .lock appended:
326 If it exists, the mail file is locked. */
327 /* Note: this locking mechanism is *required* by the mailer
328 (on systems which use it) to prevent loss of mail.
329
330 On systems that use a lock file, extracting the mail without locking
331 WILL occasionally cause loss of mail due to timing errors!
332
333 So, if creation of the lock file fails
334 due to access permission on the mail spool directory,
335 you simply MUST change the permission
336 and/or make movemail a setgid program
337 so it can create lock files properly.
338
339 You might also wish to verify that your system is one
340 which uses lock files for this purpose. Some systems use other methods.
341
342 If your system uses the `flock' system call for mail locking,
343 define MAIL_USE_SYSTEM_LOCK in config.h or the s-*.h file
344 and recompile movemail. If the s- file for your system
345 should define MAIL_USE_SYSTEM_LOCK but does not, send a bug report
346 to bug-gnu-emacs@prep.ai.mit.edu so we can fix it. */
347
348 lockname = concat (inname, ".lock", "");
349 tempname = (char *) xmalloc (strlen (inname) + strlen ("EXXXXXX") + 1);
350 strcpy (tempname, inname);
351 p = tempname + strlen (tempname);
352 while (p != tempname && !IS_DIRECTORY_SEP (p[-1]))
353 p--;
354 *p = 0;
355 strcpy (p, "EXXXXXX");
356 mktemp (tempname);
357 unlink (tempname);
358
359 while (1)
360 {
361 /* Create the lock file, but not under the lock file name. */
362 /* Give up if cannot do that. */
363 desc = open (tempname, O_WRONLY | O_CREAT | O_EXCL, 0666);
364 if (desc < 0)
365 {
366 char *message = (char *) xmalloc (strlen (tempname) + 50);
367 sprintf (message, "%s--see source file lib-src/movemail.c",
368 tempname);
369 pfatal_with_name (message);
370 }
371 close (desc);
372
373 tem = link (tempname, lockname);
374 unlink (tempname);
375 if (tem >= 0)
376 break;
377 sleep (1);
378
379 /* If lock file is five minutes old, unlock it.
380 Five minutes should be good enough to cope with crashes
381 and wedgitude, and long enough to avoid being fooled
382 by time differences between machines. */
383 if (stat (lockname, &st) >= 0)
384 {
385 now = time (0);
386 if (st.st_ctime < now - 300)
387 unlink (lockname);
388 }
389 }
390
391 delete_lockname = lockname;
392 #endif /* not MAIL_USE_SYSTEM_LOCK */
393 #endif /* not MAIL_USE_MMDF */
394
395 if (fork () == 0)
396 {
397 setuid (getuid ());
398
399 #ifndef MAIL_USE_MMDF
400 #ifdef MAIL_USE_SYSTEM_LOCK
401 indesc = open (inname, O_RDWR);
402 #else /* if not MAIL_USE_SYSTEM_LOCK */
403 indesc = open (inname, O_RDONLY);
404 #endif /* not MAIL_USE_SYSTEM_LOCK */
405 #else /* MAIL_USE_MMDF */
406 indesc = lk_open (inname, O_RDONLY, 0, 0, 10);
407 #endif /* MAIL_USE_MMDF */
408
409 if (indesc < 0)
410 pfatal_with_name (inname);
411
412 #if defined (BSD) || defined (XENIX)
413 /* In case movemail is setuid to root, make sure the user can
414 read the output file. */
415 /* This is desirable for all systems
416 but I don't want to assume all have the umask system call */
417 umask (umask (0) & 0333);
418 #endif /* BSD or Xenix */
419 outdesc = open (outname, O_WRONLY | O_CREAT | O_EXCL, 0666);
420 if (outdesc < 0)
421 pfatal_with_name (outname);
422 #ifdef MAIL_USE_SYSTEM_LOCK
423 #ifdef MAIL_USE_LOCKF
424 if (lockf (indesc, F_LOCK, 0) < 0) pfatal_with_name (inname);
425 #else /* not MAIL_USE_LOCKF */
426 #ifdef XENIX
427 if (locking (indesc, LK_RLCK, 0L) < 0) pfatal_with_name (inname);
428 #else
429 #ifdef WINDOWSNT
430 if (locking (indesc, LK_RLCK, -1L) < 0) pfatal_with_name (inname);
431 #else
432 if (flock (indesc, LOCK_EX) < 0) pfatal_with_name (inname);
433 #endif
434 #endif
435 #endif /* not MAIL_USE_LOCKF */
436 #endif /* MAIL_USE_SYSTEM_LOCK */
437
438 {
439 char buf[1024];
440
441 while (1)
442 {
443 nread = read (indesc, buf, sizeof buf);
444 if (nread != write (outdesc, buf, nread))
445 {
446 int saved_errno = errno;
447 unlink (outname);
448 errno = saved_errno;
449 pfatal_with_name (outname);
450 }
451 if (nread < sizeof buf)
452 break;
453 }
454 }
455
456 #ifdef BSD
457 if (fsync (outdesc) < 0)
458 pfatal_and_delete (outname);
459 #endif
460
461 /* Check to make sure no errors before we zap the inbox. */
462 if (close (outdesc) != 0)
463 pfatal_and_delete (outname);
464
465 #ifdef MAIL_USE_SYSTEM_LOCK
466 #if defined (STRIDE) || defined (XENIX) || defined (WINDOWSNT)
467 /* Stride, xenix have file locking, but no ftruncate. This mess will do. */
468 close (open (inname, O_CREAT | O_TRUNC | O_RDWR, 0666));
469 #else
470 ftruncate (indesc, 0L);
471 #endif /* STRIDE or XENIX */
472 #endif /* MAIL_USE_SYSTEM_LOCK */
473
474 #ifdef MAIL_USE_MMDF
475 lk_close (indesc, 0, 0, 0);
476 #else
477 close (indesc);
478 #endif
479
480 #ifndef MAIL_USE_SYSTEM_LOCK
481 /* Delete the input file; if we can't, at least get rid of its
482 contents. */
483 #ifdef MAIL_UNLINK_SPOOL
484 /* This is generally bad to do, because it destroys the permissions
485 that were set on the file. Better to just empty the file. */
486 if (unlink (inname) < 0 && errno != ENOENT)
487 #endif /* MAIL_UNLINK_SPOOL */
488 creat (inname, 0600);
489 #endif /* not MAIL_USE_SYSTEM_LOCK */
490
491 exit (0);
492 }
493
494 wait (&status);
495 if (!WIFEXITED (status))
496 exit (1);
497 else if (WEXITSTATUS (status) != 0)
498 exit (WEXITSTATUS (status));
499
500 #if !defined (MAIL_USE_MMDF) && !defined (MAIL_USE_SYSTEM_LOCK)
501 unlink (lockname);
502 #endif /* not MAIL_USE_MMDF and not MAIL_USE_SYSTEM_LOCK */
503
504 #endif /* ! DISABLE_DIRECT_ACCESS */
505
506 return 0;
507 }
508
509 /* Print error message and exit. */
510
511 static void
512 fatal (char *s1, char *s2)
513 {
514 if (delete_lockname)
515 unlink (delete_lockname);
516 error (s1, s2, NULL);
517 exit (1);
518 }
519
520 /* Print error message. `s1' is printf control string, `s2' is arg for it. */
521
522 static void
523 error (char *s1, char *s2, char *s3)
524 {
525 fprintf (stderr, "movemail: ");
526 fprintf (stderr, s1, s2, s3);
527 fprintf (stderr, "\n");
528 }
529
530 static void
531 pfatal_with_name (char *name)
532 {
533 char *s = concat ("", strerror (errno), " for %s");
534 fatal (s, name);
535 }
536
537 static void
538 pfatal_and_delete (char *name)
539 {
540 char *s = concat ("", strerror (errno), " for %s");
541 unlink (name);
542 fatal (s, name);
543 }
544
545 /* Return a newly-allocated string whose contents concatenate those of s1, s2, s3. */
546
547 static char *
548 concat (char *s1, char *s2, char *s3)
549 {
550 int len1 = strlen (s1), len2 = strlen (s2), len3 = strlen (s3);
551 char *result = (char *) xmalloc (len1 + len2 + len3 + 1);
552
553 strcpy (result, s1);
554 strcpy (result + len1, s2);
555 strcpy (result + len1 + len2, s3);
556 *(result + len1 + len2 + len3) = 0;
557
558 return result;
559 }
560
561 /* Like malloc but get fatal error if memory is exhausted. */
562
563 static long *
564 xmalloc (unsigned int size)
565 {
566 long *result = (long *) malloc (size);
567 if (!result)
568 fatal ("virtual memory exhausted", 0);
569 return result;
570 }
571
572 /* This is the guts of the interface to the Post Office Protocol. */
573
574 #ifdef MAIL_USE_POP
575
576 #ifndef WINDOWSNT
577 #include <sys/socket.h>
578 #include <netinet/in.h>
579 #include <netdb.h>
580 #else
581 #undef _WINSOCKAPI_
582 #include <winsock.h>
583 #endif
584 #include <stdio.h>
585 #include <pwd.h>
586
587 #define POP_ERROR (-1)
588 #define POP_RETRIEVED (0)
589 #define POP_DONE (1)
590
591 char *progname;
592 FILE *sfi;
593 FILE *sfo;
594 char ibuffer[BUFSIZ];
595 char obuffer[BUFSIZ];
596 char Errmsg[80];
597
598 static int
599 popmail (char *user, char *outfile, char *password)
600 {
601 int nmsgs, nbytes;
602 register int i, idx;
603 int mbfi;
604 short* retrieved_list;
605 FILE *mbf;
606 popserver server;
607
608 VERBOSE(("opening server\r"));
609 server = pop_open (0, user, password, POP_NO_GETPASS);
610 if (! server)
611 {
612 error (pop_error, NULL, NULL);
613 return (1);
614 }
615
616 VERBOSE(("stat'ing messages\r"));
617 if (pop_stat (server, &nmsgs, &nbytes))
618 {
619 error (pop_error, NULL, NULL);
620 return (1);
621 }
622
623 if (!nmsgs)
624 {
625 VERBOSE(("closing server\n"));
626 pop_close (server);
627 return (0);
628 }
629
630 /* build a retrieved table */
631 retrieved_list = (short*) xmalloc (sizeof (short) * (nmsgs+1));
632 memset (retrieved_list, 0, sizeof (short) * (nmsgs+1));
633
634 mbfi = open (outfile, O_WRONLY | O_CREAT | O_EXCL, 0666);
635 if (mbfi < 0)
636 {
637 pop_close (server);
638 error ("Error in open: %s, %s", strerror (errno), outfile);
639 return (1);
640 }
641 #if !defined(__CYGWIN32__) && !defined(WINDOWSNT)
642 fchown (mbfi, getuid (), -1);
643 #endif
644
645 if ((mbf = fdopen (mbfi, "wb")) == NULL)
646 {
647 pop_close (server);
648 error ("Error in fdopen: %s", strerror (errno), NULL);
649 close (mbfi);
650 unlink (outfile);
651 return (1);
652 }
653
654 for (idx = 0; idx < nmsgs; idx++)
655 {
656 i = reverse ? nmsgs - idx : idx + 1;
657 VERBOSE(("checking message %d \r", i));
658
659 if (!regexp_pattern
660 ||
661 pop_search_top (server, i, match_lines, regexp_pattern) == POP_RETRIEVED)
662 {
663 VERBOSE(("retrieving message %d \r", i));
664 mbx_delimit_begin (mbf);
665 if (pop_retr (server, i, mbx_write, mbf) != POP_RETRIEVED)
666 {
667 error (Errmsg, NULL, NULL);
668 close (mbfi);
669 return (1);
670 }
671
672 retrieved_list[i]=1;
673
674 mbx_delimit_end (mbf);
675 fflush (mbf);
676 if (ferror (mbf))
677 {
678 error ("Error in fflush: %s", strerror (errno), NULL);
679 pop_close (server);
680 close (mbfi);
681 return (1);
682 }
683 }
684 }
685
686 /* On AFS, a call to write only modifies the file in the local
687 * workstation's AFS cache. The changes are not written to the server
688 * until a call to fsync or close is made. Users with AFS home
689 * directories have lost mail when over quota because these checks were
690 * not made in previous versions of movemail. */
691
692 #ifdef BSD
693 if (fsync (mbfi) < 0)
694 {
695 error ("Error in fsync: %s", strerror (errno), NULL);
696 return (1);
697 }
698 #endif
699
700 if (close (mbfi) == -1)
701 {
702 error ("Error in close: %s", strerror (errno), NULL);
703 return (1);
704 }
705
706 if (!keep_messages)
707 {
708 for (i = 1; i <= nmsgs; i++)
709 {
710 if (retrieved_list[i] == 1)
711 {
712 VERBOSE(("deleting message %d \r", i));
713 if (pop_delete (server, i))
714 {
715 error (pop_error, NULL, NULL);
716 pop_close (server);
717 return (1);
718 }
719 }
720 }
721 }
722
723 VERBOSE(("closing server \n"));
724 if (pop_quit (server))
725 {
726 error (pop_error, NULL, NULL);
727 return (1);
728 }
729
730 return (0);
731 }
732
733 static int
734 pop_retr (popserver server, int msgno, int (*action)(char *, FILE *), void *arg)
735 {
736 char *line;
737 int ret;
738
739 if (pop_retrieve_first (server, msgno, &line))
740 {
741 strncpy (Errmsg, pop_error, sizeof (Errmsg));
742 Errmsg[sizeof (Errmsg)-1] = '\0';
743 return (POP_ERROR);
744 }
745
746 while (! (ret = pop_retrieve_next (server, &line)))
747 {
748 if (! line)
749 break;
750
751 if ((*action)(line, arg) != POP_RETRIEVED)
752 {
753 strcpy (Errmsg, strerror (errno));
754 pop_close (server);
755 return (POP_ERROR);
756 }
757 }
758
759 if (ret)
760 {
761 strncpy (Errmsg, pop_error, sizeof (Errmsg));
762 Errmsg[sizeof (Errmsg)-1] = '\0';
763 return (POP_ERROR);
764 }
765
766 return (POP_RETRIEVED);
767 }
768
769 /* search the top lines of each message looking for a match */
770 static int
771 pop_search_top (popserver server, int msgno, int lines, struct re_pattern_buffer* regexp)
772 {
773 char *line;
774 int ret;
775 int match = POP_DONE;
776
777 if (pop_top_first (server, msgno, lines, &line))
778 {
779 strncpy (Errmsg, pop_error, sizeof (Errmsg));
780 Errmsg[sizeof (Errmsg)-1] = '\0';
781 return (POP_ERROR);
782 }
783
784 while (! (ret = pop_top_next (server, &line)))
785 {
786 if (! line)
787 break;
788
789 /* VERBOSE (("checking %s\n", line));*/
790 if (match != POP_RETRIEVED)
791 {
792 if ((ret = re_match (regexp, line, strlen (line), 0, 0)) == -2 )
793 {
794 strcpy (Errmsg, "error in regular expression");
795 pop_close (server);
796 return (POP_ERROR);
797 }
798 else if (ret >=0)
799 {
800 match = POP_RETRIEVED;
801 }
802 }
803 }
804
805 if (ret)
806 {
807 strncpy (Errmsg, pop_error, sizeof (Errmsg));
808 Errmsg[sizeof (Errmsg)-1] = '\0';
809 return (POP_ERROR);
810 }
811
812 return match;
813 }
814
815 /* Do this as a macro instead of using strcmp to save on execution time. */
816 #define IS_FROM_LINE(a) ((a[0] == 'F') \
817 && (a[1] == 'r') \
818 && (a[2] == 'o') \
819 && (a[3] == 'm') \
820 && (a[4] == ' '))
821
822 static int
823 mbx_write (char *line, FILE *mbf)
824 {
825 if (IS_FROM_LINE (line))
826 {
827 if (fputc ('>', mbf) == EOF)
828 return (POP_ERROR);
829 }
830 if (fputs (line, mbf) == EOF)
831 return (POP_ERROR);
832 if (fputc (0x0a, mbf) == EOF)
833 return (POP_ERROR);
834 return (POP_RETRIEVED);
835 }
836
837 static int
838 mbx_delimit_begin (FILE *mbf)
839 {
840 if (fputs ("\f\n0, unseen,,\n", mbf) == EOF)
841 return (POP_ERROR);
842 return (POP_RETRIEVED);
843 }
844
845 static int
846 mbx_delimit_end (FILE *mbf)
847 {
848 if (putc ('\037', mbf) == EOF)
849 return (POP_ERROR);
850 return (POP_RETRIEVED);
851 }
852
853 /* Turn a name, which is an ed-style (but Emacs syntax) regular
854 expression, into a real regular expression by compiling it. */
855 static struct re_pattern_buffer*
856 compile_regex (char* pattern)
857 {
858 char *err;
859 struct re_pattern_buffer *patbuf=0;
860
861 patbuf = (struct re_pattern_buffer*) xmalloc (sizeof (struct re_pattern_buffer));
862 patbuf->translate = NULL;
863 patbuf->fastmap = NULL;
864 patbuf->buffer = NULL;
865 patbuf->allocated = 0;
866
867 err = (char*) re_compile_pattern (pattern, strlen (pattern), patbuf);
868 if (err != NULL)
869 {
870 error ("%s while compiling pattern", err, NULL);
871 return 0;
872 }
873
874 return patbuf;
875 }
876
877
878
879 #endif /* MAIL_USE_POP */
880
881 #ifndef HAVE_STRERROR
882 char *
883 strerror (int errnum)
884 {
885 extern char *sys_errlist[];
886 extern int sys_nerr;
887
888 if (errnum >= 0 && errnum < sys_nerr)
889 return sys_errlist[errnum];
890 return (char *) "Unknown error";
891 }
892
893 #endif /* ! HAVE_STRERROR */