#include "daemon.h"
+#include "autosample.h"
+
int init_command_socket(const char* path)
{
int fd = socket(AF_UNIX, SOCK_STREAM, 0);
return fd;
}
+void clear_fd(int fd)
+{
+ fd_set fds;
+ struct timeval tv;
+ FD_ZERO(&fds);
+ FD_SET(fd, &fds);
+ tv.tv_sec = 0;
+ tv.tv_usec = 50000;
+ for(;;) {
+ int ret = select(fd+1, &fds, NULL, NULL, &tv);
+ if(ret > 0) {
+ char buffer[100];
+ ret = read(fd, buffer, sizeof(buffer));
+ }
+ else
+ break;
+ }
+}
+
int send_command(int tty_fd, cmd_t* cmd)
{
if(!cmd)
char c;
switch(cmd->cmd) {
- case POWER: {
- c = 'A'; // get command from powerids[cmd->param]
+ case POWER_ON: {
+ if(!cmd->param)
+ return 0;
+ c = toupper(cmd->param[0]);
+ break;
+ }
+ case POWER_OFF: {
+ if(!cmd->param)
+ return 0;
+ c = tolower(cmd->param[0]);
break;
}
case SAMPLE: {
- c = 'T'; // get command from sampledevs[cmd->param]
+ if(!cmd->param)
+ return 0;
+ c = cmd->param[0];
break;
}
default: return 0;
log_printf(DEBUG, "sent %s to %d additional listeners", TYPE_NAME,listener_cnt);
-int process_cmd(const char* cmd, int fd, cmd_t **cmd_q, client_t* client_lst)
+int process_cmd(char* cmd, int fd, cmd_t **cmd_q, client_t* client_lst, options_t* opt)
{
log_printf(DEBUG, "processing command from %d", fd);
return -1;
cmd_id_t cmd_id;
- if(!strncmp(cmd, "power", 5))
- cmd_id = POWER;
+ if(!strncmp(cmd, "power on", 8)) {
+ cmd_id = POWER_ON;
+ cmd[5] = '_';
+ }
+ else if(!strncmp(cmd, "power off", 9)) {
+ cmd_id = POWER_OFF;
+ cmd[5] = '_';
+ }
else if(!strncmp(cmd, "sample", 6))
cmd_id = SAMPLE;
else if(!strncmp(cmd, "log", 3))
return 0;
}
char* param = strchr(cmd, ' ');
- if(param)
+ if(param)
param++;
- if(cmd_id == POWER || cmd_id == SAMPLE) {
+ if(cmd_id == POWER_ON || cmd_id == POWER_OFF) {
+ char* orig_param = param;
+ param = key_value_storage_find(&(opt->powerids_), param);
+ if(!param) {
+ send_response(fd, "Error: invalid power id");
+ log_printf(WARNING, "invalid power id '%s' in command from %d", orig_param, fd);
+ }
+ }
+
+ if(cmd_id == SAMPLE) {
+ char* orig_param = param;
+ param = key_value_storage_find(&(opt->sampledevs_), param);
+ if(!param) {
+ send_response(fd, "Error: invalid sample device");
+ log_printf(WARNING, "invalid sample device '%s' in command from %d", orig_param, fd);
+ }
+ }
+
+ if(cmd_id == POWER_ON || cmd_id == POWER_OFF || cmd_id == SAMPLE) {
char* resp;
asprintf(&resp, "Request: %s", cmd);
if(resp) {
}
switch(cmd_id) {
- case POWER:
+ case POWER_ON:
+ case POWER_OFF:
case SAMPLE: {
int ret = cmd_push(cmd_q, fd, cmd_id, param);
if(ret)
if(!param || !strncmp(param, "all", 3)) {
listener->request_listener = 1;
listener->error_listener = 1;
- listener->temp_listener = 1;
- listener->photo_listener = 1;
+ listener->sensor_listener = 1;
listener->movement_listener = 1;
listener->button_listener = 1;
}
else if(!strncmp(param, "none", 4)) {
listener->request_listener = 0;
listener->error_listener = 0;
- listener->temp_listener = 0;
- listener->photo_listener = 0;
+ listener->sensor_listener = 0;
listener->movement_listener = 0;
listener->button_listener = 0;
}
listener->request_listener = 1;
else if(!strncmp(param, "error", 5))
listener->error_listener = 1;
- else if(!strncmp(param, "temp", 4))
- listener->temp_listener = 1;
- else if(!strncmp(param, "photo", 5))
- listener->photo_listener = 1;
+ else if(!strncmp(param, "sensor", 6))
+ listener->sensor_listener = 1;
else if(!strncmp(param, "movement", 8))
listener->movement_listener = 1;
else if(!strncmp(param, "button", 6))
return 0;
}
-int nonblock_recvline(read_buffer_t* buffer, int fd, cmd_t** cmd_q, client_t* client_lst)
+int nonblock_readline(read_buffer_t* buffer, int fd, cmd_t** cmd_q, client_t* client_lst, options_t* opt)
{
int ret = 0;
for(;;) {
- ret = recv(fd, &buffer->buf[buffer->offset], 1, 0);
- if(!ret)
+ ret = read(fd, &buffer->buf[buffer->offset], 1);
+ if(!ret || (ret == -1 && errno == EBADF))
return 2;
- if(ret == -1 && errno == EAGAIN)
+ if(ret == -1 && (errno == EAGAIN || errno == EWOULDBLOCK))
return 0;
else if(ret < 0)
break;
if(buffer->buf[buffer->offset] == '\n') {
buffer->buf[buffer->offset] = 0;
- ret = process_cmd(buffer->buf, fd, cmd_q, client_lst);
+ ret = process_cmd(buffer->buf, fd, cmd_q, client_lst, opt);
buffer->offset = 0;
break;
}
return ret;
}
-int process_tty(read_buffer_t* buffer, int tty_fd, cmd_t **cmd_q, client_t* client_lst)
+int process_tty(read_buffer_t* buffer, int tty_fd, cmd_t **cmd_q, client_t* client_lst, options_t* opt)
{
+ u_int8_t *response_data;
int ret = 0;
struct timeval tv;
fd_set fds;
log_printf(NOTICE, "firmware: %s", buffer->buf);
+ /* modify response if necessary */
+ response_data = buffer->buf;
+ if(!strncmp(buffer->buf, "Sensor ", 7)) {
+ if (buffer->buf[7] != 0)
+ {
+ char *sampledev_key;
+ if (asprintf(&sampledev_key, "%c",buffer->buf[7]))
+ {
+ char const *sampledev_name = key_value_storage_find_first_stringvalue(&(opt->sampledevs_), sampledev_key);
+ if(sampledev_name)
+ {
+ char *rev_lookuped_output;
+ if (asprintf(&rev_lookuped_output, "%s%s", sampledev_name, &(buffer->buf[8]) ))
+ response_data = rev_lookuped_output;
+ }
+ else
+ log_printf(WARNING, "unknown sample device key '%s' encountered", sampledev_key);
+ free(sampledev_key);
+ }
+ }
+ }
+
int cmd_fd = -1;
if(cmd_q && (*cmd_q)) {
cmd_fd = (*cmd_q)->fd;
- send_response(cmd_fd, buffer->buf);
+ send_response(cmd_fd, response_data);
}
if(!strncmp(buffer->buf, "Error:", 6)) {
- SEND_TO_LISTENER(error_listener, "error", cmd_fd, buffer->buf);
+ SEND_TO_LISTENER(error_listener, "error", cmd_fd, response_data);
}
if(!strncmp(buffer->buf, "movement", 8)) {
- SEND_TO_LISTENER(movement_listener, "movement", cmd_fd, buffer->buf);
+ SEND_TO_LISTENER(movement_listener, "movement", cmd_fd, response_data);
}
if(!strncmp(buffer->buf, "PanicButton", 11)) {
- SEND_TO_LISTENER(button_listener, "panic buttont", cmd_fd, buffer->buf);
+ SEND_TO_LISTENER(button_listener, "panic button", cmd_fd, response_data);
}
- if(!strncmp(buffer->buf, "Temp ", 5)) {
- SEND_TO_LISTENER(temp_listener, "", cmd_fd, buffer->buf);
+ if(!strncmp(buffer->buf, "Sensor ", 7)) {
+ SEND_TO_LISTENER(sensor_listener, "sensor data", cmd_fd, response_data);
}
+ /* free allocated buffer if response was modified */
+ if (response_data != buffer->buf)
+ free(response_data);
+
cmd_pop(cmd_q);
buffer->offset = 0;
return 0;
return ret;
}
-int main_loop(int tty_fd, int cmd_listen_fd)
+int main_loop(int tty_fd, int cmd_listen_fd, autosample_process_t* autosample, options_t* opt)
{
log_printf(NOTICE, "entering main loop");
fd_set readfds, tmpfds;
FD_ZERO(&readfds);
+
+ clear_fd(tty_fd);
FD_SET(tty_fd, &readfds);
FD_SET(cmd_listen_fd, &readfds);
int max_fd = tty_fd > cmd_listen_fd ? tty_fd : cmd_listen_fd;
+
+ u_int8_t autosample_enabled = 0;
+ if(autosample->pid_ > 0) {
+ clear_fd(autosample->write_fd_);
+ FD_SET(autosample->write_fd_, &readfds);
+ max_fd = (max_fd < autosample->write_fd_) ? autosample->write_fd_ : max_fd;
+ }
cmd_t* cmd_q = NULL;
client_t* client_lst = NULL;
read_buffer_t tty_buffer;
tty_buffer.offset = 0;
+ read_buffer_t autosample_buffer;
+ autosample_buffer.offset = 0;
int sig_fd = signal_init();
if(sig_fd < 0)
}
if(FD_ISSET(tty_fd, &tmpfds)) {
- return_value = process_tty(&tty_buffer, tty_fd, &cmd_q, client_lst);
+ return_value = process_tty(&tty_buffer, tty_fd, &cmd_q, client_lst, opt);
if(return_value)
break;
}
client_add(&client_lst, new_fd);
}
+ if(autosample->pid_ > 0 && FD_ISSET(autosample->write_fd_, &tmpfds)) {
+ return_value = nonblock_readline(&autosample_buffer, autosample->write_fd_, &cmd_q, client_lst, opt);
+ if(return_value == 2) {
+ log_printf(WARNING, "autosample not running, removing pipe to it");
+ FD_CLR(autosample->write_fd_, &readfds);
+ return_value = 0;
+ continue;
+ }
+ if(return_value)
+ break;
+ }
+
client_t* lst = client_lst;
while(lst) {
if(FD_ISSET(lst->fd, &tmpfds)) {
- return_value = nonblock_recvline(&(lst->buffer), lst->fd, &cmd_q, client_lst);
+ return_value = nonblock_readline(&(lst->buffer), lst->fd, &cmd_q, client_lst, opt);
if(return_value == 2) {
log_printf(DEBUG, "removing closed command connection (fd=%d)", lst->fd);
client_t* deletee = lst;
if(cmd_q && !cmd_q->sent)
send_command(tty_fd, cmd_q);
+
+ if(autosample->pid_ > 0) {
+ lst = client_lst;
+ int listener_cnt = 0;
+ while(lst) {
+ if(lst->sensor_listener)
+ listener_cnt++;
+ lst = lst->next;
+ }
+ if((!autosample_enabled && listener_cnt > 0) ||
+ (autosample_enabled && listener_cnt == 0)) {
+ if(autosample_enabled) autosample_enabled = 0;
+ else autosample_enabled = 1;
+ int ret;
+ do {
+ ret = write(autosample->read_fd_, &autosample_enabled, 1);
+ } while(!ret || (ret == -1 && errno == EINTR));
+ }
+ }
}
cmd_clear(&cmd_q);
return ret;
}
- fd_set fds;
- struct timeval tv;
- FD_ZERO(&fds);
- FD_SET(fd, &fds);
- tv.tv_sec = 0;
- tv.tv_usec = 50000;
- for(;;) {
- ret = select(fd+1, &fds, NULL, NULL, &tv);
- if(ret > 0) {
- char buffer[100];
- ret = read(fd, buffer, sizeof(buffer));
- }
- else
- break;
- }
+ clear_fd(fd);
return 0;
}
}
}
log_printf(NOTICE, "just started...");
- options_parse_post(&opt);
+ if(options_parse_post(&opt)) {
+ options_clear(&opt);
+ log_close();
+ exit(-1);
+ }
priv_info_t priv;
if(opt.username_)
fprintf(pid_file, "%d", pid);
fclose(pid_file);
}
+
+ autosample_process_t autosample;
+ autosample.pid_ = -1;
+ autosample.write_fd_ = -1;
+ autosample.read_fd_ = -1;
+ if(key_value_storage_length(&opt.autosampledevs_) > 0) {
+ log_printf(NOTICE, "starting autosample process");
+ int ret = start_autosample_process(&opt, &autosample);
+ if(ret == -1) {
+ options_clear(&opt);
+ log_close();
+ exit(1);
+ }
+ }
int cmd_listen_fd = init_command_socket(opt.command_sock_);
if(cmd_listen_fd < 0) {
if(ret)
ret = 2;
else
- ret = main_loop(tty_fd, cmd_listen_fd);
+ ret = main_loop(tty_fd, cmd_listen_fd, &autosample, &opt);
}
if(ret == 2) {
close(cmd_listen_fd);
if(tty_fd > 0)
close(tty_fd);
+ if(autosample.pid_ > 0)
+ kill(autosample.pid_, SIGTERM);
if(!ret)
log_printf(NOTICE, "normal shutdown");