eleni@3: /* eleni@3: * DTMS Copyright (C) 2016 Eleni Maria Stea eleni@3: * eleni@3: * This program is free software: you can redistribute it and/or modify eleni@3: * it under the terms of the GNU General Public License as published by eleni@3: * the Free Software Foundation, either version 3 of the License, or eleni@3: * (at your option) any later version. eleni@3: * eleni@3: * This program is distributed in the hope that it will be useful, eleni@3: * but WITHOUT ANY WARRANTY; without even the implied warranty of eleni@3: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the eleni@3: * GNU General Public License for more details. eleni@3: eleni@3: * You should have received a copy of the GNU General Public License eleni@3: * along with this program. If not, see . eleni@3: * */ eleni@3: eleni@0: #include eleni@0: #include eleni@0: #include eleni@0: #include eleni@0: #include eleni@0: #include eleni@0: #include eleni@0: #include eleni@0: #include eleni@0: #include eleni@0: #include eleni@0: eleni@0: static int parse_args(int argc, char **argv); eleni@0: static void print_help(); eleni@4: static int check_device(char *device_path); eleni@0: eleni@4: static int uid = -1; eleni@4: static char *player_path; eleni@0: static char *dev_path; eleni@0: eleni@4: #ifdef PREFIX eleni@4: static const char* player_arg = PREFIX "/share/dtms/dtms.mp3"; eleni@4: #else eleni@4: static const char* player_arg = "data/dtms.mp3"; eleni@4: #endif eleni@4: eleni@0: int main(int argc, char **argv) eleni@0: { eleni@0: time_t last_touch_time = 0; eleni@0: int fd; eleni@0: eleni@4: if(parse_args(argc, argv) == -1) eleni@0: return 1; eleni@0: eleni@4: if(getuid() == 0 && uid == -1) { eleni@4: fprintf(stderr, "It's a bad idea to run this program as root, either make it setuid-root, or use the -u option to specify an unprivileged user.\n"); eleni@4: return 1; eleni@4: } eleni@4: eleni@4: if(check_device(dev_path) == -1) eleni@4: return 1; eleni@0: eleni@0: if((fd = open(dev_path, O_RDONLY | O_NONBLOCK)) == -1) { eleni@0: fprintf(stderr, "Failed to open device: %s, error: %s\n", dev_path, strerror(errno)); eleni@0: return 1; eleni@0: } eleni@0: eleni@4: if(uid == -1) { eleni@4: uid = getuid(); eleni@4: } eleni@4: eleni@0: if(seteuid(uid) == -1) { eleni@0: perror("Set uid failed"); eleni@4: return 1; eleni@0: } eleni@0: eleni@0: if(!uid) { eleni@4: if(player_path[0] != '/') { eleni@0: fprintf(stderr, "If you run this program as root you should pass the absolute path to a valid mp3 player.\n"); eleni@0: return 1; eleni@0: } eleni@0: } eleni@0: eleni@4: char *cmd = malloc(strlen(player_path) + 1 + strlen(player_arg) + 1); eleni@4: sprintf(cmd, "%s %s", player_path, player_arg); eleni@4: eleni@0: while(1) { eleni@0: fd_set read_set; eleni@0: FD_ZERO(&read_set); eleni@0: FD_SET(fd, &read_set); eleni@0: eleni@0: int res; eleni@0: while((res = select(fd + 1, &read_set, 0, 0, 0)) == -1 && errno == EINTR); eleni@0: if(res < 0) { eleni@0: perror("Select failed"); eleni@0: break; eleni@0: } eleni@0: if(res == 0) //nothing to read eleni@0: continue; eleni@0: eleni@0: if(FD_ISSET(fd, &read_set)) { eleni@0: char buf[1024]; eleni@0: time_t now = time(0); eleni@0: while(read(fd, buf, sizeof buf) > 0); eleni@0: if (now - last_touch_time > 2) { eleni@0: system(cmd); eleni@0: last_touch_time = now; eleni@0: } eleni@0: } eleni@0: } eleni@4: eleni@4: free(cmd); eleni@0: close(fd); eleni@4: eleni@4: return 0; eleni@0: } eleni@0: eleni@0: static int parse_args(int argc, char **argv) eleni@0: { eleni@0: for(int i=1; ipw_uid; eleni@4: if(uid == 0) { eleni@4: fprintf(stderr, "You should pass an unprivileged username.\n"); eleni@4: return -1; eleni@4: } eleni@0: } eleni@0: else { eleni@4: fprintf(stderr, "Missing username.\n"); eleni@4: return -1; eleni@0: } eleni@0: } eleni@4: else if((strcmp(argv[i], "-d") == 0)) { eleni@4: if(argv[++i]) { eleni@4: dev_path = argv[i]; eleni@0: } eleni@0: else { eleni@0: fprintf(stderr, "Invalid device file.\n"); eleni@4: return -1; eleni@0: } eleni@0: } eleni@4: else { eleni@4: fprintf(stderr, "Unknown argument: %s\n", argv[i]); eleni@4: return -1; eleni@4: } eleni@0: } eleni@0: return 0; eleni@0: } eleni@0: eleni@0: static void print_help() eleni@0: { eleni@0: printf("Options:\n"); eleni@0: printf("-h, prints this help\n"); eleni@0: printf("-d, path to the device\n"); eleni@0: printf("-p, path to the mp3 player\n"); eleni@0: printf("-u. username of the user that runs the program\n"); eleni@0: printf("--------\n"); eleni@0: printf("Examples:\n"); eleni@0: printf("--------\n"); eleni@0: printf("./dtms -d /dev/usb/hiddev0 -u eleni -p /usr/bin/mpv\n"); eleni@0: } eleni@0: eleni@4: static int check_device(char *device_path) eleni@0: { eleni@0: struct stat sb; eleni@0: if(stat(dev_path, &sb) == -1) { eleni@0: perror("stat"); eleni@4: return -1; eleni@0: } eleni@0: if(((sb.st_mode & S_IFMT) != S_IFBLK) && ((sb.st_mode & S_IFMT) != S_IFCHR)) { eleni@4: fprintf(stderr, "%s is not a device file.\n", device_path); eleni@4: return -1; eleni@0: } eleni@4: return 0; eleni@0: }