*** empty log message ***
[bpt/emacs.git] / lib-src / movemail.c
CommitLineData
237e0016
RS
1/* movemail foo bar -- move file foo to file bar,
2 locking file foo the way /bin/mail respects.
9fd54390 3 Copyright (C) 1986, 1992 Free Software Foundation, Inc.
237e0016
RS
4
5This file is part of GNU Emacs.
6
93320c23
JA
7GNU Emacs is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 1, or (at your option)
10any later version.
11
237e0016 12GNU Emacs is distributed in the hope that it will be useful,
93320c23
JA
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
237e0016 16
93320c23
JA
17You should have received a copy of the GNU General Public License
18along with GNU Emacs; see the file COPYING. If not, write to
19the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
237e0016 20
08d0752f
RS
21/* Important notice: defining MAIL_USE_FLOCK *will cause loss of mail*
22 if you do it on a system that does not normally use flock as its way of
23 interlocking access to inbox files. The setting of MAIL_USE_FLOCK
24 *must agree* with the system's own conventions.
25 It is not a choice that is up to you.
26
27 So, if your system uses lock files rather than flock, then the only way
28 you can get proper operation is to enable movemail to write lockfiles there.
29 This means you must either give that directory access modes
30 that permit everyone to write lockfiles in it, or you must make movemail
31 a setuid or setgid program. */
32
237e0016
RS
33/*
34 * Modified January, 1986 by Michael R. Gretzinger (Project Athena)
35 *
36 * Added POP (Post Office Protocol) service. When compiled -DPOP
37 * movemail will accept input filename arguments of the form
38 * "po:username". This will cause movemail to open a connection to
39 * a pop server running on $MAILHOST (environment variable). Movemail
40 * must be setuid to root in order to work with POP.
41 *
42 * New module: popmail.c
43 * Modified routines:
cfa191ff 44 * main - added code within #ifdef MAIL_USE_POP; added setuid (getuid ())
237e0016
RS
45 * after POP code.
46 * New routines in movemail.c:
47 * get_errmsg - return pointer to system error message
48 *
49 */
50
51#include <sys/types.h>
52#include <sys/stat.h>
53#include <sys/file.h>
54#include <errno.h>
55#define NO_SHORTNAMES /* Tell config not to load remap.h */
56#include "../src/config.h"
57
58#ifdef USG
59#include <fcntl.h>
60#include <unistd.h>
4ec9a77a
RS
61#ifndef F_OK
62#define F_OK 0
63#define X_OK 1
64#define W_OK 2
65#define R_OK 4
66#endif
237e0016
RS
67#endif /* USG */
68
69#ifdef XENIX
70#include <sys/locking.h>
71#endif
72
4293ba7f
RS
73#ifdef MAIL_USE_MMDF
74extern int lk_open (), lk_close ();
75#endif
76
237e0016
RS
77/* Cancel substitutions made by config.h for Emacs. */
78#undef open
79#undef read
80#undef write
81#undef close
82
e97dd183 83char *malloc ();
237e0016 84char *concat ();
e97dd183
DM
85char *xmalloc ();
86#ifndef errno
237e0016 87extern int errno;
e97dd183 88#endif
237e0016
RS
89
90/* Nonzero means this is name of a lock file to delete on fatal error. */
91char *delete_lockname;
92
93main (argc, argv)
94 int argc;
95 char **argv;
96{
97 char *inname, *outname;
98 int indesc, outdesc;
237e0016
RS
99 int nread;
100
101#ifndef MAIL_USE_FLOCK
102 struct stat st;
103 long now;
104 int tem;
105 char *lockname, *p;
906ad89d 106 char *tempname;
237e0016
RS
107 int desc;
108#endif /* not MAIL_USE_FLOCK */
109
110 delete_lockname = 0;
111
112 if (argc < 3)
113 fatal ("two arguments required");
114
115 inname = argv[1];
116 outname = argv[2];
117
4293ba7f
RS
118#ifdef MAIL_USE_MMDF
119 mmdf_init (argv[0]);
120#endif
121
b1ce62a8 122 /* Check access to output file. */
237e0016
RS
123 if (access (outname, F_OK) == 0 && access (outname, W_OK) != 0)
124 pfatal_with_name (outname);
125
126 /* Also check that outname's directory is writeable to the real uid. */
127 {
128 char *buf = (char *) malloc (strlen (outname) + 1);
129 char *p, q;
130 strcpy (buf, outname);
131 p = buf + strlen (buf);
132 while (p > buf && p[-1] != '/')
133 *--p = 0;
134 if (p == buf)
135 *p++ = '.';
136 if (access (buf, W_OK) != 0)
137 pfatal_with_name (buf);
138 free (buf);
139 }
140
141#ifdef MAIL_USE_POP
142 if (!bcmp (inname, "po:", 3))
143 {
144 int status; char *user;
145
146 user = (char *) rindex (inname, ':') + 1;
147 status = popmail (user, outname);
148 exit (status);
149 }
150
cfa191ff 151 setuid (getuid ());
237e0016
RS
152#endif /* MAIL_USE_POP */
153
b1ce62a8
RS
154 /* Check access to input file. */
155 if (access (inname, R_OK | W_OK) != 0)
156 pfatal_with_name (inname);
157
4293ba7f 158#ifndef MAIL_USE_MMDF
237e0016
RS
159#ifndef MAIL_USE_FLOCK
160 /* Use a lock file named /usr/spool/mail/$USER.lock:
161 If it exists, the mail file is locked. */
06000e3c
RS
162 /* Note: this locking mechanism is *required* by the mailer
163 (on systems which use it) to prevent loss of mail.
164
165 On systems that use a lock file, extracting the mail without locking
166 WILL occasionally cause loss of mail due to timing errors!
167
168 So, if creation of the lock file fails
169 due to access permission on /usr/spool/mail,
170 you simply MUST change the permission
171 and/or make movemail a setgid program
172 so it can create lock files properly.
173
174 You might also wish to verify that your system is one
175 which uses lock files for this purpose. Some systems use other methods.
176
177 If your system uses the `flock' system call for mail locking,
178 define MAIL_USE_FLOCK in config.h or the s-*.h file
179 and recompile movemail. If the s- file for your system
180 should define MAIL_USE_FLOCK but does not, send a bug report
181 to bug-gnu-emacs@prep.ai.mit.edu so we can fix it. */
182
237e0016 183 lockname = concat (inname, ".lock", "");
08564963 184 tempname = strcpy (xmalloc (strlen (inname)+1), inname);
237e0016
RS
185 p = tempname + strlen (tempname);
186 while (p != tempname && p[-1] != '/')
187 p--;
188 *p = 0;
189 strcpy (p, "EXXXXXX");
190 mktemp (tempname);
cfa191ff 191 unlink (tempname);
237e0016
RS
192
193 while (1)
194 {
195 /* Create the lock file, but not under the lock file name. */
196 /* Give up if cannot do that. */
197 desc = open (tempname, O_WRONLY | O_CREAT, 0666);
198 if (desc < 0)
06000e3c 199 pfatal_with_name ("lock file--see source file etc/movemail.c");
237e0016
RS
200 close (desc);
201
202 tem = link (tempname, lockname);
cfa191ff 203 unlink (tempname);
237e0016
RS
204 if (tem >= 0)
205 break;
206 sleep (1);
207
208 /* If lock file is a minute old, unlock it. */
209 if (stat (lockname, &st) >= 0)
210 {
211 now = time (0);
212 if (st.st_ctime < now - 60)
cfa191ff 213 unlink (lockname);
237e0016
RS
214 }
215 }
216
217 delete_lockname = lockname;
218#endif /* not MAIL_USE_FLOCK */
219
220#ifdef MAIL_USE_FLOCK
221 indesc = open (inname, O_RDWR);
222#else /* if not MAIL_USE_FLOCK */
223 indesc = open (inname, O_RDONLY);
224#endif /* not MAIL_USE_FLOCK */
4293ba7f
RS
225#else /* MAIL_USE_MMDF */
226 indesc = lk_open (inname, O_RDONLY, 0, 0, 10);
227#endif /* MAIL_USE_MMDF */
228
237e0016
RS
229 if (indesc < 0)
230 pfatal_with_name (inname);
231
cfa191ff 232#if defined (BSD) || defined (XENIX)
237e0016
RS
233 /* In case movemail is setuid to root, make sure the user can
234 read the output file. */
235 /* This is desirable for all systems
236 but I don't want to assume all have the umask system call */
237 umask (umask (0) & 0333);
238#endif /* BSD or Xenix */
239 outdesc = open (outname, O_WRONLY | O_CREAT | O_EXCL, 0666);
240 if (outdesc < 0)
241 pfatal_with_name (outname);
242#ifdef MAIL_USE_FLOCK
243#ifdef XENIX
244 if (locking (indesc, LK_RLCK, 0L) < 0) pfatal_with_name (inname);
245#else
246 if (flock (indesc, LOCK_EX) < 0) pfatal_with_name (inname);
247#endif
248#endif /* MAIL_USE_FLOCK */
249
08564963
JB
250 {
251 char buf[1024];
252
253 while (1)
254 {
255 nread = read (indesc, buf, sizeof buf);
256 if (nread != write (outdesc, buf, nread))
257 {
258 int saved_errno = errno;
259 unlink (outname);
260 errno = saved_errno;
261 pfatal_with_name (outname);
262 }
263 if (nread < sizeof buf)
264 break;
265 }
266 }
237e0016
RS
267
268#ifdef BSD
cfa191ff
RS
269 if (fsync (outdesc) < 0)
270 pfatal_and_delete (outname);
237e0016
RS
271#endif
272
273 /* Check to make sure no errors before we zap the inbox. */
274 if (close (outdesc) != 0)
cfa191ff 275 pfatal_and_delete (outname);
237e0016
RS
276
277#ifdef MAIL_USE_FLOCK
cfa191ff 278#if defined (STRIDE) || defined (XENIX)
237e0016 279 /* Stride, xenix have file locking, but no ftruncate. This mess will do. */
cfa191ff 280 close (open (inname, O_CREAT | O_TRUNC | O_RDWR, 0666));
237e0016 281#else
cfa191ff 282 ftruncate (indesc, 0L);
237e0016
RS
283#endif /* STRIDE or XENIX */
284#endif /* MAIL_USE_FLOCK */
4293ba7f
RS
285
286#ifdef MAIL_USE_MMDF
287 lk_close (indesc, 0, 0, 0);
288#else
237e0016 289 close (indesc);
4293ba7f 290#endif
237e0016
RS
291
292#ifndef MAIL_USE_FLOCK
293 /* Delete the input file; if we can't, at least get rid of its contents. */
e97dd183
DM
294#ifdef MAIL_UNLINK_SPOOL
295 /* This is generally bad to do, because it destroys the permissions
296 that were set on the file. Better to just empty the file. */
297 if (unlink (inname) < 0 && errno != ENOENT)
298#endif /* MAIL_UNLINK_SPOOL */
299 creat (inname, 0600);
4293ba7f
RS
300#ifndef MAIL_USE_MMDF
301 unlink (lockname);
302#endif /* not MAIL_USE_MMDF */
237e0016
RS
303#endif /* not MAIL_USE_FLOCK */
304 exit (0);
305}
306\f
307/* Print error message and exit. */
308
309fatal (s1, s2)
310 char *s1, *s2;
311{
312 if (delete_lockname)
313 unlink (delete_lockname);
314 error (s1, s2);
315 exit (1);
316}
317
318/* Print error message. `s1' is printf control string, `s2' is arg for it. */
319
b1ce62a8
RS
320error (s1, s2, s3)
321 char *s1, *s2, *s3;
237e0016
RS
322{
323 printf ("movemail: ");
b1ce62a8 324 printf (s1, s2, s3);
237e0016
RS
325 printf ("\n");
326}
327
328pfatal_with_name (name)
329 char *name;
330{
331 extern int errno, sys_nerr;
332 extern char *sys_errlist[];
333 char *s;
334
335 if (errno < sys_nerr)
336 s = concat ("", sys_errlist[errno], " for %s");
337 else
338 s = "cannot open %s";
339 fatal (s, name);
340}
341
cfa191ff
RS
342pfatal_and_delete (name)
343 char *name;
344{
345 extern int errno, sys_nerr;
346 extern char *sys_errlist[];
347 char *s;
348
349 if (errno < sys_nerr)
350 s = concat ("", sys_errlist[errno], " for %s");
351 else
352 s = "cannot open %s";
353
354 unlink (name);
355 fatal (s, name);
356}
357
237e0016
RS
358/* Return a newly-allocated string whose contents concatenate those of s1, s2, s3. */
359
360char *
361concat (s1, s2, s3)
362 char *s1, *s2, *s3;
363{
364 int len1 = strlen (s1), len2 = strlen (s2), len3 = strlen (s3);
365 char *result = (char *) xmalloc (len1 + len2 + len3 + 1);
366
367 strcpy (result, s1);
368 strcpy (result + len1, s2);
369 strcpy (result + len1 + len2, s3);
370 *(result + len1 + len2 + len3) = 0;
371
372 return result;
373}
374
375/* Like malloc but get fatal error if memory is exhausted. */
376
e97dd183 377char *
237e0016 378xmalloc (size)
e97dd183 379 unsigned size;
237e0016 380{
e97dd183 381 char *result = malloc (size);
237e0016
RS
382 if (!result)
383 fatal ("virtual memory exhausted", 0);
384 return result;
385}
386\f
387/* This is the guts of the interface to the Post Office Protocol. */
388
389#ifdef MAIL_USE_POP
390
391#include <sys/socket.h>
392#include <netinet/in.h>
393#include <netdb.h>
394#include <stdio.h>
395
396#ifdef USG
397#include <fcntl.h>
398/* Cancel substitutions made by config.h for Emacs. */
399#undef open
400#undef read
401#undef write
402#undef close
403#endif /* USG */
404
405#define NOTOK (-1)
406#define OK 0
407#define DONE 1
408
409char *progname;
410FILE *sfi;
411FILE *sfo;
412char Errmsg[80];
413
414static int debug = 0;
415
b1ce62a8
RS
416char *get_errmsg ();
417char *getenv ();
418int mbx_write ();
419
420popmail (user, outfile)
421 char *user;
422 char *outfile;
237e0016 423{
b1ce62a8
RS
424 char *host;
425 int nmsgs, nbytes;
426 char response[128];
427 register int i;
428 int mbfi;
429 FILE *mbf;
430
431 host = getenv ("MAILHOST");
432 if (host == NULL)
433 {
434 fatal ("no MAILHOST defined");
237e0016
RS
435 }
436
b1ce62a8
RS
437 if (pop_init (host) == NOTOK)
438 {
cfa191ff 439 fatal (Errmsg);
237e0016
RS
440 }
441
b1ce62a8
RS
442 if (getline (response, sizeof response, sfi) != OK)
443 {
cfa191ff 444 fatal (response);
237e0016
RS
445 }
446
cfa191ff 447 if (pop_command ("USER %s", user) == NOTOK
b1ce62a8
RS
448 || pop_command ("RPOP %s", user) == NOTOK)
449 {
b1ce62a8 450 pop_command ("QUIT");
cfa191ff 451 fatal (Errmsg);
237e0016
RS
452 }
453
b1ce62a8
RS
454 if (pop_stat (&nmsgs, &nbytes) == NOTOK)
455 {
b1ce62a8 456 pop_command ("QUIT");
cfa191ff 457 fatal (Errmsg);
237e0016
RS
458 }
459
b1ce62a8
RS
460 if (!nmsgs)
461 {
462 pop_command ("QUIT");
463 return 0;
464 }
465
466 mbfi = open (outfile, O_WRONLY | O_CREAT | O_EXCL, 0666);
467 if (mbfi < 0)
468 {
469 pop_command ("QUIT");
cfa191ff 470 pfatal_and_delete (outfile);
b1ce62a8
RS
471 }
472 fchown (mbfi, getuid (), -1);
473
474 if ((mbf = fdopen (mbfi, "w")) == NULL)
475 {
476 pop_command ("QUIT");
cfa191ff 477 pfatal_and_delete (outfile);
b1ce62a8
RS
478 }
479
480 for (i = 1; i <= nmsgs; i++)
481 {
482 mbx_delimit_begin (mbf);
483 if (pop_retr (i, mbx_write, mbf) != OK)
484 {
b1ce62a8
RS
485 pop_command ("QUIT");
486 close (mbfi);
cfa191ff
RS
487 unlink (outfile);
488 fatal (Errmsg);
237e0016 489 }
b1ce62a8
RS
490 mbx_delimit_end (mbf);
491 fflush (mbf);
237e0016
RS
492 }
493
cfa191ff
RS
494 if (fsync (mbfi) < 0)
495 {
496 pop_command ("QUIT");
497 pfatal_and_delete (outfile);
498 }
499
500 if (close (mbfi) == -1)
501 {
502 pop_command ("QUIT");
503 pfatal_and_delete (outfile);
504 }
505
b1ce62a8
RS
506 for (i = 1; i <= nmsgs; i++)
507 {
508 if (pop_command ("DELE %d", i) == NOTOK)
509 {
cfa191ff 510 /* Better to ignore this failure. */
237e0016
RS
511 }
512 }
513
b1ce62a8 514 pop_command ("QUIT");
cfa191ff 515 return (0);
237e0016
RS
516}
517
b1ce62a8
RS
518pop_init (host)
519 char *host;
237e0016 520{
b1ce62a8
RS
521 register struct hostent *hp;
522 register struct servent *sp;
523 int lport = IPPORT_RESERVED - 1;
524 struct sockaddr_in sin;
525 register int s;
526
527 hp = gethostbyname (host);
528 if (hp == NULL)
529 {
530 sprintf (Errmsg, "MAILHOST unknown: %s", host);
531 return NOTOK;
237e0016
RS
532 }
533
b1ce62a8
RS
534 sp = getservbyname ("pop", "tcp");
535 if (sp == 0)
536 {
537 strcpy (Errmsg, "tcp/pop: unknown service");
538 return NOTOK;
237e0016
RS
539 }
540
b1ce62a8
RS
541 sin.sin_family = hp->h_addrtype;
542 bcopy (hp->h_addr, (char *)&sin.sin_addr, hp->h_length);
543 sin.sin_port = sp->s_port;
544 s = rresvport (&lport);
545 if (s < 0)
546 {
547 sprintf (Errmsg, "error creating socket: %s", get_errmsg ());
548 return NOTOK;
237e0016
RS
549 }
550
b1ce62a8
RS
551 if (connect (s, (char *)&sin, sizeof sin) < 0)
552 {
553 sprintf (Errmsg, "error during connect: %s", get_errmsg ());
554 close (s);
555 return NOTOK;
237e0016
RS
556 }
557
b1ce62a8
RS
558 sfi = fdopen (s, "r");
559 sfo = fdopen (s, "w");
560 if (sfi == NULL || sfo == NULL)
561 {
562 sprintf (Errmsg, "error in fdopen: %s", get_errmsg ());
563 close (s);
564 return NOTOK;
237e0016
RS
565 }
566
b1ce62a8 567 return OK;
237e0016
RS
568}
569
b1ce62a8
RS
570pop_command (fmt, a, b, c, d)
571 char *fmt;
237e0016 572{
b1ce62a8
RS
573 char buf[128];
574 char errmsg[64];
237e0016 575
b1ce62a8 576 sprintf (buf, fmt, a, b, c, d);
237e0016 577
b1ce62a8
RS
578 if (debug) fprintf (stderr, "---> %s\n", buf);
579 if (putline (buf, Errmsg, sfo) == NOTOK) return NOTOK;
237e0016 580
b1ce62a8
RS
581 if (getline (buf, sizeof buf, sfi) != OK)
582 {
583 strcpy (Errmsg, buf);
584 return NOTOK;
237e0016
RS
585 }
586
cfa191ff
RS
587 if (debug)
588 fprintf (stderr, "<--- %s\n", buf);
b1ce62a8
RS
589 if (*buf != '+')
590 {
591 strcpy (Errmsg, buf);
592 return NOTOK;
593 }
594 else
595 {
596 return OK;
237e0016
RS
597 }
598}
599
600
b1ce62a8
RS
601pop_stat (nmsgs, nbytes)
602 int *nmsgs, *nbytes;
237e0016 603{
b1ce62a8 604 char buf[128];
237e0016 605
cfa191ff
RS
606 if (debug)
607 fprintf (stderr, "---> STAT\n");
608 if (putline ("STAT", Errmsg, sfo) == NOTOK)
609 return NOTOK;
237e0016 610
b1ce62a8
RS
611 if (getline (buf, sizeof buf, sfi) != OK)
612 {
613 strcpy (Errmsg, buf);
614 return NOTOK;
237e0016
RS
615 }
616
b1ce62a8
RS
617 if (debug) fprintf (stderr, "<--- %s\n", buf);
618 if (*buf != '+')
619 {
620 strcpy (Errmsg, buf);
621 return NOTOK;
622 }
623 else
624 {
625 sscanf (buf, "+OK %d %d", nmsgs, nbytes);
626 return OK;
237e0016
RS
627 }
628}
629
b1ce62a8
RS
630pop_retr (msgno, action, arg)
631 int (*action)();
237e0016 632{
b1ce62a8 633 char buf[128];
237e0016 634
b1ce62a8
RS
635 sprintf (buf, "RETR %d", msgno);
636 if (debug) fprintf (stderr, "%s\n", buf);
637 if (putline (buf, Errmsg, sfo) == NOTOK) return NOTOK;
237e0016 638
b1ce62a8
RS
639 if (getline (buf, sizeof buf, sfi) != OK)
640 {
641 strcpy (Errmsg, buf);
642 return NOTOK;
237e0016
RS
643 }
644
b1ce62a8
RS
645 while (1)
646 {
647 switch (multiline (buf, sizeof buf, sfi))
648 {
237e0016 649 case OK:
b1ce62a8
RS
650 (*action)(buf, arg);
651 break;
237e0016 652 case DONE:
b1ce62a8 653 return OK;
237e0016 654 case NOTOK:
b1ce62a8
RS
655 strcpy (Errmsg, buf);
656 return NOTOK;
237e0016
RS
657 }
658 }
659}
660
b1ce62a8
RS
661getline (buf, n, f)
662 char *buf;
663 register int n;
664 FILE *f;
237e0016 665{
b1ce62a8
RS
666 register char *p;
667 int c;
237e0016 668
b1ce62a8
RS
669 p = buf;
670 while (--n > 0 && (c = fgetc (f)) != EOF)
671 if ((*p++ = c) == '\n') break;
237e0016 672
b1ce62a8
RS
673 if (ferror (f))
674 {
675 strcpy (buf, "error on connection");
676 return NOTOK;
237e0016
RS
677 }
678
b1ce62a8
RS
679 if (c == EOF && p == buf)
680 {
681 strcpy (buf, "connection closed by foreign host");
682 return DONE;
237e0016
RS
683 }
684
b1ce62a8
RS
685 *p = NULL;
686 if (*--p == '\n') *p = NULL;
687 if (*--p == '\r') *p = NULL;
688 return OK;
237e0016
RS
689}
690
b1ce62a8
RS
691multiline (buf, n, f)
692 char *buf;
693 register int n;
694 FILE *f;
237e0016 695{
cfa191ff
RS
696 if (getline (buf, n, f) != OK)
697 return NOTOK;
b1ce62a8
RS
698 if (*buf == '.')
699 {
700 if (*(buf+1) == NULL)
cfa191ff 701 return DONE;
b1ce62a8 702 else
cfa191ff 703 strcpy (buf, buf+1);
237e0016 704 }
b1ce62a8 705 return OK;
237e0016
RS
706}
707
708char *
b1ce62a8 709get_errmsg ()
237e0016 710{
b1ce62a8
RS
711 extern int errno, sys_nerr;
712 extern char *sys_errlist[];
713 char *s;
714
715 if (errno < sys_nerr)
716 s = sys_errlist[errno];
717 else
718 s = "unknown error";
719 return (s);
237e0016
RS
720}
721
b1ce62a8
RS
722putline (buf, err, f)
723 char *buf;
724 char *err;
725 FILE *f;
237e0016 726{
b1ce62a8
RS
727 fprintf (f, "%s\r\n", buf);
728 fflush (f);
729 if (ferror (f))
730 {
731 strcpy (err, "lost connection");
732 return NOTOK;
237e0016 733 }
b1ce62a8 734 return OK;
237e0016
RS
735}
736
b1ce62a8
RS
737mbx_write (line, mbf)
738 char *line;
739 FILE *mbf;
237e0016 740{
b1ce62a8
RS
741 fputs (line, mbf);
742 fputc (0x0a, mbf);
237e0016
RS
743}
744
b1ce62a8
RS
745mbx_delimit_begin (mbf)
746 FILE *mbf;
237e0016 747{
70da2b86 748 fputs ("\f\n0, unseen,,\n", mbf);
237e0016
RS
749}
750
b1ce62a8
RS
751mbx_delimit_end (mbf)
752 FILE *mbf;
237e0016 753{
b1ce62a8 754 putc ('\037', mbf);
237e0016
RS
755}
756
757#endif /* MAIL_USE_POP */