Make sure a valid handle and assuan context is available before trying
[libpwmd.git] / assuan / assuan-pipe-server.c
blob70404144d08add599f4efb7d6cbc174e4346c3c7
1 /* assuan-pipe-server.c - Assuan server working over a pipe
2 * Copyright (C) 2001, 2002 Free Software Foundation, Inc.
4 * This file is part of Assuan.
6 * Assuan is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU Lesser General Public License as
8 * published by the Free Software Foundation; either version 2.1 of
9 * the License, or (at your option) any later version.
11 * Assuan is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this program; if not, see <http://www.gnu.org/licenses/>.
20 #include <config.h>
21 #include <stdlib.h>
22 #include <stdio.h>
23 #include <sys/types.h>
24 #include <sys/stat.h>
25 #include <unistd.h>
26 #ifdef HAVE_W32_SYSTEM
27 #include <windows.h>
28 #include <fcntl.h>
29 #endif
31 #include "assuan-defs.h"
34 static void
35 deinit_pipe_server (assuan_context_t ctx)
37 /* nothing to do for this simple server */
40 static int
41 accept_connection (assuan_context_t ctx)
43 /* This is a NOP for a pipe server */
44 return 0;
47 static int
48 finish_connection (assuan_context_t ctx)
50 /* This is a NOP for a pipe server */
51 return 0;
54 /* Create a new context. Note that the handlers are set up for a pipe
55 server/client - this way we don't need extra dummy functions */
56 int
57 _assuan_new_context (assuan_context_t *r_ctx)
59 static struct assuan_io io = { _assuan_simple_read,
60 _assuan_simple_write,
61 0, 0 };
63 assuan_context_t ctx;
64 int rc;
66 *r_ctx = NULL;
67 ctx = xtrycalloc (1, sizeof *ctx);
68 if (!ctx)
69 return _assuan_error (ASSUAN_Out_Of_Core);
70 ctx->input_fd = ASSUAN_INVALID_FD;
71 ctx->output_fd = ASSUAN_INVALID_FD;
73 ctx->inbound.fd = ASSUAN_INVALID_FD;
74 ctx->outbound.fd = ASSUAN_INVALID_FD;
75 ctx->io = &io;
77 ctx->listen_fd = ASSUAN_INVALID_FD;
78 /* Use the pipe server handler as a default. */
79 ctx->deinit_handler = deinit_pipe_server;
80 ctx->accept_handler = accept_connection;
81 ctx->finish_handler = finish_connection;
83 rc = _assuan_register_std_commands (ctx);
84 if (rc)
85 xfree (ctx);
86 else
87 *r_ctx = ctx;
88 return rc;
92 /* Returns true if atoi(S) denotes a valid socket. */
93 #ifndef HAVE_W32_SYSTEM
94 static int
95 is_valid_socket (const char *s)
97 struct stat buf;
99 if ( fstat (atoi (s), &buf ) )
100 return 0;
101 return S_ISSOCK (buf.st_mode);
103 #endif /*!HAVE_W32_SYSTEM*/
107 assuan_init_pipe_server (assuan_context_t *r_ctx, int filedes[2])
109 int rc;
111 rc = _assuan_new_context (r_ctx);
112 if (!rc)
114 assuan_context_t ctx = *r_ctx;
115 const char *s;
116 unsigned long ul;
118 ctx->is_server = 1;
119 #ifdef HAVE_W32_SYSTEM
120 /* MS Windows has so many different types of handle that one
121 needs to tranlsate them at many place forth and back. Also
122 make sure that the file descriptors are in binary mode. */
123 setmode (filedes[0], O_BINARY);
124 setmode (filedes[1], O_BINARY);
125 ctx->inbound.fd = (void*)_get_osfhandle (filedes[0]);
126 ctx->outbound.fd = (void*)_get_osfhandle (filedes[1]);
127 #else
128 s = getenv ("_assuan_connection_fd");
129 if (s && *s && is_valid_socket (s) )
131 /* Well, we are called with an bi-directional file
132 descriptor. Prepare for using sendmsg/recvmsg. In this
133 case we ignore the passed file descriptors. */
134 ctx->inbound.fd = ctx->outbound.fd = atoi (s);
135 _assuan_init_uds_io (ctx);
136 ctx->deinit_handler = _assuan_uds_deinit;
138 else if (filedes && filedes[0] != ASSUAN_INVALID_FD
139 && filedes[1] != ASSUAN_INVALID_FD )
141 /* Standard pipe server. */
142 ctx->inbound.fd = filedes[0];
143 ctx->outbound.fd = filedes[1];
145 else
147 _assuan_release_context (*r_ctx);
148 *r_ctx = NULL;
149 return ASSUAN_Problem_Starting_Server;
151 #endif
152 ctx->pipe_mode = 1;
154 s = getenv ("_assuan_pipe_connect_pid");
155 if (s && (ul=strtoul (s, NULL, 10)) && ul)
156 ctx->pid = (pid_t)ul;
157 else
158 ctx->pid = (pid_t)-1;
161 return rc;
165 void
166 _assuan_release_context (assuan_context_t ctx)
168 if (ctx)
170 _assuan_inquire_release (ctx);
171 xfree (ctx->hello_line);
172 xfree (ctx->okay_line);
173 xfree (ctx->cmdtbl);
174 xfree (ctx);
178 void
179 assuan_deinit_server (assuan_context_t ctx)
181 if (ctx)
183 /* We use this function pointer to avoid linking other server
184 when not needed but still allow for a generic deinit function. */
185 ctx->deinit_handler (ctx);
186 ctx->deinit_handler = NULL;
187 _assuan_release_context (ctx);