movemail.c 15.3 KB
Newer Older
Richard M. Stallman's avatar
Richard M. Stallman committed
1 2
/* movemail foo bar -- move file foo to file bar,
   locking file foo the way /bin/mail respects.
3
   Copyright (C) 1986, 1992, 1993, 1994 Free Software Foundation, Inc.
Richard M. Stallman's avatar
Richard M. Stallman committed
4 5 6

This file is part of GNU Emacs.

Joseph Arceneaux's avatar
Joseph Arceneaux committed
7 8
GNU Emacs is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
9
the Free Software Foundation; either version 2, or (at your option)
Joseph Arceneaux's avatar
Joseph Arceneaux committed
10 11
any later version.

Richard M. Stallman's avatar
Richard M. Stallman committed
12
GNU Emacs is distributed in the hope that it will be useful,
Joseph Arceneaux's avatar
Joseph Arceneaux committed
13 14 15
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.
Richard M. Stallman's avatar
Richard M. Stallman committed
16

Joseph Arceneaux's avatar
Joseph Arceneaux committed
17 18 19
You should have received a copy of the GNU General Public License
along with GNU Emacs; see the file COPYING.  If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
Richard M. Stallman's avatar
Richard M. Stallman committed
20

21 22 23 24 25
/* Important notice: defining MAIL_USE_FLOCK or MAIL_USE_LOCKF *will
   cause loss of mail* if you do it on a system that does not normally
   use flock as its way of interlocking access to inbox files.  The
   setting of MAIL_USE_FLOCK and MAIL_USE_LOCKF *must agree* with the
   system's own conventions.  It is not a choice that is up to you.
26 27 28 29 30 31 32

   So, if your system uses lock files rather than flock, then the only way
   you can get proper operation is to enable movemail to write lockfiles there.
   This means you must either give that directory access modes
   that permit everyone to write lockfiles in it, or you must make movemail
   a setuid or setgid program.  */

Richard M. Stallman's avatar
Richard M. Stallman committed
33 34 35 36 37 38 39 40 41 42 43
/*
 * Modified January, 1986 by Michael R. Gretzinger (Project Athena)
 *
 * Added POP (Post Office Protocol) service.  When compiled -DPOP
 * movemail will accept input filename arguments of the form
 * "po:username".  This will cause movemail to open a connection to
 * a pop server running on $MAILHOST (environment variable).  Movemail
 * must be setuid to root in order to work with POP.
 * 
 * New module: popmail.c
 * Modified routines:
44
 *	main - added code within #ifdef MAIL_USE_POP; added setuid (getuid ())
Richard M. Stallman's avatar
Richard M. Stallman committed
45 46 47 48
 *		after POP code. 
 * New routines in movemail.c:
 *	get_errmsg - return pointer to system error message
 *
49 50 51 52 53
 * Modified August, 1993 by Jonathan Kamens (OpenVision Technologies)
 *
 * Move all of the POP code into a separate file, "pop.c".
 * Use strerror instead of get_errmsg.
 *
Richard M. Stallman's avatar
Richard M. Stallman committed
54 55
 */

56 57
#define NO_SHORTNAMES   /* Tell config not to load remap.h */
#include <../src/config.h>
Richard M. Stallman's avatar
Richard M. Stallman committed
58 59 60
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/file.h>
61
#include <stdio.h>
Richard M. Stallman's avatar
Richard M. Stallman committed
62
#include <errno.h>
Richard M. Stallman's avatar
Richard M. Stallman committed
63
#include <../src/syswait.h>
64 65 66
#ifdef MAIL_USE_POP
#include "pop.h"
#endif
Richard M. Stallman's avatar
Richard M. Stallman committed
67

68 69 70 71
#ifdef MSDOS
#undef access
#endif /* MSDOS */

Richard M. Stallman's avatar
Richard M. Stallman committed
72 73 74
#ifdef USG
#include <fcntl.h>
#include <unistd.h>
75 76 77 78 79 80
#ifndef F_OK
#define F_OK 0
#define X_OK 1
#define W_OK 2
#define R_OK 4
#endif
Richard M. Stallman's avatar
Richard M. Stallman committed
81 82
#endif /* USG */

83 84 85 86
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif

