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