main.c 9.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379
  1. #define _GNU_SOURCE
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <dirent.h>
  5. #include <string.h>
  6. #include <unistd.h>
  7. #include <limits.h>
  8. typedef enum LBOOL{
  9. TRUE = 0,
  10. FALSE = 1
  11. } LBOOL;
  12. typedef enum LOPTYPE{
  13. SET = 0,
  14. ADD = 1,
  15. SUB = 2
  16. } LOPTYPE;
  17. /* Flags */
  18. LBOOL q; /* Quiet, supresses output */
  19. LBOOL c; /* print unprecise current value in percentage */
  20. LBOOL m; /* read max value*/
  21. LBOOL p; /* precision read current value */
  22. int wbright;
  23. LOPTYPE ot;
  24. LBOOL readint(const char* f, unsigned int *i){
  25. FILE* ff = fopen(f, "r");
  26. if(ff){
  27. fscanf(ff, "%u", i);
  28. fclose(ff);
  29. return TRUE;
  30. }else{
  31. return FALSE;
  32. }
  33. }
  34. LBOOL writeint(const char* f, unsigned int i){
  35. FILE* ff = fopen(f, "w");
  36. if(ff){
  37. fprintf(ff, "%u", i);
  38. fclose(ff);
  39. return TRUE;
  40. }else{
  41. return FALSE;
  42. }
  43. }
  44. LBOOL is_dir(const char* d){
  45. DIR* dd = opendir(d);
  46. if(dd){
  47. closedir(dd);
  48. return TRUE;
  49. }else{
  50. return FALSE;
  51. }
  52. }
  53. LBOOL is_writable(const char* f){
  54. FILE* dd = fopen(f, "w");
  55. if(dd){
  56. fclose(dd);
  57. return TRUE;
  58. }else{
  59. return FALSE;
  60. }
  61. }
  62. typedef struct {
  63. char* name;
  64. unsigned int current_brightness;
  65. unsigned int max_brightness;
  66. char* c_path; /* Controller-path */
  67. char* cb_path; /* Current brightness-path */
  68. char* mb_path; /* Max brightness-path */
  69. char* b_path; /* Brightness-path */
  70. enum LBOOL is_ok;
  71. } controller;
  72. typedef struct {
  73. controller controllers[256];
  74. unsigned int num_controllers;
  75. } fetch_result;
  76. fetch_result fetch_controllers(const char* ctrldir){
  77. fetch_result returner;
  78. struct dirent* ep;
  79. DIR* lcdir = opendir(ctrldir);
  80. returner.num_controllers = 0;
  81. if(!lcdir){
  82. if(q == FALSE)
  83. printf("Error: Could not open directory '%s'!\n", ctrldir);
  84. }else{
  85. while( ( ep = readdir(lcdir) ) ){
  86. char* currctrldir = "";
  87. char* currctrldir_curr = "";
  88. char* currctrldir_max = "";
  89. char* currctrldir_f = "";
  90. if( ep->d_name[0] != '.'){
  91. returner.controllers[returner.num_controllers].name = ep->d_name;
  92. /* Set some default values, in case something fails we dont just get null */
  93. returner.controllers[returner.num_controllers].current_brightness = 0;
  94. returner.controllers[returner.num_controllers].max_brightness = 0;
  95. returner.controllers[returner.num_controllers].is_ok = TRUE;
  96. returner.controllers[returner.num_controllers].c_path = NULL;
  97. returner.controllers[returner.num_controllers].cb_path = NULL;
  98. returner.controllers[returner.num_controllers].b_path = NULL;
  99. returner.controllers[returner.num_controllers].mb_path = NULL;
  100. /* Get path to the current controller dir */
  101. asprintf(&currctrldir, "%s/%s", ctrldir, ep->d_name);
  102. returner.controllers[returner.num_controllers].c_path = currctrldir;
  103. if(is_dir(currctrldir) == FALSE){
  104. if(q == FALSE)
  105. printf("Warning: '%s' is not a directory, check your system.\n", currctrldir);
  106. returner.controllers[returner.num_controllers].is_ok = FALSE;
  107. }
  108. /* Get path to current actual_brightness-file */
  109. asprintf(&currctrldir_curr, "%s/%s", currctrldir, "actual_brightness");
  110. returner.controllers[returner.num_controllers].cb_path = currctrldir_curr;
  111. if( readint(currctrldir_curr, &returner.controllers[returner.num_controllers].current_brightness) == FALSE ){
  112. if(q == FALSE)
  113. printf("Warning: Can't read actual_brightness-file of '%s'. Will ignore this controller.\n", ep->d_name);
  114. returner.controllers[returner.num_controllers].is_ok = FALSE;
  115. }
  116. /* Get path to current max_brightness-file*/
  117. asprintf(&currctrldir_max, "%s/%s", currctrldir, "max_brightness");
  118. returner.controllers[returner.num_controllers].mb_path = currctrldir_max;
  119. if( readint(currctrldir_max, &returner.controllers[returner.num_controllers].max_brightness) == FALSE ){
  120. if(q == FALSE)
  121. printf("Warning: Can't read max_brightness-file of '%s'. Will ignore this controller.\n", ep->d_name);
  122. returner.controllers[returner.num_controllers].is_ok = FALSE;
  123. }
  124. /* Get path to current brightness-file */
  125. asprintf(&currctrldir_f, "%s/%s", currctrldir, "brightness");
  126. returner.controllers[returner.num_controllers].b_path = currctrldir_f;
  127. if( is_writable(currctrldir_f) == FALSE){
  128. if(q == FALSE)
  129. printf("Warning: Controllerfile of '%s' is not writable. Will ignore this controller.\n", ep->d_name);
  130. returner.controllers[returner.num_controllers].is_ok = FALSE;
  131. }
  132. returner.num_controllers++;
  133. }
  134. }
  135. closedir(lcdir);
  136. }
  137. return returner;
  138. }
  139. controller* get_best_controller(fetch_result* res){
  140. unsigned int it;
  141. unsigned int cmax;
  142. LBOOL foundokctrl;
  143. controller* returner;
  144. it = 0;
  145. cmax = 0;
  146. foundokctrl = FALSE;
  147. returner = NULL;
  148. while(it < res->num_controllers){
  149. if(res->controllers[it].is_ok == TRUE){
  150. if(foundokctrl != TRUE){
  151. foundokctrl = TRUE;
  152. returner = &res->controllers[it];
  153. }
  154. if(res->controllers[it].max_brightness > cmax){
  155. cmax = res->controllers[it].max_brightness;
  156. returner = &res->controllers[it];
  157. }
  158. }
  159. it++;
  160. }
  161. return returner;
  162. }
  163. void usage(){
  164. printf("Usage: light [-qcas] <value>\n\n\t-q:\t Run quiet, supresses output.\n\t-c:\t Prints the current brightness in percent and exits.(Not precise)\n\t-p:\t Prints the current brightness directly from controller and exits. (Precise)\n\t-m:\t Prints the max brightness directly from controller and exits. (To be used side-by-side with -p)\n\t-a:\t Add the value instead of setting it.\n\t-s:\t Subtract the value instead of setting it.\n\n\t<value>\t Brightness wanted in percent.\n\n");
  165. }
  166. int main(int argc, char **argv) {
  167. unsigned int argsit;
  168. fetch_result res;
  169. controller* best_ctrl;
  170. unsigned int citr;
  171. uid_t uid;
  172. unsigned int minlight;
  173. LBOOL given;
  174. unsigned int real_wbright;
  175. unsigned int minlight_nonp;
  176. unsigned int curr_bright;
  177. unsigned int curr_brightp;
  178. /* Get UID */
  179. uid = getuid();
  180. /* Parse arguments */
  181. q=FALSE;
  182. c=FALSE;
  183. m=FALSE;
  184. p=FALSE;
  185. ot=SET;
  186. wbright=0;
  187. argsit = 1;
  188. given=FALSE;
  189. while(argsit < argc){
  190. char* carg = argv[argsit];
  191. if(carg[0] == '-'){
  192. unsigned int cargit = 1;
  193. while(cargit < strlen(carg)){
  194. switch(carg[cargit]){
  195. case 'q':
  196. q = TRUE;
  197. break;
  198. case 'a':
  199. ot = ADD;
  200. break;
  201. case 's':
  202. ot = SUB;
  203. break;
  204. case 'c':
  205. c = TRUE;
  206. break;
  207. case 'p':
  208. p = TRUE;
  209. break;
  210. case 'm':
  211. m = TRUE;
  212. break;
  213. default:
  214. break;
  215. }
  216. cargit++;
  217. }
  218. }else{
  219. wbright = atoi(carg);
  220. given=TRUE;
  221. }
  222. argsit++;
  223. }
  224. if(c == TRUE || m == TRUE || p == TRUE){
  225. q = TRUE;
  226. }
  227. if(given == FALSE && c == FALSE && m == FALSE && p == FALSE){
  228. usage();
  229. return 0;
  230. }
  231. if(q == FALSE)
  232. printf("Light v0.4 - Fredrik Haikarainen\n");
  233. /* Get and check minlight */
  234. if(readint("/etc/light/minlight", &minlight) == FALSE){
  235. minlight = 5;
  236. if(q == FALSE)
  237. printf("Warning: Couldn't read /etc/light/minlight, using 5 as default.\n");
  238. }
  239. /* Fetch controllers */
  240. if(q == FALSE)
  241. printf("Fetching controllers..\n");
  242. res = fetch_controllers("/sys/class/backlight");
  243. citr = 0;
  244. while(citr < res.num_controllers){
  245. controller* currc = &res.controllers[citr];
  246. if(currc->is_ok == TRUE){
  247. if(q == FALSE)
  248. printf("\tFound '%s' (%u/%u)\n", currc->name, currc->current_brightness, currc->max_brightness);
  249. }else{
  250. if(q == FALSE)
  251. printf("\tFound '%s', but ignoring\n", currc->name);
  252. }
  253. citr++;
  254. }
  255. if(q == FALSE)
  256. printf("\n");
  257. /* Get the best controller */
  258. best_ctrl = get_best_controller(&res);
  259. if(best_ctrl == NULL){
  260. if(uid == 0){
  261. if(q == FALSE)
  262. printf("No okay controller found, even though you are root! Check your system.\n");
  263. }else{
  264. if(q == FALSE)
  265. printf("No okay controller found, check your permissions or try to run as root.\n");
  266. }
  267. return 1;
  268. }
  269. if(p == TRUE){
  270. printf("%u\n", best_ctrl->current_brightness);
  271. return 0;
  272. }
  273. if(m == TRUE){
  274. printf("%u\n", best_ctrl->max_brightness);
  275. return 0;
  276. }
  277. if(q == FALSE)
  278. printf("Using controller '%s' ..\n", best_ctrl->name);
  279. if(wbright < 0){ wbright = 0;}
  280. if(wbright > 100){wbright=100;}
  281. curr_bright = best_ctrl->current_brightness;
  282. curr_brightp = (float)((float)curr_bright / (float)best_ctrl->max_brightness) * 100;
  283. if(c == TRUE){
  284. printf("%u\n", curr_brightp);
  285. return 0;
  286. }
  287. switch(ot){
  288. case SET:
  289. real_wbright = best_ctrl->max_brightness * ( (float)wbright / 100 );
  290. break;
  291. case ADD:
  292. real_wbright = ( best_ctrl->max_brightness * ( (float)( curr_brightp + wbright +1) / 100 ));
  293. break;
  294. case SUB:
  295. real_wbright = ( best_ctrl->max_brightness * ( (float)( curr_brightp - wbright + 1) / 100 ));
  296. break;
  297. default:
  298. break;
  299. }
  300. minlight_nonp = best_ctrl->max_brightness * ( (float)minlight / 100);
  301. /* FIXME
  302. Line below makes sure the value never wraps around and gets higher. Puts a (high) limit on max brightness.
  303. Not sure if safe for portabilities sake.
  304. */
  305. if(real_wbright > ((UINT_MAX/2) - best_ctrl->max_brightness)){ real_wbright = minlight_nonp; }
  306. if(real_wbright > best_ctrl->max_brightness){real_wbright = best_ctrl->max_brightness;}
  307. if(real_wbright < minlight_nonp){real_wbright = minlight_nonp;}
  308. if(q == FALSE)
  309. printf("Writing %u to file '%s'..\n", real_wbright, best_ctrl->b_path);
  310. if(writeint(best_ctrl->b_path, real_wbright) == FALSE){
  311. if(q == FALSE){
  312. printf("Error: Could not write to file %s, check your permissions!\n", best_ctrl->b_path);
  313. }
  314. return 1;
  315. }
  316. return 0;
  317. }