bool cmd_getscript(struct client_command_context *cmd) { struct client *client = cmd->client; struct cmd_getscript_context *ctx; const char *scriptname; enum sieve_error error; /* <scriptname> */ if ( !client_read_string_args(cmd, TRUE, 1, &scriptname) ) return FALSE; ctx = p_new(cmd->pool, struct cmd_getscript_context, 1); ctx->cmd = cmd; ctx->client = client; ctx->storage = client->storage; ctx->failed = FALSE; ctx->script = sieve_storage_open_script (client->storage, scriptname, NULL); if (ctx->script == NULL) { ctx->failed = TRUE; return cmd_getscript_finish(ctx); } if ( sieve_script_get_stream (ctx->script, &ctx->script_stream, &error) < 0 ) { if ( error == SIEVE_ERROR_NOT_FOUND ) sieve_storage_set_error(client->storage, error, "Script does not exist."); ctx->failed = TRUE; return cmd_getscript_finish(ctx); } if ( sieve_script_get_size(ctx->script, &ctx->script_size) <= 0 ) { sieve_storage_set_critical(ctx->storage, "failed to obtain script size for script `%s' from %s", sieve_script_name(ctx->script), sieve_script_location(ctx->script)); ctx->failed = TRUE; return cmd_getscript_finish(ctx); } i_assert(ctx->script_stream->v_offset == 0); client_send_line (client, t_strdup_printf("{%"PRIuUOFF_T"}", ctx->script_size)); client->command_pending = TRUE; cmd->func = cmd_getscript_continue; cmd->context = ctx; return cmd_getscript_continue(cmd); }
bool cmd_getscript(struct client_command_context *cmd) { struct client *client = cmd->client; struct cmd_getscript_context *ctx; const char *scriptname; enum sieve_error error; /* <scriptname> */ if ( !client_read_string_args(cmd, 1, TRUE, &scriptname) ) return FALSE; ctx = p_new(cmd->pool, struct cmd_getscript_context, 1); ctx->cmd = cmd; ctx->client = client; ctx->storage = client->storage; ctx->failed = FALSE; ctx->script = sieve_storage_script_init(client->storage, scriptname); if (ctx->script == NULL) { ctx->failed = TRUE; return cmd_getscript_finish(ctx); } ctx->script_stream = sieve_script_open(ctx->script, &error); if ( ctx->script_stream == NULL ) { ctx->failed = TRUE; if ( error == SIEVE_ERROR_NOT_FOUND ) sieve_storage_set_error(client->storage, error, "Script does not exist."); return cmd_getscript_finish(ctx); } ctx->script_size = sieve_script_get_size(ctx->script); ctx->script_offset = 0; client_send_line (client, t_strdup_printf("{%"PRIuUOFF_T"}", ctx->script_size)); client->command_pending = TRUE; cmd->func = cmd_getscript_continue; cmd->context = ctx; return cmd_getscript_continue(cmd); }
static bool cmd_getscript_continue(struct client_command_context *cmd) { struct client *client = cmd->client; struct cmd_getscript_context *ctx = cmd->context; off_t ret; ret = o_stream_send_istream(client->output, ctx->script_stream); if ( ret < 0 ) { sieve_storage_set_critical(ctx->storage, "o_stream_send_istream(%s) failed: %m", sieve_script_filename(ctx->script)); ctx->failed = TRUE; return cmd_getscript_finish(ctx); } ctx->script_offset += ret; if ( ctx->script_offset != ctx->script_size && !ctx->failed ) { /* unfinished */ if ( !i_stream_have_bytes_left(ctx->script_stream) ) { /* Input stream gave less data than expected */ sieve_storage_set_critical(ctx->storage, "GETSCRIPT for SCRIPT %s got too little data: " "%"PRIuUOFF_T" vs %"PRIuUOFF_T, sieve_script_name(ctx->script), ctx->script_offset, ctx->script_size); client_disconnect(ctx->client, "GETSCRIPT failed"); ctx->failed = TRUE; return cmd_getscript_finish(ctx); } return FALSE; } return cmd_getscript_finish(ctx); }
static bool cmd_getscript_continue(struct client_command_context *cmd) { struct client *client = cmd->client; struct cmd_getscript_context *ctx = cmd->context; switch (o_stream_send_istream(client->output, ctx->script_stream)) { case OSTREAM_SEND_ISTREAM_RESULT_FINISHED: if ( ctx->script_stream->v_offset != ctx->script_size && !ctx->failed ) { /* Input stream gave less data than expected */ sieve_storage_set_critical(ctx->storage, "GETSCRIPT for script `%s' from %s got too little data: " "%"PRIuUOFF_T" vs %"PRIuUOFF_T, sieve_script_name(ctx->script), sieve_script_location(ctx->script), ctx->script_stream->v_offset, ctx->script_size); client_disconnect(ctx->client, "GETSCRIPT failed"); ctx->failed = TRUE; } break; case OSTREAM_SEND_ISTREAM_RESULT_WAIT_INPUT: i_unreached(); case OSTREAM_SEND_ISTREAM_RESULT_WAIT_OUTPUT: return FALSE; case OSTREAM_SEND_ISTREAM_RESULT_ERROR_INPUT: sieve_storage_set_critical(ctx->storage, "o_stream_send_istream() failed for script `%s' from %s: %s", sieve_script_name(ctx->script), sieve_script_location(ctx->script), i_stream_get_error(ctx->script_stream)); ctx->failed = TRUE; break; case OSTREAM_SEND_ISTREAM_RESULT_ERROR_OUTPUT: client_disconnect(ctx->client, io_stream_get_disconnect_reason(client->input, client->output)); ctx->failed = TRUE; break; } return cmd_getscript_finish(ctx); }