aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--camel/ChangeLog20
-rw-r--r--camel/camel-io.c166
-rw-r--r--camel/camel-io.h42
-rw-r--r--camel/camel-process.c153
-rw-r--r--camel/camel-process.h44
-rw-r--r--camel/camel-tcp-stream-openssl.c9
-rw-r--r--camel/camel-tcp-stream-raw.c4
7 files changed, 434 insertions, 4 deletions
diff --git a/camel/ChangeLog b/camel/ChangeLog
index c3fb16e43e..345a653cb8 100644
--- a/camel/ChangeLog
+++ b/camel/ChangeLog
@@ -1,3 +1,23 @@
+2003-03-03 Jeffrey Stedfast <fejj@ximian.com>
+
+ * camel-tcp-stream-openssl.c (camel_tcp_stream_ssl_new): Updated
+ to use the new API from a fe commits ago for the NSS stream. This
+ is just to make it compile, but does not update the behaviour to
+ act like the NSS stream. Note that people shouldn't be using
+ OpenSSL anyway.
+ (camel_tcp_stream_ssl_new_raw): Same.
+
+ * camel-process.[c,h]: New source file containing convenience
+ functions for process creation/termination mainly for use with
+ Pipe filters but should be usable for anything we want.
+
+ * camel-io.[c,h]: New source files implementing read/write system
+ calls with proper error checking and cancellation
+ (ie. StreamFs::read/write and CamelTcpStreamRaw::read/write). No
+ sense duplicating the same code over and over. Now I can use this
+ same code easily in other i/o code (such as Pipe filters and gpg
+ code?).
+
2003-03-03 Not Zed <NotZed@Ximian.com>
* camel-store.c (camel_store_unsubscribe_folder): Do similar
diff --git a/camel/camel-io.c b/camel/camel-io.c
new file mode 100644
index 0000000000..88ddcf692d
--- /dev/null
+++ b/camel/camel-io.c
@@ -0,0 +1,166 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Authors: Jeffrey Stedfast <fejj@ximian.com>
+ *
+ * Copyright 2003 Ximian, Inc. (www.ximian.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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 Street #330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <sys/time.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include "camel-io.h"
+#include "camel-operation.h"
+
+
+/* FIXME: should we trade out select() for a poll() instead? */
+
+ssize_t
+camel_read (int fd, char *buf, size_t n)
+{
+ ssize_t nread;
+ int cancel_fd;
+
+ if (camel_operation_cancel_check (NULL)) {
+ errno = EINTR;
+ return -1;
+ }
+
+ cancel_fd = camel_operation_cancel_fd (NULL);
+ if (cancel_fd == -1) {
+ do {
+ nread = read (fd, buf, n);
+ } while (nread == -1 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK));
+ } else {
+ int errnosav, flags, fdmax;
+ fd_set rdset;
+
+ flags = fcntl (fd, F_GETFL);
+ fcntl (fd, F_SETFL, flags | O_NONBLOCK);
+
+ do {
+ FD_ZERO (&rdset);
+ FD_SET (fd, &rdset);
+ FD_SET (cancel_fd, &rdset);
+ fdmax = MAX (fd, cancel_fd) + 1;
+
+ nread = -1;
+ if (select (fdmax, &rdset, 0, 0, NULL) != -1) {
+ if (FD_ISSET (cancel_fd, &rdset)) {
+ fcntl (fd, F_SETFL, flags);
+ errno = EINTR;
+ return -1;
+ }
+
+ do {
+ nread = read (fd, buf, n);
+ } while (nread == -1 && errno == EINTR);
+ } else if (errno == EINTR) {
+ errno = EAGAIN;
+ }
+ } while (nread == -1 && (errno == EAGAIN || errno == EWOULDBLOCK));
+
+ errnosav = errno;
+ fcntl (fd, F_SETFL, flags);
+ errno = errnosav;
+ }
+
+ return nread;
+}
+
+
+ssize_t
+camel_write (int fd, const char *buf, size_t n)
+{
+ ssize_t w, written = 0;
+ int cancel_fd;
+
+ if (camel_operation_cancel_check (NULL)) {
+ errno = EINTR;
+ return -1;
+ }
+
+ cancel_fd = camel_operation_cancel_fd (NULL);
+ if (cancel_fd == -1) {
+ do {
+ do {
+ w = write (fd, buf + written, n - written);
+ } while (w == -1 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK));
+
+ if (w > 0)
+ written += w;
+ } while (w != -1 && written < n);
+ } else {
+ int errnosav, flags, fdmax;
+ fd_set rdset, wrset;
+
+ flags = fcntl (fd, F_GETFL);
+ fcntl (fd, F_SETFL, flags | O_NONBLOCK);
+
+ fdmax = MAX (fd, cancel_fd) + 1;
+ do {
+ FD_ZERO (&rdset);
+ FD_ZERO (&wrset);
+ FD_SET (fd, &wrset);
+ FD_SET (cancel_fd, &rdset);
+
+ w = -1;
+ if (select (fdmax, &rdset, &wrset, 0, NULL) != -1) {
+ if (FD_ISSET (cancel_fd, &rdset)) {
+ fcntl (fd, F_SETFL, flags);
+ errno = EINTR;
+ return -1;
+ }
+
+ do {
+ w = write (fd, buf + written, n - written);
+ } while (w == -1 && errno == EINTR);
+
+ if (w == -1) {
+ if (errno == EAGAIN || errno == EWOULDBLOCK) {
+ w = 0;
+ } else {
+ errnosav = errno;
+ fcntl (fd, F_SETFL, flags);
+ errno = errnosav;
+ return -1;
+ }
+ } else
+ written += w;
+ } else if (errno == EINTR) {
+ w = 0;
+ }
+ } while (w != -1 && written < n);
+
+ errnosav = errno;
+ fcntl (fd, F_SETFL, flags);
+ errno = errnosav;
+ }
+
+ if (w == -1)
+ return -1;
+
+ return written;
+}
diff --git a/camel/camel-io.h b/camel/camel-io.h
new file mode 100644
index 0000000000..a4e47c018f
--- /dev/null
+++ b/camel/camel-io.h
@@ -0,0 +1,42 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Authors: Jeffrey Stedfast <fejj@ximian.com>
+ *
+ * Copyright 2003 Ximian, Inc. (www.ximian.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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 Street #330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+
+#ifndef __CAMEL_IO_H__
+#define __CAMEL_IO_H__
+
+#include <sys/types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#pragma }
+#endif /* __cplusplus */
+
+ssize_t camel_read (int fd, char *buf, size_t n);
+
+ssize_t camel_write (int fd, const char *buf, size_t n);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __CAMEL_IO_H__ */
diff --git a/camel/camel-process.c b/camel/camel-process.c
new file mode 100644
index 0000000000..01c1e3be3d
--- /dev/null
+++ b/camel/camel-process.c
@@ -0,0 +1,153 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Authors: Jeffrey Stedfast <fejj@ximian.com>
+ *
+ * Copyright 2003 Ximian, Inc. (www.ximian.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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 Street #330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include "camel-process.h"
+
+
+pid_t
+camel_process_fork (const char *path, char **argv, int *infd, int *outfd, int *errfd, CamelException *ex)
+{
+ int errnosav, fd[6], i;
+ pid_t pid;
+
+ for (i = 0; i < 6; i++)
+ fds[i] = -1;
+
+ for (i = 0; i < 6; i += 2) {
+ if (pipe (fd + i) == -1) {
+ errnosav = errno;
+ camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
+ _("Failed to create pipe to '%s': %s"),
+ argv[0], strerror (errno));
+
+ for (i = 0; i < 6; i++) {
+ if (fd[i] == -1)
+ break;
+ close (fd[i]);
+ }
+
+ errno = errnosav;
+
+ return -1;
+ }
+ }
+
+ if (!(pid = fork ())) {
+ /* child process */
+ int maxfd, nullfd = -1;
+
+ if (!outfd || !errfd)
+ nullfd = open ("/dev/null", O_WRONLY);
+
+ if (dup2 (fd[0], STDIN_FILENO) == -1)
+ _exit (255);
+
+ if (dup2 (outfd ? fd[3] : nullfd, STDOUT_FILENO) == -1)
+ _exit (255);
+
+ if (dup2 (errfd ? fd[5] : nullfd, STDERR_FILENO) == -1)
+ _exit (255);
+
+ setsid ();
+
+ if ((maxfd = sysconf (_SC_OPEN_MAX)) > 0) {
+ for (i = 0; i < maxfd; i++) {
+ if (i != STDIN_FILENO && i != STDOUT_FILENO && i != STDERR_FILENO)
+ close (i);
+ }
+ }
+
+ execv (path, argv);
+ _exit (255);
+ } else if (pid == -1) {
+ camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM,
+ _("Failed to create create child process '%s': %s"),
+ argv[0], strerror (errno));
+ return -1;
+ }
+
+ /* parent process */
+ close (fd[0]);
+ close (fd[3]);
+ close (fd[5]);
+
+ if (infd)
+ *infd = fd[1];
+ else
+ close (fd[1]);
+
+ if (outfd)
+ *outfd = fd[2];
+ else
+ close (fd[2]);
+
+ if (errfd)
+ *errfd = fd[4];
+ else
+ close (fd[4]);
+
+ return pid;
+}
+
+
+int
+camel_process_wait (pid_t pid)
+{
+ sigset_t mask, omask;
+ int status;
+ pid_t r;
+
+ sigemptyset (&mask);
+ sigaddset (&mask, SIGALRM);
+ sigprocmask (SIG_BLOCK, &mask, &omask);
+ alarm (1);
+
+ r = waitpid (pid, &status, 0);
+
+ alarm (0);
+ sigprocmask (SIG_SETMASK, &omask, NULL);
+
+ if (r == (pid_t) -1 && errno == EINTR) {
+ kill (pid, SIGTERM);
+ sleep (1);
+ r = waitpid (pid, &status, WNOHANG);
+ if (r == (pid_t) 0) {
+ kill (pid, SIGKILL);
+ sleep (1);
+ r = waitpid (pid, &status, WNOHANG);
+ }
+ }
+
+ if (r != (pid_t) -1 && WIFEXITED (status))
+ return WEXITSTATUS (status);
+ else
+ return -1;
+}
diff --git a/camel/camel-process.h b/camel/camel-process.h
new file mode 100644
index 0000000000..a87db24d5c
--- /dev/null
+++ b/camel/camel-process.h
@@ -0,0 +1,44 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Authors: Jeffrey Stedfast <fejj@ximian.com>
+ *
+ * Copyright 2003 Ximian, Inc. (www.ximian.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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 Street #330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+
+#ifndef __CAMEL_PROCESS_H__
+#define __CAMEL_PROCESS_H__
+
+#include <sys/types.h>
+
+#include <camel/camel-exception.h>
+
+#ifdef __cplusplus
+extern "C" {
+#pragma }
+#endif /* __cplusplus */
+
+pid_t camel_process_fork (const char *path, char **argv, int *infd, int *outfd, int *errfd, CamelException *ex);
+
+int camel_process_wait (pid_t pid);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __CAMEL_PROCESS_H__ */
diff --git a/camel/camel-tcp-stream-openssl.c b/camel/camel-tcp-stream-openssl.c
index abd2e5d9c0..f83a6d0d72 100644
--- a/camel/camel-tcp-stream-openssl.c
+++ b/camel/camel-tcp-stream-openssl.c
@@ -76,6 +76,7 @@ struct _CamelTcpStreamSSLPrivate {
CamelService *service;
char *expected_host;
gboolean ssl_mode;
+ guint32 flags;
};
static void
@@ -162,6 +163,7 @@ camel_tcp_stream_ssl_get_type (void)
* camel_tcp_stream_ssl_new:
* @service: camel service
* @expected_host: host that the stream is expecting to connect with.
+ * @flags: flags
*
* Since the SSL certificate authenticator may need to prompt the
* user, a CamelService is needed. @expected_host is needed as a
@@ -170,7 +172,7 @@ camel_tcp_stream_ssl_get_type (void)
* Return value: a ssl stream (in ssl mode)
**/
CamelStream *
-camel_tcp_stream_ssl_new (CamelService *service, const char *expected_host)
+camel_tcp_stream_ssl_new (CamelService *service, const char *expected_host, guint32 flags)
{
CamelTcpStreamSSL *stream;
@@ -179,6 +181,7 @@ camel_tcp_stream_ssl_new (CamelService *service, const char *expected_host)
stream->priv->service = service;
stream->priv->expected_host = g_strdup (expected_host);
stream->priv->ssl_mode = TRUE;
+ stream->priv->flags = flags;
return CAMEL_STREAM (stream);
}
@@ -188,6 +191,7 @@ camel_tcp_stream_ssl_new (CamelService *service, const char *expected_host)
* camel_tcp_stream_ssl_new_raw:
* @service: camel service
* @expected_host: host that the stream is expecting to connect with.
+ * @flags: flags
*
* Since the SSL certificate authenticator may need to prompt the
* user, a CamelService is needed. @expected_host is needed as a
@@ -196,7 +200,7 @@ camel_tcp_stream_ssl_new (CamelService *service, const char *expected_host)
* Return value: a ssl-capable stream (in non ssl mode)
**/
CamelStream *
-camel_tcp_stream_ssl_new_raw (CamelService *service, const char *expected_host)
+camel_tcp_stream_ssl_new_raw (CamelService *service, const char *expected_host, guint32 flags)
{
CamelTcpStreamSSL *stream;
@@ -205,6 +209,7 @@ camel_tcp_stream_ssl_new_raw (CamelService *service, const char *expected_host)
stream->priv->service = service;
stream->priv->expected_host = g_strdup (expected_host);
stream->priv->ssl_mode = FALSE;
+ stream->priv->flags = flags;
return CAMEL_STREAM (stream);
}
diff --git a/camel/camel-tcp-stream-raw.c b/camel/camel-tcp-stream-raw.c
index 04dcb0d3cb..cf6a1f539d 100644
--- a/camel/camel-tcp-stream-raw.c
+++ b/camel/camel-tcp-stream-raw.c
@@ -25,14 +25,14 @@
#include <config.h>
#endif
+#include <stdio.h>
+#include <string.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/stat.h>
-#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
-#include <string.h>
#include "camel-tcp-stream-raw.h"
#include "camel-operation.h"