Richard M. Stallman's avatar
Richard M. Stallman committed
87 88 89 90
#ifdef XENIX
#include <sys/locking.h>
#endif

91 92 93 94 95 96 97 98
#ifdef MAIL_USE_LOCKF
#define MAIL_USE_SYSTEM_LOCK
#endif

#ifdef MAIL_USE_FLOCK
#define MAIL_USE_SYSTEM_LOCK
#endif

99 100 101 102
#ifdef MAIL_USE_MMDF
extern int lk_open (), lk_close ();
#endif

Richard M. Stallman's avatar
Richard M. Stallman committed
103 104 105 106 107 108
/* Cancel substitutions made by config.h for Emacs.  */
#undef open
#undef read
#undef write
#undef close

David J. MacKenzie's avatar
David J. MacKenzie committed
109
#ifndef errno
Richard M. Stallman's avatar
Richard M. Stallman committed
110
extern int errno;
David J. MacKenzie's avatar
David J. MacKenzie committed
111
#endif
112 113 114 115 116 117 118
char *strerror ();

void fatal ();
void error ();
void pfatal_with_name ();
void pfatal_and_delete ();
char *concat ();
119
long *xmalloc ();
120 121 122 123 124
int popmail ();
int pop_retr ();
int mbx_write ();
int mbx_delimit_begin ();
int mbx_delimit_end ();
Richard M. Stallman's avatar
Richard M. Stallman committed
125 126 127 128

/* Nonzero means this is name of a lock file to delete on fatal error.  */
char *delete_lockname;

