uxser.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599
  1. /*
  2. * Serial back end (Unix-specific).
  3. */
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <assert.h>
  7. #include <limits.h>
  8. #include <errno.h>
  9. #include <unistd.h>
  10. #include <fcntl.h>
  11. #include <termios.h>
  12. #include "putty.h"
  13. #include "tree234.h"
  14. #define SERIAL_MAX_BACKLOG 4096
  15. typedef struct serial_backend_data {
  16. void *frontend;
  17. int fd;
  18. int finished;
  19. int inbufsize;
  20. bufchain output_data;
  21. } *Serial;
  22. /*
  23. * We store our serial backends in a tree sorted by fd, so that
  24. * when we get an uxsel notification we know which backend instance
  25. * is the owner of the serial port that caused it.
  26. */
  27. static int serial_compare_by_fd(void *av, void *bv)
  28. {
  29. Serial a = (Serial)av;
  30. Serial b = (Serial)bv;
  31. if (a->fd < b->fd)
  32. return -1;
  33. else if (a->fd > b->fd)
  34. return +1;
  35. return 0;
  36. }
  37. static int serial_find_by_fd(void *av, void *bv)
  38. {
  39. int a = *(int *)av;
  40. Serial b = (Serial)bv;
  41. if (a < b->fd)
  42. return -1;
  43. else if (a > b->fd)
  44. return +1;
  45. return 0;
  46. }
  47. static tree234 *serial_by_fd = NULL;
  48. static int serial_select_result(int fd, int event);
  49. static void serial_uxsel_setup(Serial serial);
  50. static void serial_try_write(Serial serial);
  51. static const char *serial_configure(Serial serial, Conf *conf)
  52. {
  53. struct termios options;
  54. int bflag, bval, speed, flow, parity;
  55. const char *str;
  56. char *msg;
  57. if (serial->fd < 0)
  58. return "Unable to reconfigure already-closed serial connection";
  59. tcgetattr(serial->fd, &options);
  60. /*
  61. * Find the appropriate baud rate flag.
  62. */
  63. speed = conf_get_int(conf, CONF_serspeed);
  64. #define SETBAUD(x) (bflag = B ## x, bval = x)
  65. #define CHECKBAUD(x) do { if (speed >= x) SETBAUD(x); } while (0)
  66. SETBAUD(50);
  67. #ifdef B75
  68. CHECKBAUD(75);
  69. #endif
  70. #ifdef B110
  71. CHECKBAUD(110);
  72. #endif
  73. #ifdef B134
  74. CHECKBAUD(134);
  75. #endif
  76. #ifdef B150
  77. CHECKBAUD(150);
  78. #endif
  79. #ifdef B200
  80. CHECKBAUD(200);
  81. #endif
  82. #ifdef B300
  83. CHECKBAUD(300);
  84. #endif
  85. #ifdef B600
  86. CHECKBAUD(600);
  87. #endif
  88. #ifdef B1200
  89. CHECKBAUD(1200);
  90. #endif
  91. #ifdef B1800
  92. CHECKBAUD(1800);
  93. #endif
  94. #ifdef B2400
  95. CHECKBAUD(2400);
  96. #endif
  97. #ifdef B4800
  98. CHECKBAUD(4800);
  99. #endif
  100. #ifdef B9600
  101. CHECKBAUD(9600);
  102. #endif
  103. #ifdef B19200
  104. CHECKBAUD(19200);
  105. #endif
  106. #ifdef B38400
  107. CHECKBAUD(38400);
  108. #endif
  109. #ifdef B57600
  110. CHECKBAUD(57600);
  111. #endif
  112. #ifdef B76800
  113. CHECKBAUD(76800);
  114. #endif
  115. #ifdef B115200
  116. CHECKBAUD(115200);
  117. #endif
  118. #ifdef B153600
  119. CHECKBAUD(153600);
  120. #endif
  121. #ifdef B230400
  122. CHECKBAUD(230400);
  123. #endif
  124. #ifdef B307200
  125. CHECKBAUD(307200);
  126. #endif
  127. #ifdef B460800
  128. CHECKBAUD(460800);
  129. #endif
  130. #ifdef B500000
  131. CHECKBAUD(500000);
  132. #endif
  133. #ifdef B576000
  134. CHECKBAUD(576000);
  135. #endif
  136. #ifdef B921600
  137. CHECKBAUD(921600);
  138. #endif
  139. #ifdef B1000000
  140. CHECKBAUD(1000000);
  141. #endif
  142. #ifdef B1152000
  143. CHECKBAUD(1152000);
  144. #endif
  145. #ifdef B1500000
  146. CHECKBAUD(1500000);
  147. #endif
  148. #ifdef B2000000
  149. CHECKBAUD(2000000);
  150. #endif
  151. #ifdef B2500000
  152. CHECKBAUD(2500000);
  153. #endif
  154. #ifdef B3000000
  155. CHECKBAUD(3000000);
  156. #endif
  157. #ifdef B3500000
  158. CHECKBAUD(3500000);
  159. #endif
  160. #ifdef B4000000
  161. CHECKBAUD(4000000);
  162. #endif
  163. #undef CHECKBAUD
  164. #undef SETBAUD
  165. cfsetispeed(&options, bflag);
  166. cfsetospeed(&options, bflag);
  167. msg = dupprintf("Configuring baud rate %d", bval);
  168. logevent(serial->frontend, msg);
  169. sfree(msg);
  170. options.c_cflag &= ~CSIZE;
  171. switch (conf_get_int(conf, CONF_serdatabits)) {
  172. case 5: options.c_cflag |= CS5; break;
  173. case 6: options.c_cflag |= CS6; break;
  174. case 7: options.c_cflag |= CS7; break;
  175. case 8: options.c_cflag |= CS8; break;
  176. default: return "Invalid number of data bits (need 5, 6, 7 or 8)";
  177. }
  178. msg = dupprintf("Configuring %d data bits",
  179. conf_get_int(conf, CONF_serdatabits));
  180. logevent(serial->frontend, msg);
  181. sfree(msg);
  182. if (conf_get_int(conf, CONF_serstopbits) >= 4) {
  183. options.c_cflag |= CSTOPB;
  184. } else {
  185. options.c_cflag &= ~CSTOPB;
  186. }
  187. msg = dupprintf("Configuring %d stop bits",
  188. (options.c_cflag & CSTOPB ? 2 : 1));
  189. logevent(serial->frontend, msg);
  190. sfree(msg);
  191. options.c_iflag &= ~(IXON|IXOFF);
  192. #ifdef CRTSCTS
  193. options.c_cflag &= ~CRTSCTS;
  194. #endif
  195. #ifdef CNEW_RTSCTS
  196. options.c_cflag &= ~CNEW_RTSCTS;
  197. #endif
  198. flow = conf_get_int(conf, CONF_serflow);
  199. if (flow == SER_FLOW_XONXOFF) {
  200. options.c_iflag |= IXON | IXOFF;
  201. str = "XON/XOFF";
  202. } else if (flow == SER_FLOW_RTSCTS) {
  203. #ifdef CRTSCTS
  204. options.c_cflag |= CRTSCTS;
  205. #endif
  206. #ifdef CNEW_RTSCTS
  207. options.c_cflag |= CNEW_RTSCTS;
  208. #endif
  209. str = "RTS/CTS";
  210. } else
  211. str = "no";
  212. msg = dupprintf("Configuring %s flow control", str);
  213. logevent(serial->frontend, msg);
  214. sfree(msg);
  215. /* Parity */
  216. parity = conf_get_int(conf, CONF_serparity);
  217. if (parity == SER_PAR_ODD) {
  218. options.c_cflag |= PARENB;
  219. options.c_cflag |= PARODD;
  220. str = "odd";
  221. } else if (parity == SER_PAR_EVEN) {
  222. options.c_cflag |= PARENB;
  223. options.c_cflag &= ~PARODD;
  224. str = "even";
  225. } else {
  226. options.c_cflag &= ~PARENB;
  227. str = "no";
  228. }
  229. msg = dupprintf("Configuring %s parity", str);
  230. logevent(serial->frontend, msg);
  231. sfree(msg);
  232. options.c_cflag |= CLOCAL | CREAD;
  233. options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
  234. options.c_iflag &= ~(ISTRIP | IGNCR | INLCR | ICRNL
  235. #ifdef IUCLC
  236. | IUCLC
  237. #endif
  238. );
  239. options.c_oflag &= ~(OPOST
  240. #ifdef ONLCR
  241. | ONLCR
  242. #endif
  243. #ifdef OCRNL
  244. | OCRNL
  245. #endif
  246. #ifdef ONOCR
  247. | ONOCR
  248. #endif
  249. #ifdef ONLRET
  250. | ONLRET
  251. #endif
  252. );
  253. options.c_cc[VMIN] = 1;
  254. options.c_cc[VTIME] = 0;
  255. if (tcsetattr(serial->fd, TCSANOW, &options) < 0)
  256. return "Unable to configure serial port";
  257. return NULL;
  258. }
  259. /*
  260. * Called to set up the serial connection.
  261. *
  262. * Returns an error message, or NULL on success.
  263. *
  264. * Also places the canonical host name into `realhost'. It must be
  265. * freed by the caller.
  266. */
  267. static const char *serial_init(void *frontend_handle, void **backend_handle,
  268. Conf *conf,
  269. const char *host, int port, char **realhost,
  270. int nodelay, int keepalive)
  271. {
  272. Serial serial;
  273. const char *err;
  274. char *line;
  275. serial = snew(struct serial_backend_data);
  276. *backend_handle = serial;
  277. serial->frontend = frontend_handle;
  278. serial->finished = FALSE;
  279. serial->inbufsize = 0;
  280. bufchain_init(&serial->output_data);
  281. line = conf_get_str(conf, CONF_serline);
  282. {
  283. char *msg = dupprintf("Opening serial device %s", line);
  284. logevent(serial->frontend, msg);
  285. sfree(msg);
  286. }
  287. serial->fd = open(line, O_RDWR | O_NOCTTY | O_NDELAY | O_NONBLOCK);
  288. if (serial->fd < 0)
  289. return "Unable to open serial port";
  290. cloexec(serial->fd);
  291. err = serial_configure(serial, conf);
  292. if (err)
  293. return err;
  294. *realhost = dupstr(line);
  295. if (!serial_by_fd)
  296. serial_by_fd = newtree234(serial_compare_by_fd);
  297. add234(serial_by_fd, serial);
  298. serial_uxsel_setup(serial);
  299. /*
  300. * Specials are always available.
  301. */
  302. update_specials_menu(serial->frontend);
  303. return NULL;
  304. }
  305. static void serial_close(Serial serial)
  306. {
  307. if (serial->fd >= 0) {
  308. close(serial->fd);
  309. serial->fd = -1;
  310. }
  311. }
  312. static void serial_free(void *handle)
  313. {
  314. Serial serial = (Serial) handle;
  315. serial_close(serial);
  316. bufchain_clear(&serial->output_data);
  317. sfree(serial);
  318. }
  319. static void serial_reconfig(void *handle, Conf *conf)
  320. {
  321. Serial serial = (Serial) handle;
  322. /*
  323. * FIXME: what should we do if this returns an error?
  324. */
  325. serial_configure(serial, conf);
  326. }
  327. static int serial_select_result(int fd, int event)
  328. {
  329. Serial serial;
  330. char buf[4096];
  331. int ret;
  332. int finished = FALSE;
  333. serial = find234(serial_by_fd, &fd, serial_find_by_fd);
  334. if (!serial)
  335. return 1; /* spurious event; keep going */
  336. if (event == 1) {
  337. ret = read(serial->fd, buf, sizeof(buf));
  338. if (ret == 0) {
  339. /*
  340. * Shouldn't happen on a real serial port, but I'm open
  341. * to the idea that there might be two-way devices we
  342. * can treat _like_ serial ports which can return EOF.
  343. */
  344. finished = TRUE;
  345. } else if (ret < 0) {
  346. #ifdef EAGAIN
  347. if (errno == EAGAIN)
  348. return 1; /* spurious */
  349. #endif
  350. #ifdef EWOULDBLOCK
  351. if (errno == EWOULDBLOCK)
  352. return 1; /* spurious */
  353. #endif
  354. perror("read serial port");
  355. exit(1);
  356. } else if (ret > 0) {
  357. serial->inbufsize = from_backend(serial->frontend, 0, buf, ret);
  358. serial_uxsel_setup(serial); /* might acquire backlog and freeze */
  359. }
  360. } else if (event == 2) {
  361. /*
  362. * Attempt to send data down the pty.
  363. */
  364. serial_try_write(serial);
  365. }
  366. if (finished) {
  367. serial_close(serial);
  368. serial->finished = TRUE;
  369. notify_remote_exit(serial->frontend);
  370. }
  371. return !finished;
  372. }
  373. static void serial_uxsel_setup(Serial serial)
  374. {
  375. int rwx = 0;
  376. if (serial->inbufsize <= SERIAL_MAX_BACKLOG)
  377. rwx |= 1;
  378. if (bufchain_size(&serial->output_data))
  379. rwx |= 2; /* might also want to write to it */
  380. uxsel_set(serial->fd, rwx, serial_select_result);
  381. }
  382. static void serial_try_write(Serial serial)
  383. {
  384. void *data;
  385. int len, ret;
  386. assert(serial->fd >= 0);
  387. while (bufchain_size(&serial->output_data) > 0) {
  388. bufchain_prefix(&serial->output_data, &data, &len);
  389. ret = write(serial->fd, data, len);
  390. if (ret < 0 && (errno == EWOULDBLOCK)) {
  391. /*
  392. * We've sent all we can for the moment.
  393. */
  394. break;
  395. }
  396. if (ret < 0) {
  397. perror("write serial port");
  398. exit(1);
  399. }
  400. bufchain_consume(&serial->output_data, ret);
  401. }
  402. serial_uxsel_setup(serial);
  403. }
  404. /*
  405. * Called to send data down the serial connection.
  406. */
  407. static int serial_send(void *handle, const char *buf, int len)
  408. {
  409. Serial serial = (Serial) handle;
  410. if (serial->fd < 0)
  411. return 0;
  412. bufchain_add(&serial->output_data, buf, len);
  413. serial_try_write(serial);
  414. return bufchain_size(&serial->output_data);
  415. }
  416. /*
  417. * Called to query the current sendability status.
  418. */
  419. static int serial_sendbuffer(void *handle)
  420. {
  421. Serial serial = (Serial) handle;
  422. return bufchain_size(&serial->output_data);
  423. }
  424. /*
  425. * Called to set the size of the window
  426. */
  427. static void serial_size(void *handle, int width, int height)
  428. {
  429. /* Do nothing! */
  430. return;
  431. }
  432. /*
  433. * Send serial special codes.
  434. */
  435. static void serial_special(void *handle, Telnet_Special code)
  436. {
  437. Serial serial = (Serial) handle;
  438. if (serial->fd >= 0 && code == TS_BRK) {
  439. tcsendbreak(serial->fd, 0);
  440. logevent(serial->frontend, "Sending serial break at user request");
  441. }
  442. return;
  443. }
  444. /*
  445. * Return a list of the special codes that make sense in this
  446. * protocol.
  447. */
  448. static const struct telnet_special *serial_get_specials(void *handle)
  449. {
  450. static const struct telnet_special specials[] = {
  451. {"Break", TS_BRK},
  452. {NULL, TS_EXITMENU}
  453. };
  454. return specials;
  455. }
  456. static int serial_connected(void *handle)
  457. {
  458. return 1; /* always connected */
  459. }
  460. static int serial_sendok(void *handle)
  461. {
  462. return 1;
  463. }
  464. static void serial_unthrottle(void *handle, int backlog)
  465. {
  466. Serial serial = (Serial) handle;
  467. serial->inbufsize = backlog;
  468. serial_uxsel_setup(serial);
  469. }
  470. static int serial_ldisc(void *handle, int option)
  471. {
  472. /*
  473. * Local editing and local echo are off by default.
  474. */
  475. return 0;
  476. }
  477. static void serial_provide_ldisc(void *handle, void *ldisc)
  478. {
  479. /* This is a stub. */
  480. }
  481. static void serial_provide_logctx(void *handle, void *logctx)
  482. {
  483. /* This is a stub. */
  484. }
  485. static int serial_exitcode(void *handle)
  486. {
  487. Serial serial = (Serial) handle;
  488. if (serial->fd >= 0)
  489. return -1; /* still connected */
  490. else
  491. /* Exit codes are a meaningless concept with serial ports */
  492. return INT_MAX;
  493. }
  494. /*
  495. * cfg_info for Serial does nothing at all.
  496. */
  497. static int serial_cfg_info(void *handle)
  498. {
  499. return 0;
  500. }
  501. Backend serial_backend = {
  502. serial_init,
  503. serial_free,
  504. serial_reconfig,
  505. serial_send,
  506. serial_sendbuffer,
  507. serial_size,
  508. serial_special,
  509. serial_get_specials,
  510. serial_connected,
  511. serial_exitcode,
  512. serial_sendok,
  513. serial_ldisc,
  514. serial_provide_ldisc,
  515. serial_provide_logctx,
  516. serial_unthrottle,
  517. serial_cfg_info,
  518. NULL /* test_for_upstream */,
  519. "serial",
  520. PROT_SERIAL,
  521. 0
  522. };