1
0

termios.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732
  1. /*++
  2. Copyright (c) 2013 Minoca Corp.
  3. This file is licensed under the terms of the GNU General Public License
  4. version 3. Alternative licensing terms are available. Contact
  5. info@minocacorp.com for details. See the LICENSE file at the root of this
  6. project for complete licensing information.
  7. Module Name:
  8. termios.c
  9. Abstract:
  10. This module implements terminal support.
  11. Author:
  12. Evan Green 23-Jun-2013
  13. Environment:
  14. User Mode C Library
  15. --*/
  16. //
  17. // ------------------------------------------------------------------- Includes
  18. //
  19. #include "libcp.h"
  20. #include <assert.h>
  21. #include <errno.h>
  22. #include <string.h>
  23. #include <sys/ioctl.h>
  24. #include <termios.h>
  25. #include <unistd.h>
  26. //
  27. // ---------------------------------------------------------------------- Macro
  28. //
  29. //
  30. // This macro asserts that the terminal flags are equivalent between the
  31. // kernel and the C library.
  32. //
  33. #define ASSERT_TERMINAL_FLAGS_EQUIVALENT() \
  34. assert((BRKINT == TERMINAL_INPUT_SIGNAL_ON_BREAK) && \
  35. (ICRNL == TERMINAL_INPUT_CR_TO_NEWLINE) && \
  36. (IGNBRK == TERMINAL_INPUT_IGNORE_BREAK) && \
  37. (IGNCR == TERMINAL_INPUT_IGNORE_CR) && \
  38. (IGNPAR == TERMINAL_INPUT_IGNORE_PARITY_ERRORS) && \
  39. (INLCR == TERMINAL_INPUT_NEWLINE_TO_CR) && \
  40. (INPCK == TERMINAL_INPUT_ENABLE_PARITY_CHECK) && \
  41. (ISTRIP == TERMINAL_INPUT_STRIP) && \
  42. (IXANY == TERMINAL_INPUT_ANY_CHARACTER_RESTARTS_OUTPUT) && \
  43. (IXOFF == TERMINAL_INPUT_ENABLE_INPUT_FLOW_CONTROL) && \
  44. (IXON == TERMINAL_INPUT_ENABLE_OUTPUT_FLOW_CONTROL) && \
  45. (IMAXBEL == TERMINAL_INPUT_MAX_BELL) && \
  46. (PARMRK == TERMINAL_INPUT_MARK_PARITY_ERRORS) && \
  47. (OPOST == TERMINAL_OUTPUT_POST_PROCESS) && \
  48. (ONLCR == TERMINAL_OUTPUT_NEWLINE_TO_CRLF) && \
  49. (OCRNL == TERMINAL_OUTPUT_CR_TO_NEWLINE) && \
  50. (ONOCR == TERMINAL_OUTPUT_NO_CR_AT_COLUMN_ZERO) && \
  51. (ONLRET == TERMINAL_OUTPUT_NEWLINE_IS_CR) && \
  52. (OFILL == TERMINAL_OUTPUT_USE_FILL_CHARACTERS) && \
  53. (NLDLY == TERMINAL_OUTPUT_NEWLINE_DELAY) && \
  54. (NL0 == 0) && \
  55. (NL1 == TERMINAL_OUTPUT_NEWLINE_DELAY) && \
  56. (CRDLY == TERMINAL_OUTPUT_CR_DELAY_MASK) && \
  57. (CR0 == 0) && \
  58. (CR1 == TERMINAL_OUTPUT_CR_DELAY_1) && \
  59. (CR2 == TERMINAL_OUTPUT_CR_DELAY_2) && \
  60. (CR3 == TERMINAL_OUTPUT_CR_DELAY_3) && \
  61. (TABDLY == TERMINAL_OUTPUT_TAB_DELAY_MASK) && \
  62. (TAB0 == 0) && \
  63. (TAB1 == TERMINAL_OUTPUT_TAB_DELAY_1) && \
  64. (TAB2 == TERMINAL_OUTPUT_TAB_DELAY_2) && \
  65. (TAB3 == TERMINAL_OUTPUT_TAB_DELAY_3) && \
  66. (BSDLY == TERMINAL_OUTPUT_BACKSPACE_DELAY) && \
  67. (BS0 == 0) && \
  68. (BS1 == TERMINAL_OUTPUT_BACKSPACE_DELAY) && \
  69. (VTDLY == TERMINAL_OUTPUT_VERTICAL_TAB_DELAY) && \
  70. (VT0 == 0) && \
  71. (VT1 == TERMINAL_OUTPUT_VERTICAL_TAB_DELAY) && \
  72. (FFDLY == TERMINAL_OUTPUT_FORM_FEED_DELAY) && \
  73. (FF0 == 0) && \
  74. (FF1 == TERMINAL_OUTPUT_FORM_FEED_DELAY) && \
  75. (OFDEL == TERMINAL_OUTPUT_FILL_DEL) && \
  76. (CSIZE == TERMINAL_CONTROL_CHARACTER_SIZE_MASK) && \
  77. (CS5 == TERMINAL_CONTROL_5_BITS_PER_CHARACTER) && \
  78. (CS6 == TERMINAL_CONTROL_6_BITS_PER_CHARACTER) && \
  79. (CS7 == TERMINAL_CONTROL_7_BITS_PER_CHARACTER) && \
  80. (CS8 == TERMINAL_CONTROL_8_BITS_PER_CHARACTER) && \
  81. (CSTOPB == TERMINAL_CONTROL_2_STOP_BITS) && \
  82. (CREAD == TERMINAL_CONTROL_ENABLE_RECEIVE) && \
  83. (PARENB == TERMINAL_CONTROL_ENABLE_PARITY) && \
  84. (PARODD == TERMINAL_CONTROL_ODD_PARITY) && \
  85. (HUPCL == TERMINAL_CONTROL_HANGUP_ON_CLOSE) && \
  86. (CLOCAL == TERMINAL_CONTROL_NO_HANGUP) && \
  87. (ECHO == TERMINAL_LOCAL_ECHO) && \
  88. (ECHOE == TERMINAL_LOCAL_ECHO_ERASE) && \
  89. (ECHOK == TERMINAL_LOCAL_ECHO_KILL_NEWLINE) && \
  90. (ECHOKE == TERMINAL_LOCAL_ECHO_KILL_EXTENDED) && \
  91. (ECHONL == TERMINAL_LOCAL_ECHO_NEWLINE) && \
  92. (ECHOCTL == TERMINAL_LOCAL_ECHO_CONTROL) && \
  93. (ICANON == TERMINAL_LOCAL_CANONICAL) && \
  94. (IEXTEN == TERMINAL_LOCAL_EXTENDED) && \
  95. (ISIG == TERMINAL_LOCAL_SIGNALS) && \
  96. (NOFLSH == TERMINAL_LOCAL_NO_FLUSH) && \
  97. (TOSTOP == TERMINAL_LOCAL_STOP_BACKGROUND_WRITES))
  98. //
  99. // ---------------------------------------------------------------- Definitions
  100. //
  101. //
  102. // ------------------------------------------------------ Data Type Definitions
  103. //
  104. //
  105. // ----------------------------------------------- Internal Function Prototypes
  106. //
  107. //
  108. // -------------------------------------------------------------------- Globals
  109. //
  110. //
  111. // ------------------------------------------------------------------ Functions
  112. //
  113. LIBC_API
  114. int
  115. isatty (
  116. int FileDescriptor
  117. )
  118. /*++
  119. Routine Description:
  120. This routine determines if the given file descriptor is backed by an
  121. interactive terminal device or not.
  122. Arguments:
  123. FileDescriptor - Supplies the file descriptor to query.
  124. Return Value:
  125. 1 if the given file descriptor is backed by a terminal device.
  126. 0 on error or if the file descriptor is not a terminal device. On error,
  127. the errno variable will be set to give more details.
  128. --*/
  129. {
  130. struct termios Settings;
  131. if (tcgetattr(FileDescriptor, &Settings) == 0) {
  132. return 1;
  133. }
  134. return 0;
  135. }
  136. LIBC_API
  137. int
  138. tcgetattr (
  139. int FileDescriptor,
  140. struct termios *Settings
  141. )
  142. /*++
  143. Routine Description:
  144. This routine gets the current terminal settings.
  145. Arguments:
  146. FileDescriptor - Supplies the file descriptor for the terminal.
  147. Settings - Supplies a pointer where the terminal settings will be returned
  148. on success.
  149. Return Value:
  150. 0 on success.
  151. -1 on failure, and the errno variable will be set to provide more
  152. information.
  153. --*/
  154. {
  155. return ioctl(FileDescriptor, TCGETS, Settings);
  156. }
  157. LIBC_API
  158. int
  159. tcsetattr (
  160. int FileDescriptor,
  161. int When,
  162. const struct termios *NewSettings
  163. )
  164. /*++
  165. Routine Description:
  166. This routine sets the given terminal's attributes.
  167. Arguments:
  168. FileDescriptor - Supplies the file descriptor for the terminal.
  169. When - Supplies more information about when the new settings should take
  170. effect. See TCSA* definitions.
  171. NewSettings - Supplies a pointer to the new settings.
  172. Return Value:
  173. 0 on success.
  174. -1 on failure, and the errno variable will be set to provide more
  175. information.
  176. --*/
  177. {
  178. int Result;
  179. if (When == TCSANOW) {
  180. Result = ioctl(FileDescriptor, TCSETS, NewSettings);
  181. } else if (When == TCSADRAIN) {
  182. Result = ioctl(FileDescriptor, TCSETSW, NewSettings);
  183. } else if (When == TCSAFLUSH) {
  184. Result = ioctl(FileDescriptor, TCSETSF, NewSettings);
  185. } else {
  186. errno = EINVAL;
  187. Result = -1;
  188. }
  189. return Result;
  190. }
  191. LIBC_API
  192. speed_t
  193. cfgetispeed (
  194. const struct termios *Settings
  195. )
  196. /*++
  197. Routine Description:
  198. This routine gets the input baud rate from the given terminal settings.
  199. Arguments:
  200. Settings - Supplies a pointer to the terminal settings retrieved with a
  201. call to tcgetattr.
  202. Return Value:
  203. Returns the input speed, in baud.
  204. --*/
  205. {
  206. return Settings->c_ispeed;
  207. }
  208. LIBC_API
  209. speed_t
  210. cfgetospeed (
  211. const struct termios *Settings
  212. )
  213. /*++
  214. Routine Description:
  215. This routine gets the output baud rate from the given terminal settings.
  216. Arguments:
  217. Settings - Supplies a pointer to the terminal settings retrieved with a
  218. call to tcgetattr.
  219. Return Value:
  220. Returns the output speed, in baud.
  221. --*/
  222. {
  223. return Settings->c_ospeed;
  224. }
  225. LIBC_API
  226. int
  227. cfsetispeed (
  228. struct termios *Settings,
  229. speed_t NewBaudRate
  230. )
  231. /*++
  232. Routine Description:
  233. This routine sets the input baud rate from the given terminal settings.
  234. Arguments:
  235. Settings - Supplies a pointer to the terminal settings retrieved with a
  236. call to tcgetattr.
  237. NewBaudRate - Supplies the new input baud rate to set.
  238. Return Value:
  239. 0 on success.
  240. -1 on failure, and the errno will be set to EINVAL to indicate the given
  241. baud rate is invalid or not achievable.
  242. --*/
  243. {
  244. Settings->c_ispeed = NewBaudRate;
  245. return 0;
  246. }
  247. LIBC_API
  248. int
  249. cfsetospeed (
  250. struct termios *Settings,
  251. speed_t NewBaudRate
  252. )
  253. /*++
  254. Routine Description:
  255. This routine sets the output baud rate from the given terminal settings.
  256. Arguments:
  257. Settings - Supplies a pointer to the terminal settings retrieved with a
  258. call to tcgetattr.
  259. NewBaudRate - Supplies the new output baud rate to set.
  260. Return Value:
  261. 0 on success.
  262. -1 on failure, and the errno will be set to EINVAL to indicate the given
  263. baud rate is invalid or not achievable.
  264. --*/
  265. {
  266. Settings->c_ospeed = NewBaudRate;
  267. return 0;
  268. }
  269. LIBC_API
  270. void
  271. cfmakeraw (
  272. struct termios *Settings
  273. )
  274. /*++
  275. Routine Description:
  276. This routine sets the given settings to "raw" mode, disabling all line
  277. processing features and making the terminal as basic as possible.
  278. Arguments:
  279. Settings - Supplies a pointer to the terminal settings to adjust to raw
  280. mode.
  281. Return Value:
  282. None.
  283. --*/
  284. {
  285. Settings->c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR |
  286. ICRNL | IXON | IMAXBEL);
  287. Settings->c_oflag &= ~OPOST;
  288. Settings->c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
  289. Settings->c_cflag &= ~(CSIZE | PARENB);
  290. Settings->c_cflag |= CS8;
  291. Settings->c_cc[VMIN] = 1;
  292. Settings->c_cc[VTIME] = 0;
  293. return;
  294. }
  295. LIBC_API
  296. int
  297. tcflush (
  298. int FileDescriptor,
  299. int Selector
  300. )
  301. /*++
  302. Routine Description:
  303. This routine discards data written to the the given terminal, data received
  304. but not yet read from the terminal, or both.
  305. Attempts to use this function from a process which is a member of the
  306. background process group on the given terminal will cause the process group
  307. to be sent a SIGTTOU. If the calling process is blocking or ignoring
  308. SIGTTOU, the process shall be allowed to perform the operation, and no
  309. signal is sent.
  310. Arguments:
  311. FileDescriptor - Supplies the file descriptor of the terminal to flush.
  312. Selector - Supplies the type of flush to perform. Valid values are
  313. TCIFLUSH to flush data received but not read, TCOFLUSH to flush data
  314. written but not transmitted, and TCIOFLUSH to flush both types.
  315. Return Value:
  316. 0 on success.
  317. -1 on failure, and the errno will be set to contain more information.
  318. --*/
  319. {
  320. assert((TCIFLUSH == SYS_FLUSH_FLAG_READ) &&
  321. (TCOFLUSH == SYS_FLUSH_FLAG_WRITE) &&
  322. (TCIOFLUSH == (SYS_FLUSH_FLAG_READ | SYS_FLUSH_FLAG_WRITE)));
  323. return ioctl(FileDescriptor, TCFLSH, Selector);
  324. }
  325. LIBC_API
  326. int
  327. tcdrain (
  328. int FileDescriptor
  329. )
  330. /*++
  331. Routine Description:
  332. This routine waits until all output written to the terminal at the given
  333. file descriptor is written.
  334. Attempts to use this function from a process which is a member of the
  335. background process group on the given terminal will cause the process group
  336. to be sent a SIGTTOU. If the calling process is blocking or ignoring
  337. SIGTTOU, the process shall be allowed to perform the operation, and no
  338. signal is sent.
  339. Arguments:
  340. FileDescriptor - Supplies the file descriptor of the terminal to drain.
  341. Return Value:
  342. 0 on success.
  343. -1 on failure, and the errno will be set to contain more information.
  344. --*/
  345. {
  346. //
  347. // TCSBRK with a non-zero value is undefined, but in this implementation
  348. // implements tcdrain behavior.
  349. //
  350. return ioctl(FileDescriptor, TCSBRK, 1);
  351. }
  352. LIBC_API
  353. int
  354. tcflow (
  355. int FileDescriptor,
  356. int Action
  357. )
  358. /*++
  359. Routine Description:
  360. This routine suspends or restarts transmission of data on the given
  361. terminal.
  362. Attempts to use this function from a process which is a member of the
  363. background process group on the given terminal will cause the process group
  364. to be sent a SIGTTOU. If the calling process is blocking or ignoring
  365. SIGTTOU, the process shall be allowed to perform the operation, and no
  366. signal is sent.
  367. Arguments:
  368. FileDescriptor - Supplies the file descriptor of the terminal.
  369. Action - Supplies the action to perform. Valid values are:
  370. TCOOFF - Suspends output.
  371. TCOON - Resumes suspended output.
  372. TCIOFF - Causes the system to transmit a STOP character, which is
  373. intended to cause the terminal device to stop transmitting data to
  374. this system.
  375. TCION - Causes the system to transmit a START character, which is
  376. intended to restart the sending of data to this terminal.
  377. Return Value:
  378. 0 on success.
  379. -1 on failure, and the errno will be set to contain more information.
  380. --*/
  381. {
  382. return ioctl(FileDescriptor, TCXONC, Action);
  383. }
  384. LIBC_API
  385. int
  386. tcsendbreak (
  387. int FileDescriptor,
  388. int Duration
  389. )
  390. /*++
  391. Routine Description:
  392. This routine sends a continuous stream of zero-valued bits for a specific
  393. duration if the given terminal is using asynchronous serial data
  394. transmission. If the terminal is not using asynchronous serial data
  395. transmission, this routine returns without performing any action.
  396. Attempts to use this function from a process which is a member of the
  397. background process group on the given terminal will cause the process group
  398. to be sent a SIGTTOU. If the calling process is blocking or ignoring
  399. SIGTTOU, the process shall be allowed to perform the operation, and no
  400. signal is sent.
  401. Arguments:
  402. FileDescriptor - Supplies the file descriptor of the terminal.
  403. Duration - Supplies a value that if zero causes the duration to be between
  404. 0.25 and 0.5 seconds. If duration is not zero, it sends zero-valued
  405. bits for an implementation-defined length of time.
  406. Return Value:
  407. 0 on success.
  408. -1 on failure, and the errno will be set to contain more information.
  409. --*/
  410. {
  411. return ioctl(FileDescriptor, TCSBRK, Duration);
  412. }
  413. LIBC_API
  414. pid_t
  415. tcgetsid (
  416. int FileDescriptor
  417. )
  418. /*++
  419. Routine Description:
  420. This routine gets the process group ID of the session for which the
  421. terminal specified by the given file descriptor is the controlling terminal.
  422. Arguments:
  423. FileDescriptor - Supplies the file descriptor of the terminal.
  424. Return Value:
  425. Returns the process group ID associated with the terminal on success.
  426. -1 on failure, and errno will be set to contain more information.
  427. --*/
  428. {
  429. pid_t ProcessGroup;
  430. int Status;
  431. ProcessGroup = -1;
  432. Status = ioctl(FileDescriptor, TIOCGSID, &ProcessGroup);
  433. if (Status != 0) {
  434. return (pid_t)-1;
  435. }
  436. return ProcessGroup;
  437. }
  438. LIBC_API
  439. int
  440. tcsetpgrp (
  441. int FileDescriptor,
  442. pid_t ProcessGroupId
  443. )
  444. /*++
  445. Routine Description:
  446. This routine sets the foreground process group ID associated with the
  447. given terminal file descriptor. The application shall ensure that the file
  448. associated with the given descriptor is the controlling terminal of the
  449. calling process and the controlling terminal is currently associated with
  450. the session of the calling process. The application shall ensure that the
  451. given process group ID is led by a process in the same session as the
  452. calling process.
  453. Arguments:
  454. FileDescriptor - Supplies the file descriptor of the terminal.
  455. ProcessGroupId - Supplies the process group ID to set for the terminal.
  456. Return Value:
  457. 0 on success.
  458. -1 on failure, and the errno will be set to contain more information.
  459. --*/
  460. {
  461. PROCESS_GROUP_ID Identifier;
  462. Identifier = ProcessGroupId;
  463. return ioctl(FileDescriptor, TIOCSPGRP, &Identifier);
  464. }
  465. LIBC_API
  466. pid_t
  467. tcgetpgrp (
  468. int FileDescriptor
  469. )
  470. /*++
  471. Routine Description:
  472. This routine returns the value of the process group ID of the foreground
  473. process associated with the given terminal. If ther is no foreground
  474. process group, this routine returns a value greater than 1 that does not
  475. match the process group ID of any existing process group.
  476. Arguments:
  477. FileDescriptor - Supplies the file descriptor of the terminal.
  478. Return Value:
  479. Returns the process group ID of the foreground process associated with the
  480. terminal on success.
  481. -1 on failure, and errno will be set to contain more information. Possible
  482. values of errno are:
  483. EBADF if the file descriptor is invalid.
  484. ENOTTY if the calling process does not having a controlling terminal, or
  485. the file is not the controlling terminal.
  486. --*/
  487. {
  488. PROCESS_GROUP_ID Identifier;
  489. int Result;
  490. Result = ioctl(FileDescriptor, TIOCGPGRP, &Identifier);
  491. if (Result < 0) {
  492. return Result;
  493. }
  494. return (pid_t)Identifier;
  495. }
  496. //
  497. // --------------------------------------------------------- Internal Functions
  498. //