129
int
Richard M. Stallman's avatar
Richard M. Stallman committed
130 131 132 133 134 135 136
main (argc, argv)
     int argc;
     char **argv;
{
  char *inname, *outname;
  int indesc, outdesc;
  int nread;
Richard M. Stallman's avatar
Richard M. Stallman committed
137
  WAITTYPE status;
Richard M. Stallman's avatar
Richard M. Stallman committed
138

139
#ifndef MAIL_USE_SYSTEM_LOCK
Richard M. Stallman's avatar
Richard M. Stallman committed
140 141 142 143
  struct stat st;
  long now;
  int tem;
  char *lockname, *p;
144
  char *tempname;
Richard M. Stallman's avatar
Richard M. Stallman committed
145
  int desc;
146
#endif /* not MAIL_USE_SYSTEM_LOCK */
Richard M. Stallman's avatar
Richard M. Stallman committed
147 148 149 150

  delete_lockname = 0;

  if (argc < 3)
151
    {
152
      fprintf (stderr, "Usage: movemail inbox destfile\n");
153 154
      exit(1);
    }
Richard M. Stallman's avatar
Richard M. Stallman committed
155 156 157 158

  inname = argv[1];
  outname = argv[2];

159 160 161 162
#ifdef MAIL_USE_MMDF
  mmdf_init (argv[0]);
#endif

163
  /* Check access to output file.  */
Richard M. Stallman's avatar
Richard M. Stallman committed
164 165 166 167 168
  if (access (outname, F_OK) == 0 && access (outname, W_OK) != 0)
    pfatal_with_name (outname);

  /* Also check that outname's directory is writeable to the real uid.  */
  {
169
    char *buf = (char *) xmalloc (strlen (outname) + 1);
170
    char *p;
Richard M. Stallman's avatar
Richard M. Stallman committed
171 172 173 174 175 176 177 178 179 180 181 182
    strcpy (buf, outname);
    p = buf + strlen (buf);
    while (p > buf && p[-1] != '/')
      *--p = 0;
    if (p == buf)
      *p++ = '.';
    if (access (buf, W_OK) != 0)
      pfatal_with_name (buf);
    free (buf);
  }

#ifdef MAIL_USE_POP
183
  if (!strncmp (inname, "po:", 3))
Richard M. Stallman's avatar
Richard M. Stallman committed
184
    {
185
      int status;
Richard M. Stallman's avatar
Richard M. Stallman committed
186

187
      status = popmail (inname + 3, outname);
Richard M. Stallman's avatar
Richard M. Stallman committed
188 189 190
      exit (status);
    }

191
  setuid (getuid ());
Richard M. Stallman's avatar
Richard M. Stallman committed
192 193
#endif /* MAIL_USE_POP */

194 195 196 197
  /* Check access to input file.  */
  if (access (inname, R_OK | W_OK) != 0)
    pfatal_with_name (inname);

198
#ifndef MAIL_USE_MMDF
199
#ifndef MAIL_USE_SYSTEM_LOCK
Richard M. Stallman's avatar
Richard M. Stallman committed
200 201
  /* Use a lock file named /usr/spool/mail/$USER.lock:
     If it exists, the mail file is locked.  */
202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217
  /* Note: this locking mechanism is *required* by the mailer
     (on systems which use it) to prevent loss of mail.

     On systems that use a lock file, extracting the mail without locking
     WILL occasionally cause loss of mail due to timing errors!

     So, if creation of the lock file fails
     due to access permission on /usr/spool/mail,
     you simply MUST change the permission
     and/or make movemail a setgid program
     so it can create lock files properly.

     You might also wish to verify that your system is one
     which uses lock files for this purpose.  Some systems use other methods.

     If your system uses the `flock' system call for mail locking,
218
     define MAIL_USE_SYSTEM_LOCK in config.h or the s-*.h file
219
     and recompile movemail.  If the s- file for your system
220
     should define MAIL_USE_SYSTEM_LOCK but does not, send a bug report
221 222
     to bug-gnu-emacs@prep.ai.mit.edu so we can fix it.  */

Richard M. Stallman's avatar
Richard M. Stallman committed
223
  lockname = concat (inname, ".lock", "");
224 225
  tempname = (char *) xmalloc (strlen (inname) + strlen ("EXXXXXX") + 1);
  strcpy (tempname, inname);
Richard M. Stallman's avatar
Richard M. Stallman committed
226 227 228 229 230 231
  p = tempname + strlen (tempname);
  while (p != tempname && p[-1] != '/')
    p--;
  *p = 0;
  strcpy (p, "EXXXXXX");
  mktemp (tempname);
232
  unlink (tempname);
Richard M. Stallman's avatar
Richard M. Stallman committed
233 234 235 236 237

  while (1)
    {
      /* Create the lock file, but not under the lock file name.  */
      /* Give up if cannot do that.  */
Richard M. Stallman's avatar
Richard M. Stallman committed
238
      desc = open (tempname, O_WRONLY | O_CREAT | O_EXCL, 0666);
Richard M. Stallman's avatar
Richard M. Stallman committed
239
      if (desc < 0)
Richard M. Stallman's avatar
Richard M. Stallman committed
240
	pfatal_with_name ("lock file--see source file lib-src/movemail.c");
Richard M. Stallman's avatar
Richard M. Stallman committed
241 242 243
      close (desc);

      tem = link (tempname, lockname);
244
      unlink (tempname);
Richard M. Stallman's avatar
Richard M. Stallman committed
245 246 247 248
      if (tem >= 0)
	break;
      sleep (1);

249 250 251 252
      /* If lock file is five minutes old, unlock it.
	 Five minutes should be good enough to cope with crashes
	 and wedgitude, and long enough to avoid being fooled
	 by time differences between machines.  */
Richard M. Stallman's avatar
Richard M. Stallman committed
253 254 255
      if (stat (lockname, &st) >= 0)
	{
	  now = time (0);
256
	  if (st.st_ctime < now - 300)
257
	    unlink (lockname);
Richard M. Stallman's avatar
Richard M. Stallman committed
258 259 260 261
	}
    }

  delete_lockname = lockname;
262 263
#endif /* not MAIL_USE_SYSTEM_LOCK */
#endif /* not MAIL_USE_MMDF */
Richard M. Stallman's avatar
Richard M. Stallman committed
264

Richard M. Stallman's avatar
Richard M. Stallman committed
265 266
  if (fork () == 0)
    {
Karl Heuer's avatar
Karl Heuer committed
267
      setuid (getuid ());
Richard M. Stallman's avatar
Richard M. Stallman committed
268

269 270
#ifndef MAIL_USE_MMDF
#ifdef MAIL_USE_SYSTEM_LOCK
Richard M. Stallman's avatar
Richard M. Stallman committed
271
      indesc = open (inname, O_RDWR);
272
#else  /* if not MAIL_USE_SYSTEM_LOCK */
Richard M. Stallman's avatar
Richard M. Stallman committed
273
      indesc = open (inname, O_RDONLY);
274
#endif /* not MAIL_USE_SYSTEM_LOCK */
Richard M. Stallman's avatar
Richard M. Stallman committed
275 276
#else  /* MAIL_USE_MMDF */
      indesc = lk_open (inname, O_RDONLY, 0, 0, 10);
277 278
#endif /* MAIL_USE_MMDF */

Richard M. Stallman's avatar
Richard M. Stallman committed
279 280
      if (indesc < 0)
	pfatal_with_name (inname);
Richard M. Stallman's avatar
Richard M. Stallman committed
281

282
#if defined (BSD) || defined (XENIX)
Richard M. Stallman's avatar
Richard M. Stallman committed
283 284 285 286 287
      /* In case movemail is setuid to root, make sure the user can
	 read the output file.  */
      /* This is desirable for all systems
	 but I don't want to assume all have the umask system call */
      umask (umask (0) & 0333);
Richard M. Stallman's avatar
Richard M. Stallman committed
288
#endif /* BSD or Xenix */
Richard M. Stallman's avatar
Richard M. Stallman committed
289 290 291
      outdesc = open (outname, O_WRONLY | O_CREAT | O_EXCL, 0666);
      if (outdesc < 0)
	pfatal_with_name (outname);
292 293 294 295
#ifdef MAIL_USE_SYSTEM_LOCK
#ifdef MAIL_USE_LOCKF
      if (lockf (indesc, F_LOCK, 0) < 0) pfatal_with_name (inname);
#else /* not MAIL_USE_LOCKF */
Richard M. Stallman's avatar
Richard M. Stallman committed
296
#ifdef XENIX
Richard M. Stallman's avatar
Richard M. Stallman committed
297
      if (locking (indesc, LK_RLCK, 0L) < 0) pfatal_with_name (inname);
Richard M. Stallman's avatar
Richard M. Stallman committed
298
#else
Richard M. Stallman's avatar
Richard M. Stallman committed
299
      if (flock (indesc, LOCK_EX) < 0) pfatal_with_name (inname);
Richard M. Stallman's avatar
Richard M. Stallman committed
300
#endif
301 302
#endif /* not MAIL_USE_LOCKF */
#endif /* MAIL_USE_SYSTEM_LOCK */
Richard M. Stallman's avatar
Richard M. Stallman committed
303

Jim Blandy's avatar
Jim Blandy committed
304
      {
Richard M. Stallman's avatar
Richard M. Stallman committed
305 306 307
	char buf[1024];

	while (1)
Jim Blandy's avatar
Jim Blandy committed
308
	  {
Richard M. Stallman's avatar
Richard M. Stallman committed
309 310 311 312 313 314 315 316 317 318
	    nread = read (indesc, buf, sizeof buf);
	    if (nread != write (outdesc, buf, nread))
	      {
		int saved_errno = errno;
		unlink (outname);
		errno = saved_errno;
		pfatal_with_name (outname);
	      }
	    if (nread < sizeof buf)
	      break;
Jim Blandy's avatar
Jim Blandy committed
319 320
	  }
      }
Richard M. Stallman's avatar
Richard M. Stallman committed
321 322

#ifdef BSD
Richard M. Stallman's avatar
Richard M. Stallman committed
323 324
      if (fsync (outdesc) < 0)
	pfatal_and_delete (outname);
Richard M. Stallman's avatar
Richard M. Stallman committed
325 326
#endif

Richard M. Stallman's avatar
Richard M. Stallman committed
327 328 329
      /* Check to make sure no errors before we zap the inbox.  */
      if (close (outdesc) != 0)
	pfatal_and_delete (outname);
Richard M. Stallman's avatar
Richard M. Stallman committed
330

331
#ifdef MAIL_USE_SYSTEM_LOCK
332
#if defined (STRIDE) || defined (XENIX)
Richard M. Stallman's avatar
Richard M. Stallman committed
333 334
      /* Stride, xenix have file locking, but no ftruncate.  This mess will do. */
      close (open (inname, O_CREAT | O_TRUNC | O_RDWR, 0666));
Richard M. Stallman's avatar
Richard M. Stallman committed
335
#else
Richard M. Stallman's avatar
Richard M. Stallman committed
336
      ftruncate (indesc, 0L);
Richard M. Stallman's avatar
Richard M. Stallman committed
337
#endif /* STRIDE or XENIX */
338
#endif /* MAIL_USE_SYSTEM_LOCK */
339 340

#ifdef MAIL_USE_MMDF
Richard M. Stallman's avatar
Richard M. Stallman committed
341
      lk_close (indesc, 0, 0, 0);
342
#else
Richard M. Stallman's avatar
Richard M. Stallman committed
343
      close (indesc);
344
#endif
Richard M. Stallman's avatar
Richard M. Stallman committed
345

346
#ifndef MAIL_USE_SYSTEM_LOCK
347 348
      /* Delete the input file; if we can't, at least get rid of its
	 contents.  */
David J. MacKenzie's avatar
David J. MacKenzie committed
349
#ifdef MAIL_UNLINK_SPOOL
Richard M. Stallman's avatar
Richard M. Stallman committed
350 351 352
      /* This is generally bad to do, because it destroys the permissions
	 that were set on the file.  Better to just empty the file.  */
      if (unlink (inname) < 0 && errno != ENOENT)
David J. MacKenzie's avatar
David J. MacKenzie committed
353
#endif /* MAIL_UNLINK_SPOOL */
Richard M. Stallman's avatar
Richard M. Stallman committed
354
	creat (inname, 0600);
355
#endif /* not MAIL_USE_SYSTEM_LOCK */
Richard M. Stallman's avatar
Richard M. Stallman committed
356 357 358 359 360 361 362 363 364 365

      exit (0);
    }

  wait (&status);
  if (!WIFEXITED (status))
    exit (1);
  else if (WRETCODE (status) != 0)
    exit (WRETCODE (status));

366
#if !defined (MAIL_USE_MMDF) && !defined (MAIL_USE_SYSTEM_LOCK)
367
  unlink (lockname);
368
#endif /* not MAIL_USE_MMDF and not MAIL_USE_SYSTEM_LOCK */
369
  return 0;
Richard M. Stallman's avatar
Richard M. Stallman committed
370 371 372 373
}

