Back to index

lightning-sunbird  0.9+nobinonly
Defines | Typedefs | Functions | Variables
movemail.c File Reference
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <sys/wait.h>
#include <sys/errno.h>

Go to the source code of this file.

Defines

#define TRUE   1
#define FALSE   0
#define LINUX_GLIBC_2
#define TMP_SUFFIX   ".nslock"
#define LOCK_SUFFIX   ".lock"
#define NAME_LEN   1024
#define BUFSIZ   1024

Typedefs

typedef int XP_Bool

Functions

char * XP_GetString (int i)
static void fe_movemail_perror (const char *message)
int fe_MoveMail (char *from, char *to)
 main ()

Variables

int XFE_CANT_MOVE_MAIL = 0
int XFE_CANT_GET_NEW_MAIL_LOCK_FILE_EXISTS = 0
int XFE_CANT_GET_NEW_MAIL_UNABLE_TO_CREATE_LOCK_FILE = 0
int XFE_CANT_GET_NEW_MAIL_SYSTEM_ERROR = 0
int XFE_CANT_MOVE_MAIL_UNABLE_TO_OPEN = 0
int XFE_CANT_MOVE_MAIL_UNABLE_TO_READ = 0
int XFE_CANT_MOVE_MAIL_UNABLE_TO_WRITE = 0
int XFE_THERE_WERE_PROBLEMS_MOVING_MAIL = 0
int XFE_THERE_WERE_PROBLEMS_MOVING_MAIL_EXIT_STATUS = 0
int XFE_THERE_WERE_PROBLEMS_CLEANING_UP = 0
int XFE_MOVEMAIL_FAILURE_SUFFIX = 0
int XFE_UNKNOWN_ERROR_CODE = 0
int XFE_MOVEMAIL_NO_MESSAGES = 0
int XFE_MOVEMAIL_CANT_DELETE_LOCK = 0

Define Documentation

#define BUFSIZ   1024

Definition at line 81 of file movemail.c.

#define FALSE   0

Definition at line 50 of file movemail.c.

Definition at line 52 of file movemail.c.

#define LOCK_SUFFIX   ".lock"

Definition at line 76 of file movemail.c.

#define NAME_LEN   1024

Definition at line 78 of file movemail.c.

#define TMP_SUFFIX   ".nslock"

Definition at line 75 of file movemail.c.

#define TRUE   1

Definition at line 49 of file movemail.c.


Typedef Documentation

typedef int XP_Bool

Definition at line 47 of file movemail.c.


Function Documentation

int fe_MoveMail ( char *  from,
char *  to 
)

Definition at line 126 of file movemail.c.

