tdebase
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

main.cpp 22KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838
  1. /*
  2. Copyright 2010 Adam Marchetti
  3. Copyright 2011-2013 Timothy Pearson <kb9vqf@pearsoncomputing.net>
  4. This file is part of tsak, the TDE Secure Attention Key daemon
  5. tsak is free software: you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as
  7. published by the Free Software Foundation, either version 3
  8. of the License, or (at your option) any later version.
  9. tsak is distributed in the hope that it will be useful, but
  10. WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public
  14. License along with tsak. If not, see http://www.gnu.org/licenses/.
  15. */
  16. #include <stdio.h>
  17. #include <stdlib.h>
  18. #include <exception>
  19. #include <string.h>
  20. #include <unistd.h>
  21. #include <errno.h>
  22. #include <fcntl.h>
  23. #include <limits.h>
  24. #include <dirent.h>
  25. #include <linux/input.h>
  26. #include <linux/uinput.h>
  27. #include <sys/types.h>
  28. #include <sys/stat.h>
  29. #include <sys/select.h>
  30. #include <sys/time.h>
  31. #include <sys/wait.h>
  32. #include <termios.h>
  33. #include <signal.h>
  34. extern "C" {
  35. #include <libudev.h>
  36. }
  37. #include <libgen.h>
  38. using namespace std;
  39. #define FIFO_DIR "/tmp/tdesocket-global"
  40. #define FIFO_FILE_OUT "/tmp/tdesocket-global/tsak"
  41. #define FIFO_LOCKFILE_OUT "/tmp/tdesocket-global/tsak.lock"
  42. // WARNING
  43. // MAX_KEYBOARDS must be greater than or equal to MAX_INPUT_NODE
  44. #define MAX_KEYBOARDS 128
  45. #define MAX_INPUT_NODE 128
  46. #define TestBit(bit, array) (array[(bit) / 8] & (1 << ((bit) % 8)))
  47. typedef unsigned char byte;
  48. bool mPipeOpen_out = false;
  49. int mPipe_fd_out = -1;
  50. int mPipe_lockfd_out = -1;
  51. char filename[32];
  52. char key_bitmask[(KEY_MAX + 7) / 8];
  53. struct sigaction usr_action;
  54. sigset_t block_mask;
  55. int keyboard_fd_num;
  56. int keyboard_fds[MAX_KEYBOARDS];
  57. int child_pids[MAX_KEYBOARDS];
  58. int child_led_pids[MAX_KEYBOARDS];
  59. int current_keyboard = -1;
  60. int devout[MAX_KEYBOARDS];
  61. const char *keycode[256] =
  62. {
  63. "", "<esc>", "1", "2", "3", "4", "5", "6", "7", "8",
  64. "9", "0", "−", "=", "<backspace>", "<tab>", "q", "w", "e", "r",
  65. "t", "y", "u", "i", "o", "p", "[", "]", "\n", "<control>",
  66. "a", "s", "d", "f", "g", "h", "j", "k", "l", ";",
  67. "'", "", "<shift>", "\\", "z", "x", "c", "v", "b", "n",
  68. "m", ",", ".", "/", "<shift>", "", "<alt>", " ", "<capslock>",
  69. "<f1>", "<f2>", "<f3>", "<f4>", "<f5>", "<f6>", "<f7>", "<f8>", "<f9>", "<f10>",
  70. "<numlock>", "<scrolllock>", "", "", "", "", "", "", "", "",
  71. "", "", "\\", "f11", "f12", "", "", "", "", "",
  72. "", "", "", "<control>", "", "<sysrq>", "", "", "<control>", "", "",
  73. "<alt>", "", "", "", "", "", "", "", "", "",
  74. "", "<del>", "", "", "", "", "", "", "", "",
  75. "", "", "", "", "", "", "", "", "", "",
  76. "", "", "", "", "", "", "", "", "", "",
  77. "", "", "", "", "", "", "", "", "", "",
  78. "", "", "", "", "", "", "", "", "", "",
  79. "", "", "", "", "", "", "", "", "", "",
  80. "", "", "", "", "", "", "", "", "", "",
  81. "", "", "", "", "", "", "", "", "", "",
  82. "", "", "", "", "", "", "", "", "", ""
  83. };
  84. /* returns 1 if bit number i is set, otherwise returns 0 */
  85. int bit_set(size_t i, const byte* a)
  86. {
  87. return a[i/CHAR_BIT] & (1 << i%CHAR_BIT);
  88. }
  89. /* exception handling */
  90. struct exit_exception {
  91. int c;
  92. exit_exception(int c):c(c) { }
  93. };
  94. /* signal handler */
  95. void signal_callback_handler(int signum)
  96. {
  97. // Terminate program
  98. throw exit_exception(signum);
  99. }
  100. /* termination handler */
  101. void tsak_friendly_termination() {
  102. int i;
  103. if ((current_keyboard >= 0) && (devout[current_keyboard] > 0)) {
  104. if (ioctl(devout[current_keyboard],UI_DEV_DESTROY)<0) {
  105. fprintf(stderr, "[tsak] Unable to destroy input device with UI_DEV_DESTROY\n");
  106. }
  107. else {
  108. fprintf(stderr, "[tsak] Device destroyed\n");
  109. }
  110. }
  111. // Close down all child processes
  112. for (i=0; i<MAX_KEYBOARDS; i++) {
  113. if (child_pids[i] != 0) {
  114. kill(child_pids[i], SIGTERM);
  115. }
  116. if (child_led_pids[i] != 0) {
  117. kill(child_led_pids[i], SIGTERM);
  118. }
  119. }
  120. // Wait for process termination
  121. sleep(1);
  122. fprintf(stderr, "[tsak] tsak terminated by external request\n");
  123. exit(17);
  124. }
  125. // --------------------------------------------------------------------------------------
  126. // Useful function from Stack Overflow
  127. // http://stackoverflow.com/questions/874134/find-if-string-endswith-another-string-in-c
  128. // --------------------------------------------------------------------------------------
  129. /* returns 1 iff str ends with suffix */
  130. int str_ends_with(const char * str, const char * suffix) {
  131. if( str == NULL || suffix == NULL )
  132. return 0;
  133. size_t str_len = strlen(str);
  134. size_t suffix_len = strlen(suffix);
  135. if(suffix_len > str_len)
  136. return 0;
  137. return 0 == strncmp( str + str_len - suffix_len, suffix, suffix_len );
  138. }
  139. // --------------------------------------------------------------------------------------
  140. /*
  141. * Set a file descriptor to blocking or non-blocking mode.
  142. *
  143. * @param fd The file descriptor
  144. * @param blocking 0:non-blocking mode, 1:blocking mode
  145. *
  146. * @return 1:success, 0:failure.
  147. */
  148. int fd_set_blocking(int fd, int blocking)
  149. {
  150. /* Save the current flags */
  151. int flags = fcntl(fd, F_GETFL, 0);
  152. if (flags == -1) {
  153. return 0;
  154. }
  155. if (blocking) {
  156. flags &= ~O_NONBLOCK;
  157. }
  158. else {
  159. flags |= O_NONBLOCK;
  160. }
  161. return fcntl(fd, F_SETFL, flags) != -1;
  162. }
  163. /* Assign features (supported axes and keys) of the physical input device (devin)
  164. * to the virtual input device (devout) */
  165. static void copy_features(int devin, int devout)
  166. {
  167. byte evtypes[EV_MAX/CHAR_BIT + 1] = {0};
  168. byte codes[KEY_MAX/CHAR_BIT + 1];
  169. unsigned i,code;
  170. int op;
  171. if (ioctl(devin, EVIOCGBIT(0, sizeof(evtypes)), evtypes) < 0) return;
  172. for(i=0;i<EV_MAX;++i) {
  173. if (bit_set(i, evtypes)) {
  174. switch(i) {
  175. case EV_KEY: op = UI_SET_KEYBIT; break;
  176. case EV_REL: op = UI_SET_RELBIT; break;
  177. case EV_ABS: op = UI_SET_ABSBIT; break;
  178. case EV_MSC: op = UI_SET_MSCBIT; break;
  179. case EV_LED: op = UI_SET_LEDBIT; break;
  180. case EV_SND: op = UI_SET_SNDBIT; break;
  181. case EV_SW: op = UI_SET_SWBIT; break;
  182. default: op = -1;
  183. }
  184. }
  185. if (op == -1) continue;
  186. ioctl(devout, UI_SET_EVBIT, i);
  187. memset(codes,0,sizeof(codes));
  188. if (ioctl(devin, EVIOCGBIT(i, sizeof(codes)), codes) >= 0) {
  189. for(code=0;code<KEY_MAX;code++) {
  190. if (bit_set(code, codes)) ioctl(devout, op, code);
  191. }
  192. }
  193. }
  194. }
  195. int find_keyboards() {
  196. int i, j;
  197. int fd;
  198. char name[256] = "Unknown";
  199. keyboard_fd_num = 0;
  200. for (i=0; i<MAX_KEYBOARDS; i++) {
  201. keyboard_fds[i] = 0;
  202. }
  203. for (i=0; i<MAX_INPUT_NODE; i++) {
  204. snprintf(filename, sizeof(filename), "/dev/input/event%d", i);
  205. fd = open(filename, O_RDWR|O_SYNC);
  206. if (fd >= 0) {
  207. ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(key_bitmask)), key_bitmask);
  208. // Ensure that we do not detect our own tsak faked keyboards
  209. ioctl (fd, EVIOCGNAME(sizeof(name)), name);
  210. if (str_ends_with(name, "+tsak") == 0) {
  211. // Do not attempt to use virtual keyboards per Bug 1275
  212. struct input_id input_info;
  213. ioctl (fd, EVIOCGID, &input_info);
  214. if ((input_info.vendor != 0) && (input_info.product != 0)) {
  215. /* We assume that anything that has an alphabetic key in the
  216. QWERTYUIOP range in it is the main keyboard. */
  217. for (j = KEY_Q; j <= KEY_P; j++) {
  218. if (TestBit(j, key_bitmask)) {
  219. keyboard_fds[keyboard_fd_num] = fd;
  220. }
  221. }
  222. }
  223. }
  224. if (keyboard_fds[keyboard_fd_num] == 0) {
  225. close(fd);
  226. }
  227. else {
  228. keyboard_fd_num++;
  229. }
  230. }
  231. }
  232. return 0;
  233. }
  234. void tearDownPipe()
  235. {
  236. if (mPipeOpen_out == true) {
  237. mPipeOpen_out = false;
  238. close(mPipe_fd_out);
  239. unlink(FIFO_FILE_OUT);
  240. }
  241. }
  242. void tearDownLockingPipe()
  243. {
  244. close(mPipe_lockfd_out);
  245. unlink(FIFO_LOCKFILE_OUT);
  246. }
  247. bool setFileLock(int fd, bool close_on_failure)
  248. {
  249. struct flock fl;
  250. fl.l_type = F_WRLCK;
  251. fl.l_whence = SEEK_SET;
  252. fl.l_start = 0;
  253. fl.l_len = 1;
  254. // Set the exclusive file lock
  255. if (fcntl(fd, F_SETLK, &fl) == -1) {
  256. close(fd);
  257. return false;
  258. }
  259. return true;
  260. }
  261. bool checkFileLock()
  262. {
  263. struct flock fl;
  264. fl.l_type = F_WRLCK; /* Test for any lock on any part of file. */
  265. fl.l_start = 0;
  266. fl.l_whence = SEEK_SET;
  267. fl.l_len = 0;
  268. int fd = open(FIFO_LOCKFILE_OUT, O_RDWR | O_NONBLOCK);
  269. fcntl(fd, F_GETLK, &fl); /* Overwrites lock structure with preventors. */
  270. if (fd > -1) {
  271. if (fl.l_type == F_WRLCK) {
  272. return false;
  273. }
  274. return true;
  275. }
  276. return true;
  277. }
  278. bool setupPipe()
  279. {
  280. /* Create the FIFOs if they do not exist */
  281. umask(0);
  282. mkdir(FIFO_DIR,0644);
  283. mknod(FIFO_FILE_OUT, S_IFIFO|0600, 0);
  284. chmod(FIFO_FILE_OUT, 0600);
  285. mPipe_fd_out = open(FIFO_FILE_OUT, O_RDWR | O_NONBLOCK);
  286. if (mPipe_fd_out > -1) {
  287. mPipeOpen_out = true;
  288. }
  289. // Set the exclusive file lock
  290. return setFileLock(mPipe_fd_out, true);
  291. }
  292. bool setupLockingPipe(bool writepid)
  293. {
  294. /* Create the FIFOs as they may not exist */
  295. umask(0);
  296. mkdir(FIFO_DIR,0644);
  297. mknod(FIFO_LOCKFILE_OUT, 0600, 0);
  298. chmod(FIFO_LOCKFILE_OUT, 0600);
  299. mPipe_lockfd_out = open(FIFO_LOCKFILE_OUT, O_RDWR | O_NONBLOCK);
  300. if (mPipe_lockfd_out > -1) {
  301. if (writepid) {
  302. // Write my PID to the file
  303. pid_t tsakpid = getpid();
  304. char pidstring[1024];
  305. sprintf(pidstring, "%d", tsakpid);
  306. write(mPipe_lockfd_out, pidstring, strlen(pidstring));
  307. }
  308. // Set the exclusive file lock
  309. return setFileLock(mPipe_lockfd_out, true);
  310. }
  311. return false;
  312. }
  313. void broadcast_sak()
  314. {
  315. // Let anyone listening to our interface know that an SAK keypress was received
  316. // I highly doubt there are more than 255 VTs active at once...
  317. int i;
  318. for (i=0;i<255;i++) {
  319. if (write(mPipe_fd_out, "SAK\n\r", 6) < 0) {
  320. fprintf(stderr, "[tsak] Unable to send SAK signal to clients\n");
  321. }
  322. }
  323. }
  324. void restart_tsak()
  325. {
  326. int i;
  327. fprintf(stderr, "[tsak] Forcibly terminating...\n");
  328. // Close down all child processes
  329. for (i=0; i<MAX_KEYBOARDS; i++) {
  330. if (child_pids[i] != 0) {
  331. kill(child_pids[i], SIGTERM);
  332. }
  333. if (child_led_pids[i] != 0) {
  334. kill(child_led_pids[i], SIGTERM);
  335. }
  336. }
  337. // Wait for child process termination
  338. for (i=0; i<MAX_KEYBOARDS; i++) {
  339. if (child_pids[i] != 0) {
  340. waitpid(child_pids[i], NULL, 0);
  341. child_pids[i] = 0;
  342. }
  343. if (child_led_pids[i] != 0) {
  344. waitpid(child_led_pids[i], NULL, 0);
  345. child_led_pids[i] = 0;
  346. }
  347. }
  348. // Unset the exclusive file lock
  349. if (mPipe_fd_out != -1) {
  350. struct flock fl;
  351. if (fcntl(mPipe_fd_out, F_UNLCK, &fl) == -1) {
  352. fprintf(stderr, "[tsak] Failed to release exclusive pipe lock\n");
  353. }
  354. close(mPipe_fd_out);
  355. }
  356. #if 1
  357. // Restart now
  358. // Note that the execl function never returns
  359. char me[2048];
  360. int chars = readlink("/proc/self/exe", me, sizeof(me));
  361. me[chars] = 0;
  362. me[2047] = 0;
  363. execl(me, basename(me), (char*)NULL);
  364. #else
  365. _exit(0);
  366. #endif
  367. }
  368. class PipeHandler
  369. {
  370. public:
  371. PipeHandler();
  372. ~PipeHandler();
  373. bool active;
  374. };
  375. PipeHandler::PipeHandler()
  376. {
  377. active = false;
  378. }
  379. PipeHandler::~PipeHandler()
  380. {
  381. if (active) {
  382. tearDownPipe();
  383. tearDownLockingPipe();
  384. }
  385. }
  386. int main (int argc, char *argv[])
  387. {
  388. struct input_event ev[64];
  389. struct input_event event;
  390. struct input_event revev;
  391. struct uinput_user_dev devinfo={{0},{0}};
  392. int rd;
  393. int i;
  394. int size = sizeof (struct input_event);
  395. char name[256] = "Unknown";
  396. bool ctrl_down = false;
  397. bool alt_down = false;
  398. bool hide_event = false;
  399. bool established = false;
  400. bool testrun = false;
  401. bool depcheck = false;
  402. bool can_proceed;
  403. // Ignore SIGPIPE
  404. signal(SIGPIPE, SIG_IGN);
  405. // Register signal handlers
  406. // Register signal and signal handler
  407. signal(SIGINT, signal_callback_handler);
  408. signal(SIGTERM, signal_callback_handler);
  409. set_terminate(tsak_friendly_termination);
  410. try {
  411. for (i=0; i<MAX_KEYBOARDS; i++) {
  412. child_pids[i] = 0;
  413. child_led_pids[i] = 0;
  414. }
  415. if (argc == 2) {
  416. if (strcmp(argv[1], "checkactive") == 0) {
  417. testrun = true;
  418. }
  419. if (strcmp(argv[1], "checkdeps") == 0) {
  420. depcheck = true;
  421. }
  422. }
  423. if (depcheck == false) {
  424. // Check for existing file locks
  425. if (!checkFileLock()) {
  426. fprintf(stderr, "[tsak] Another instance of this program is already running [1]\n");
  427. return 8;
  428. }
  429. if (!setupLockingPipe(true)) {
  430. fprintf(stderr, "[tsak] Another instance of this program is already running [2]\n");
  431. return 8;
  432. }
  433. }
  434. // Create the output pipe
  435. PipeHandler controlpipe;
  436. if (depcheck == false) {
  437. if (!setupPipe()) {
  438. fprintf(stderr, "[tsak] Another instance of this program is already running\n");
  439. return 8;
  440. }
  441. }
  442. if ((testrun == false) && (depcheck == false)) {
  443. // fork to background
  444. int i=fork();
  445. if (i<0) {
  446. return 10; // fork failed
  447. }
  448. if (i>0) {
  449. // Terminate parent
  450. controlpipe.active = false;
  451. return 0;
  452. }
  453. }
  454. while (1) {
  455. if (depcheck == false) {
  456. controlpipe.active = true;
  457. }
  458. if ((getuid ()) != 0) {
  459. printf ("[tsak] You are not root! This WILL NOT WORK!\nDO NOT attempt to bypass security restrictions, e.g. by changing keyboard permissions or owner, if you want the SAK system to remain secure...\n");
  460. return 5;
  461. }
  462. // Find keyboards
  463. find_keyboards();
  464. if (keyboard_fd_num == 0) {
  465. printf ("[tsak] Could not find any usable keyboard(s)!\n");
  466. if (depcheck == true) {
  467. return 50;
  468. }
  469. // Make sure everyone knows we physically can't detect a SAK
  470. // Before we do this we broadcast one so that active dialogs are updated appropriately
  471. // Also, we keep watching for a keyboard to be added via a forked child process...
  472. broadcast_sak();
  473. if (established)
  474. sleep(1);
  475. else {
  476. int i=fork();
  477. if (i<0) {
  478. return 12; // fork failed
  479. }
  480. if (i>0) {
  481. return 4;
  482. }
  483. sleep(1);
  484. restart_tsak();
  485. }
  486. }
  487. else {
  488. fprintf(stderr, "[tsak] Found %d keyboard(s)\n", keyboard_fd_num);
  489. can_proceed = true;
  490. for (current_keyboard=0;current_keyboard<keyboard_fd_num;current_keyboard++) {
  491. // Print Device Name
  492. ioctl (keyboard_fds[current_keyboard], EVIOCGNAME (sizeof (name)), name);
  493. fprintf(stderr, "[tsak] Reading from keyboard: (%s)\n", name);
  494. // Create filtered virtual output device
  495. devout[current_keyboard]=open("/dev/misc/uinput",O_RDWR|O_NONBLOCK);
  496. if (devout[current_keyboard]<0) {
  497. devout[current_keyboard]=open("/dev/uinput",O_RDWR|O_NONBLOCK);
  498. if (devout[current_keyboard]<0) {
  499. perror("open(\"/dev/misc/uinput\")");
  500. }
  501. }
  502. if (devout[current_keyboard]<0) {
  503. can_proceed = false;
  504. fprintf(stderr, "[tsak] Unable to open /dev/uinput or /dev/misc/uinput (char device 10:223).\nPossible causes:\n 1) Device node does not exist\n 2) Kernel not compiled with evdev [INPUT_EVDEV] and uinput [INPUT_UINPUT] user level driver support\n 3) Permission denied.\n");
  505. perror("open(\"/dev/uinput\")");
  506. if (established)
  507. sleep(1);
  508. else
  509. return 3;
  510. }
  511. fd_set_blocking(devout[current_keyboard], true);
  512. }
  513. if (depcheck == true) {
  514. return 0;
  515. }
  516. if (can_proceed == true) {
  517. for (current_keyboard=0;current_keyboard<keyboard_fd_num;current_keyboard++) {
  518. if(ioctl(keyboard_fds[current_keyboard], EVIOCGRAB, 2) < 0) {
  519. close(keyboard_fds[current_keyboard]);
  520. fprintf(stderr, "[tsak] Failed to grab exclusive input device lock\n");
  521. if (established) {
  522. sleep(1);
  523. }
  524. else {
  525. return 1;
  526. }
  527. }
  528. else {
  529. ioctl(keyboard_fds[current_keyboard], EVIOCGNAME(UINPUT_MAX_NAME_SIZE), devinfo.name);
  530. strncat(devinfo.name, "+tsak", UINPUT_MAX_NAME_SIZE-1);
  531. fprintf(stderr, "[tsak] %s\n", devinfo.name);
  532. ioctl(keyboard_fds[current_keyboard], EVIOCGID, &devinfo.id);
  533. copy_features(keyboard_fds[current_keyboard], devout[current_keyboard]);
  534. if (write(devout[current_keyboard],&devinfo,sizeof(devinfo)) < 0) {
  535. fprintf(stderr, "[tsak] Unable to write to output device\n");
  536. }
  537. if (ioctl(devout[current_keyboard],UI_DEV_CREATE)<0) {
  538. fprintf(stderr, "[tsak] Unable to create input device with UI_DEV_CREATE\n");
  539. if (established) {
  540. sleep(1);
  541. }
  542. else {
  543. return 2;
  544. }
  545. }
  546. else {
  547. fprintf(stderr, "[tsak] Device created.\n");
  548. if (established == false) {
  549. int i=fork();
  550. if (i<0) return 9; // fork failed
  551. if (i>0) {
  552. child_pids[current_keyboard] = i;
  553. int i=fork();
  554. if (i<0) return 9; // fork failed
  555. if (i>0) {
  556. child_led_pids[current_keyboard] = i;
  557. continue;
  558. }
  559. if (testrun == true) {
  560. return 0;
  561. }
  562. while (1) {
  563. // Replicate LED events from the virtual keyboard to the physical keyboard
  564. int rrd = read(devout[current_keyboard], &revev, size);
  565. if (rrd >= size) {
  566. if ((revev.type == EV_LED) || (revev.type == EV_MSC)) {
  567. if (write(keyboard_fds[current_keyboard], &revev, sizeof(revev)) < 0) {
  568. fprintf(stderr, "[tsak] Unable to replicate LED event\n");
  569. }
  570. }
  571. }
  572. }
  573. return 0;
  574. }
  575. setupLockingPipe(false);
  576. }
  577. established = true;
  578. if (testrun == true) {
  579. return 0;
  580. }
  581. while (1) {
  582. if ((rd = read(keyboard_fds[current_keyboard], ev, size)) < size) {
  583. fprintf(stderr, "[tsak] Read failed.\n");
  584. if (ioctl(devout[current_keyboard],UI_DEV_DESTROY)<0) {
  585. fprintf(stderr, "[tsak] Unable to destroy input device with UI_DEV_DESTROY\n");
  586. return 13;
  587. }
  588. else {
  589. fprintf(stderr, "[tsak] Device destroyed.\n");
  590. }
  591. return 14;
  592. }
  593. if (ev[0].value == 0 && ev[0].type == 1) { // Read the key release event
  594. if (keycode[(ev[0].code)]) {
  595. if (strcmp(keycode[(ev[0].code)], "<control>") == 0) ctrl_down = false;
  596. if (strcmp(keycode[(ev[0].code)], "<alt>") == 0) alt_down = false;
  597. }
  598. }
  599. if (ev[0].value == 1 && ev[0].type == 1) { // Read the key press event
  600. if (keycode[(ev[0].code)]) {
  601. if (strcmp(keycode[(ev[0].code)], "<control>") == 0) ctrl_down = true;
  602. if (strcmp(keycode[(ev[0].code)], "<alt>") == 0) alt_down = true;
  603. }
  604. }
  605. hide_event = false;
  606. if (ev[0].value == 1 && ev[0].type == 1) { // Read the key press event
  607. if (keycode[(ev[0].code)]) {
  608. if (alt_down && ctrl_down && (strcmp(keycode[(ev[0].code)], "<del>") == 0)) {
  609. hide_event = true;
  610. }
  611. }
  612. }
  613. if ((hide_event == false) && (ev[0].type != EV_LED) && (ev[0].type != EV_MSC)) {
  614. // Pass the event on...
  615. event = ev[0];
  616. if (write(devout[current_keyboard], &event, sizeof(event)) < 0) {
  617. fprintf(stderr, "[tsak] Unable to replicate keyboard event!\n");
  618. }
  619. }
  620. if (hide_event == true) {
  621. // Let anyone listening to our interface know that an SAK keypress was received
  622. broadcast_sak();
  623. }
  624. }
  625. }
  626. }
  627. }
  628. // Close all keyboard file descriptors; we don't need them in this process and they can end up dangling/locked during forced restart
  629. for (int current_keyboard=0;current_keyboard<keyboard_fd_num;current_keyboard++) {
  630. close(keyboard_fds[current_keyboard]);
  631. keyboard_fds[current_keyboard] = 0;
  632. }
  633. keyboard_fd_num = 0;
  634. if (testrun == true) {
  635. return 0;
  636. }
  637. // Prevent multiple process instances from starting
  638. setupLockingPipe(true);
  639. // Wait a little bit so that udev hotplug can stabilize before we start monitoring
  640. sleep(1);
  641. fprintf(stderr, "[tsak] Hotplug monitoring process started\n");
  642. // Monitor for hotplugged keyboards
  643. int j;
  644. int hotplug_fd;
  645. bool is_new_keyboard;
  646. struct udev *udev;
  647. struct udev_device *dev;
  648. struct udev_monitor *mon;
  649. // Create the udev object
  650. udev = udev_new();
  651. if (!udev) {
  652. fprintf(stderr, "[tsak] Cannot connect to udev interface\n");
  653. return 11;
  654. }
  655. // Set up a udev monitor to monitor input devices
  656. mon = udev_monitor_new_from_netlink(udev, "udev");
  657. udev_monitor_filter_add_match_subsystem_devtype(mon, "input", NULL);
  658. udev_monitor_enable_receiving(mon);
  659. while (1) {
  660. // Watch for input from the monitoring process
  661. fd_set readfds;
  662. FD_ZERO(&readfds);
  663. FD_SET(udev_monitor_get_fd(mon), &readfds);
  664. int fdcount = select(udev_monitor_get_fd(mon)+1, &readfds, NULL, NULL, NULL);
  665. if (fdcount < 0) {
  666. if (errno == EINTR) {
  667. fprintf(stderr, "[tsak] Signal caught in hotplug monitoring process; ignoring\n");
  668. }
  669. else {
  670. fprintf(stderr, "[tsak] Select failed on udev file descriptor in hotplug monitoring process\n");
  671. }
  672. usleep(1000);
  673. continue;
  674. }
  675. dev = udev_monitor_receive_device(mon);
  676. if (dev) {
  677. // If a keyboard was removed we need to restart...
  678. if (strcmp(udev_device_get_action(dev), "remove") == 0) {
  679. udev_device_unref(dev);
  680. udev_unref(udev);
  681. restart_tsak();
  682. }
  683. is_new_keyboard = false;
  684. snprintf(filename,sizeof(filename), "%s", udev_device_get_devnode(dev));
  685. udev_device_unref(dev);
  686. // Print name of keyboard
  687. hotplug_fd = open(filename, O_RDWR|O_SYNC);
  688. ioctl(hotplug_fd, EVIOCGBIT(EV_KEY, sizeof(key_bitmask)), key_bitmask);
  689. /* We assume that anything that has an alphabetic key in the
  690. QWERTYUIOP range in it is the main keyboard. */
  691. for (j = KEY_Q; j <= KEY_P; j++) {
  692. if (TestBit(j, key_bitmask)) {
  693. is_new_keyboard = true;
  694. }
  695. }
  696. ioctl (hotplug_fd, EVIOCGNAME (sizeof (name)), name);
  697. close(hotplug_fd);
  698. // Ensure that we do not detect our own tsak faked keyboards
  699. if (str_ends_with(name, "+tsak") == 1) {
  700. is_new_keyboard = false;
  701. }
  702. // If a keyboard was added we need to restart...
  703. if (is_new_keyboard == true) {
  704. fprintf(stderr, "[tsak] Hotplugged new keyboard: (%s)\n", name);
  705. udev_unref(udev);
  706. restart_tsak();
  707. }
  708. }
  709. else {
  710. fprintf(stderr, "[tsak] No device from receive_device(). A udev error has occurred; terminating hotplug monitoring process.\n");
  711. return 12;
  712. }
  713. }
  714. udev_unref(udev);
  715. fprintf(stderr, "[tsak] Hotplug monitoring process terminated\n");
  716. }
  717. }
  718. }
  719. }
  720. catch(exit_exception& e) {
  721. tsak_friendly_termination();
  722. }
  723. return 6;
  724. }