/* Print error message and exit.  */

374
void
Richard M. Stallman's avatar
Richard M. Stallman committed
375 376 377 378 379 380 381 382 383 384 385
fatal (s1, s2)
     char *s1, *s2;
{
  if (delete_lockname)
    unlink (delete_lockname);
  error (s1, s2);
  exit (1);
}

/* Print error message.  `s1' is printf control string, `s2' is arg for it. */

386
void
387 388
error (s1, s2, s3)
     char *s1, *s2, *s3;
Richard M. Stallman's avatar
Richard M. Stallman committed
389
{
390 391 392
  fprintf (stderr, "movemail: ");
  fprintf (stderr, s1, s2, s3);
  fprintf (stderr, "\n");
Richard M. Stallman's avatar
Richard M. Stallman committed
393 394
}

395
void
Richard M. Stallman's avatar
Richard M. Stallman committed
396 397 398
pfatal_with_name (name)
     char *name;
{
399
  char *s = concat ("", strerror (errno), " for %s");
Richard M. Stallman's avatar
Richard M. Stallman committed
400 401 402
  fatal (s, name);
}

403
void
404 405 406
pfatal_and_delete (name)
     char *name;
{
407
  char *s = concat ("", strerror (errno), " for %s");
408 409 410 411
  unlink (name);
  fatal (s, name);
}