{
  XP_Bool succeeded = FALSE;
  char tmp_file[NAME_LEN];
  char lock_file[NAME_LEN];
  char spool_dir[NAME_LEN];
  char *bp, buf[BUFSIZ];
  char msgbuf[1024];
  int from_fd = -1;
  int to_fd = -1;
  int tmp_fd = -1;
  int nread, nwritten, nbytes, ntodo;
  struct stat st;

  *lock_file = 0;

  if (!from || !to)
    return FALSE;

  if (strlen(from) > NAME_LEN - 1) return FALSE;

  /* Make spool_dir be "/var/spool/mail" from "/var/spool/mail/$USER". */
  strcpy(spool_dir, from);
  while ((bp = strrchr(spool_dir, '/')) && bp[1] == '\0')
    *bp = '\0';
  if (!bp) return FALSE;
  *bp = 0;

  printf("%s\n", spool_dir);

  /* If we can't write into the directory itself, we can't create files,
     so we lose. */
  if (access(spool_dir, R_OK|W_OK) < 0)
    {
      snprintf(msgbuf, sizeof (msgbuf),
                XP_GetString(XFE_CANT_MOVE_MAIL_UNABLE_TO_WRITE),
                from);
       printf("XFE_CANT_MOVE_MAIL_UNABLE_TO_WRITE\n");
      fe_movemail_perror(msgbuf);
      goto FAIL;
    }

  /* If the mail-spool file doesn't exist, or is 0-length, bug out.
   */
  if (stat(from, &st) < 0 ||
      st.st_size == 0)
    {
#if 0
      NET_Progress (XP_GetString(XFE_MOVEMAIL_NO_MESSAGES));
#endif
      goto FAIL;
    }
  
  snprintf(tmp_file, sizeof (tmp_file), "%s%s", from, TMP_SUFFIX);

  if (access(tmp_file, 0) == 0) {
    /* The tmp file exists; try to get rid of it */

    if (unlink(tmp_file) < 0) {
      snprintf(msgbuf, sizeof (msgbuf),
                  XP_GetString( XFE_CANT_GET_NEW_MAIL_LOCK_FILE_EXISTS ),
                  tmp_file);
      fe_movemail_perror(msgbuf);
      goto FAIL;
    }
  }

  snprintf(lock_file, sizeof (lock_file), "%s%s", from, LOCK_SUFFIX);

  while (1) {
    int ret;

    /* First create a real file, $USER.nslock
     */
    tmp_fd = open(tmp_file, O_WRONLY|O_CREAT|O_EXCL, 0666);

    if (tmp_fd < 0) {
      snprintf(msgbuf, sizeof (msgbuf),
              XP_GetString( XFE_CANT_GET_NEW_MAIL_UNABLE_TO_CREATE_LOCK_FILE ),
              tmp_file);
      fe_movemail_perror(msgbuf);
      goto FAIL;
    }
    close(tmp_fd);
    tmp_fd = -1;
  
    /* Then make a hard link from $USER.lock to $USER.nslock -- this is the
       trick to make NFS behave synchronously.
     */
    ret = link(tmp_file, lock_file);

    /* Now we've (attempted to) make the link.  `ret' says whether it was
       successful.  It would have failed if the lock was already being held.

       Regardless of whether it succeeded, we can now delete $USER.nslock
       (the thing to which the hard-link points.)
     */
    if (unlink(tmp_file) < 0) {
      snprintf(msgbuf, sizeof (msgbuf),
                /* This error message isn't quite right; what it really
                   means is "can't delete $MAIL.nslock", but I guess that
                   could only happen if some other user was the owner of
                   it?  Or if it was already gone?  Weird... */
       XP_GetString(XFE_MOVEMAIL_CANT_DELETE_LOCK), tmp_file);
       printf("XFE_MOVEMAIL_CANT_DELETE_LOCK\n");
      fe_movemail_perror(msgbuf);
      goto FAIL;
    }

    /* If we didn't obtain the lock (== make the hard-link), above, then
       retry getting it until the file is 60 seconds old...   Then get
       Guido to go over and bust its kneecaps.
     */
    if (ret < 0) {
      sleep (1);
      if (stat(lock_file, &st) >= 0) {
       int current = time(NULL);
       if (st.st_ctime < current - 60)
         unlink (lock_file);
      }
    } else {
      /* Got the lock - done waiting. */
      break;
    }
  }

  /* All of this junk used to happen in a forked process, but that's not
     necessary any more (actually, hasn't been for a long time) since we
     no longer play any setuid/setgid games -- there is no gain to doing
     this in another fork and waiting for it to complete.
   */

  /* Open the mail spool file for input...
   */
  from_fd = open(from, O_RDWR, 0666);
  if (from_fd < 0)
    {
      int err;
      if (access(from, W_OK) < 0)  /* look again, for right error message */
       err = XFE_CANT_MOVE_MAIL_UNABLE_TO_WRITE;
      else if (access(from, 0) == 0)
       err = XFE_CANT_MOVE_MAIL_UNABLE_TO_READ;
      else
       err = XFE_CANT_MOVE_MAIL_UNABLE_TO_OPEN;
      snprintf(msgbuf, sizeof (msgbuf), XP_GetString(err), from);
      fe_movemail_perror(msgbuf);
      goto FAIL;
    }

  /* Open the destination file for output...
   */
  to_fd = open(to, O_WRONLY|O_CREAT|O_EXCL, 0666);
  if (to_fd < 0) {
    snprintf(msgbuf, sizeof (msgbuf),
              XP_GetString( XFE_CANT_MOVE_MAIL_UNABLE_TO_OPEN ),
              to);
    fe_movemail_perror(msgbuf);
    goto FAIL;
  }

  /* copy the file */

  nbytes = BUFSIZ;

  while (1) {
    nread = read(from_fd, buf, nbytes);

    if (nread < 0) {
      /* we're busted */
      snprintf(msgbuf, sizeof (msgbuf),
                XP_GetString( XFE_CANT_MOVE_MAIL_UNABLE_TO_READ ), from);
      fe_movemail_perror(msgbuf);
      goto FAIL;
    }

    if (!nread) {
      /* we're done */
      break;
    }

    for (ntodo = nread, bp = buf;
        ntodo > 0;
        ntodo -= nwritten, bp += nwritten) {
      nwritten = write(to_fd, bp, ntodo);

      if (nwritten < 0) {
       snprintf(msgbuf, sizeof (msgbuf),
                  XP_GetString( XFE_CANT_MOVE_MAIL_UNABLE_TO_WRITE ), to); 
       fe_movemail_perror(msgbuf);
       goto FAIL;
      }
    }
  }

  /* if we made it this far, we're done copying the file contents.
     First, close and sync the output file.
   */

  if (fsync(to_fd) < 0 ||
      close(to_fd) < 0)
    {
      snprintf(msgbuf, sizeof (msgbuf),
                XP_GetString( XFE_CANT_MOVE_MAIL_UNABLE_TO_WRITE ), to); 
      fe_movemail_perror(msgbuf);
      goto FAIL;
    }
  to_fd = -1;

  /* Now the output file is closed and sync'ed, so we can truncate the
     spool file.
   */
  if (ftruncate(from_fd, (off_t)0) < 0)
    {
      snprintf(msgbuf, sizeof (msgbuf),
                XP_GetString( XFE_THERE_WERE_PROBLEMS_CLEANING_UP ),
                from);
      fe_movemail_perror(msgbuf);
      goto FAIL;
    }

  succeeded = TRUE;

 FAIL:

  if (to_fd >= 0) close(to_fd);
  if (from_fd >= 0) close(from_fd);
  if (tmp_fd >= 0) close(tmp_fd);

  /* Unlink the lock file.
     If this fails, but we were otherwise successful, then whine about it.
     Otherwise, we've already presented an error dialog about something else.
   */
  if (*lock_file && unlink(lock_file) < 0 && succeeded)
    {
      snprintf(msgbuf, sizeof (msgbuf),
                XP_GetString( XFE_THERE_WERE_PROBLEMS_CLEANING_UP ),
                lock_file);
      fe_movemail_perror(msgbuf);
      succeeded = FALSE;
    }

  return succeeded;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void fe_movemail_perror ( const char *  message) [static]

Definition at line 89 of file movemail.c.

{
  int e = errno;
  char *es = 0;
  char *buf1 = 0;
  char buf2[512];
  char *suffix;
  int L;

  if ((unsigned)e < (unsigned)sys_nerr)
    {
      es = sys_errlist [e];
    }
  else
    {
      snprintf (buf2, sizeof (buf2), XP_GetString( XFE_UNKNOWN_ERROR_CODE ),
              errno);
       printf("XFE_UNKNOWN_ERROR_CODE\n");
      es = buf2;
    }

  suffix = XP_GetString(XFE_MOVEMAIL_FAILURE_SUFFIX);
  printf("XFE_MOVEMAIL_FAILURE_SUFFIX\n");
  if(!suffix) suffix = "";
  if(!message) message = "";
  L = strlen(message) + strlen(es) + strlen(suffix) + 40;
  buf1 = (char *) malloc(L);
  if(!buf1) return;
  snprintf (buf1, L-1, "%s\n%s\n\n%s", message, es, suffix);
#if 0
  FE_Alert (buf1);
#endif
  free(buf1);
}

Here is the call graph for this function:

Here is the caller graph for this function:

main ( void  )

Definition at line 370 of file movemail.c.

{
  fe_MoveMail ("/var/spool/mail/localguy","/home/localguy/mozilla.mail-recovery");
}

Here is the call graph for this function:

char* XP_GetString ( int  i)

Definition at line 84 of file movemail.c.

                          {
  return NULL;
}

Here is the caller graph for this function:


Variable Documentation

Definition at line 61 of file movemail.c.

Definition at line 63 of file movemail.c.

Definition at line 62 of file movemail.c.

Definition at line 60 of file movemail.c.

Definition at line 64 of file movemail.c.

Definition at line 65 of file movemail.c.

Definition at line 66 of file movemail.c.

Definition at line 73 of file movemail.c.

Definition at line 70 of file movemail.c.

Definition at line 72 of file movemail.c.

Definition at line 69 of file movemail.c.

Definition at line 67 of file movemail.c.

Definition at line 68 of file movemail.c.

Definition at line 71 of file movemail.c.