rev |
line source |
eleni@3
|
1 /*
|
eleni@3
|
2 * DTMS Copyright (C) 2016 Eleni Maria Stea <elene.mst@gmail.com>
|
eleni@3
|
3 *
|
eleni@3
|
4 * This program is free software: you can redistribute it and/or modify
|
eleni@3
|
5 * it under the terms of the GNU General Public License as published by
|
eleni@3
|
6 * the Free Software Foundation, either version 3 of the License, or
|
eleni@3
|
7 * (at your option) any later version.
|
eleni@3
|
8 *
|
eleni@3
|
9 * This program is distributed in the hope that it will be useful,
|
eleni@3
|
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
eleni@3
|
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
eleni@3
|
12 * GNU General Public License for more details.
|
eleni@3
|
13
|
eleni@3
|
14 * You should have received a copy of the GNU General Public License
|
eleni@3
|
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
|
eleni@3
|
16 * */
|
eleni@3
|
17
|
eleni@0
|
18 #include <errno.h>
|
eleni@0
|
19 #include <fcntl.h>
|
eleni@0
|
20 #include <pwd.h>
|
eleni@0
|
21 #include <stdio.h>
|
eleni@0
|
22 #include <stdlib.h>
|
eleni@0
|
23 #include <string.h>
|
eleni@0
|
24 #include <sys/select.h>
|
eleni@0
|
25 #include <sys/stat.h>
|
eleni@0
|
26 #include <sys/types.h>
|
eleni@0
|
27 #include <time.h>
|
eleni@0
|
28 #include <unistd.h>
|
eleni@0
|
29
|
eleni@0
|
30 static int parse_args(int argc, char **argv);
|
eleni@0
|
31 static void print_help();
|
eleni@4
|
32 static int check_device(char *device_path);
|
eleni@0
|
33
|
eleni@4
|
34 static int uid = -1;
|
eleni@4
|
35 static char *player_path;
|
eleni@0
|
36 static char *dev_path;
|
eleni@0
|
37
|
eleni@4
|
38 #ifdef PREFIX
|
eleni@4
|
39 static const char* player_arg = PREFIX "/share/dtms/dtms.mp3";
|
eleni@4
|
40 #else
|
eleni@4
|
41 static const char* player_arg = "data/dtms.mp3";
|
eleni@4
|
42 #endif
|
eleni@4
|
43
|
eleni@0
|
44 int main(int argc, char **argv)
|
eleni@0
|
45 {
|
eleni@0
|
46 time_t last_touch_time = 0;
|
eleni@0
|
47 int fd;
|
eleni@0
|
48
|
eleni@4
|
49 if(parse_args(argc, argv) == -1)
|
eleni@0
|
50 return 1;
|
eleni@0
|
51
|
eleni@4
|
52 if(getuid() == 0 && uid == -1) {
|
eleni@4
|
53 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
|
54 return 1;
|
eleni@4
|
55 }
|
eleni@4
|
56
|
eleni@4
|
57 if(check_device(dev_path) == -1)
|
eleni@4
|
58 return 1;
|
eleni@0
|
59
|
eleni@0
|
60 if((fd = open(dev_path, O_RDONLY | O_NONBLOCK)) == -1) {
|
eleni@0
|
61 fprintf(stderr, "Failed to open device: %s, error: %s\n", dev_path, strerror(errno));
|
eleni@0
|
62 return 1;
|
eleni@0
|
63 }
|
eleni@0
|
64
|
eleni@4
|
65 if(uid == -1) {
|
eleni@4
|
66 uid = getuid();
|
eleni@4
|
67 }
|
eleni@4
|
68
|
eleni@0
|
69 if(seteuid(uid) == -1) {
|
eleni@0
|
70 perror("Set uid failed");
|
eleni@4
|
71 return 1;
|
eleni@0
|
72 }
|
eleni@0
|
73
|
eleni@0
|
74 if(!uid) {
|
eleni@4
|
75 if(player_path[0] != '/') {
|
eleni@0
|
76 fprintf(stderr, "If you run this program as root you should pass the absolute path to a valid mp3 player.\n");
|
eleni@0
|
77 return 1;
|
eleni@0
|
78 }
|
eleni@0
|
79 }
|
eleni@0
|
80
|
eleni@4
|
81 char *cmd = malloc(strlen(player_path) + 1 + strlen(player_arg) + 1);
|
eleni@4
|
82 sprintf(cmd, "%s %s", player_path, player_arg);
|
eleni@4
|
83
|
eleni@0
|
84 while(1) {
|
eleni@0
|
85 fd_set read_set;
|
eleni@0
|
86 FD_ZERO(&read_set);
|
eleni@0
|
87 FD_SET(fd, &read_set);
|
eleni@0
|
88
|
eleni@0
|
89 int res;
|
eleni@0
|
90 while((res = select(fd + 1, &read_set, 0, 0, 0)) == -1 && errno == EINTR);
|
eleni@0
|
91 if(res < 0) {
|
eleni@0
|
92 perror("Select failed");
|
eleni@0
|
93 break;
|
eleni@0
|
94 }
|
eleni@0
|
95 if(res == 0) //nothing to read
|
eleni@0
|
96 continue;
|
eleni@0
|
97
|
eleni@0
|
98 if(FD_ISSET(fd, &read_set)) {
|
eleni@0
|
99 char buf[1024];
|
eleni@0
|
100 time_t now = time(0);
|
eleni@0
|
101 while(read(fd, buf, sizeof buf) > 0);
|
eleni@0
|
102 if (now - last_touch_time > 2) {
|
eleni@0
|
103 system(cmd);
|
eleni@0
|
104 last_touch_time = now;
|
eleni@0
|
105 }
|
eleni@0
|
106 }
|
eleni@0
|
107 }
|
eleni@4
|
108
|
eleni@4
|
109 free(cmd);
|
eleni@0
|
110 close(fd);
|
eleni@4
|
111
|
eleni@4
|
112 return 0;
|
eleni@0
|
113 }
|
eleni@0
|
114
|
eleni@0
|
115 static int parse_args(int argc, char **argv)
|
eleni@0
|
116 {
|
eleni@0
|
117 for(int i=1; i<argc; i++) {
|
eleni@0
|
118 if((strcmp(argv[i], "-h") == 0)) {
|
eleni@0
|
119 print_help();
|
eleni@0
|
120 exit(0);
|
eleni@0
|
121 }
|
eleni@4
|
122
|
eleni@4
|
123 else if((strcmp(argv[i], "-p") == 0)) {
|
eleni@4
|
124 if(argv[++i]) {
|
eleni@4
|
125 player_path = argv[i];
|
eleni@0
|
126 }
|
eleni@0
|
127 else {
|
eleni@0
|
128 fprintf(stderr, "Invalid path. Please give the absolute path to an mp3 player.\n");
|
eleni@4
|
129 return -1;
|
eleni@0
|
130 }
|
eleni@0
|
131 }
|
eleni@0
|
132
|
eleni@4
|
133 else if((strcmp(argv[i], "-u") == 0)) {
|
eleni@4
|
134 if(argv[++i]) {
|
eleni@4
|
135 struct passwd *passwd = getpwnam(argv[i]);
|
eleni@0
|
136 if(!passwd) {
|
eleni@4
|
137 fprintf(stderr, "Failed to get uid for: %s : %s.\n", argv[i], strerror(errno));
|
eleni@4
|
138 return -1;
|
eleni@0
|
139 }
|
eleni@0
|
140 uid = passwd->pw_uid;
|
eleni@4
|
141 if(uid == 0) {
|
eleni@4
|
142 fprintf(stderr, "You should pass an unprivileged username.\n");
|
eleni@4
|
143 return -1;
|
eleni@4
|
144 }
|
eleni@0
|
145 }
|
eleni@0
|
146 else {
|
eleni@4
|
147 fprintf(stderr, "Missing username.\n");
|
eleni@4
|
148 return -1;
|
eleni@0
|
149 }
|
eleni@0
|
150 }
|
eleni@4
|
151 else if((strcmp(argv[i], "-d") == 0)) {
|
eleni@4
|
152 if(argv[++i]) {
|
eleni@4
|
153 dev_path = argv[i];
|
eleni@0
|
154 }
|
eleni@0
|
155 else {
|
eleni@0
|
156 fprintf(stderr, "Invalid device file.\n");
|
eleni@4
|
157 return -1;
|
eleni@0
|
158 }
|
eleni@0
|
159 }
|
eleni@4
|
160 else {
|
eleni@4
|
161 fprintf(stderr, "Unknown argument: %s\n", argv[i]);
|
eleni@4
|
162 return -1;
|
eleni@4
|
163 }
|
eleni@0
|
164 }
|
eleni@0
|
165 return 0;
|
eleni@0
|
166 }
|
eleni@0
|
167
|
eleni@0
|
168 static void print_help()
|
eleni@0
|
169 {
|
eleni@0
|
170 printf("Options:\n");
|
eleni@0
|
171 printf("-h, prints this help\n");
|
eleni@0
|
172 printf("-d, path to the device\n");
|
eleni@0
|
173 printf("-p, path to the mp3 player\n");
|
eleni@0
|
174 printf("-u. username of the user that runs the program\n");
|
eleni@0
|
175 printf("--------\n");
|
eleni@0
|
176 printf("Examples:\n");
|
eleni@0
|
177 printf("--------\n");
|
eleni@0
|
178 printf("./dtms -d /dev/usb/hiddev0 -u eleni -p /usr/bin/mpv\n");
|
eleni@0
|
179 }
|
eleni@0
|
180
|
eleni@4
|
181 static int check_device(char *device_path)
|
eleni@0
|
182 {
|
eleni@0
|
183 struct stat sb;
|
eleni@0
|
184 if(stat(dev_path, &sb) == -1) {
|
eleni@0
|
185 perror("stat");
|
eleni@4
|
186 return -1;
|
eleni@0
|
187 }
|
eleni@0
|
188 if(((sb.st_mode & S_IFMT) != S_IFBLK) && ((sb.st_mode & S_IFMT) != S_IFCHR)) {
|
eleni@4
|
189 fprintf(stderr, "%s is not a device file.\n", device_path);
|
eleni@4
|
190 return -1;
|
eleni@0
|
191 }
|
eleni@4
|
192 return 0;
|
eleni@0
|
193 }
|