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