#include <stdlib.h>
#include <stdio.h>
+#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
return ret;
}
-int start_autosample_process(options_t* opt)
+int start_autosample_process(options_t* opt, autosample_process_t* a)
{
- int pipefd[2];
+ int write_pipefd[2];
+ int read_pipefd[2];
pid_t cpid;
- if (pipe(pipefd) == -1) {
+ if (pipe(write_pipefd) == -1) {
log_printf(ERROR, "autosample_process: pipe() failed: %s", strerror(errno));
return -1;
}
+
+ if (pipe(read_pipefd) == -1) {
+ log_printf(ERROR, "autosample_process: pipe() failed: %s", strerror(errno));
+ close(write_pipefd[0]);
+ close(write_pipefd[1]);
+ return -1;
+ }
cpid = fork();
if (cpid == -1) {
log_printf(ERROR, "autosample_process: fork() failed: %s", strerror(errno));
- close(pipefd[0]);
- close(pipefd[1]);
+ close(write_pipefd[0]);
+ close(write_pipefd[1]);
+ close(read_pipefd[0]);
+ close(read_pipefd[1]);
return -1;
}
if (cpid == 0) {
- close(pipefd[0]);
- return autosample_process(opt, pipefd[1]);
+ close(write_pipefd[0]);
+ close(read_pipefd[1]);
+ int ret = autosample_process(opt, write_pipefd[1], read_pipefd[0]);
+ if(!ret)
+ log_printf(NOTICE, "autosample process normal shutdown");
+ else if(ret > 0)
+ log_printf(NOTICE, "autosample shutdown after signal");
+ else
+ log_printf(NOTICE, "autosample shutdown after error");
+
+ options_clear(opt);
+ log_close();
+ exit(0);
}
- close(pipefd[1]);
- return pipefd[0];
+ close(write_pipefd[1]);
+ close(read_pipefd[0]);
+ a->pid_ = cpid;
+ a->write_fd_ = write_pipefd[0];
+ a->read_fd_ = read_pipefd[1];
+ return 0;
}
-int autosample_process(options_t *opt, int pipefd)
+int autosample_process(options_t *opt, int writefd, int readfd)
{
log_printf(NOTICE, "autosample process just started");
int sig_fd = signal_init();
if(sig_fd < 0)
- return -3;
+ return -1;
+
+ fd_set readfds, tmpfds;
+ FD_ZERO(&readfds);
+ FD_SET(readfd, &readfds);
+ FD_SET(sig_fd, &readfds);
+ int max_fd = (readfd < sig_fd) ? sig_fd : readfd;
- fd_set readfds;
struct timeval timeout;
int return_value = 0;
+ unsigned char sample_enabled = 0;
while(!return_value) {
- FD_SET(sig_fd, &readfds);
+ memcpy(&tmpfds, &readfds, sizeof(tmpfds));
timeout.tv_sec = 0;
timeout.tv_usec = 1000000;
- int ret = select(sig_fd+1, &readfds, NULL, NULL, &timeout);
+ int ret = select(max_fd+1, &tmpfds, NULL, NULL, &timeout);
if(ret == -1 && errno != EINTR) {
log_printf(ERROR, "autosample process select returned with error: %s", strerror(errno));
return_value = -3;
for(i = 0; i < device_num; i++) {
devices[i].cnt_++;
if(devices[i].cnt_ >= devices[i].delay_) {
- log_printf(DEBUG, "autosample send sample command for '%s'", devices[i].device_name_);
- send_sample_cmd(pipefd, devices[i].device_name_);
+ if(sample_enabled) {
+ log_printf(DEBUG, "autosample send sample command for '%s'", devices[i].device_name_);
+ send_sample_cmd(writefd, devices[i].device_name_);
+ }
devices[i].cnt_ = 0;
}
}
}
- if(FD_ISSET(sig_fd, &readfds)) {
+ if(FD_ISSET(readfd, &tmpfds)) {
+ int ret;
+ do {
+ ret = read(readfd, &sample_enabled, 1);
+ } while(!ret || (ret == -1 && errno == EINTR));
+ log_printf(NOTICE, "autosample %s", sample_enabled == 0 ? "disabled" : "enabled");
+ }
+
+ if(FD_ISSET(sig_fd, &tmpfds)) {
if(signal_handle()) {
- return_value = -2;
+ return_value = 1;
break;
}
}
#include "options.h"
+struct autosample_process_struct {
+ pid_t pid_;
+ int read_fd_;
+ int write_fd_;
+};
+typedef struct autosample_process_struct autosample_process_t;
+
struct autosample_device_struct {
int delay_;
int cnt_;
typedef struct autosample_device_struct autosample_device_t;
int send_sample_cmd(int fd, const char* device_name);
-int start_autosample_process(options_t* opt);
-int autosample_process(options_t *opt, int pipefd);
+int start_autosample_process(options_t* opt, autosample_process_t* a);
+int autosample_process(options_t *opt, int writefd, int readfd);
#endif
return ret;
}
-int main_loop(int tty_fd, int cmd_listen_fd, int autosample_fd, options_t* opt)
+int main_loop(int tty_fd, int cmd_listen_fd, autosample_process_t* autosample, options_t* opt)
{
log_printf(NOTICE, "entering main loop");
- clear_fd(tty_fd);
- clear_fd(autosample_fd);
-
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;
- FD_SET(autosample_fd, &readfds);
- max_fd = (max_fd < autosample_fd) ? autosample_fd : max_fd;
+
+ int 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;
client_add(&client_lst, new_fd);
}
- if(FD_ISSET(autosample_fd, &tmpfds)) {
- return_value = nonblock_readline(&autosample_buffer, autosample_fd, &cmd_q, client_lst, opt);
+ 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_fd, &readfds);
+ FD_CLR(autosample->write_fd_, &readfds);
return_value = 0;
continue;
}
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->temp_listener || lst->photo_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);
fclose(pid_file);
}
- int autosample_fd = -1;
+ 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");
- autosample_fd = start_autosample_process(&opt);
- if(autosample_fd == -1) {
- options_clear(&opt);
- log_close();
- exit(1);
- }
- else if(autosample_fd <= 0) {
- if(!autosample_fd)
- log_printf(NOTICE, "autosample process normal shutdown");
- else if(autosample_fd == -2)
- log_printf(NOTICE, "autosample shutdown after signal");
- else
- log_printf(NOTICE, "autosample shutdown after error");
-
+ int ret = start_autosample_process(&opt, &autosample);
+ if(ret == -1) {
options_clear(&opt);
log_close();
exit(1);
if(ret)
ret = 2;
else
- ret = main_loop(tty_fd, cmd_listen_fd, autosample_fd, &opt);
+ 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");