diff options
Diffstat (limited to 'camel/camel-movemail.c')
-rw-r--r-- | camel/camel-movemail.c | 542 |
1 files changed, 0 insertions, 542 deletions
diff --git a/camel/camel-movemail.c b/camel/camel-movemail.c deleted file mode 100644 index b5a287cfa6..0000000000 --- a/camel/camel-movemail.c +++ /dev/null @@ -1,542 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* camel-movemail.c: mbox copying function */ - -/* - * Author: - * Dan Winship <danw@ximian.com> - * - * Copyright 2000 Ximian, Inc. (www.ximian.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <sys/stat.h> -#include <sys/uio.h> -#include <errno.h> -#include <fcntl.h> -#include <stdlib.h> -#include <stdio.h> -#include <time.h> -#include <unistd.h> -#include <string.h> -#include <signal.h> -#ifdef HAVE_ALLOCA_H -#include <alloca.h> -#endif - -#include "camel-movemail.h" -#include "camel-exception.h" - -#include "camel-mime-parser.h" -#include "camel-mime-filter.h" -#include "camel-mime-filter-from.h" - -#include "camel-lock-client.h" - -#define d(x) - -#ifdef MOVEMAIL_PATH -#include <sys/wait.h> - -static void movemail_external (const char *source, const char *dest, - CamelException *ex); -#endif - -#ifdef HAVE_BROKEN_SPOOL -static int camel_movemail_copy_filter(int fromfd, int tofd, off_t start, size_t bytes, CamelMimeFilter *filter); -static int camel_movemail_solaris (int oldsfd, int dfd, CamelException *ex); -#else -/* these could probably be exposed as a utility? (but only mbox needs it) */ -static int camel_movemail_copy_file(int sfd, int dfd, CamelException *ex); -#endif - -#if 0 -static int camel_movemail_copy(int fromfd, int tofd, off_t start, size_t bytes); -#endif - -/** - * camel_movemail: Copy an mbox file from a shared spool directory to a - * new folder in a Camel store - * @source: source file - * @dest: destination file - * @ex: a CamelException - * - * This copies an mbox file from a shared directory with multiple - * readers and writers into a private (presumably Camel-controlled) - * directory. Dot locking is used on the source file (but not the - * destination). - * - * Return Value: Returns -1 on error. - **/ -int -camel_movemail(const char *source, const char *dest, CamelException *ex) -{ - int lockid = -1; - int res = -1; - int sfd, dfd; - struct stat st; - - camel_exception_clear(ex); - - /* Stat and then open the spool file. If it doesn't exist or - * is empty, the user has no mail. (There's technically a race - * condition here in that an MDA might have just now locked it - * to deliver a message, but we don't care. In that case, - * assuming it's unlocked is equivalent to pretending we were - * called a fraction earlier.) - */ - if (stat (source, &st) == -1) { - if (errno != ENOENT) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not check mail file %s: %s"), - source, g_strerror (errno)); - } - return -1; - } - - if (st.st_size == 0) - return 0; - - /* open files */ - sfd = open (source, O_RDWR); - if (sfd == -1) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not open mail file %s: %s"), - source, g_strerror (errno)); - return -1; - } - - dfd = open (dest, O_WRONLY | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR); - if (dfd == -1) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not open temporary mail " - "file %s: %s"), dest, - g_strerror (errno)); - close (sfd); - return -1; - } - - /* lock our source mailbox */ - lockid = camel_lock_helper_lock(source, ex); - if (lockid == -1) { - close(sfd); - close(dfd); - return -1; - } - -#ifdef HAVE_BROKEN_SPOOL - res = camel_movemail_solaris(sfd, dfd, ex); -#else - res = camel_movemail_copy_file(sfd, dfd, ex); -#endif - - /* If no errors occurred copying the data, and we successfully - * close the destination file, then truncate the source file. - */ - if (res != -1) { - if (close (dfd) == 0) { - ftruncate (sfd, 0); - } else { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Failed to store mail in temp file %s: %s"), - dest, g_strerror (errno)); - res = -1; - } - } else - close (dfd); - close (sfd); - - camel_lock_helper_unlock(lockid); - - return res; -} - -#ifdef MOVEMAIL_PATH -static void -movemail_external (const char *source, const char *dest, CamelException *ex) -{ - sigset_t mask, omask; - pid_t pid; - int fd[2], len = 0, nread, status; - char buf[BUFSIZ], *output = NULL; - - /* Block SIGCHLD so the app can't mess us up. */ - sigemptyset (&mask); - sigaddset (&mask, SIGCHLD); - sigprocmask (SIG_BLOCK, &mask, &omask); - - if (pipe (fd) == -1) { - sigprocmask (SIG_SETMASK, &omask, NULL); - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not create pipe: %s"), - g_strerror (errno)); - return; - } - - pid = fork (); - switch (pid) { - case -1: - close (fd[0]); - close (fd[1]); - sigprocmask (SIG_SETMASK, &omask, NULL); - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Could not fork: %s"), - g_strerror (errno)); - return; - - case 0: - /* Child */ - close (fd[0]); - close (STDIN_FILENO); - dup2 (fd[1], STDOUT_FILENO); - dup2 (fd[1], STDERR_FILENO); - - execl (MOVEMAIL_PATH, MOVEMAIL_PATH, source, dest, NULL); - _exit (255); - break; - - default: - break; - } - - /* Parent */ - close (fd[1]); - - /* Read movemail's output. */ - while ((nread = read (fd[0], buf, sizeof (buf))) > 0) { - output = g_realloc (output, len + nread + 1); - memcpy (output + len, buf, nread); - len += nread; - output[len] = '\0'; - } - close (fd[0]); - - /* Now get the exit status. */ - while (waitpid (pid, &status, 0) == -1 && errno == EINTR) - ; - sigprocmask (SIG_SETMASK, &omask, NULL); - - if (!WIFEXITED (status) || WEXITSTATUS (status) != 0) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Movemail program failed: %s"), - output ? output : _("(Unknown error)")); - } - g_free (output); -} -#endif - -#ifndef HAVE_BROKEN_SPOOL -static int -camel_movemail_copy_file(int sfd, int dfd, CamelException *ex) -{ - int nread, nwrote; - char buf[4096]; - - while (1) { - int written = 0; - - nread = read (sfd, buf, sizeof (buf)); - if (nread == 0) - break; - else if (nread == -1) { - if (errno == EINTR) - continue; - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Error reading mail file: %s"), - g_strerror (errno)); - return -1; - } - - while (nread) { - nwrote = write (dfd, buf + written, nread); - if (nwrote == -1) { - if (errno == EINTR) - continue; /* continues inner loop */ - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Error writing mail temp file: %s"), - g_strerror (errno)); - return -1; - } - written += nwrote; - nread -= nwrote; - } - } - - return 0; -} -#endif - -#if 0 -static int -camel_movemail_copy(int fromfd, int tofd, off_t start, size_t bytes) -{ - char buffer[4096]; - int written = 0; - - d(printf("writing %d bytes ... ", bytes)); - - if (lseek(fromfd, start, SEEK_SET) != start) - return -1; - - while (bytes>0) { - int toread, towrite; - - toread = bytes; - if (bytes>4096) - toread = 4096; - else - toread = bytes; - do { - towrite = read(fromfd, buffer, toread); - } while (towrite == -1 && errno == EINTR); - - if (towrite == -1) - return -1; - - /* check for 'end of file' */ - if (towrite == 0) { - d(printf("end of file?\n")); - break; - } - - do { - toread = write(tofd, buffer, towrite); - } while (toread == -1 && errno == EINTR); - - if (toread == -1) - return -1; - - written += toread; - bytes -= toread; - } - - d(printf("written %d bytes\n", written)); - - return written; -} -#endif - -#define PRE_SIZE (32) - -#ifdef HAVE_BROKEN_SPOOL -static int -camel_movemail_copy_filter(int fromfd, int tofd, off_t start, size_t bytes, CamelMimeFilter *filter) -{ - char buffer[4096+PRE_SIZE]; - int written = 0; - char *filterbuffer; - int filterlen, filterpre; - - d(printf("writing %d bytes ... ", bytes)); - - camel_mime_filter_reset(filter); - - if (lseek(fromfd, start, SEEK_SET) != start) - return -1; - - while (bytes>0) { - int toread, towrite; - - toread = bytes; - if (bytes>4096) - toread = 4096; - else - toread = bytes; - do { - towrite = read(fromfd, buffer+PRE_SIZE, toread); - } while (towrite == -1 && errno == EINTR); - - if (towrite == -1) - return -1; - - d(printf("read %d unfiltered bytes\n", towrite)); - - /* check for 'end of file' */ - if (towrite == 0) { - d(printf("end of file?\n")); - camel_mime_filter_complete(filter, buffer+PRE_SIZE, towrite, PRE_SIZE, - &filterbuffer, &filterlen, &filterpre); - towrite = filterlen; - if (towrite == 0) - break; - } else { - camel_mime_filter_filter(filter, buffer+PRE_SIZE, towrite, PRE_SIZE, - &filterbuffer, &filterlen, &filterpre); - towrite = filterlen; - } - - d(printf("writing %d filtered bytes\n", towrite)); - - do { - toread = write(tofd, filterbuffer, towrite); - } while (toread == -1 && errno == EINTR); - - if (toread == -1) - return -1; - - written += toread; - bytes -= toread; - } - - d(printf("written %d bytes\n", written)); - - return written; -} - -/* write the headers back out again, but not he Content-Length header, because we dont - want to maintain it! */ -static int -solaris_header_write(int fd, struct _header_raw *header) -{ - struct iovec iv[4]; - int outlen = 0, len; - - iv[1].iov_base = ":"; - iv[1].iov_len = 1; - iv[3].iov_base = "\n"; - iv[3].iov_len = 1; - - while (header) { - if (strcasecmp(header->name, "Content-Length")) { - iv[0].iov_base = header->name; - iv[0].iov_len = strlen(header->name); - iv[2].iov_base = header->value; - iv[2].iov_len = strlen(header->value); - - do { - len = writev(fd, iv, 4); - } while (len == -1 && errno == EINTR); - - if (len == -1) - return -1; - outlen += len; - } - header = header->next; - } - - do { - len = write(fd, "\n", 1); - } while (len == -1 && errno == EINTR); - - if (len == -1) - return -1; - - outlen += 1; - - d(printf("Wrote %d bytes of headers\n", outlen)); - - return outlen; -} - -/* Well, since Solaris is a tad broken wrt its 'mbox' folder format, - we must convert it to a real mbox format. Thankfully this is - mostly pretty easy */ -static int -camel_movemail_solaris (int oldsfd, int dfd, CamelException *ex) -{ - CamelMimeParser *mp; - char *buffer; - int len; - int sfd; - CamelMimeFilterFrom *ffrom; - int ret = 1; - char *from = NULL; - - /* need to dup as the mime parser will close on finish */ - sfd = dup(oldsfd); - if (sfd == -1) { - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Error copying mail temp file: %s"), - g_strerror (errno)); - return -1; - } - - mp = camel_mime_parser_new(); - camel_mime_parser_scan_from(mp, TRUE); - camel_mime_parser_init_with_fd(mp, sfd); - - ffrom = camel_mime_filter_from_new(); - - while (camel_mime_parser_step(mp, &buffer, &len) == HSCAN_FROM) { - g_assert(camel_mime_parser_from_line(mp)); - from = g_strdup(camel_mime_parser_from_line(mp)); - if (camel_mime_parser_step(mp, &buffer, &len) != HSCAN_FROM_END) { - const char *cl; - int length; - int start, body; - off_t newpos; - - ret = 0; - - start = camel_mime_parser_tell_start_from(mp); - body = camel_mime_parser_tell(mp); - - if (write(dfd, from, strlen(from)) != strlen(from)) - goto fail; - - /* write out headers, but NOT content-length header */ - if (solaris_header_write(dfd, camel_mime_parser_headers_raw(mp)) == -1) - goto fail; - - cl = camel_mime_parser_header(mp, "content-length", NULL); - if (cl == NULL) { - g_warning("Required Content-Length header is missing from solaris mail box @ %d", (int)camel_mime_parser_tell(mp)); - camel_mime_parser_drop_step(mp); - camel_mime_parser_drop_step(mp); - camel_mime_parser_step(mp, &buffer, &len); - camel_mime_parser_unstep(mp); - length = camel_mime_parser_tell_start_from(mp) - body; - newpos = -1; - } else { - length = atoi(cl); - camel_mime_parser_drop_step(mp); - camel_mime_parser_drop_step(mp); - newpos = length+body; - } - /* copy body->length converting From lines */ - if (camel_movemail_copy_filter(sfd, dfd, body, length, (CamelMimeFilter *)ffrom) == -1) - goto fail; - if (newpos != -1) - camel_mime_parser_seek(mp, newpos, SEEK_SET); - } else { - g_error("Inalid parser state: %d", camel_mime_parser_state(mp)); - } - g_free(from); - } - - camel_object_unref((CamelObject *)mp); - camel_object_unref((CamelObject *)ffrom); - - return ret; - -fail: - g_free(from); - - camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, - _("Error copying mail temp file: %s"), - g_strerror (errno)); - - - camel_object_unref((CamelObject *)mp); - camel_object_unref((CamelObject *)ffrom); - - return -1; -} -#endif /* HAVE_BROKEN_SPOOL */ - |