static void control_connection_io_output(gpointer s) { ControlConnection *self = (ControlConnection *) s; gint rc; rc = write(self->control_io.fd, self->output_buffer->str + self->pos, self->output_buffer->len - self->pos); if (rc < 0) { if (errno != EAGAIN) { msg_error("Error writing control channel", evt_tag_errno("error", errno), NULL); control_connection_stop_watches(self); control_connection_free(self); return; } } else { self->pos += rc; } control_connection_update_watches(self); }
void control_server_connection_closed(ControlServer *self, ControlConnection *cc) { control_connection_stop_watches(cc); control_connection_free(cc); }
/* * NOTE: the channel is not in nonblocking mode, thus the control channel * may block syslog-ng completely. */ static void control_connection_io_input(void *s) { ControlConnection *self = (ControlConnection *) s; GString *command = NULL; gchar *nl; gint rc; gint cmd; gint orig_len; if (self->input_buffer->len > MAX_CONTROL_LINE_LENGTH) { /* too much data in input, drop the connection */ msg_error("Too much data in the control socket input buffer", NULL); control_connection_stop_watches(self); control_connection_free(self); return; } orig_len = self->input_buffer->len; /* NOTE: plus one for the terminating NUL */ g_string_set_size(self->input_buffer, self->input_buffer->len + 128 + 1); rc = read(self->control_io.fd, self->input_buffer->str + orig_len, 128); if (rc < 0) { if (errno != EAGAIN) { msg_error("Error reading command on control channel, closing control channel", evt_tag_errno("error", errno), NULL); goto destroy_connection; } /* EAGAIN, should try again when data comes */ control_connection_update_watches(self); return; } else if (rc == 0) { msg_error("EOF on control channel, closing connection", NULL); goto destroy_connection; } else { self->input_buffer->len = orig_len + rc; self->input_buffer->str[self->input_buffer->len] = 0; } /* here we have finished reading the input, check if there's a newline somewhere */ nl = strchr(self->input_buffer->str, '\n'); if (nl) { command = g_string_sized_new(128); /* command doesn't contain NL */ g_string_assign_len(command, self->input_buffer->str, nl - self->input_buffer->str); /* strip NL */ g_string_erase(self->input_buffer, 0, command->len + 1); } else { /* no EOL in the input buffer, wait for more data */ control_connection_update_watches(self); return; } for (cmd = 0; commands[cmd].func; cmd++) { if (strncmp(commands[cmd].command, command->str, strlen(commands[cmd].command)) == 0) { commands[cmd].func(self, command); break; } } if (!commands[cmd].func) { msg_error("Unknown command read on control channel, closing control channel", evt_tag_str("command", command->str), NULL); goto destroy_connection; } control_connection_update_watches(self); g_string_free(command, TRUE); return; destroy_connection: control_connection_stop_watches(self); control_connection_free(self); }