Update FSF's address in the preamble.
[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.
39356651 3 Copyright (C) 1986, 1992, 1993, 1994 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
39356651 9the Free Software Foundation; either version 2, or (at your option)
93320c23
JA
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
3b7ad313
EN
19the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20Boston, MA 02111-1307, USA. */
237e0016 21
63cf923d
RS
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.
08d0752f
RS
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
237e0016
RS
34/*
35 * Modified January, 1986 by Michael R. Gretzinger (Project Athena)
36 *
37 * Added POP (Post Office Protocol) service. When compiled -DPOP
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:
cfa191ff 45 * main - added code within #ifdef MAIL_USE_POP; added setuid (getuid ())
237e0016
RS
46 * after POP code.
47 * New routines in movemail.c:
48 * get_errmsg - return pointer to system error message
49 *
2e82e3c3
RS
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 *
237e0016
RS
55 */
56
3b9ee819
RS
57#define NO_SHORTNAMES /* Tell config not to load remap.h */
58#include <../src/config.h>
237e0016
RS
59#include <sys/types.h>
60#include <sys/stat.h>
61#include <sys/file.h>
e2f9d9af 62#include <stdio.h>
237e0016 63#include <errno.h>
8ca83cfd 64#include <../src/syswait.h>
2e82e3c3
RS
65#ifdef MAIL_USE_POP
66#include "pop.h"
67#endif
237e0016 68
91cf09ac
RS
69#ifdef MSDOS
70#undef access
71#endif /* MSDOS */
72
237e0016
RS
73#ifdef USG
74#include <fcntl.h>
75#include <unistd.h>
4ec9a77a
RS
76#ifndef F_OK
77#define F_OK 0
78#define X_OK 1
79#define W_OK 2
80#define R_OK 4
81#endif
237e0016
RS
82#endif /* USG */
83
29beb080
RS
84#ifdef HAVE_UNISTD_H
85#include <unistd.h>
86#endif
87
237e0016
RS
88#ifdef XENIX
89#include <sys/locking.h>
90#endif
91
63cf923d
RS
92#ifdef MAIL_USE_LOCKF
93#define MAIL_USE_SYSTEM_LOCK
94#endif
95
96#ifdef MAIL_USE_FLOCK
97#define MAIL_USE_SYSTEM_LOCK
98#endif
99
4293ba7f
RS
100#ifdef MAIL_USE_MMDF
101extern int lk_open (), lk_close ();
102#endif
103
237e0016
RS
104/* Cancel substitutions made by config.h for Emacs. */
105#undef open
106#undef read
107#undef write
108#undef close
109
e97dd183 110#ifndef errno
237e0016 111extern int errno;
e97dd183 112#endif
e2f9d9af 113char *strerror ();
e2f9d9af
DM
114
115void fatal ();
116void error ();
117void pfatal_with_name ();
118void pfatal_and_delete ();
119char *concat ();
2583d6d7 120long *xmalloc ();
e2f9d9af
DM
121int popmail ();
122int pop_retr ();
123int mbx_write ();
124int mbx_delimit_begin ();
125int mbx_delimit_end ();
237e0016
RS
126
127/* Nonzero means this is name of a lock file to delete on fatal error. */
128char *delete_lockname;
129
e2f9d9af 130int
237e0016
RS
131main (argc, argv)
132 int argc;
133 char **argv;
134{
135 char *inname, *outname;
136 int indesc, outdesc;
237e0016 137 int nread;
8ca83cfd 138 WAITTYPE status;
237e0016 139
63cf923d 140#ifndef MAIL_USE_SYSTEM_LOCK
237e0016
RS
141 struct stat st;
142 long now;
143 int tem;
144 char *lockname, *p;
906ad89d 145 char *tempname;
237e0016 146 int desc;
63cf923d 147#endif /* not MAIL_USE_SYSTEM_LOCK */
237e0016
RS
148
149 delete_lockname = 0;
150
151 if (argc < 3)
e2f9d9af 152 {
837a3add 153 fprintf (stderr, "Usage: movemail inbox destfile\n");
e2f9d9af
DM
154 exit(1);
155 }
237e0016
RS
156
157 inname = argv[1];
158 outname = argv[2];
159
4293ba7f
RS
160#ifdef MAIL_USE_MMDF
161 mmdf_init (argv[0]);
162#endif
163
af7bd34e
RS
164 if (*outname == 0)
165 fatal ("Destination file name is empty", 0);
166
b1ce62a8 167 /* Check access to output file. */
237e0016
RS
168 if (access (outname, F_OK) == 0 && access (outname, W_OK) != 0)
169 pfatal_with_name (outname);
170
8e6208c5 171 /* Also check that outname's directory is writable to the real uid. */
237e0016 172 {
91cf09ac 173 char *buf = (char *) xmalloc (strlen (outname) + 1);
e2f9d9af 174 char *p;
237e0016
RS
175 strcpy (buf, outname);
176 p = buf + strlen (buf);
177 while (p > buf && p[-1] != '/')
178 *--p = 0;
179 if (p == buf)
180 *p++ = '.';
181 if (access (buf, W_OK) != 0)
182 pfatal_with_name (buf);
183 free (buf);
184 }
185
186#ifdef MAIL_USE_POP
12a0565a 187 if (!strncmp (inname, "po:", 3))
237e0016 188 {
b3112191 189 int status;
237e0016 190
b3112191 191 status = popmail (inname + 3, outname);
237e0016
RS
192 exit (status);
193 }
194
cfa191ff 195 setuid (getuid ());
237e0016
RS
196#endif /* MAIL_USE_POP */
197
b1ce62a8
RS
198 /* Check access to input file. */
199 if (access (inname, R_OK | W_OK) != 0)
200 pfatal_with_name (inname);
201
4293ba7f 202#ifndef MAIL_USE_MMDF
63cf923d 203#ifndef MAIL_USE_SYSTEM_LOCK
f7f8635d 204 /* Use a lock file named after our first argument with .lock appended:
237e0016 205 If it exists, the mail file is locked. */
06000e3c
RS
206 /* Note: this locking mechanism is *required* by the mailer
207 (on systems which use it) to prevent loss of mail.
208
209 On systems that use a lock file, extracting the mail without locking
210 WILL occasionally cause loss of mail due to timing errors!
211
212 So, if creation of the lock file fails
f7f8635d 213 due to access permission on the mail spool directory,
06000e3c
RS
214 you simply MUST change the permission
215 and/or make movemail a setgid program
216 so it can create lock files properly.
217
218 You might also wish to verify that your system is one
219 which uses lock files for this purpose. Some systems use other methods.
220
221 If your system uses the `flock' system call for mail locking,
63cf923d 222 define MAIL_USE_SYSTEM_LOCK in config.h or the s-*.h file
06000e3c 223 and recompile movemail. If the s- file for your system
63cf923d 224 should define MAIL_USE_SYSTEM_LOCK but does not, send a bug report
06000e3c
RS
225 to bug-gnu-emacs@prep.ai.mit.edu so we can fix it. */
226
237e0016 227 lockname = concat (inname, ".lock", "");
3f628ebd
RS
228 tempname = (char *) xmalloc (strlen (inname) + strlen ("EXXXXXX") + 1);
229 strcpy (tempname, inname);
237e0016
RS
230 p = tempname + strlen (tempname);
231 while (p != tempname && p[-1] != '/')
232 p--;
233 *p = 0;
234 strcpy (p, "EXXXXXX");
235 mktemp (tempname);
cfa191ff 236 unlink (tempname);
237e0016
RS
237
238 while (1)
239 {
240 /* Create the lock file, but not under the lock file name. */
241 /* Give up if cannot do that. */
8ca83cfd 242 desc = open (tempname, O_WRONLY | O_CREAT | O_EXCL, 0666);
237e0016 243 if (desc < 0)
d0776f5c 244 {
af7bd34e
RS
245 char *message = (char *) xmalloc (strlen (tempname) + 50);
246 sprintf (message, "%s--see source file lib-src/movemail.c",
247 tempname);
d0776f5c
RS
248 pfatal_with_name (message);
249 }
237e0016
RS
250 close (desc);
251
252 tem = link (tempname, lockname);
cfa191ff 253 unlink (tempname);
237e0016
RS
254 if (tem >= 0)
255 break;
256 sleep (1);
257
66a8ad0f
RS
258 /* If lock file is five minutes old, unlock it.
259 Five minutes should be good enough to cope with crashes
260 and wedgitude, and long enough to avoid being fooled
261 by time differences between machines. */
237e0016
RS
262 if (stat (lockname, &st) >= 0)
263 {
264 now = time (0);
66a8ad0f 265 if (st.st_ctime < now - 300)
cfa191ff 266 unlink (lockname);
237e0016
RS
267 }
268 }
269
270 delete_lockname = lockname;
63cf923d
RS
271#endif /* not MAIL_USE_SYSTEM_LOCK */
272#endif /* not MAIL_USE_MMDF */
237e0016 273
8ca83cfd
RS
274 if (fork () == 0)
275 {
d5216c20 276 setuid (getuid ());
8ca83cfd 277
63cf923d
RS
278#ifndef MAIL_USE_MMDF
279#ifdef MAIL_USE_SYSTEM_LOCK
8ca83cfd 280 indesc = open (inname, O_RDWR);
63cf923d 281#else /* if not MAIL_USE_SYSTEM_LOCK */
8ca83cfd 282 indesc = open (inname, O_RDONLY);
63cf923d 283#endif /* not MAIL_USE_SYSTEM_LOCK */
8ca83cfd
RS
284#else /* MAIL_USE_MMDF */
285 indesc = lk_open (inname, O_RDONLY, 0, 0, 10);
4293ba7f
RS
286#endif /* MAIL_USE_MMDF */
287
8ca83cfd
RS
288 if (indesc < 0)
289 pfatal_with_name (inname);
237e0016 290
cfa191ff 291#if defined (BSD) || defined (XENIX)
8ca83cfd
RS
292 /* In case movemail is setuid to root, make sure the user can
293 read the output file. */
294 /* This is desirable for all systems
295 but I don't want to assume all have the umask system call */
296 umask (umask (0) & 0333);
237e0016 297#endif /* BSD or Xenix */
8ca83cfd
RS
298 outdesc = open (outname, O_WRONLY | O_CREAT | O_EXCL, 0666);
299 if (outdesc < 0)
300 pfatal_with_name (outname);
63cf923d
RS
301#ifdef MAIL_USE_SYSTEM_LOCK
302#ifdef MAIL_USE_LOCKF
303 if (lockf (indesc, F_LOCK, 0) < 0) pfatal_with_name (inname);
304#else /* not MAIL_USE_LOCKF */
237e0016 305#ifdef XENIX
8ca83cfd 306 if (locking (indesc, LK_RLCK, 0L) < 0) pfatal_with_name (inname);
237e0016 307#else
8ca83cfd 308 if (flock (indesc, LOCK_EX) < 0) pfatal_with_name (inname);
237e0016 309#endif
63cf923d
RS
310#endif /* not MAIL_USE_LOCKF */
311#endif /* MAIL_USE_SYSTEM_LOCK */
237e0016 312
08564963 313 {
8ca83cfd
RS
314 char buf[1024];
315
316 while (1)
08564963 317 {
8ca83cfd
RS
318 nread = read (indesc, buf, sizeof buf);
319 if (nread != write (outdesc, buf, nread))
320 {
321 int saved_errno = errno;
322 unlink (outname);
323 errno = saved_errno;
324 pfatal_with_name (outname);
325 }
326 if (nread < sizeof buf)
327 break;
08564963 328 }
08564963 329 }
237e0016
RS
330
331#ifdef BSD
8ca83cfd
RS
332 if (fsync (outdesc) < 0)
333 pfatal_and_delete (outname);
237e0016
RS
334#endif
335
8ca83cfd
RS
336 /* Check to make sure no errors before we zap the inbox. */
337 if (close (outdesc) != 0)
338 pfatal_and_delete (outname);
237e0016 339
63cf923d 340#ifdef MAIL_USE_SYSTEM_LOCK
cfa191ff 341#if defined (STRIDE) || defined (XENIX)
8ca83cfd
RS
342 /* Stride, xenix have file locking, but no ftruncate. This mess will do. */
343 close (open (inname, O_CREAT | O_TRUNC | O_RDWR, 0666));
237e0016 344#else
8ca83cfd 345 ftruncate (indesc, 0L);
237e0016 346#endif /* STRIDE or XENIX */
63cf923d 347#endif /* MAIL_USE_SYSTEM_LOCK */
4293ba7f
RS
348
349#ifdef MAIL_USE_MMDF
8ca83cfd 350 lk_close (indesc, 0, 0, 0);
4293ba7f 351#else
8ca83cfd 352 close (indesc);
4293ba7f 353#endif
237e0016 354
63cf923d 355#ifndef MAIL_USE_SYSTEM_LOCK
e5f7ea68
RM
356 /* Delete the input file; if we can't, at least get rid of its
357 contents. */
e97dd183 358#ifdef MAIL_UNLINK_SPOOL
8ca83cfd
RS
359 /* This is generally bad to do, because it destroys the permissions
360 that were set on the file. Better to just empty the file. */
361 if (unlink (inname) < 0 && errno != ENOENT)
e97dd183 362#endif /* MAIL_UNLINK_SPOOL */
8ca83cfd 363 creat (inname, 0600);
63cf923d 364#endif /* not MAIL_USE_SYSTEM_LOCK */
8ca83cfd
RS
365
366 exit (0);
367 }
368
369 wait (&status);
370 if (!WIFEXITED (status))
371 exit (1);
372 else if (WRETCODE (status) != 0)
373 exit (WRETCODE (status));
374
63cf923d 375#if !defined (MAIL_USE_MMDF) && !defined (MAIL_USE_SYSTEM_LOCK)
4293ba7f 376 unlink (lockname);
63cf923d 377#endif /* not MAIL_USE_MMDF and not MAIL_USE_SYSTEM_LOCK */
e2f9d9af 378 return 0;
237e0016
RS
379}
380\f
381/* Print error message and exit. */
382
e2f9d9af 383void
237e0016
RS
384fatal (s1, s2)
385 char *s1, *s2;
386{
387 if (delete_lockname)
388 unlink (delete_lockname);
389 error (s1, s2);
390 exit (1);
391}
392
393/* Print error message. `s1' is printf control string, `s2' is arg for it. */
394
e2f9d9af 395void
b1ce62a8
RS
396error (s1, s2, s3)
397 char *s1, *s2, *s3;
237e0016 398{
e2f9d9af
DM
399 fprintf (stderr, "movemail: ");
400 fprintf (stderr, s1, s2, s3);
401 fprintf (stderr, "\n");
237e0016
RS
402}
403
e2f9d9af 404void
237e0016
RS
405pfatal_with_name (name)
406 char *name;
407{
e2f9d9af 408 char *s = concat ("", strerror (errno), " for %s");
237e0016
RS
409 fatal (s, name);
410}
411
e2f9d9af 412void
cfa191ff
RS
413pfatal_and_delete (name)
414 char *name;
415{
e2f9d9af 416 char *s = concat ("", strerror (errno), " for %s");
cfa191ff
RS
417 unlink (name);
418 fatal (s, name);
419}
420
237e0016
RS
421/* Return a newly-allocated string whose contents concatenate those of s1, s2, s3. */
422
423char *
424concat (s1, s2, s3)
425 char *s1, *s2, *s3;
426{
427 int len1 = strlen (s1), len2 = strlen (s2), len3 = strlen (s3);
428 char *result = (char *) xmalloc (len1 + len2 + len3 + 1);
429
430 strcpy (result, s1);
431 strcpy (result + len1, s2);
432 strcpy (result + len1 + len2, s3);
433 *(result + len1 + len2 + len3) = 0;
434
435 return result;
436}
437
438/* Like malloc but get fatal error if memory is exhausted. */
439
2583d6d7 440long *
237e0016 441xmalloc (size)
e97dd183 442 unsigned size;
237e0016 443{
2583d6d7 444 long *result = (long *) malloc (size);
237e0016
RS
445 if (!result)
446 fatal ("virtual memory exhausted", 0);
447 return result;
448}
449\f
450/* This is the guts of the interface to the Post Office Protocol. */
451
452#ifdef MAIL_USE_POP
453
454#include <sys/socket.h>
455#include <netinet/in.h>
456#include <netdb.h>
457#include <stdio.h>
cecf0f21 458#include <pwd.h>
237e0016
RS
459
460#ifdef USG
461#include <fcntl.h>
462/* Cancel substitutions made by config.h for Emacs. */
463#undef open
464#undef read
465#undef write
466#undef close
467#endif /* USG */
468
469#define NOTOK (-1)
470#define OK 0
471#define DONE 1
472
473char *progname;
474FILE *sfi;
475FILE *sfo;
2e82e3c3
RS
476char ibuffer[BUFSIZ];
477char obuffer[BUFSIZ];
237e0016
RS
478char Errmsg[80];
479
b1ce62a8
RS
480popmail (user, outfile)
481 char *user;
482 char *outfile;
237e0016 483{
b1ce62a8 484 int nmsgs, nbytes;
b1ce62a8
RS
485 register int i;
486 int mbfi;
487 FILE *mbf;
2e82e3c3
RS
488 char *getenv ();
489 int mbx_write ();
b32701a7 490 popserver server;
2e82e3c3 491 extern char *strerror ();
237e0016 492
2e82e3c3
RS
493 server = pop_open (0, user, 0, POP_NO_GETPASS);
494 if (! server)
b1ce62a8 495 {
2e82e3c3
RS
496 error (pop_error);
497 return (1);
237e0016
RS
498 }
499
2e82e3c3 500 if (pop_stat (server, &nmsgs, &nbytes))
b1ce62a8 501 {
2e82e3c3
RS
502 error (pop_error);
503 return (1);
237e0016
RS
504 }
505
b1ce62a8
RS
506 if (!nmsgs)
507 {
2e82e3c3
RS
508 pop_close (server);
509 return (0);
b1ce62a8
RS
510 }
511
512 mbfi = open (outfile, O_WRONLY | O_CREAT | O_EXCL, 0666);
513 if (mbfi < 0)
514 {
2e82e3c3
RS
515 pop_close (server);
516 error ("Error in open: %s, %s", strerror (errno), outfile);
517 return (1);
b1ce62a8
RS
518 }
519 fchown (mbfi, getuid (), -1);
520
521 if ((mbf = fdopen (mbfi, "w")) == NULL)
522 {
2e82e3c3
RS
523 pop_close (server);
524 error ("Error in fdopen: %s", strerror (errno));
525 close (mbfi);
526 unlink (outfile);
527 return (1);
b1ce62a8
RS
528 }
529
530 for (i = 1; i <= nmsgs; i++)
531 {
532 mbx_delimit_begin (mbf);
2e82e3c3 533 if (pop_retr (server, i, mbx_write, mbf) != OK)
b1ce62a8 534 {
2e82e3c3 535 error (Errmsg);
b1ce62a8 536 close (mbfi);
2e82e3c3 537 return (1);
237e0016 538 }
b1ce62a8
RS
539 mbx_delimit_end (mbf);
540 fflush (mbf);
2e82e3c3
RS
541 if (ferror (mbf))
542 {
543 error ("Error in fflush: %s", strerror (errno));
544 pop_close (server);
545 close (mbfi);
546 return (1);
547 }
237e0016
RS
548 }
549
2e82e3c3
RS
550 /* On AFS, a call to write only modifies the file in the local
551 * workstation's AFS cache. The changes are not written to the server
552 * until a call to fsync or close is made. Users with AFS home
553 * directories have lost mail when over quota because these checks were
554 * not made in previous versions of movemail. */
555
340ff9de 556#ifdef BSD
cfa191ff
RS
557 if (fsync (mbfi) < 0)
558 {
2e82e3c3
RS
559 error ("Error in fsync: %s", strerror (errno));
560 return (1);
cfa191ff 561 }
340ff9de 562#endif
cfa191ff
RS
563
564 if (close (mbfi) == -1)
565 {
2e82e3c3
RS
566 error ("Error in close: %s", strerror (errno));
567 return (1);
cfa191ff
RS
568 }
569
b1ce62a8
RS
570 for (i = 1; i <= nmsgs; i++)
571 {
2e82e3c3 572 if (pop_delete (server, i))
b1ce62a8 573 {
2e82e3c3
RS
574 error (pop_error);
575 pop_close (server);
576 return (1);
237e0016
RS
577 }
578 }
579
2e82e3c3 580 if (pop_quit (server))
b1ce62a8 581 {
2e82e3c3
RS
582 error (pop_error);
583 return (1);
237e0016 584 }
237e0016 585
2e82e3c3 586 return (0);
237e0016
RS
587}
588
2e82e3c3 589pop_retr (server, msgno, action, arg)
b32701a7 590 popserver server;
b1ce62a8 591 int (*action)();
237e0016 592{
2e82e3c3
RS
593 extern char *strerror ();
594 char *line;
595 int ret;
237e0016 596
2e82e3c3 597 if (pop_retrieve_first (server, msgno, &line))
b1ce62a8 598 {
2e82e3c3
RS
599 strncpy (Errmsg, pop_error, sizeof (Errmsg));
600 Errmsg[sizeof (Errmsg)-1] = '\0';
601 return (NOTOK);
237e0016
RS
602 }
603
2e82e3c3 604 while (! (ret = pop_retrieve_next (server, &line)))
b1ce62a8 605 {
2e82e3c3
RS
606 if (! line)
607 break;
608
609 if ((*action)(line, arg) != OK)
b1ce62a8 610 {
2e82e3c3
RS
611 strcpy (Errmsg, strerror (errno));
612 pop_close (server);
613 return (NOTOK);
237e0016
RS
614 }
615 }
237e0016 616
2e82e3c3 617 if (ret)
b1ce62a8 618 {
2e82e3c3
RS
619 strncpy (Errmsg, pop_error, sizeof (Errmsg));
620 Errmsg[sizeof (Errmsg)-1] = '\0';
621 return (NOTOK);
237e0016
RS
622 }
623
2e82e3c3 624 return (OK);
237e0016
RS
625}
626
2e82e3c3
RS
627/* Do this as a macro instead of using strcmp to save on execution time. */
628#define IS_FROM_LINE(a) ((a[0] == 'F') \
629 && (a[1] == 'r') \
630 && (a[2] == 'o') \
631 && (a[3] == 'm') \
632 && (a[4] == ' '))
237e0016 633
2e82e3c3 634int
b1ce62a8
RS
635mbx_write (line, mbf)
636 char *line;
637 FILE *mbf;
237e0016 638{
2e82e3c3
RS
639 if (IS_FROM_LINE (line))
640 {
641 if (fputc ('>', mbf) == EOF)
642 return (NOTOK);
643 }
644 if (fputs (line, mbf) == EOF)
645 return (NOTOK);
646 if (fputc (0x0a, mbf) == EOF)
647 return (NOTOK);
648 return (OK);
237e0016
RS
649}
650
2e82e3c3 651int
b1ce62a8
RS
652mbx_delimit_begin (mbf)
653 FILE *mbf;
237e0016 654{
2e82e3c3
RS
655 if (fputs ("\f\n0, unseen,,\n", mbf) == EOF)
656 return (NOTOK);
657 return (OK);
237e0016
RS
658}
659
b1ce62a8
RS
660mbx_delimit_end (mbf)
661 FILE *mbf;
237e0016 662{
2e82e3c3
RS
663 if (putc ('\037', mbf) == EOF)
664 return (NOTOK);
665 return (OK);
237e0016
RS
666}
667
668#endif /* MAIL_USE_POP */
e5f7ea68
RM
669\f
670#ifndef HAVE_STRERROR
671char *
672strerror (errnum)
673 int errnum;
674{
675 extern char *sys_errlist[];
676 extern int sys_nerr;
677
678 if (errnum >= 0 && errnum < sys_nerr)
679 return sys_errlist[errnum];
680 return (char *) "Unknown error";
681}
682
683#endif /* ! HAVE_STRERROR */