static void list_iter_callback(const char *user, void *context) { struct auth_worker_list_context *ctx = context; string_t *str; if (user == NULL) { if (ctx->sending) ctx->done = TRUE; else list_iter_deinit(ctx); return; } T_BEGIN { str = t_str_new(128); str_printfa(str, "%u\t*\t%s\n", ctx->id, user); o_stream_send(ctx->client->output, str_data(str), str_len(str)); } T_END; if (ctx->sending) { /* avoid recursively looping to this same function */ ctx->sent = TRUE; return; } do { ctx->sending = TRUE; ctx->sent = FALSE; ctx->userdb->iface->iterate_next(ctx->iter); } while (ctx->sent && o_stream_get_buffer_used_size(ctx->client->output) == 0); ctx->sending = FALSE; if (ctx->done) list_iter_deinit(ctx); }
static void program_client_program_input(struct program_client *pclient) { struct istream *input = pclient->program_input; struct ostream *output = pclient->output; const unsigned char *data; size_t size; int ret = 0; if ( input != NULL ) { while ( (ret=i_stream_read_data(input, &data, &size, 0)) > 0 ) { if ( output != NULL ) { ssize_t sent; if ( (sent=o_stream_send(output, data, size)) < 0 ) { program_client_fail(pclient, PROGRAM_CLIENT_ERROR_IO); return; } size = (size_t)sent; } i_stream_skip(input, size); } if ( ret < 0 ) { if ( i_stream_is_eof(input) ) { if ( !program_client_input_pending(pclient) ) program_client_disconnect(pclient, FALSE); return; } program_client_fail(pclient, PROGRAM_CLIENT_ERROR_IO); } } }
static bool replicator_send_buf(struct replicator_connection *conn, buffer_t *buf) { const unsigned char *data = buf->data; unsigned int len = IO_BLOCK_SIZE; /* try to send about IO_BLOCK_SIZE amount of data, but only full lines */ if (len > buf->used) len = buf->used; for (;; len++) { i_assert(len < buf->used); /* there is always LF */ if (data[len] == '\n') { len++; break; } } if (o_stream_send(conn->output, data, len) < 0) { replicator_connection_disconnect(conn); return FALSE; } buffer_delete(buf, 0, len); return TRUE; }
static int fetch_binary_size(struct imap_fetch_context *ctx, struct mail *mail, struct imap_fetch_body_data *body) { string_t *str; uoff_t size; if (mail == NULL) { imap_msgpart_free(&body->msgpart); return 1; } if (imap_msgpart_size(mail, body->msgpart, &size) < 0) return -1; str = t_str_new(128); if (ctx->state.cur_first) ctx->state.cur_first = FALSE; else str_append_c(str, ' '); str_printfa(str, "%s %"PRIuUOFF_T, get_body_name(body), size); if (o_stream_send(ctx->client->output, str_data(str), str_len(str)) < 0) return -1; return 1; }
static void test_ostream_dot_one(const struct dot_test *test) { struct istream *test_input; struct ostream *output, *test_output; buffer_t *output_data; const unsigned char *data; size_t size; ssize_t ret; test_input = test_istream_create(test->input); output_data = buffer_create_dynamic(pool_datastack_create(), 1024); test_output = o_stream_create_buffer(output_data); output = o_stream_create_dot(test_output, FALSE); while ((ret = i_stream_read(test_input)) > 0 || ret == -2) { data = i_stream_get_data(test_input, &size); ret = o_stream_send(output, data, size); test_assert(ret >= 0); if (ret <= 0) break; i_stream_skip(test_input, ret); } test_assert(test_input->eof); test_assert(o_stream_flush(output) > 0); o_stream_unref(&output); o_stream_unref(&test_output); test_assert(strcmp(str_c(output_data), test->output) == 0); i_stream_unref(&test_input); }
static int program_client_program_output(struct program_client *pclient) { struct istream *input = pclient->input; struct ostream *output = pclient->program_output; const unsigned char *data; size_t size; int ret = 0; if ((ret = o_stream_flush(output)) <= 0) { if (ret < 0) program_client_fail(pclient, PROGRAM_CLIENT_ERROR_IO); return ret; } if ( input != NULL && output != NULL ) { do { while ( (data=i_stream_get_data(input, &size)) != NULL ) { ssize_t sent; if ( (sent=o_stream_send(output, data, size)) < 0 ) { program_client_fail(pclient, PROGRAM_CLIENT_ERROR_IO); return -1; } if ( sent == 0 ) return 0; i_stream_skip(input, sent); } } while ( (ret=i_stream_read(input)) > 0 ); if ( ret == 0 ) return 1; if ( ret < 0 ) { if ( !input->eof ) { program_client_fail(pclient, PROGRAM_CLIENT_ERROR_IO); return -1; } else if ( !i_stream_have_bytes_left(input) ) { i_stream_unref(&pclient->input); input = NULL; if ( (ret = o_stream_flush(output)) <= 0 ) { if ( ret < 0 ) program_client_fail(pclient, PROGRAM_CLIENT_ERROR_IO); return ret; } } } } if ( input == NULL ) { if ( !program_client_input_pending(pclient) ) { program_client_disconnect(pclient, FALSE); } else if (program_client_close_output(pclient) < 0) { program_client_fail(pclient, PROGRAM_CLIENT_ERROR_IO); } } return 1; }
static void test_iostream_temp_create_sized_disk(void) { struct ostream *output; test_begin("iostream_temp_create_sized() disk"); output = iostream_temp_create_sized(".", 0, "test", 4); test_assert(o_stream_send(output, "123", 3) == 3); test_assert(output->offset == 3); test_assert(o_stream_send(output, "4", 1) == 1); test_assert(output->offset == 4); test_assert(o_stream_get_fd(output) == -1); test_assert(o_stream_send(output, "5", 1) == 1); test_assert(output->offset == 5); test_assert(o_stream_get_fd(output) != -1); o_stream_destroy(&output); test_end(); }
static void config_request_output(const char *key, const char *value, enum config_key_type type ATTR_UNUSED, void *context) { struct ostream *output = context; const char *p; o_stream_send_str(output, key); o_stream_send_str(output, "="); while ((p = strchr(value, '\n')) != NULL) { o_stream_send(output, value, p-value); o_stream_send(output, SETTING_STREAM_LF_CHAR, 1); value = p+1; } o_stream_send_str(output, value); o_stream_send_str(output, "\n"); }
static int mbox_append_lf(struct mbox_save_context *ctx) { if (o_stream_send(ctx->output, "\n", 1) < 0) { write_error(ctx); return -1; } return 0; }
static void http_transfer_chunked_ostream_close(struct iostream_private *stream, bool close_parent) { struct http_transfer_chunked_ostream *tcstream = (struct http_transfer_chunked_ostream *)stream; (void)o_stream_send(tcstream->ostream.parent, "0\r\n\r\n", 5); (void)o_stream_flush(&tcstream->ostream.ostream); if (close_parent) o_stream_close(tcstream->ostream.parent); }
static void test_iostream_temp_create_sized_memory(void) { struct ostream *output; test_begin("iostream_temp_create_sized() memory"); output = iostream_temp_create_sized(".intentional-nonexistent-error/", 0, "test", 4); test_assert(o_stream_send(output, "123", 3) == 3); test_assert(output->offset == 3); test_assert(o_stream_send(output, "4", 1) == 1); test_assert(output->offset == 4); test_assert(o_stream_get_fd(output) == -1); /* now we'll try to switch to writing to a file, but it'll fail */ test_expect_error_string("safe_mkstemp"); test_assert(o_stream_send(output, "5", 1) == 1); test_expect_no_more_errors(); test_assert(o_stream_get_fd(output) == -1); o_stream_destroy(&output); test_end(); }
static int o_stream_zlib_lsb_uint32(struct ostream *output, uint32_t num) { unsigned char buf[sizeof(uint32_t)]; unsigned int i; for (i = 0; i < sizeof(buf); i++) { buf[i] = num & 0xff; num >>= 8; } if (o_stream_send(output, buf, sizeof(buf)) != sizeof(buf)) return -1; return 0; }
static int o_stream_zlib_send_gz_header(struct zlib_ostream *zstream) { ssize_t ret; ret = o_stream_send(zstream->output, zstream->gz_header, sizeof(zstream->gz_header)); if ((size_t)ret != sizeof(zstream->gz_header)) { zstream_copy_error(zstream); return -1; } zstream->header_sent = TRUE; return 0; }
static bool openssl_iostream_bio_output(struct ssl_iostream *ssl_io) { size_t bytes, max_bytes; ssize_t sent; unsigned char buffer[IO_BLOCK_SIZE]; bool bytes_sent = FALSE; int ret; o_stream_cork(ssl_io->plain_output); while ((bytes = BIO_ctrl_pending(ssl_io->bio_ext)) > 0) { /* bytes contains how many SSL encrypted bytes we should be sending out */ max_bytes = o_stream_get_buffer_avail_size(ssl_io->plain_output); if (bytes > max_bytes) { if (max_bytes == 0) { /* wait until output buffer clears */ o_stream_set_flush_pending(ssl_io->plain_output, TRUE); break; } bytes = max_bytes; } if (bytes > sizeof(buffer)) bytes = sizeof(buffer); /* BIO_read() is guaranteed to return all the bytes that BIO_ctrl_pending() returned */ ret = BIO_read(ssl_io->bio_ext, buffer, bytes); i_assert(ret == (int)bytes); /* we limited number of read bytes to plain_output's available size. this send() is guaranteed to either fully succeed or completely fail due to some error. */ sent = o_stream_send(ssl_io->plain_output, buffer, bytes); if (sent < 0) { i_assert(ssl_io->plain_output->closed || ssl_io->plain_output->stream_errno != 0); i_free(ssl_io->plain_stream_errstr); ssl_io->plain_stream_errstr = i_strdup(o_stream_get_error(ssl_io->plain_output)); ssl_io->plain_stream_errno = ssl_io->plain_output->stream_errno; ssl_io->closed = TRUE; break; } i_assert(sent == (ssize_t)bytes); bytes_sent = TRUE; } o_stream_uncork(ssl_io->plain_output); return bytes_sent; }
static int client_input_status_overview(struct doveadm_connection *client) { struct replicator_queue *queue = replicator_brain_get_queue(client->brain); struct replicator_queue_iter *iter; struct replicator_user *user; enum replication_priority priority; unsigned int pending_counts[REPLICATION_PRIORITY_SYNC+1]; unsigned int user_count, next_secs, pending_failed_count; unsigned int pending_full_resync_count, waiting_failed_count; string_t *str = t_str_new(256); memset(pending_counts, 0, sizeof(pending_counts)); pending_failed_count = 0; waiting_failed_count = 0; pending_full_resync_count = 0; user_count = 0; iter = replicator_queue_iter_init(queue); while ((user = replicator_queue_iter_next(iter)) != NULL) { if (user->priority != REPLICATION_PRIORITY_NONE) pending_counts[user->priority]++; else if (replicator_queue_want_sync_now(queue, user, &next_secs)) { if (user->last_sync_failed) pending_failed_count++; else pending_full_resync_count++; } else { if (user->last_sync_failed) waiting_failed_count++; } user_count++; } replicator_queue_iter_deinit(&iter); for (priority = REPLICATION_PRIORITY_SYNC; priority > 0; priority--) { str_printfa(str, "Queued '%s' requests\t%u\n", replicator_priority_to_str(priority), pending_counts[priority]); } str_printfa(str, "Queued 'failed' requests\t%u\n", pending_failed_count); str_printfa(str, "Queued 'full resync' requests\t%u\n", pending_full_resync_count); str_printfa(str, "Waiting 'failed' requests\t%u\n", waiting_failed_count); str_printfa(str, "Total number of known users\t%u\n", user_count); str_append_c(str, '\n'); o_stream_send(client->conn.output, str_data(str), str_len(str)); return 0; }
static void client_handle(int fd) { struct ostream *output; output = o_stream_create_fd(fd, (size_t)-1, TRUE); o_stream_send(output, ssl_params->data, ssl_params->used); if (o_stream_get_buffer_used_size(output) == 0) client_deinit(output); else { o_stream_set_flush_callback(output, client_output_flush, output); } }
static int o_stream_mail_filter_flush(struct ostream_private *stream) { struct mail_filter_ostream *mstream = (struct mail_filter_ostream *)stream; const unsigned char *data; size_t size; ssize_t ret; if (mstream->ext_out == NULL) { /* connect failed */ return -1; } if (mstream->flushed) return 0; if (shutdown(mstream->fd, SHUT_WR) < 0) i_error("ext-filter: shutdown() failed: %m"); while ((ret = i_stream_read_data(mstream->ext_in, &data, &size, 0)) > 0) { ret = o_stream_send(stream->parent, data, size); if (ret != (ssize_t)size) { i_assert(ret < 0); o_stream_copy_error_from_parent(stream); return -1; } i_stream_skip(mstream->ext_in, size); } i_assert(ret == -1); if (!i_stream_have_bytes_left(mstream->ext_in) && mstream->ext_in->v_offset == 0) { /* EOF without any input -> assume the script is repoting failure. pretty ugly way, but currently there's no error reporting channel. */ stream->ostream.stream_errno = EIO; return -1; } if (mstream->ext_in->stream_errno != 0) { stream->ostream.stream_errno = mstream->ext_in->stream_errno; return -1; } ret = o_stream_flush(stream->parent); if (ret < 0) o_stream_copy_error_from_parent(stream); else mstream->flushed = TRUE; return ret; }
static void test_iostream_temp_create_write_error(void) { struct ostream *output; test_begin("iostream_temp_create_sized() write error"); output = iostream_temp_create_sized(".", 0, "test", 1); test_assert(o_stream_send(output, "123", 3) == 3); test_assert(o_stream_get_fd(output) != -1); test_assert(output->offset == 3); test_assert(o_stream_temp_move_to_memory(output) == 0); test_assert(o_stream_get_fd(output) == -1); test_assert(o_stream_send(output, "45", 2) == 2); test_assert(output->offset == 5); const unsigned char *data; size_t size; struct istream *input = iostream_temp_finish(&output, 128); test_assert(i_stream_read_bytes(input, &data, &size, 5) == 1 && memcmp(data, "12345", 5) == 0); i_stream_destroy(&input); test_end(); }
static int o_stream_zlib_send_flush(struct zlib_ostream *zstream) { z_stream *zs = &zstream->zs; unsigned int len; bool done = FALSE; int ret; i_assert(zs->avail_in == 0); if (zstream->flushed) return 0; if (!zstream->header_sent) o_stream_zlib_send_gz_header(zstream); do { len = sizeof(zstream->outbuf) - zs->avail_out; if (len != 0) { zs->next_out = zstream->outbuf; zs->avail_out = sizeof(zstream->outbuf); ret = o_stream_send(zstream->output, zstream->outbuf, len); if (ret != (int)len) { zstream_copy_error(zstream); return -1; } if (done) break; } switch (deflate(zs, zstream->gz ? Z_FINISH : Z_SYNC_FLUSH)) { case Z_OK: case Z_BUF_ERROR: break; case Z_STREAM_END: done = TRUE; break; default: i_unreached(); } } while (zs->avail_out != sizeof(zstream->outbuf)); if (o_stream_zlib_send_gz_trailer(zstream) < 0) return -1; zstream->flushed = TRUE; return 0; }
void http_server_request_abort(struct http_server_request **_req, const char *reason) { struct http_server_request *req = *_req; struct http_server_connection *conn = req->conn; if (req->state >= HTTP_SERVER_REQUEST_STATE_FINISHED) return; http_server_request_debug(req, "Abort"); req->conn = NULL; if (req->state < HTTP_SERVER_REQUEST_STATE_FINISHED) { if (conn != NULL) { http_server_connection_remove_request(conn, req); if (!conn->closed) { /* send best-effort response if appropriate */ if (!conn->output_locked && req->state >= HTTP_SERVER_REQUEST_STATE_PROCESSING && req->state < HTTP_SERVER_REQUEST_STATE_SENT_RESPONSE) { static const char *response = "HTTP/1.1 500 Internal Server Error\r\n" "Content-Length: 0\r\n" "\r\n"; (void)o_stream_send(conn->conn.output, response, strlen(response)); } /* close the connection */ http_server_connection_close(&conn, reason); } } req->state = HTTP_SERVER_REQUEST_STATE_ABORTED; } if (req->response != NULL && !req->response->payload_blocking) { http_server_response_free(req->response); req->response = NULL; } http_server_request_destroy(_req); }
static void proxy_send_login(struct pop3_client *client, struct ostream *output) { string_t *str; str = t_str_new(128); if (client->common.proxy_master_user == NULL) { /* send USER command */ str_append(str, "USER "); str_append(str, client->common.proxy_user); str_append(str, "\r\n"); } else { /* master user login - use AUTH PLAIN. */ str_append(str, "AUTH PLAIN\r\n"); } (void)o_stream_send(output, str_data(str), str_len(str)); client->common.proxy_state = POP3_PROXY_LOGIN1; }
static void test_ostream_file_random(void) { struct ostream *output; string_t *path = t_str_new(128); char buf[MAX_BUFSIZE*4], buf2[MAX_BUFSIZE*4], randbuf[MAX_BUFSIZE]; unsigned int i, offset, size; ssize_t ret; int fd; memset(buf, 0, sizeof(buf)); fd = safe_mkstemp(path, 0600, (uid_t)-1, (gid_t)-1); if (fd == -1) i_fatal("safe_mkstemp(%s) failed: %m", str_c(path)); if (unlink(str_c(path)) < 0) i_fatal("unlink(%s) failed: %m", str_c(path)); output = o_stream_create_fd(fd, MAX_BUFSIZE, FALSE); o_stream_cork(output); size = (rand() % MAX_BUFSIZE) + 1; random_fill_weak(randbuf, size); memcpy(buf, randbuf, size); test_assert(o_stream_send(output, buf, size) > 0); for (i = 0; i < 10; i++) { offset = rand() % (MAX_BUFSIZE*3); size = (rand() % MAX_BUFSIZE) + 1; random_fill_weak(randbuf, size); memcpy(buf + offset, randbuf, size); test_assert(o_stream_pwrite(output, randbuf, size, offset) == 0); if (rand() % 10 == 0) test_assert(o_stream_flush(output) > 0); } test_assert(o_stream_flush(output) > 0); o_stream_uncork(output); ret = pread(fd, buf2, sizeof(buf2), 0); if (ret < 0) i_fatal("pread() failed: %m"); else { i_assert(ret > 0); test_assert(memcmp(buf, buf2, ret) == 0); } o_stream_unref(&output); i_close_fd(&fd); }
static int client_handle_request(struct client *client, struct http_request *request) { string_t *str = t_str_new(128); if (strcmp(request->method, "GET") != 0) { o_stream_send_str(client->conn.output, "HTTP/1.1 501 Not Implemented\r\nAllow: GET\r\n\r\n"); return 0; } str_append(str, "HTTP/1.1 200 OK\r\n"); str_printfa(str, "Date: %s\r\n", http_date_create(ioloop_time)); str_printfa(str, "Content-Length: %d\r\n", (int)strlen(request->target_raw)); str_append(str, "Content-Type: text/plain\r\n"); str_append(str, "\r\n"); str_append(str, request->target_raw); o_stream_send(client->conn.output, str_data(str), str_len(str)); return 0; }
static int mbox_write_content_length(struct mbox_save_context *ctx) { uoff_t end_offset; const char *str; size_t len; i_assert(ctx->eoh_offset != (uoff_t)-1); if (ctx->mbox->mbox_writeonly) { /* we can't seek, don't set Content-Length */ return 0; } end_offset = ctx->output->offset; /* write Content-Length headers */ str = t_strdup_printf("\nContent-Length: %s", dec2str(end_offset - ctx->eoh_offset)); len = strlen(str); /* flush manually here so that we don't confuse seek() errors with buffer flushing errors */ if (o_stream_flush(ctx->output) < 0) { write_error(ctx); return -1; } if (o_stream_seek(ctx->output, ctx->extra_hdr_offset + ctx->space_end_idx - len) < 0) { mbox_set_syscall_error(ctx->mbox, "lseek()"); return -1; } if (o_stream_send(ctx->output, str, len) < 0 || o_stream_flush(ctx->output) < 0) { write_error(ctx); return -1; } if (o_stream_seek(ctx->output, end_offset) < 0) { mbox_set_syscall_error(ctx->mbox, "lseek()"); return -1; } return 0; }
void auth_client_connection_create(struct auth *auth, int fd, bool login_requests, bool token_auth) { static unsigned int connect_uid_counter = 0; struct auth_client_connection *conn; const char *mechanisms; string_t *str; conn = i_new(struct auth_client_connection, 1); conn->auth = auth; conn->refcount = 1; conn->connect_uid = ++connect_uid_counter; conn->login_requests = login_requests; conn->token_auth = token_auth; random_fill(conn->cookie, sizeof(conn->cookie)); conn->fd = fd; conn->input = i_stream_create_fd(fd, AUTH_CLIENT_MAX_LINE_LENGTH); conn->output = o_stream_create_fd(fd, (size_t)-1); o_stream_set_no_error_handling(conn->output, TRUE); o_stream_set_flush_callback(conn->output, auth_client_output, conn); conn->io = io_add(fd, IO_READ, auth_client_input, conn); DLLIST_PREPEND(&auth_client_connections, conn); if (token_auth) { mechanisms = t_strconcat("MECH\t", mech_dovecot_token.mech_name, "\n", NULL); } else { mechanisms = str_c(auth->reg->handshake); } str = t_str_new(128); str_printfa(str, "VERSION\t%u\t%u\n%sSPID\t%s\nCUID\t%u\nCOOKIE\t", AUTH_CLIENT_PROTOCOL_MAJOR_VERSION, AUTH_CLIENT_PROTOCOL_MINOR_VERSION, mechanisms, my_pid, conn->connect_uid); binary_to_hex_append(str, conn->cookie, sizeof(conn->cookie)); str_append(str, "\nDONE\n"); if (o_stream_send(conn->output, str_data(str), str_len(str)) < 0) auth_client_disconnected(&conn); }
static int o_stream_encrypt_send(struct encrypt_ostream *stream, const unsigned char *data, size_t size) { ssize_t ec; ec = o_stream_send(stream->ostream.parent, data, size); if (ec == (ssize_t)size) return 0; else if (ec < 0) { o_stream_copy_error_from_parent(&stream->ostream); return -1; } else { io_stream_set_error(&stream->ostream.iostream, "ostream-encrypt: Unexpectedly short write to parent stream"); stream->ostream.ostream.stream_errno = EINVAL; return -1; } }
static int o_stream_zlib_send_chunk(struct zlib_ostream *zstream, const void *data, size_t size) { z_stream *zs = &zstream->zs; ssize_t ret; int flush; flush = zstream->ostream.corked || zstream->gz ? Z_NO_FLUSH : Z_SYNC_FLUSH; if (!zstream->header_sent) o_stream_zlib_send_gz_header(zstream); zs->next_in = (void *)data; zs->avail_in = size; while (zs->avail_in > 0) { if (zs->avail_out == 0) { zs->next_out = zstream->outbuf; zs->avail_out = sizeof(zstream->outbuf); ret = o_stream_send(zstream->output, zstream->outbuf, sizeof(zstream->outbuf)); if (ret != (ssize_t)sizeof(zstream->outbuf)) { zstream_copy_error(zstream); return -1; } } switch (deflate(zs, flush)) { case Z_OK: case Z_BUF_ERROR: break; default: i_unreached(); } } zstream->crc = crc32_data_more(zstream->crc, data, size); zstream->bytes32 += size; zstream->flushed = FALSE; return 0; }
static int fetch_stream_send_direct(struct imap_fetch_context *ctx) { off_t ret; o_stream_set_max_buffer_size(ctx->client->output, 0); ret = o_stream_send_istream(ctx->client->output, ctx->cur_input); o_stream_set_max_buffer_size(ctx->client->output, (size_t)-1); if (ret < 0) return -1; ctx->cur_offset += ret; if (ctx->cur_append_eoh && ctx->cur_offset + 2 == ctx->cur_size) { /* Netscape missing EOH workaround. */ if (o_stream_send(ctx->client->output, "\r\n", 2) < 0) return -1; ctx->cur_offset += 2; ctx->cur_append_eoh = FALSE; } if (ctx->cur_offset != ctx->cur_size) { /* unfinished */ if (!i_stream_have_bytes_left(ctx->cur_input)) { /* Input stream gave less data than expected */ i_error("FETCH %s for mailbox %s UID %u " "got too little data (copying): " "%"PRIuUOFF_T" vs %"PRIuUOFF_T, ctx->cur_name, mailbox_get_vname(ctx->mail->box), ctx->mail->uid, ctx->cur_offset, ctx->cur_size); mail_set_cache_corrupted(ctx->mail, ctx->cur_size_field); client_disconnect(ctx->client, "FETCH failed"); return -1; } o_stream_set_flush_pending(ctx->client->output, TRUE); return 0; } return 1; }
static ssize_t o_stream_escaped_send_outbuf(struct escaped_ostream *estream) { ssize_t ret; if (estream->flushed) return 1; /* nothing to send */ ret = o_stream_send(estream->ostream.parent, str_data(estream->buf), str_len(estream->buf)); if (ret < 0) { o_stream_copy_error_from_parent(&estream->ostream); return -1; } if ((size_t)ret != str_len(estream->buf)) { /* move data */ str_delete(estream->buf, 0, ret); return 0; } str_truncate(estream->buf, 0); estream->flushed = TRUE; return 1; }
static int filter_connect(struct mail_filter_istream *mstream, const char *socket_path, const char *args) { const char **argv; string_t *str; int fd; argv = t_strsplit(args, " "); if ((fd = net_connect_unix_with_retries(socket_path, 1000)) < 0) { if (errno == EACCES) { i_error("ext-filter: %s", eacces_error_get("net_connect_unix", socket_path)); } else { i_error("ext-filter: net_connect_unix(%s) failed: %m", socket_path); } return -1; } if (mstream->istream.istream.blocking) net_set_nonblock(fd, FALSE); mstream->fd = fd; mstream->ext_in = i_stream_create_fd(fd, mstream->istream.max_buffer_size, FALSE); mstream->ext_out = o_stream_create_fd(fd, 0, FALSE); str = t_str_new(256); str_append(str, "VERSION\tscript\t3\t0\nnoreply\n"); for (; *argv != NULL; argv++) { str_append(str, *argv); str_append_c(str, '\n'); } str_append_c(str, '\n'); o_stream_send(mstream->ext_out, str_data(str), str_len(str)); return 0; }