int assuan_init_pipe_server (assuan_context_t *r_ctx, int filedes[2]) { int rc; rc = _assuan_new_context (r_ctx); if (!rc) { assuan_context_t ctx = *r_ctx; const char *s; unsigned long ul; ctx->is_server = 1; #ifdef HAVE_W32_SYSTEM /* MS Windows has so many different types of handle that one needs to tranlsate them at many place forth and back. Also make sure that the file descriptors are in binary mode. */ setmode (filedes[0], O_BINARY); setmode (filedes[1], O_BINARY); ctx->inbound.fd = (void*)_get_osfhandle (filedes[0]); ctx->outbound.fd = (void*)_get_osfhandle (filedes[1]); #else s = getenv ("_assuan_connection_fd"); if (s && *s && is_valid_socket (s) ) { /* Well, we are called with an bi-directional file descriptor. Prepare for using sendmsg/recvmsg. In this case we ignore the passed file descriptors. */ ctx->inbound.fd = ctx->outbound.fd = atoi (s); _assuan_init_uds_io (ctx); ctx->deinit_handler = _assuan_uds_deinit; } else if (filedes && filedes[0] != ASSUAN_INVALID_FD && filedes[1] != ASSUAN_INVALID_FD ) { /* Standard pipe server. */ ctx->inbound.fd = filedes[0]; ctx->outbound.fd = filedes[1]; } else { _assuan_release_context (*r_ctx); *r_ctx = NULL; return ASSUAN_Problem_Starting_Server; } #endif ctx->pipe_mode = 1; s = getenv ("_assuan_pipe_connect_pid"); if (s && (ul=strtoul (s, NULL, 10)) && ul) ctx->pid = (pid_t)ul; else ctx->pid = (pid_t)-1; } return rc; }
void assuan_deinit_server(assuan_context_t ctx) { if(ctx) { /* We use this function pointer to avoid linking other server when not needed but still allow for a generic deinit function. */ ctx->deinit_handler(ctx); ctx->deinit_handler = NULL; _assuan_release_context(ctx); } }
/* Make a connection to the Unix domain socket NAME and return a new Assuan context in CTX. SERVER_PID is currently not used but may become handy in the future. With flags set to 1 sendmsg and recvmesg are used. */ assuan_error_t assuan_socket_connect_ext(assuan_context_t *r_ctx, const char *name, pid_t server_pid, unsigned int flags) { static struct assuan_io io = { _assuan_simple_read, _assuan_simple_write }; assuan_error_t err; assuan_context_t ctx; int fd; struct sockaddr_un srvr_addr; size_t len; const char *s; if(!r_ctx || !name) return _assuan_error(ASSUAN_Invalid_Value); *r_ctx = NULL; /* We require that the name starts with a slash, so that we eventually can reuse this function for other socket types. To make things easier we allow an optional dirver prefix. */ s = name; if(*s && s[1] == ':') s += 2; if(*s != DIRSEP_C && *s != '/') return _assuan_error(ASSUAN_Invalid_Value); if(strlen(name) + 1 >= sizeof srvr_addr.sun_path) return _assuan_error(ASSUAN_Invalid_Value); err = _assuan_new_context(&ctx); if(err) return err; ctx->deinit_handler = ((flags & 1)) ? _assuan_uds_deinit : do_deinit; ctx->finish_handler = do_finish; fd = _assuan_sock_new(PF_LOCAL, SOCK_STREAM, 0); if(fd == -1) { _assuan_log_printf("can't create socket: %s\n", strerror(errno)); _assuan_release_context(ctx); return _assuan_error(ASSUAN_General_Error); } memset(&srvr_addr, 0, sizeof srvr_addr); srvr_addr.sun_family = AF_LOCAL; strncpy(srvr_addr.sun_path, name, sizeof(srvr_addr.sun_path) - 1); srvr_addr.sun_path[sizeof(srvr_addr.sun_path) - 1] = 0; len = SUN_LEN(&srvr_addr); if(_assuan_sock_connect(fd, (struct sockaddr *) &srvr_addr, len) == -1) { _assuan_log_printf("can't connect to `%s': %s\n", name, strerror(errno)); _assuan_release_context(ctx); _assuan_close(fd); return _assuan_error(ASSUAN_Connect_Failed); } ctx->inbound.fd = fd; ctx->outbound.fd = fd; ctx->io = &io; if((flags & 1)) _assuan_init_uds_io(ctx); /* initial handshake */ { int okay, off; err = _assuan_read_from_server(ctx, &okay, &off); if(err) _assuan_log_printf("can't connect to server: %s\n", assuan_strerror(err)); else if(okay != 1) { /*LOG ("can't connect to server: `");*/ _assuan_log_sanitized_string(ctx->inbound.line); fprintf(assuan_get_assuan_log_stream(), "'\n"); err = _assuan_error(ASSUAN_Connect_Failed); } } if(err) { assuan_disconnect(ctx); } else *r_ctx = ctx; return 0; }