to github
[svn42.git] / powersensordaemon / autosample.c
index 69b9184..00ab7d8 100644 (file)
@@ -25,6 +25,8 @@
 #include "log.h"
 
 #include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
 #include <unistd.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 
 #include "autosample.h"
  
-int start_autosample_process(options_t* opt)
+int send_sample_cmd(int fd, const char* device_name)
 {
-  int pipefd[2];
+  if(!device_name)
+    return -1;
+
+  char* buf;
+  int len = asprintf(&buf, "sample %s\n", device_name);
+  if(len <= 0)
+    return len;
+  int offset = 0;
+  int ret;
+  for(;;) {
+    ret = write(fd, &buf[offset], len - offset);
+    if(ret < 0) {
+      if(errno != EINTR) {
+        free(buf);
+        return ret;
+      }
+
+      ret = 0;
+    }
+
+    offset += ret;
+    if(offset+1 >= len)
+      break;
+  }
+  free(buf);
+
+  if(ret > 0)
+    return 0;
+
+  return ret;
+}
+
+int start_autosample_process(options_t* opt, autosample_process_t* a)
+{
+  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");
 
@@ -85,20 +146,27 @@ int autosample_process(options_t *opt, int pipefd)
     devices[i].device_name_ = k->string_;
     k = k->next_;
     v = v->next_;
+    i++;
   }
 
   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);
-    timeout.tv_sec = 0;
-    timeout.tv_usec = 1000000;
-    int ret = select(sig_fd+1, &readfds, NULL, NULL, &timeout);
+    memcpy(&tmpfds, &readfds, sizeof(tmpfds));
+    timeout.tv_sec = 1;
+    timeout.tv_usec = 0;
+    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;
@@ -111,16 +179,26 @@ int autosample_process(options_t *opt, int pipefd)
       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_);
-              // call send sample
+          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;
       }
     }