Richard M. Stallman's avatar
Richard M. Stallman committed
412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430
/* Return a newly-allocated string whose contents concatenate those of s1, s2, s3.  */

char *
concat (s1, s2, s3)
     char *s1, *s2, *s3;
{
  int len1 = strlen (s1), len2 = strlen (s2), len3 = strlen (s3);
  char *result = (char *) xmalloc (len1 + len2 + len3 + 1);

  strcpy (result, s1);
  strcpy (result + len1, s2);
  strcpy (result + len1 + len2, s3);
  *(result + len1 + len2 + len3) = 0;

  return result;
}

/* Like malloc but get fatal error if memory is exhausted.  */

431
long *
Richard M. Stallman's avatar
Richard M. Stallman committed
432
xmalloc (size)
David J. MacKenzie's avatar
David J. MacKenzie committed
433
     unsigned size;
Richard M. Stallman's avatar
Richard M. Stallman committed
434
{
435
  long *result = (long *) malloc (size);
Richard M. Stallman's avatar
Richard M. Stallman committed
436 437 438 439 440 441 442 443 444 445 446 447 448
  if (!result)
    fatal ("virtual memory exhausted", 0);
  return result;
}

/* This is the guts of the interface to the Post Office Protocol.  */

#ifdef MAIL_USE_POP

