aboutsummaryrefslogtreecommitdiffstats
path: root/src/system.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/system.c')
-rw-r--r--src/system.c660
1 files changed, 10 insertions, 650 deletions
diff --git a/src/system.c b/src/system.c
index fa942f7..22d7a0b 100644
--- a/src/system.c
+++ b/src/system.c
@@ -28,11 +28,6 @@
#include <sys/types.h>
#include <time.h>
#include <fcntl.h>
-#ifdef HAVE_W32_SYSTEM
-# include <windows.h>
-#else
-# include <sys/wait.h>
-#endif
#include "assuan-defs.h"
#include "debug.h"
@@ -45,30 +40,7 @@
#define DEBUG_SYSIO 0
-
-assuan_fd_t
-assuan_fdopen (int fd)
-{
-#ifdef HAVE_W32_SYSTEM
-#ifdef HAVE_W32CE_SYSTEM
- assuan_fd_t ifd = (assuan_fd_t)fd;
-#else
- assuan_fd_t ifd = (assuan_fd_t) _get_osfhandle (fd);
-#endif
- assuan_fd_t ofd;
- if (! DuplicateHandle(GetCurrentProcess(), ifd,
- GetCurrentProcess(), &ofd, 0,
- TRUE, DUPLICATE_SAME_ACCESS))
- {
- gpg_err_set_errno (EIO);
- return ASSUAN_INVALID_FD;
- }
- return ofd;
-#else
- return dup (fd);
-#endif
-}
/* Manage memory specific to a context. */
@@ -154,40 +126,8 @@ _assuan_system_hooks_copy (assuan_system_hooks_t dst,
;
}
-
-/* Sleep for the given number of microseconds. Default
- implementation. */
-void
-__assuan_usleep (assuan_context_t ctx, unsigned int usec)
-{
- if (! usec)
- return;
-
-#ifdef HAVE_NANOSLEEP
- {
- struct timespec req;
- struct timespec rem;
-
- req.tv_sec = 0;
- req.tv_nsec = usec * 1000;
-
- while (nanosleep (&req, &rem) < 0 && errno == EINTR)
- req = rem;
- }
-#elif defined(HAVE_W32_SYSTEM)
- Sleep (usec / 1000);
-#else
- {
- struct timeval tv;
-
- tv.tv_sec = usec / 1000000;
- tv.tv_usec = usec % 1000000;
- select (0, NULL, NULL, NULL, &tv);
- }
-#endif
-}
-
+
/* Sleep for the given number of microseconds. */
void
_assuan_usleep (assuan_context_t ctx, unsigned int usec)
@@ -198,61 +138,8 @@ _assuan_usleep (assuan_context_t ctx, unsigned int usec)
(ctx->system.usleep) (ctx, usec);
}
-
-/* Create a pipe with one inheritable end. Default implementation. */
-int
-__assuan_pipe (assuan_context_t ctx, assuan_fd_t fd[2], int inherit_idx)
-{
-#ifdef HAVE_W32_SYSTEM
- HANDLE rh;
- HANDLE wh;
- HANDLE th;
- SECURITY_ATTRIBUTES sec_attr;
-
- memset (&sec_attr, 0, sizeof (sec_attr));
- sec_attr.nLength = sizeof (sec_attr);
- sec_attr.bInheritHandle = FALSE;
-
- if (!CreatePipe (&rh, &wh, &sec_attr, 0))
- {
- TRACE1 (ctx, ASSUAN_LOG_SYSIO, "__assuan_pipe", ctx,
- "CreatePipe failed: %s", _assuan_w32_strerror (ctx, -1));
- gpg_err_set_errno (EIO);
- return -1;
- }
-
- if (! DuplicateHandle (GetCurrentProcess(), (inherit_idx == 0) ? rh : wh,
- GetCurrentProcess(), &th, 0,
- TRUE, DUPLICATE_SAME_ACCESS ))
- {
- TRACE1 (ctx, ASSUAN_LOG_SYSIO, "__assuan_pipe", ctx,
- "DuplicateHandle failed: %s", _assuan_w32_strerror (ctx, -1));
- CloseHandle (rh);
- CloseHandle (wh);
- gpg_err_set_errno (EIO);
- return -1;
- }
- if (inherit_idx == 0)
- {
- CloseHandle (rh);
- rh = th;
- }
- else
- {
- CloseHandle (wh);
- wh = th;
- }
-
- fd[0] = rh;
- fd[1] = wh;
-
- return 0;
-#else
- return pipe (fd);
-#endif
-}
-
+
/* Create a pipe with one inheritable end. */
int
_assuan_pipe (assuan_context_t ctx, assuan_fd_t fd[2], int inherit_idx)
@@ -269,30 +156,8 @@ _assuan_pipe (assuan_context_t ctx, assuan_fd_t fd[2], int inherit_idx)
return TRACE_SUC2 ("read=0x%x, write=0x%x", fd[0], fd[1]);
}
-
-/* Close the given file descriptor, created with _assuan_pipe or one
- of the socket functions. Default implementation. */
-int
-__assuan_close (assuan_context_t ctx, assuan_fd_t fd)
-{
-#ifdef HAVE_W32_SYSTEM
- int rc = closesocket (HANDLE2SOCKET(fd));
- if (rc)
- gpg_err_set_errno ( _assuan_sock_wsa2errno (WSAGetLastError ()) );
- if (rc && WSAGetLastError () == WSAENOTSOCK)
- {
- rc = CloseHandle (fd);
- if (rc)
- /* FIXME. */
- gpg_err_set_errno (EIO);
- }
- return rc;
-#else
- return close (fd);
-#endif
-}
-
+
/* Close the given file descriptor, created with _assuan_pipe or one
of the socket functions. */
int
@@ -304,64 +169,8 @@ _assuan_close (assuan_context_t ctx, assuan_fd_t fd)
return (ctx->system.close) (ctx, fd);
}
-
-static ssize_t
-__assuan_read (assuan_context_t ctx, assuan_fd_t fd, void *buffer, size_t size)
-{
-#ifdef HAVE_W32_SYSTEM
- /* Due to the peculiarities of the W32 API we can't use read for a
- network socket and thus we try to use recv first and fallback to
- read if recv detects that it is not a network socket. */
- int res;
-
- res = recv (HANDLE2SOCKET (fd), buffer, size, 0);
- if (res == -1)
- {
- switch (WSAGetLastError ())
- {
- case WSAENOTSOCK:
- {
- DWORD nread = 0;
-
- res = ReadFile (fd, buffer, size, &nread, NULL);
- if (! res)
- {
- switch (GetLastError ())
- {
- case ERROR_BROKEN_PIPE:
- gpg_err_set_errno (EPIPE);
- break;
-
- default:
- gpg_err_set_errno (EIO);
- }
- res = -1;
- }
- else
- res = (int) nread;
- }
- break;
-
- case WSAEWOULDBLOCK:
- gpg_err_set_errno (EAGAIN);
- break;
-
- case ERROR_BROKEN_PIPE:
- gpg_err_set_errno (EPIPE);
- break;
-
- default:
- gpg_err_set_errno (EIO);
- break;
- }
- }
- return res;
-#else /*!HAVE_W32_SYSTEM*/
- return read (fd, buffer, size);
-#endif /*!HAVE_W32_SYSTEM*/
-}
-
+
ssize_t
_assuan_read (assuan_context_t ctx, assuan_fd_t fd, void *buffer, size_t size)
{
@@ -376,48 +185,8 @@ _assuan_read (assuan_context_t ctx, assuan_fd_t fd, void *buffer, size_t size)
#endif
}
-
-static ssize_t
-__assuan_write (assuan_context_t ctx, assuan_fd_t fd, const void *buffer,
- size_t size)
-{
-#ifdef HAVE_W32_SYSTEM
- /* Due to the peculiarities of the W32 API we can't use write for a
- network socket and thus we try to use send first and fallback to
- write if send detects that it is not a network socket. */
- int res;
-
- res = send (HANDLE2SOCKET (fd), buffer, size, 0);
- if (res == -1 && WSAGetLastError () == WSAENOTSOCK)
- {
- DWORD nwrite;
-
- res = WriteFile (fd, buffer, size, &nwrite, NULL);
- if (! res)
- {
- switch (GetLastError ())
- {
- case ERROR_BROKEN_PIPE:
- case ERROR_NO_DATA:
- gpg_err_set_errno (EPIPE);
- break;
-
- default:
- gpg_err_set_errno (EIO);
- break;
- }
- res = -1;
- }
- else
- res = (int) nwrite;
- }
- return res;
-#else /*!HAVE_W32_SYSTEM*/
- return write (fd, buffer, size);
-#endif /*!HAVE_W32_SYSTEM*/
-}
-
+
ssize_t
_assuan_write (assuan_context_t ctx, assuan_fd_t fd, const void *buffer,
size_t size)
@@ -433,25 +202,8 @@ _assuan_write (assuan_context_t ctx, assuan_fd_t fd, const void *buffer,
#endif
}
-
-static int
-__assuan_recvmsg (assuan_context_t ctx, assuan_fd_t fd, assuan_msghdr_t msg,
- int flags)
-{
-#ifdef HAVE_W32_SYSTEM
- gpg_err_set_errno (ENOSYS);
- return -1;
-#else
- int ret;
- do
- ret = recvmsg (fd, msg, flags);
- while (ret == -1 && errno == EINTR);
-
- return ret;
-#endif
-}
-
+
int
_assuan_recvmsg (assuan_context_t ctx, assuan_fd_t fd, assuan_msghdr_t msg,
int flags)
@@ -485,25 +237,8 @@ _assuan_recvmsg (assuan_context_t ctx, assuan_fd_t fd, assuan_msghdr_t msg,
#endif
}
-
-static int
-__assuan_sendmsg (assuan_context_t ctx, assuan_fd_t fd, assuan_msghdr_t msg,
- int flags)
-{
-#ifdef HAVE_W32_SYSTEM
- gpg_err_set_errno (ENOSYS);
- return -1;
-#else
- int ret;
- do
- ret = sendmsg (fd, msg, flags);
- while (ret == -1 && errno == EINTR);
-
- return ret;
-#endif
-}
-
+
int
_assuan_sendmsg (assuan_context_t ctx, assuan_fd_t fd, assuan_msghdr_t msg,
int flags)
@@ -536,340 +271,8 @@ _assuan_sendmsg (assuan_context_t ctx, assuan_fd_t fd, assuan_msghdr_t msg,
#endif
}
-
-#ifdef HAVE_W32_SYSTEM
-/* Build a command line for use with W32's CreateProcess. On success
- CMDLINE gets the address of a newly allocated string. */
-static int
-build_w32_commandline (assuan_context_t ctx, const char * const *argv,
- char **cmdline)
-{
- int i, n;
- const char *s;
- char *buf, *p;
-
- *cmdline = NULL;
- n = 0;
- for (i=0; (s = argv[i]); i++)
- {
- n += strlen (s) + 1 + 2; /* (1 space, 2 quoting */
- for (; *s; s++)
- if (*s == '\"')
- n++; /* Need to double inner quotes. */
- }
- n++;
-
- buf = p = _assuan_malloc (ctx, n);
- if (! buf)
- return -1;
-
- for (i = 0; argv[i]; i++)
- {
- if (i)
- p = stpcpy (p, " ");
- if (! *argv[i]) /* Empty string. */
- p = stpcpy (p, "\"\"");
- else if (strpbrk (argv[i], " \t\n\v\f\""))
- {
- p = stpcpy (p, "\"");
- for (s = argv[i]; *s; s++)
- {
- *p++ = *s;
- if (*s == '\"')
- *p++ = *s;
- }
- *p++ = '\"';
- *p = 0;
- }
- else
- p = stpcpy (p, argv[i]);
- }
-
- *cmdline= buf;
- return 0;
-}
-
-
-int
-__assuan_spawn (assuan_context_t ctx, pid_t *r_pid, const char *name,
- const char **argv,
- assuan_fd_t fd_in, assuan_fd_t fd_out,
- assuan_fd_t *fd_child_list,
- void (*atfork) (void *opaque, int reserved),
- void *atforkvalue, unsigned int flags)
-{
- SECURITY_ATTRIBUTES sec_attr;
- PROCESS_INFORMATION pi =
- {
- NULL, /* Returns process handle. */
- 0, /* Returns primary thread handle. */
- 0, /* Returns pid. */
- 0 /* Returns tid. */
- };
- STARTUPINFO si;
- assuan_fd_t fd;
- assuan_fd_t *fdp;
- char *cmdline;
- HANDLE nullfd = INVALID_HANDLE_VALUE;
-
- /* fixme: Actually we should set the "_assuan_pipe_connect_pid" env
- variable. However this requires us to write a full environment
- handler, because the strings are expected in sorted order. The
- suggestion given in the MS Reference Library, to save the old
- value, changeit, create proces and restore it, is not thread
- safe. */
-
- /* Build the command line. */
- if (build_w32_commandline (ctx, argv, &cmdline))
- return -1;
-
- /* Start the process. */
- memset (&sec_attr, 0, sizeof sec_attr);
- sec_attr.nLength = sizeof sec_attr;
- sec_attr.bInheritHandle = FALSE;
-
- memset (&si, 0, sizeof si);
- si.cb = sizeof (si);
- si.dwFlags = STARTF_USESTDHANDLES;
- /* FIXME: Dup to nul if ASSUAN_INVALID_FD. */
- si.hStdInput = fd_in;
- si.hStdOutput = fd_out;
-
- /* Dup stderr to /dev/null unless it is in the list of FDs to be
- passed to the child. */
- fd = assuan_fd_from_posix_fd (fileno (stderr));
- fdp = fd_child_list;
- if (fdp)
- {
- for (; *fdp != ASSUAN_INVALID_FD && *fdp != fd; fdp++)
- ;
- }
- if (!fdp || *fdp == ASSUAN_INVALID_FD)
- {
- nullfd = CreateFileW (L"nul", GENERIC_WRITE,
- FILE_SHARE_READ | FILE_SHARE_WRITE,
- NULL, OPEN_EXISTING, 0, NULL);
- if (nullfd == INVALID_HANDLE_VALUE)
- {
- TRACE1 (ctx, ASSUAN_LOG_SYSIO, "__assuan_spawn", ctx,
- "can't open `nul': %s", _assuan_w32_strerror (ctx, -1));
- _assuan_free (ctx, cmdline);
- gpg_err_set_errno (EIO);
- return -1;
- }
- si.hStdError = nullfd;
- }
- else
- si.hStdError = fd;
-
-#ifdef HAVE_W32CE_SYSTEM
-# define DETACHED_PROCESS (0)
-#endif
- /* Note: We inherit all handles flagged as inheritable. This seems
- to be a security flaw but there seems to be no way of selecting
- handles to inherit. */
- /* _assuan_log_printf ("CreateProcess, path=`%s' cmdline=`%s'\n", */
- /* name, cmdline); */
- if (!CreateProcess (name, /* Program to start. */
- cmdline, /* Command line arguments. */
- &sec_attr, /* Process security attributes. */
- &sec_attr, /* Thread security attributes. */
- TRUE, /* Inherit handles. */
- (CREATE_DEFAULT_ERROR_MODE
- | ((flags & 128)? DETACHED_PROCESS : 0)
-#ifndef HAVE_W32CE_SYSTEM
- | GetPriorityClass (GetCurrentProcess ())
-#endif
- | CREATE_SUSPENDED), /* Creation flags. */
- NULL, /* Environment. */
- NULL, /* Use current drive/directory. */
- &si, /* Startup information. */
- &pi /* Returns process information. */
- ))
- {
- TRACE1 (ctx, ASSUAN_LOG_SYSIO, "pipe_connect_w32", ctx,
- "CreateProcess failed: %s", _assuan_w32_strerror (ctx, -1));
- _assuan_free (ctx, cmdline);
- if (nullfd != INVALID_HANDLE_VALUE)
- CloseHandle (nullfd);
-
- gpg_err_set_errno (EIO);
- return -1;
- }
-
- _assuan_free (ctx, cmdline);
- if (nullfd != INVALID_HANDLE_VALUE)
- CloseHandle (nullfd);
-
- ResumeThread (pi.hThread);
- CloseHandle (pi.hThread);
-
- /* _assuan_log_printf ("CreateProcess ready: hProcess=%p hThread=%p" */
- /* " dwProcessID=%d dwThreadId=%d\n", */
- /* pi.hProcess, pi.hThread, */
- /* (int) pi.dwProcessId, (int) pi.dwThreadId); */
-
- *r_pid = (pid_t) pi.hProcess;
-
- /* No need to modify peer process, as we don't change the handle
- names. However this also means we are not safe, as we inherit
- too many handles. Should use approach similar to gpgme and glib
- using a helper process. */
-
- return 0;
-}
-
-#else
-
-static int
-writen (int fd, const char *buffer, size_t length)
-{
- while (length)
- {
- int nwritten = write (fd, buffer, length);
-
- if (nwritten < 0)
- {
- if (errno == EINTR)
- continue;
- return -1; /* write error */
- }
- length -= nwritten;
- buffer += nwritten;
- }
- return 0; /* okay */
-}
-
-
-int
-__assuan_spawn (assuan_context_t ctx, pid_t *r_pid, const char *name,
- const char **argv,
- assuan_fd_t fd_in, assuan_fd_t fd_out,
- assuan_fd_t *fd_child_list,
- void (*atfork) (void *opaque, int reserved),
- void *atforkvalue, unsigned int flags)
-{
- int pid;
-
- pid = fork ();
- if (pid < 0)
- return -1;
-
- if (pid == 0)
- {
- /* Child process (server side). */
- int i;
- int n;
- char errbuf[512];
- int *fdp;
- int fdnul;
-
- if (atfork)
- atfork (atforkvalue, 0);
-
- fdnul = open ("/dev/null", O_WRONLY);
- if (fdnul == -1)
- {
- TRACE1 (ctx, ASSUAN_LOG_SYSIO, "__assuan_spawn", ctx,
- "can't open `/dev/null': %s", strerror (errno));
- _exit (4);
- }
-
- /* Dup handles to stdin/stdout. */
- if (fd_out != STDOUT_FILENO)
- {
- if (dup2 (fd_out == ASSUAN_INVALID_FD ? fdnul : fd_out,
- STDOUT_FILENO) == -1)
- {
- TRACE1 (ctx, ASSUAN_LOG_SYSIO, "__assuan_spawn", ctx,
- "dup2 failed in child: %s", strerror (errno));
- _exit (4);
- }
- }
-
- if (fd_in != STDIN_FILENO)
- {
- if (dup2 (fd_in == ASSUAN_INVALID_FD ? fdnul : fd_in,
- STDIN_FILENO) == -1)
- {
- TRACE1 (ctx, ASSUAN_LOG_SYSIO, "__assuan_spawn", ctx,
- "dup2 failed in child: %s", strerror (errno));
- _exit (4);
- }
- }
-
- /* Dup stderr to /dev/null unless it is in the list of FDs to be
- passed to the child. */
- fdp = fd_child_list;
- if (fdp)
- {
- for (; *fdp != -1 && *fdp != STDERR_FILENO; fdp++)
- ;
- }
- if (!fdp || *fdp == -1)
- {
- if (dup2 (fdnul, STDERR_FILENO) == -1)
- {
- TRACE1 (ctx, ASSUAN_LOG_SYSIO, "pipe_connect_unix", ctx,
- "dup2(dev/null, 2) failed: %s", strerror (errno));
- _exit (4);
- }
- }
- close (fdnul);
-
- /* Close all files which will not be duped and are not in the
- fd_child_list. */
- n = sysconf (_SC_OPEN_MAX);
- if (n < 0)
- n = MAX_OPEN_FDS;
- for (i = 0; i < n; i++)
- {
- if (i == STDIN_FILENO || i == STDOUT_FILENO || i == STDERR_FILENO)
- continue;
- fdp = fd_child_list;
- if (fdp)
- {
- while (*fdp != -1 && *fdp != i)
- fdp++;
- }
-
- if (!(fdp && *fdp != -1))
- close (i);
- }
- gpg_err_set_errno (0);
-
- if (! name)
- {
- /* No name and no args given, thus we don't do an exec
- but continue the forked process. */
- *argv = "server";
-
- /* FIXME: Cleanup. */
- return 0;
- }
-
- execv (name, (char *const *) argv);
-
- /* oops - use the pipe to tell the parent about it */
- snprintf (errbuf, sizeof(errbuf)-1,
- "ERR %d can't exec `%s': %.50s\n",
- _assuan_error (ctx, GPG_ERR_ASS_SERVER_START),
- name, strerror (errno));
- errbuf[sizeof(errbuf)-1] = 0;
- writen (1, errbuf, strlen (errbuf));
- _exit (4);
- }
-
- if (! name)
- *argv = "client";
-
- *r_pid = pid;
-
- return 0;
-}
-#endif /* ! HAVE_W32_SYSTEM */
-
+
/* Create a new process from NAME and ARGV. Provide FD_IN and FD_OUT
as stdin and stdout. Inherit the ASSUAN_INVALID_FD-terminated
FD_CHILD_LIST as given (no remapping), which must be inheritable.
@@ -924,26 +327,10 @@ _assuan_spawn (assuan_context_t ctx, pid_t *r_pid, const char *name,
return TRACE_SYSERR (res);
}
+
/* FIXME: Add some sort of waitpid function that covers GPGME and
gpg-agent's use of assuan. */
-static pid_t
-__assuan_waitpid (assuan_context_t ctx, pid_t pid, int nowait,
- int *status, int options)
-{
-#ifndef HAVE_W32_SYSTEM
- /* We can't just release the PID, a waitpid is mandatory. But
- NOWAIT in POSIX systems just means the caller already did the
- waitpid for this child. */
- if (! nowait)
- return waitpid (pid, NULL, 0);
-#else /* ! HAVE_W32_SYSTEM */
- CloseHandle ((HANDLE) pid);
-#endif /* HAVE_W32_SYSTEM */
- return 0;
-}
-
-
pid_t
_assuan_waitpid (assuan_context_t ctx, pid_t pid, int action,
int *status, int options)
@@ -960,19 +347,8 @@ _assuan_waitpid (assuan_context_t ctx, pid_t pid, int action,
#endif
}
-
-int
-__assuan_socketpair (assuan_context_t ctx, int namespace, int style,
- int protocol, assuan_fd_t filedes[2])
-{
-#if HAVE_W32_SYSTEM
- gpg_err_set_errno (ENOSYS);
- return -1;
-#else
- return socketpair (namespace, style, protocol, filedes);
-#endif
-}
+
int
_assuan_socketpair (assuan_context_t ctx, int namespace, int style,
int protocol, assuan_fd_t filedes[2])
@@ -989,19 +365,3 @@ _assuan_socketpair (assuan_context_t ctx, int namespace, int style,
return TRACE_SYSERR (res);
}
-
-/* The default system hooks for assuan contexts. */
-struct assuan_system_hooks _assuan_system_hooks =
- {
- ASSUAN_SYSTEM_HOOKS_VERSION,
- __assuan_usleep,
- __assuan_pipe,
- __assuan_close,
- __assuan_read,
- __assuan_write,
- __assuan_recvmsg,
- __assuan_sendmsg,
- __assuan_spawn,
- __assuan_waitpid,
- __assuan_socketpair
- };