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