#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
449
#include <pwd.h>
Richard M. Stallman's avatar
Richard M. Stallman committed
450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466

#ifdef USG
#include <fcntl.h>
/* Cancel substitutions made by config.h for Emacs.  */
#undef open
#undef read
#undef write
#undef close
#endif /* USG */

#define NOTOK (-1)
#define OK 0
#define DONE 1

char *progname;
FILE *sfi;
FILE *sfo;
467 468
char ibuffer[BUFSIZ];
char obuffer[BUFSIZ];
Richard M. Stallman's avatar
Richard M. Stallman committed
469 470
char Errmsg[80];

471 472 473
popmail (user, outfile)
     char *user;
     char *outfile;
Richard M. Stallman's avatar
Richard M. Stallman committed
474
{
475 476 477 478
  int nmsgs, nbytes;
  register int i;
  int mbfi;
  FILE *mbf;
479 480
  char *getenv ();
  int mbx_write ();
481
  popserver server;
482
  extern char *strerror ();
Richard M. Stallman's avatar
Richard M. Stallman committed
483

484 485
  server = pop_open (0, user, 0, POP_NO_GETPASS);
  if (! server)
486
    {
487 488
      error (pop_error);
      return (1);
Richard M. Stallman's avatar
Richard M. Stallman committed
489 490
    }

491
  if (pop_stat (server, &nmsgs, &nbytes))
492
    {
493 494
      error (pop_error);
      return (1);
Richard M. Stallman's avatar
Richard M. Stallman committed
495 496
    }

497 498
  if (!nmsgs)
    {
499 500
      pop_close (server);
      return (0);
501 502 503 504 505
    }

  mbfi = open (outfile, O_WRONLY | O_CREAT | O_EXCL, 0666);
  if (mbfi < 0)
    {
506 507 508
      pop_close (server);
      error ("Error in open: %s, %s", strerror (errno), outfile);
      return (1);
509 510 511 512 513
    }
  fchown (mbfi, getuid (), -1);

  if ((mbf = fdopen (mbfi, "w")) == NULL)
    {
514 515 516 517 518
      pop_close (server);
      error ("Error in fdopen: %s", strerror (errno));
      close (mbfi);
      unlink (outfile);
      return (1);
519 520 521 522 523
    }

  for (i = 1; i <= nmsgs; i++)
    {
      mbx_delimit_begin (mbf);
524
      if (pop_retr (server, i, mbx_write, mbf) != OK)
525
	{
526
	  error (Errmsg);
527
	  close (mbfi);
528
	  return (1);
Richard M. Stallman's avatar
Richard M. Stallman committed
529
	}
530 531
      mbx_delimit_end (mbf);
      fflush (mbf);
532 533 534 535 536 537 538
      if (ferror (mbf))
	{
	  error ("Error in fflush: %s", strerror (errno));
	  pop_close (server);
	  close (mbfi);
	  return (1);
	}
Richard M. Stallman's avatar
Richard M. Stallman committed
539 540
    }

541 542 543 544 545 546
  /* On AFS, a call to write only modifies the file in the local
   *     workstation's AFS cache.  The changes are not written to the server
   *      until a call to fsync or close is made.  Users with AFS home
   *      directories have lost mail when over quota because these checks were
   *      not made in previous versions of movemail. */

547
#ifdef BSD
548 549
  if (fsync (mbfi) < 0)
    {
550 551
      error ("Error in fsync: %s", strerror (errno));
      return (1);
552
    }
553
#endif
554 555 556

  if (close (mbfi) == -1)
    {
557 558
      error ("Error in close: %s", strerror (errno));
      return (1);
559 560
    }

561 562
  for (i = 1; i <= nmsgs; i++)
    {
563
      if (pop_delete (server, i))
564
	{
565 566 567
	  error (pop_error);
	  pop_close (server);
	  return (1);
Richard M. Stallman's avatar
Richard M. Stallman committed
568 569 570
	}
    }

571
  if (pop_quit (server))
572
    {
573 574
      error (pop_error);
      return (1);
Richard M. Stallman's avatar
Richard M. Stallman committed
575 576
    }
    
577
  return (0);
Richard M. Stallman's avatar
Richard M. Stallman committed
578 579
}

