/* Simple button demon * * Petr Malat (c) 2008 * mail: petris at penguin dot cz * * Distributed under the terms of GNU GPL version 3 * */ #include #include #include #include #include #include #include #include #include #include #include #include /****************** Edit this to configure *****************************/ /* If button is pressed for (min, max) intervall, the cmd is executed via system() call */ struct action_s { float min; float max; char *cmd; }; const struct action_s actions[] = { {0., 1.5, "shutdown -h now"}, {4., 8., "ifconfig eth0 192.168.1.1 netmask 255.255.255.0"} }; /***********************************************************************/ struct settings_s { FILE *log_file; int dev_fd; } settings; void logerror(char *cmd, ...){ if( settings.log_file != NULL ){ va_list list; va_start(list, cmd); vfprintf(settings.log_file, cmd, list); va_end(list); } } void system_exec(const char* cmd){ pid_t pid; pid = fork(); if( pid == 0 ){ /* child */ if( system(cmd) == -1) logerror("Couldn't execute system(\"%s\"): %d\n", cmd, errno); exit(0); } else if (pid == -1){ logerror("Couldn't fork new process: %d\n", errno); } } int process_events(int fd){ struct input_event event; time_t KEY_POWER_sec = 0; suseconds_t KEY_POWER_usec = 0; float sec; int i; while(1){ read(fd, &event, sizeof(event)); if( event.type == EV_KEY ){ switch(event.code){ case KEY_POWER: if(event.value == 1){ KEY_POWER_sec = event.time.tv_sec; KEY_POWER_usec = event.time.tv_usec; } else { sec = ((event.time.tv_sec - KEY_POWER_sec)*1000000 + event.time.tv_usec - KEY_POWER_usec)/1000000.; for(i = 0; i < sizeof(actions)/sizeof(struct action_s); i++){ if( sec > actions[i].min && sec < actions[i].max ) system_exec(actions[i].cmd); } } } } } return 0; } void parse_cmd (int argc, char *argv[]) { char *dev_file = NULL; char *log_file = NULL; int opt; while( (opt = getopt(argc, argv, "l:d:h")) != -1 ){ switch(opt){ case 'd': dev_file = optarg; break; case 'l': log_file = optarg; break; case ':': case '?': fprintf(stderr, "Bad commandline syntax\n"); case 'h': default: fprintf(stderr, "Usage: buttond -d device_filename [-l log_filename] [-h]\n"); exit(0); } } if( log_file == NULL ){ settings.log_file = NULL; } else { if( (settings.log_file = fopen(log_file, "a")) == NULL){ fprintf(stderr, "Couldn't open file '%s'. Errno %d\n", log_file, errno); exit(1); } } if( dev_file == NULL ){ fprintf(stderr, "Usage: buttond -d device_filename [-l log_filename] [-h]\n"); exit(0); } else if( (settings.dev_fd = open(dev_file, O_RDONLY)) == -1){ logerror("Couldn't open device '%s'. Errno %d\n", dev_file, errno); fprintf(stderr, "Couldn't open device '%s'. Errno %d\n", dev_file, errno); exit(1); } } int main(int argc, char *argv[]){ struct sigaction sa; pid_t pid; parse_cmd(argc, argv); pid = fork(); if( pid == 0 ){ close(0); close(1); close(2); sa.sa_handler = SIG_IGN; sigaction(SIGCHLD, &sa, NULL); sigaction(SIGTSTP, &sa, NULL); sigaction(SIGTTOU, &sa, NULL); sigaction(SIGTTIN, &sa, NULL); setsid(); return process_events(settings.dev_fd); } else if (pid == -1){ logerror("Couldn't fork demon process. Errno %d\n", errno); fprintf(stderr, "Couldn't fork demon process. Errno %d\n", errno); return 1; } return 0; }