Finished the conversion to C.
[breezed.git] / breezed.cc
diff --git a/breezed.cc b/breezed.cc
deleted file mode 100644 (file)
index 14809ac..0000000
+++ /dev/null
@@ -1,594 +0,0 @@
-
-/*
-
-   breezed is a fan speed control daemon for Linux computers.
-
-   Copyright (c) 2008, 2009 Francois Fleuret
-   Written by Francois Fleuret <francois@fleuret.org>
-
-   This file is part of breezed.
-
-   breezed is free software: you can redistribute it and/or modify it
-   under the terms of the GNU General Public License version 3 as
-   published by the Free Software Foundation.
-
-   breezed is distributed in the hope that it will be useful, but
-   WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with breezed.  If not, see <http://www.gnu.org/licenses/>.
-
-*/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <unistd.h>
-#include <string.h>
-
-#define BUFFER_SIZE 4096
-
-using namespace std;
-
-const int major_version_number = 1;
-const int minor_version_number = 2;
-
-const int buffer_size = 1024;
-
-const char *default_configuration_file = "/etc/breezed.conf";
-
-// The time period to check the temperature.
-const int polling_delay = 5;
-
-// Minimum time between last change and a change down.
-const int minimum_delay_to_go_down = 30;
-
-// Gap between a threshold to go up and a threshold to go down to
-// reduce the oscillations.
-const int down_temperature_delta = 2;
-
-char *file_fan = 0;
-
-int debug = 0;
-int nb_rounds_since_last_change = 0;
-int last_level = -1;
-
-int file_fan_fd;
-
-int nb_temperature_thresholds;
-int *temperature_thresholds = 0;
-
-int nb_file_thermal = 0;
-char **file_thermal = 0;
-int *file_thermal_fd = 0;
-
-char *configuration_file;
-
-//////////////////////////////////////////////////////////////////////
-
-char *next_word(char *buffer, char *r, int buffer_size) {
-  char *s;
-  s = buffer;
-
-  if(r != 0) {
-    while((*r == ' ') || (*r == '\t') || (*r == ',')) r++;
-    if(*r == '"') {
-      r++;
-      while((*r != '"') && (*r != '\0') &&
-            (s<buffer+buffer_size-1))
-        *s++ = *r++;
-      if(*r == '"') r++;
-    } else {
-      while((*r != '\r') && (*r != '\n') && (*r != '\0') &&
-            (*r != '\t') && (*r != ' ') && (*r != ',')) {
-        if(s == buffer + buffer_size) {
-          fprintf(stderr, "Buffer overflow in next_word.\n");
-          exit(1);
-        }
-        *s++ = *r++;
-      }
-    }
-
-    while((*r == ' ') || (*r == '\t') || (*r == ',')) r++;
-    if((*r == '\0') || (*r=='\r') || (*r=='\n')) r = 0;
-  }
-  *s = '\0';
-
-  return r;
-}
-
-void set_fan_level(int fan_fd, int f, int max_fan_level) {
-  char buffer[buffer_size];
-  if(f < 0 || f > max_fan_level) f = max_fan_level;
-  sprintf(buffer, "level %d\n", f);
-  if(write(fan_fd, buffer, strlen(buffer)) < 0) {
-    fprintf(stderr, "Error in setting the fan level (%s).\n",
-            strerror(errno));
-    exit(1);
-  }
-}
-
-void define_thermal_files(char *definition) {
-  char token[buffer_size];
-
-  if(file_thermal) {
-    fprintf(stderr, "Thermal files already defined.\n");
-    exit(1);
-  }
-
-  char *s;
-  s = definition;
-  while(s) {
-    s = next_word(token, s, buffer_size);
-    nb_file_thermal++;
-  }
-  file_thermal = new char *[nb_file_thermal];
-  file_thermal_fd = new int[nb_file_thermal];
-  s = definition;
-  int k = 0;
-  while(s) {
-    s = next_word(token, s, buffer_size);
-    file_thermal[k] = new char[strlen(token) + 1];
-    strcpy(file_thermal[k], token);
-    k++;
-  }
-}
-
-void define_temperature_thresholds(char *definition) {
-  char token[buffer_size];
-
-  if(temperature_thresholds) {
-    fprintf(stderr, "Temperature thresholds already defined.\n");
-    exit(1);
-  }
-
-  nb_temperature_thresholds = 1;
-
-  char *s;
-  s = definition;
-  while(s) {
-    s = next_word(token, s, buffer_size);
-    nb_temperature_thresholds++;
-  }
-
-  temperature_thresholds = new int[nb_temperature_thresholds];
-
-  temperature_thresholds[0] = -1;
-
-  s = definition;
-  int k = 1;
-  while(s) {
-    s = next_word(token, s, buffer_size);
-    temperature_thresholds[k] = atoi(token);
-    if(k > 0 &&
-       temperature_thresholds[k] < temperature_thresholds[k-1]) {
-      fprintf(stderr, "The temperature thresholds have to be increasing.\n");
-      exit(0);
-    }
-    k++;
-  }
-}
-
-//////////////////////////////////////////////////////////////////////
-
-int main(int argc, char **argv) {
-
-  char buffer[buffer_size], token[buffer_size];
-
-  configuration_file = new char[strlen(default_configuration_file) + 1];
-  strcpy(configuration_file, default_configuration_file);
-
-  int i = 1;
-  while(i < argc) {
-
-    if(strcmp(argv[i], "--debug") == 0 || strcmp(argv[i], "-d") == 0) {
-      debug = 1;
-      i++;
-    }
-
-    else if(strcmp(argv[i], "--version") == 0 || strcmp(argv[i], "-v") == 0) {
-      printf("Breezed v%d.%d. Written by Francois Fleuret (francois@fleuret.org).\n",
-             major_version_number, minor_version_number);
-      exit(0);
-    }
-
-    else if(strcmp(argv[i], "--no-configuration-file") == 0 ||
-            strcmp(argv[i], "-ncf") == 0) {
-      delete[] configuration_file;
-      configuration_file = 0;
-      i++;
-    }
-
-    else if(strcmp(argv[i], "--configuration-file") == 0 ||
-            strcmp(argv[i], "-cf") == 0) {
-      i++;
-      if(i == argc) {
-        fprintf(stderr, "Missing parameter for %s.\n", argv[i - 1]);
-        exit(1);
-      }
-
-      delete[] configuration_file;
-      configuration_file = new char[strlen(argv[i]) + 1];
-      strcpy(configuration_file, argv[i]);
-
-      i++;
-    }
-
-    else if(strcmp(argv[i], "--thermal-files") == 0 ||
-            strcmp(argv[i], "-tf") == 0) {
-      i++;
-      if(i == argc) {
-        fprintf(stderr, "Missing parameter for %s.\n", argv[i - 1]);
-        exit(1);
-      }
-      define_thermal_files(argv[i]);
-      i++;
-    }
-
-    else if(strcmp(argv[i], "--fan-file") == 0 ||
-            strcmp(argv[i], "-ff") == 0) {
-      i++;
-      if(i == argc) {
-        fprintf(stderr, "Missing parameter for %s.\n", argv[i - 1]);
-        exit(1);
-      }
-
-      if(file_fan) {
-        fprintf(stderr, "Fan file already defined.\n");
-        exit(1);
-      }
-      file_fan = new char[strlen(argv[i]) + 1];
-      strcpy(file_fan, argv[i]);
-
-      i++;
-    }
-
-    else if(strcmp(argv[i], "--temperature-thresholds") == 0 ||
-            strcmp(argv[i], "-tt") == 0) {
-      i++;
-
-      if(i == argc) {
-        fprintf(stderr, "Missing parameter for %s.\n", argv[i - 1]);
-        exit(1);
-      }
-
-      define_temperature_thresholds(argv[i]);
-      i++;
-    }
-
-    else if(strcmp(argv[i], "--help") == 0 || strcmp(argv[i], "-h") == 0) {
-
-      printf("%s [--version|-v] [--help|-h] [--debug|-d]\\\n\
-  [--configuration-file|-cf <file>]\\\n\
-  [--no-configuration-file|-ncf]\\\n\
-  [--thermal-files|-tf <thermalfile1,thermalfile2,...>] \\\n\
-  [--fanfile|-ff <fan file>] \\\n\
-  [--temperature-thresholds|-tt <t1,t2,t3,t4,...>]\n\
-\n\
-  --help|-h :                    shows this help\n\
-  --version|-v :                 shows the version number\n\
-  --debug|-d :                   prints out additional information\n\
-  --configuration-file|-cf       sets the configuration file\n\
-  --no-configuration-file|-ncf   do not load a configuration file\n\
-  --thermal-files|-tf :          sets where to look for temperatures\n\
-  --fanfile|-ff :                sets where to control the fan level\n\
-  --temperature-thresholds|-tt : sets the temperature thresholds\n\
-\n\
-This daemon polls the temperatures every 5s, takes the max and sets\n\
-the fan level accordingly. It uses as temperatures all the numbers it\n\
-finds in the provided \"thermal files\". Hence you can use as well\n\
-/proc/acpi/thermal_zone/THM*/temperature or /proc/acpi/ibm/thermal.\n\
-\n\
-The fan speed is set by echoing into the provided fan file.\n\
-\n\
-To reduce oscillations, it will not reduce the fan speed less than 30s\n\
-after the last previous change and the thresholds actually used to\n\
-reduce the fan speed are two degrees lower than the provided\n\
-thresholds, which are used to increase the fan speed.\n\
-\n\
-This daemon should be started through the adequate shell script in\n\
-/etc/init.d.\n\
-\n\
-Options can be set either in the configuration file, or on the \n\
-command line. Options can not be set twice.\n\
-\n\
-Version %d.%d, November 2009.\n\
-\n\
-Written by Francois Fleuret (francois@fleuret.org).\n",
-             argv[0],
-             major_version_number, minor_version_number);
-
-      exit(0);
-    }
-
-    else {
-      fprintf(stderr, "Unknown argument %s.\n", argv[i]);
-      exit(1);
-    }
-  }
-
-
-  //////////////////////////////////////////////////////////////////////
-
-  if(configuration_file) {
-    char raw_line[BUFFER_SIZE];
-    int start, end, eol, k;
-    FILE *file;
-
-    file = fopen(configuration_file, "r");
-
-    if(!file) {
-      fprintf(stderr, "Can not open `%s' for reading.\n", configuration_file);
-      exit(1);
-    }
-
-    start = 0;
-    end = 0;
-
-    char *s;
-
-    int line_number = 0;
-
-    while(end > start || !feof(file)) {
-      eol = start;
-
-      /* Look for the end of a line in what is already in the buffer */
-      while(eol < end && raw_line[eol] != '\n') eol++;
-
-      /* if we did not find the of a line, move what has not been
-         processed and is in the buffer to the beginning of the buffer,
-         fill the buffer with new data from the file, and look for the
-         end of a line */
-      if(eol == end) {
-        for(k = 0; k < end - start; k++) {
-          raw_line[k] = raw_line[k + start];
-        }
-        end -= start;
-        eol -= start;
-        start = 0;
-        end += fread(raw_line + end, sizeof(char), BUFFER_SIZE - end, file);
-        while(eol < end && raw_line[eol] != '\n') eol++;
-      }
-
-      /* The end of the line is the buffer size, which means the line is
-         too long */
-
-      if(eol == BUFFER_SIZE) {
-        raw_line[BUFFER_SIZE - 1] = '\0';
-        fprintf(stderr, "Selector: Line too long (max is %d characters):\n",
-                BUFFER_SIZE);
-        fprintf(stderr, raw_line);
-        fprintf(stderr, "\n");
-        exit(1);
-      }
-
-      /* If we got a line, we replace the carriage return by a \0 to
-         finish the string */
-
-      raw_line[eol] = '\0';
-
-      /* here we process the line */
-
-      line_number++;
-
-      if(debug) {
-        printf("%s:%d \"%s\"\n",
-               configuration_file, line_number, raw_line + start);
-      }
-
-      s = next_word(token, raw_line + start, buffer_size);
-
-      if(strcmp(token, "thermal_files") == 0) {
-        if(s == 0) {
-          fprintf(stderr, "Missing parameter in %s:%d\n",
-                  configuration_file, line_number);
-          exit(1);
-        }
-        define_thermal_files(s);
-      }
-
-      else if(strcmp(token, "debug") == 0) {
-        debug = 1;
-      }
-
-      else if(strcmp(token, "fan_file") == 0) {
-        if(file_fan) {
-          fprintf(stderr, "Fan file already defined.\n");
-          exit(1);
-        }
-        if(s == 0) {
-          fprintf(stderr, "Missing parameter in %s:%d\n",
-                  configuration_file, line_number);
-          exit(1);
-        }
-        file_fan = new char[strlen(s) + 1];
-        strcpy(file_fan, s);
-      }
-
-      else if(strcmp(token, "temperature_thresholds") == 0) {
-        if(s == 0) {
-          fprintf(stderr, "Missing parameter in %s:%d\n",
-                  configuration_file, line_number);
-          exit(1);
-        }
-        define_temperature_thresholds(s);
-      }
-
-      else if(token[0] && token[0] != '#') {
-        fprintf(stderr, "Unknown keyword '%s' in %s:%d.\n",
-                token, configuration_file, line_number);
-        exit(1);
-      }
-
-      start = eol + 1;
-    }
-
-  }
-
-  //////////////////////////////////////////////////////////////////////
-
-  if(nb_temperature_thresholds == 0) {
-    fprintf(stderr, "No temperature threshold was provided.\n");
-    exit(1);
-  }
-
-  if(nb_file_thermal == 0) {
-    fprintf(stderr, "No thermal file was provided.\n");
-    exit(1);
-  }
-
-  if(file_fan == 0){
-    fprintf(stderr, "No fan file was provided.\n");
-    exit(1);
-  }
-
-  for(int i = 0; i < nb_file_thermal; i++) {
-    file_thermal_fd[i] = open(file_thermal[i], O_RDONLY);
-    if(file_thermal_fd[i] < 0) {
-      fprintf(stderr, "Can not open %s for reading (%s).\n",
-              file_thermal[i], strerror(errno));
-      exit(1);
-    }
-  }
-
-  file_fan_fd = open(file_fan, O_WRONLY);
-
-  if(file_fan_fd < 0) {
-    fprintf(stderr, "Can not open %s for writing (%s).\n",
-            file_fan, strerror(errno));
-    exit(1);
-  }
-
-  //////////////////////////////////////////////////////////////////////
-
-  if(debug) {
-    for(int t = 0; t < nb_file_thermal; t++) {
-      printf("file_thermal[%d] %s\n", t, file_thermal[t]);
-    }
-
-    printf("file_fan %s\n", file_fan);
-
-    for(int t = 0; t < nb_temperature_thresholds; t++) {
-      printf("temperature_thresholds[%d] %d",
-             t, temperature_thresholds[t]);
-    }
-  }
-
-  //////////////////////////////////////////////////////////////////////
-
-  while(1) {
-
-    int temperature = -1;
-
-    if(debug) {
-      printf("Temperature:");
-    }
-
-    for(int i = 0; i < nb_file_thermal; i++) {
-      lseek(file_thermal_fd[i], 0, SEEK_SET);
-      int size = read(file_thermal_fd[i], buffer, buffer_size);
-
-      if(size > 0 && size < buffer_size) {
-        buffer[size] = '\0';
-
-        char *s = buffer;
-
-        while(*s) {
-          while(*s && *s != '-' && (*s < '0') || (*s > '9')) s++;
-
-          if(*s) {
-            int t = 0, sign = 1;
-            if(*s == '-') {
-              sign = -1;
-              s++;
-            }
-
-            while(*s >= '0' && *s <= '9') {
-              t = t * 10 + (*s - '0');
-              s++;
-            }
-
-            t *= sign;
-            if(debug) {
-              printf(" %d", t);
-            }
-
-            // So that we can deal with the new files where the
-            // temperature are in 1/1000th of C
-            if(t > 1000) t /= 1000;
-
-            if(t > temperature) temperature = t;
-          }
-        }
-
-        if(debug) {
-          if(i < nb_file_thermal - 1)
-            printf(" /");
-          else
-            printf("\n");
-        }
-      } else {
-        if(size == 0) {
-          fprintf(stderr, "Nothing to read in %d.\n", file_thermal[i]);
-        } else if(size < 0) {
-          fprintf(stderr, "Error while reading %s (%s).\n",
-                  file_thermal[i], strerror(errno));
-        } else {
-          fprintf(stderr, "Error while reading %s (too large).\n",
-                  file_thermal[i]);
-        }
-        exit(1);
-      }
-    }
-
-    if(temperature < 0) {
-      fprintf(stderr, "Could not read a meaningful temperature.\n");
-      exit(1);
-    }
-
-    nb_rounds_since_last_change++;
-
-    int new_level = last_level;
-
-    int new_level_up = nb_temperature_thresholds - 1;
-    while(new_level_up > 0 &&
-          temperature < temperature_thresholds[new_level_up]) {
-      new_level_up--;
-    }
-
-    if(new_level_up > last_level) {
-      new_level = new_level_up;
-    } else {
-      int new_level_down = nb_temperature_thresholds - 1;
-      while(new_level_down > 0 &&
-            temperature <
-            temperature_thresholds[new_level_down] - down_temperature_delta)
-        new_level_down--;
-      if(new_level_down < last_level &&
-         nb_rounds_since_last_change * polling_delay >=
-         minimum_delay_to_go_down) {
-        new_level = new_level_down;
-      }
-    }
-
-    // We set it every time, even when there is no change, to handle
-    // when the level has been modified somewhere else (for instance
-    // when combing back from suspend).
-
-    set_fan_level(file_fan_fd, new_level, nb_temperature_thresholds - 1);
-
-    if(new_level != last_level) {
-      nb_rounds_since_last_change = 0;
-      last_level = new_level;
-      if(debug) {
-        printf("Temperature is %dC setting the fan level to %d.",
-               temperature, new_level);
-      }
-    }
-
-    sleep(polling_delay);
-  }
-}