580
pop_retr (server, msgno, action, arg)
581
     popserver server;
582
     int (*action)();
Richard M. Stallman's avatar
Richard M. Stallman committed
583
{
584 585 586
  extern char *strerror ();
  char *line;
  int ret;
Richard M. Stallman's avatar
Richard M. Stallman committed
587

588
  if (pop_retrieve_first (server, msgno, &line))
589
    {
590 591 592
      strncpy (Errmsg, pop_error, sizeof (Errmsg));
      Errmsg[sizeof (Errmsg)-1] = '\0';
      return (NOTOK);
Richard M. Stallman's avatar
Richard M. Stallman committed
593 594
    }

595
  while (! (ret = pop_retrieve_next (server, &line)))
596
    {
597 598 599 600
      if (! line)
	break;

      if ((*action)(line, arg) != OK)
601
	{
602 603 604
	  strcpy (Errmsg, strerror (errno));
	  pop_close (server);
	  return (NOTOK);
Richard M. Stallman's avatar
Richard M. Stallman committed
605 606 607
	}
    }

608
  if (ret)
609
    {
610 611 612
      strncpy (Errmsg, pop_error, sizeof (Errmsg));
      Errmsg[sizeof (Errmsg)-1] = '\0';
      return (NOTOK);
Richard M. Stallman's avatar
Richard M. Stallman committed
613 614
    }

615
  return (OK);
Richard M. Stallman's avatar
Richard M. Stallman committed
616 617
}

618 619 620 621 622 623
/* Do this as a macro instead of using strcmp to save on execution time. */
#define IS_FROM_LINE(a) ((a[0] == 'F') \
			 && (a[1] == 'r') \
			 && (a[2] == 'o') \
			 && (a[3] == 'm') \
			 && (a[4] == ' '))
Richard M. Stallman's avatar
Richard M. Stallman committed
624

625
int
626 627 628
mbx_write (line, mbf)
     char *line;
     FILE *mbf;
Richard M. Stallman's avatar
Richard M. Stallman committed
629
{
630 631 632 633 634 635 636 637 638 639
  if (IS_FROM_LINE (line))
    {
      if (fputc ('>', mbf) == EOF)
	return (NOTOK);
    }
  if (fputs (line, mbf) == EOF) 
    return (NOTOK);
  if (fputc (0x0a, mbf) == EOF)
    return (NOTOK);
  return (OK);
Richard M. Stallman's avatar
Richard M. Stallman committed
640 641
}

642
int
643 644
mbx_delimit_begin (mbf)
     FILE *mbf;
Richard M. Stallman's avatar
Richard M. Stallman committed
645
{
646 647 648
  if (fputs ("\f\n0, unseen,,\n", mbf) == EOF)
    return (NOTOK);
  return (OK);
Richard M. Stallman's avatar
Richard M. Stallman committed
649 650
}

651 652
mbx_delimit_end (mbf)
     FILE *mbf;
Richard M. Stallman's avatar
Richard M. Stallman committed
653
{
654 655 656
  if (putc ('\037', mbf) == EOF)
    return (NOTOK);
  return (OK);
Richard M. Stallman's avatar
Richard M. Stallman committed
657 658 659
}

#endif /* MAIL_USE_POP */
660 661 662 663 664 665 666 667 668 669 670 671 672 673 674

#ifndef HAVE_STRERROR
char *
strerror (errnum)
     int errnum;
{
  extern char *sys_errlist[];
  extern int sys_nerr;

  if (errnum >= 0 && errnum < sys_nerr)
    return sys_errlist[errnum];
  return (char *) "Unknown error";
}

#endif /* ! HAVE_STRERROR */