uxser.c 13 KB

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