aboutsummaryrefslogblamecommitdiffstats
path: root/src/adjbacklight.c
blob: d50fbce1324fc98407fb1e84d34faaa67c2f64ef (plain) (tree)















































































































































































































































































                                                                                                          
/**
 * adjbacklight – Convient method for adjusting the backlight on your portable computer
 * 
 * Copyright © 2012, 2013, 2014  Mattias Andrée (maandree@member.fsf.org)
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
 */
#include <stdlib.h>
#include <stdio.h>
#include <termios.h>
#include <sys/ioctl.h>
#include <sys/wait.h>
#include <unistd.h>
#include <dirent.h>
#include <string.h>


/**
 * The years this software has been developed
 */
#define _YEARS_  "2012, 2013, 2014"


/**
 * Forking method
 */
#define FORK  vfork


/**
 * Print a line to stdout
 * 
 * @param  S:char*  The string to print
 */
#define P(S)  printf("%s", S "\n")



#define  adjust(X,Y,Z)



/**
 * This is the mane entry point of the program
 * 
 * @param   argc  The number of elements in `argv`
 * @parma   argv  Command line arguments, including the command
 * @return        Exit value, zero on success
 */
int main(int argc, char** argv)
{
  struct winsize win;
  int rows, cols;
  struct termios saved_stty;
  struct termios stty;
  pid_t pid;
  
  int i, j;
  int all = 0;
  char** devices = alloca(argc * sizeof(char*));
  int ndevices = 0;
  
  
  if (argc > 1)
    {
      char* arg;
      for (i = 1; i < argc; i++)
	{
	  #define T(S)  (!strcmp(arg, S))
	  arg = *(argv + i);
	  if (T("-a") || T("--all"))
	    all = 1;
	  else if (T("-c") || T("--copyright") || T("--copying"))
	    {
	      P("\n");
	      P("adjbacklight – Convient method for adjusting the backlight on your portable computer");
	      P("");
	      P("Copyright © " _YEARS_ "  Mattias Andrée (maandree@member.fsf.org)");
	      P("");
	      P("This program is free software: you can redistribute it and/or modify");
	      P("it under the terms of the GNU General Public License as published by");
	      P("the Free Software Foundation, either version 3 of the License, or");
	      P("(at your option) any later version.");
	      P("");
	      P("This program is distributed in the hope that it will be useful,");
	      P("but WITHOUT ANY WARRANTY; without even the implied warranty of");
	      P("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the");
	      P("GNU General Public License for more details.");
	      P("");
	      P("You should have received a copy of the GNU General Public License");
	      P("along with this program.  If not, see <http://www.gnu.org/licenses/>.");
	      P("\n");
	      return 0;
	    }
	  else if (T("-w") || T("--warranty"))
	    {
	      P("\n");
	      P("This program is distributed in the hope that it will be useful,");
	      P("but WITHOUT ANY WARRANTY; without even the implied warranty of");
	      P("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the");
	      P("GNU General Public License for more details.");
	      P("\n");
	      return 0;
	    }
	  else
	    {
	      if (*arg && (*arg != '-'))
		*(devices + ndevices++) = arg;
	    }
	  #undef T
	}
      if (all + ndevices == 0)
	{
	  P("\n");
	  P("adjbacklight - Convient method for adjusting the backlight on your portable computer");
	  P("");
	  P("USAGE: adjbacklight [ -c | -w | -a | DEVICE...]");
	  P("");
	  P("Run with options to adjust the backlight on your monitors.");
	  P("");
	  P("");
	  P("OPTIONS:");
	  P("");
	  P("-c");
	  P("--copyright");
	  P("--copying       Display copyright information");
	  P("");
	  P("-w");
	  P("--warranty      Display warranty disclaimer");
	  P("");
	  P("-a");
	  P("--all           Run for all devices, including ACPI devices ");
	  P("");
	  P("");
	  P("KEYBOARD:");
	  P("");
	  P("←");
	  P("↓               Darken the screen");
	  P("");
	  P("→");
	  P("↑               Brighten the screen");
	  P("");
	  P("q");
	  P("enter");
	  P("C-d             Continue to next controller, or if at last, quit");
	  P("");
	  P("");
	  P("");
	  P("Copyright © " _YEARS_ "  Mattias Andrée (maandree@member.fsf.org)");
	  P("");
	  P("This program is free software: you can redistribute it and/or modify");
	  P("it under the terms of the GNU General Public License as published by");
	  P("the Free Software Foundation, either version 3 of the License, or");
	  P("(at your option) any later version.");
	  P("");
	  return 0;
	}
    }
  
  
  P("\n");
  P("If the program is abnormally aborted the may be some residual");
  P("effects on the terminal. the following commands should reset it:");
  P("");
  P("    stty icanon echo");
  P("    echo -en '\\e[?25h'");
  P("");
  P("\n\n\n");
  
  
  /* rows cols = $(stty size) */
  if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &win) == -1)
    {
      perror(*argv);
      rows = 24;
      cols = 80;
    }
  else
    {
      rows = win.ws_row;
      cols = win.ws_col;
    }
  
  /* Hide cursor */
  printf("%s", "\033[?25l");
  fflush(stdout);
  
  /* stty -icanon -echo */
  if (tcgetattr(STDIN_FILENO, &saved_stty))
    {
      perror(*argv);
      return 1;
    }
  saved_stty = stty;
  stty.c_lflag &= ~(ICANON | ECHO);
  if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &stty))
    {
      perror(*argv);
      return 1;
    }
  
  
  /* Fork to diminish risk for unclean exit  */
  pid = FORK();
  if (pid == (pid_t)-1)
    {
      perror(*argv);
      pid = 0;
    }
  
  if (pid)
    waitpid(pid, NULL, 0);
  else
    if (ndevices)
      {
	char* device;
	for (i = 0; i < ndevices; i++)
	  {
	    device = *(devices + i);
	    for (j = 0; *(device + j); j++)
	      if (*(device + j) == '/')
		{
		  device += j + 1;
		  j = -1;
		}
	    adjust(rows, cols, device);
	  }
      }
    else
      {
	struct dirent* ent;
	DIR* dir = opendir("/sys/class/backlight");
	if (dir)
	  {
	    char* device;
	    char* forbidden = "acpi_video";
	    while ((ent = readdir(dir)))
	      {
		device = ent->d_name;
		if (all || (strstr(device, forbidden) != forbidden))
		  adjust(rows, cols, device);
	      }
	    closedir(dir);
	  }
      }
  
  
  /* `stty icanon echo` */
  tcsetattr(STDIN_FILENO, TCSAFLUSH, &saved_stty);
    {
      perror(*argv);
      return 1;
    }
  
  /* Show cursor */
  printf("%s", "\033[?25h");
  fflush(stdout);
  
  return 0;
}