/rust/registry/src/index.crates.io-6f17d22bba15001f/nix-0.26.2/src/sys/termios.rs
Line | Count | Source (jump to first uncovered line) |
1 | | //! An interface for controlling asynchronous communication ports |
2 | | //! |
3 | | //! This interface provides a safe wrapper around the termios subsystem defined by POSIX. The |
4 | | //! underlying types are all implemented in libc for most platforms and either wrapped in safer |
5 | | //! types here or exported directly. |
6 | | //! |
7 | | //! If you are unfamiliar with the `termios` API, you should first read the |
8 | | //! [API documentation](https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/termios.h.html) and |
9 | | //! then come back to understand how `nix` safely wraps it. |
10 | | //! |
11 | | //! It should be noted that this API incurs some runtime overhead above the base `libc` definitions. |
12 | | //! As this interface is not used with high-bandwidth information, this should be fine in most |
13 | | //! cases. The primary cost when using this API is that the `Termios` datatype here duplicates the |
14 | | //! standard fields of the underlying `termios` struct and uses safe type wrappers for those fields. |
15 | | //! This means that when crossing the FFI interface to the underlying C library, data is first |
16 | | //! copied into the underlying `termios` struct, then the operation is done, and the data is copied |
17 | | //! back (with additional sanity checking) into the safe wrapper types. The `termios` struct is |
18 | | //! relatively small across all platforms (on the order of 32-64 bytes). |
19 | | //! |
20 | | //! The following examples highlight some of the API use cases such that users coming from using C |
21 | | //! or reading the standard documentation will understand how to use the safe API exposed here. |
22 | | //! |
23 | | //! Example disabling processing of the end-of-file control character: |
24 | | //! |
25 | | //! ``` |
26 | | //! # use self::nix::sys::termios::SpecialCharacterIndices::VEOF; |
27 | | //! # use self::nix::sys::termios::{_POSIX_VDISABLE, Termios}; |
28 | | //! # let mut termios: Termios = unsafe { std::mem::zeroed() }; |
29 | | //! termios.control_chars[VEOF as usize] = _POSIX_VDISABLE; |
30 | | //! ``` |
31 | | //! |
32 | | //! The flags within `Termios` are defined as bitfields using the `bitflags` crate. This provides |
33 | | //! an interface for working with bitfields that is similar to working with the raw unsigned |
34 | | //! integer types but offers type safety because of the internal checking that values will always |
35 | | //! be a valid combination of the defined flags. |
36 | | //! |
37 | | //! An example showing some of the basic operations for interacting with the control flags: |
38 | | //! |
39 | | //! ``` |
40 | | //! # use self::nix::sys::termios::{ControlFlags, Termios}; |
41 | | //! # let mut termios: Termios = unsafe { std::mem::zeroed() }; |
42 | | //! termios.control_flags & ControlFlags::CSIZE == ControlFlags::CS5; |
43 | | //! termios.control_flags |= ControlFlags::CS5; |
44 | | //! ``` |
45 | | //! |
46 | | //! # Baud rates |
47 | | //! |
48 | | //! This API is not consistent across platforms when it comes to `BaudRate`: Android and Linux both |
49 | | //! only support the rates specified by the `BaudRate` enum through their termios API while the BSDs |
50 | | //! support arbitrary baud rates as the values of the `BaudRate` enum constants are the same integer |
51 | | //! value of the constant (`B9600` == `9600`). Therefore the `nix::termios` API uses the following |
52 | | //! conventions: |
53 | | //! |
54 | | //! * `cfgetispeed()` - Returns `u32` on BSDs, `BaudRate` on Android/Linux |
55 | | //! * `cfgetospeed()` - Returns `u32` on BSDs, `BaudRate` on Android/Linux |
56 | | //! * `cfsetispeed()` - Takes `u32` or `BaudRate` on BSDs, `BaudRate` on Android/Linux |
57 | | //! * `cfsetospeed()` - Takes `u32` or `BaudRate` on BSDs, `BaudRate` on Android/Linux |
58 | | //! * `cfsetspeed()` - Takes `u32` or `BaudRate` on BSDs, `BaudRate` on Android/Linux |
59 | | //! |
60 | | //! The most common use case of specifying a baud rate using the enum will work the same across |
61 | | //! platforms: |
62 | | //! |
63 | | //! ```rust |
64 | | //! # use nix::sys::termios::{BaudRate, cfsetispeed, cfsetospeed, cfsetspeed, Termios}; |
65 | | //! # fn main() { |
66 | | //! # let mut t: Termios = unsafe { std::mem::zeroed() }; |
67 | | //! cfsetispeed(&mut t, BaudRate::B9600).unwrap(); |
68 | | //! cfsetospeed(&mut t, BaudRate::B9600).unwrap(); |
69 | | //! cfsetspeed(&mut t, BaudRate::B9600).unwrap(); |
70 | | //! # } |
71 | | //! ``` |
72 | | //! |
73 | | //! Additionally round-tripping baud rates is consistent across platforms: |
74 | | //! |
75 | | //! ```rust |
76 | | //! # use nix::sys::termios::{BaudRate, cfgetispeed, cfgetospeed, cfsetispeed, cfsetspeed, Termios}; |
77 | | //! # fn main() { |
78 | | //! # let mut t: Termios = unsafe { std::mem::zeroed() }; |
79 | | //! # cfsetspeed(&mut t, BaudRate::B9600).unwrap(); |
80 | | //! let speed = cfgetispeed(&t); |
81 | | //! assert_eq!(speed, cfgetospeed(&t)); |
82 | | //! cfsetispeed(&mut t, speed).unwrap(); |
83 | | //! # } |
84 | | //! ``` |
85 | | //! |
86 | | //! On non-BSDs, `cfgetispeed()` and `cfgetospeed()` both return a `BaudRate`: |
87 | | //! |
88 | | #![cfg_attr( |
89 | | any( |
90 | | target_os = "freebsd", |
91 | | target_os = "dragonfly", |
92 | | target_os = "ios", |
93 | | target_os = "macos", |
94 | | target_os = "netbsd", |
95 | | target_os = "openbsd" |
96 | | ), |
97 | | doc = " ```rust,ignore" |
98 | | )] |
99 | | #![cfg_attr( |
100 | | not(any( |
101 | | target_os = "freebsd", |
102 | | target_os = "dragonfly", |
103 | | target_os = "ios", |
104 | | target_os = "macos", |
105 | | target_os = "netbsd", |
106 | | target_os = "openbsd" |
107 | | )), |
108 | | doc = " ```rust" |
109 | | )] |
110 | | //! # use nix::sys::termios::{BaudRate, cfgetispeed, cfgetospeed, cfsetspeed, Termios}; |
111 | | //! # fn main() { |
112 | | //! # let mut t: Termios = unsafe { std::mem::zeroed() }; |
113 | | //! # cfsetspeed(&mut t, BaudRate::B9600); |
114 | | //! assert_eq!(cfgetispeed(&t), BaudRate::B9600); |
115 | | //! assert_eq!(cfgetospeed(&t), BaudRate::B9600); |
116 | | //! # } |
117 | | //! ``` |
118 | | //! |
119 | | //! But on the BSDs, `cfgetispeed()` and `cfgetospeed()` both return `u32`s: |
120 | | //! |
121 | | #![cfg_attr( |
122 | | any( |
123 | | target_os = "freebsd", |
124 | | target_os = "dragonfly", |
125 | | target_os = "ios", |
126 | | target_os = "macos", |
127 | | target_os = "netbsd", |
128 | | target_os = "openbsd" |
129 | | ), |
130 | | doc = " ```rust" |
131 | | )] |
132 | | #![cfg_attr( |
133 | | not(any( |
134 | | target_os = "freebsd", |
135 | | target_os = "dragonfly", |
136 | | target_os = "ios", |
137 | | target_os = "macos", |
138 | | target_os = "netbsd", |
139 | | target_os = "openbsd" |
140 | | )), |
141 | | doc = " ```rust,ignore" |
142 | | )] |
143 | | //! # use nix::sys::termios::{BaudRate, cfgetispeed, cfgetospeed, cfsetspeed, Termios}; |
144 | | //! # fn main() { |
145 | | //! # let mut t: Termios = unsafe { std::mem::zeroed() }; |
146 | | //! # cfsetspeed(&mut t, 9600u32); |
147 | | //! assert_eq!(cfgetispeed(&t), 9600u32); |
148 | | //! assert_eq!(cfgetospeed(&t), 9600u32); |
149 | | //! # } |
150 | | //! ``` |
151 | | //! |
152 | | //! It's trivial to convert from a `BaudRate` to a `u32` on BSDs: |
153 | | //! |
154 | | #![cfg_attr( |
155 | | any( |
156 | | target_os = "freebsd", |
157 | | target_os = "dragonfly", |
158 | | target_os = "ios", |
159 | | target_os = "macos", |
160 | | target_os = "netbsd", |
161 | | target_os = "openbsd" |
162 | | ), |
163 | | doc = " ```rust" |
164 | | )] |
165 | | #![cfg_attr( |
166 | | not(any( |
167 | | target_os = "freebsd", |
168 | | target_os = "dragonfly", |
169 | | target_os = "ios", |
170 | | target_os = "macos", |
171 | | target_os = "netbsd", |
172 | | target_os = "openbsd" |
173 | | )), |
174 | | doc = " ```rust,ignore" |
175 | | )] |
176 | | //! # use nix::sys::termios::{BaudRate, cfgetispeed, cfsetspeed, Termios}; |
177 | | //! # fn main() { |
178 | | //! # let mut t: Termios = unsafe { std::mem::zeroed() }; |
179 | | //! # cfsetspeed(&mut t, 9600u32); |
180 | | //! assert_eq!(cfgetispeed(&t), BaudRate::B9600.into()); |
181 | | //! assert_eq!(u32::from(BaudRate::B9600), 9600u32); |
182 | | //! # } |
183 | | //! ``` |
184 | | //! |
185 | | //! And on BSDs you can specify arbitrary baud rates (**note** this depends on hardware support) |
186 | | //! by specifying baud rates directly using `u32`s: |
187 | | //! |
188 | | #![cfg_attr( |
189 | | any( |
190 | | target_os = "freebsd", |
191 | | target_os = "dragonfly", |
192 | | target_os = "ios", |
193 | | target_os = "macos", |
194 | | target_os = "netbsd", |
195 | | target_os = "openbsd" |
196 | | ), |
197 | | doc = " ```rust" |
198 | | )] |
199 | | #![cfg_attr( |
200 | | not(any( |
201 | | target_os = "freebsd", |
202 | | target_os = "dragonfly", |
203 | | target_os = "ios", |
204 | | target_os = "macos", |
205 | | target_os = "netbsd", |
206 | | target_os = "openbsd" |
207 | | )), |
208 | | doc = " ```rust,ignore" |
209 | | )] |
210 | | //! # use nix::sys::termios::{cfsetispeed, cfsetospeed, cfsetspeed, Termios}; |
211 | | //! # fn main() { |
212 | | //! # let mut t: Termios = unsafe { std::mem::zeroed() }; |
213 | | //! cfsetispeed(&mut t, 9600u32); |
214 | | //! cfsetospeed(&mut t, 9600u32); |
215 | | //! cfsetspeed(&mut t, 9600u32); |
216 | | //! # } |
217 | | //! ``` |
218 | | use crate::errno::Errno; |
219 | | use crate::Result; |
220 | | use cfg_if::cfg_if; |
221 | | use libc::{self, c_int, tcflag_t}; |
222 | | use std::cell::{Ref, RefCell}; |
223 | | use std::convert::From; |
224 | | use std::mem; |
225 | | use std::os::unix::io::RawFd; |
226 | | |
227 | | #[cfg(feature = "process")] |
228 | | use crate::unistd::Pid; |
229 | | |
230 | | /// Stores settings for the termios API |
231 | | /// |
232 | | /// This is a wrapper around the `libc::termios` struct that provides a safe interface for the |
233 | | /// standard fields. The only safe way to obtain an instance of this struct is to extract it from |
234 | | /// an open port using `tcgetattr()`. |
235 | 0 | #[derive(Clone, Debug, Eq, PartialEq)] |
236 | | pub struct Termios { |
237 | | inner: RefCell<libc::termios>, |
238 | | /// Input mode flags (see `termios.c_iflag` documentation) |
239 | | pub input_flags: InputFlags, |
240 | | /// Output mode flags (see `termios.c_oflag` documentation) |
241 | | pub output_flags: OutputFlags, |
242 | | /// Control mode flags (see `termios.c_cflag` documentation) |
243 | | pub control_flags: ControlFlags, |
244 | | /// Local mode flags (see `termios.c_lflag` documentation) |
245 | | pub local_flags: LocalFlags, |
246 | | /// Control characters (see `termios.c_cc` documentation) |
247 | | pub control_chars: [libc::cc_t; NCCS], |
248 | | /// Line discipline (see `termios.c_line` documentation) |
249 | | #[cfg(any(target_os = "linux", target_os = "android",))] |
250 | | pub line_discipline: libc::cc_t, |
251 | | /// Line discipline (see `termios.c_line` documentation) |
252 | | #[cfg(target_os = "haiku")] |
253 | | pub line_discipline: libc::c_char, |
254 | | } |
255 | | |
256 | | impl Termios { |
257 | | /// Exposes an immutable reference to the underlying `libc::termios` data structure. |
258 | | /// |
259 | | /// This is not part of `nix`'s public API because it requires additional work to maintain type |
260 | | /// safety. |
261 | 0 | pub(crate) fn get_libc_termios(&self) -> Ref<libc::termios> { |
262 | 0 | { |
263 | 0 | let mut termios = self.inner.borrow_mut(); |
264 | 0 | termios.c_iflag = self.input_flags.bits(); |
265 | 0 | termios.c_oflag = self.output_flags.bits(); |
266 | 0 | termios.c_cflag = self.control_flags.bits(); |
267 | 0 | termios.c_lflag = self.local_flags.bits(); |
268 | 0 | termios.c_cc = self.control_chars; |
269 | 0 | #[cfg(any( |
270 | 0 | target_os = "linux", |
271 | 0 | target_os = "android", |
272 | 0 | target_os = "haiku", |
273 | 0 | ))] |
274 | 0 | { |
275 | 0 | termios.c_line = self.line_discipline; |
276 | 0 | } |
277 | 0 | } |
278 | 0 | self.inner.borrow() |
279 | 0 | } |
280 | | |
281 | | /// Exposes the inner `libc::termios` datastore within `Termios`. |
282 | | /// |
283 | | /// This is unsafe because if this is used to modify the inner `libc::termios` struct, it will |
284 | | /// not automatically update the safe wrapper type around it. In this case it should also be |
285 | | /// paired with a call to `update_wrapper()` so that the wrapper-type and internal |
286 | | /// representation stay consistent. |
287 | 0 | pub(crate) unsafe fn get_libc_termios_mut(&mut self) -> *mut libc::termios { |
288 | 0 | { |
289 | 0 | let mut termios = self.inner.borrow_mut(); |
290 | 0 | termios.c_iflag = self.input_flags.bits(); |
291 | 0 | termios.c_oflag = self.output_flags.bits(); |
292 | 0 | termios.c_cflag = self.control_flags.bits(); |
293 | 0 | termios.c_lflag = self.local_flags.bits(); |
294 | 0 | termios.c_cc = self.control_chars; |
295 | 0 | #[cfg(any( |
296 | 0 | target_os = "linux", |
297 | 0 | target_os = "android", |
298 | 0 | target_os = "haiku", |
299 | 0 | ))] |
300 | 0 | { |
301 | 0 | termios.c_line = self.line_discipline; |
302 | 0 | } |
303 | 0 | } |
304 | 0 | self.inner.as_ptr() |
305 | 0 | } |
306 | | |
307 | | /// Updates the wrapper values from the internal `libc::termios` data structure. |
308 | 0 | pub(crate) fn update_wrapper(&mut self) { |
309 | 0 | let termios = *self.inner.borrow_mut(); |
310 | 0 | self.input_flags = InputFlags::from_bits_truncate(termios.c_iflag); |
311 | 0 | self.output_flags = OutputFlags::from_bits_truncate(termios.c_oflag); |
312 | 0 | self.control_flags = ControlFlags::from_bits_truncate(termios.c_cflag); |
313 | 0 | self.local_flags = LocalFlags::from_bits_truncate(termios.c_lflag); |
314 | 0 | self.control_chars = termios.c_cc; |
315 | 0 | #[cfg(any( |
316 | 0 | target_os = "linux", |
317 | 0 | target_os = "android", |
318 | 0 | target_os = "haiku", |
319 | 0 | ))] |
320 | 0 | { |
321 | 0 | self.line_discipline = termios.c_line; |
322 | 0 | } |
323 | 0 | } |
324 | | } |
325 | | |
326 | | impl From<libc::termios> for Termios { |
327 | 0 | fn from(termios: libc::termios) -> Self { |
328 | 0 | Termios { |
329 | 0 | inner: RefCell::new(termios), |
330 | 0 | input_flags: InputFlags::from_bits_truncate(termios.c_iflag), |
331 | 0 | output_flags: OutputFlags::from_bits_truncate(termios.c_oflag), |
332 | 0 | control_flags: ControlFlags::from_bits_truncate(termios.c_cflag), |
333 | 0 | local_flags: LocalFlags::from_bits_truncate(termios.c_lflag), |
334 | 0 | control_chars: termios.c_cc, |
335 | 0 | #[cfg(any( |
336 | 0 | target_os = "linux", |
337 | 0 | target_os = "android", |
338 | 0 | target_os = "haiku", |
339 | 0 | ))] |
340 | 0 | line_discipline: termios.c_line, |
341 | 0 | } |
342 | 0 | } |
343 | | } |
344 | | |
345 | | impl From<Termios> for libc::termios { |
346 | 0 | fn from(termios: Termios) -> Self { |
347 | 0 | termios.inner.into_inner() |
348 | 0 | } |
349 | | } |
350 | | |
351 | | libc_enum! { |
352 | | /// Baud rates supported by the system. |
353 | | /// |
354 | | /// For the BSDs, arbitrary baud rates can be specified by using `u32`s directly instead of this |
355 | | /// enum. |
356 | | /// |
357 | | /// B0 is special and will disable the port. |
358 | | #[cfg_attr(all(any(target_os = "haiku"), target_pointer_width = "64"), repr(u8))] |
359 | | #[cfg_attr(all(any(target_os = "ios", target_os = "macos"), target_pointer_width = "64"), repr(u64))] |
360 | | #[cfg_attr(not(all(any(target_os = "ios", target_os = "macos", target_os = "haiku"), target_pointer_width = "64")), repr(u32))] |
361 | | #[non_exhaustive] |
362 | | pub enum BaudRate { |
363 | | B0, |
364 | | B50, |
365 | | B75, |
366 | | B110, |
367 | | B134, |
368 | | B150, |
369 | | B200, |
370 | | B300, |
371 | | B600, |
372 | | B1200, |
373 | | B1800, |
374 | | B2400, |
375 | | B4800, |
376 | | #[cfg(any(target_os = "dragonfly", |
377 | | target_os = "freebsd", |
378 | | target_os = "macos", |
379 | | target_os = "netbsd", |
380 | | target_os = "openbsd"))] |
381 | | #[cfg_attr(docsrs, doc(cfg(all())))] |
382 | | B7200, |
383 | | B9600, |
384 | | #[cfg(any(target_os = "dragonfly", |
385 | | target_os = "freebsd", |
386 | | target_os = "macos", |
387 | | target_os = "netbsd", |
388 | | target_os = "openbsd"))] |
389 | | #[cfg_attr(docsrs, doc(cfg(all())))] |
390 | | B14400, |
391 | | B19200, |
392 | | #[cfg(any(target_os = "dragonfly", |
393 | | target_os = "freebsd", |
394 | | target_os = "macos", |
395 | | target_os = "netbsd", |
396 | | target_os = "openbsd"))] |
397 | | #[cfg_attr(docsrs, doc(cfg(all())))] |
398 | | B28800, |
399 | | B38400, |
400 | | B57600, |
401 | | #[cfg(any(target_os = "dragonfly", |
402 | | target_os = "freebsd", |
403 | | target_os = "macos", |
404 | | target_os = "netbsd", |
405 | | target_os = "openbsd"))] |
406 | | #[cfg_attr(docsrs, doc(cfg(all())))] |
407 | | B76800, |
408 | | B115200, |
409 | | #[cfg(any(target_os = "illumos", target_os = "solaris"))] |
410 | | #[cfg_attr(docsrs, doc(cfg(all())))] |
411 | | B153600, |
412 | | B230400, |
413 | | #[cfg(any(target_os = "illumos", target_os = "solaris"))] |
414 | | #[cfg_attr(docsrs, doc(cfg(all())))] |
415 | | B307200, |
416 | | #[cfg(any(target_os = "android", |
417 | | target_os = "freebsd", |
418 | | target_os = "illumos", |
419 | | target_os = "linux", |
420 | | target_os = "netbsd", |
421 | | target_os = "solaris"))] |
422 | | #[cfg_attr(docsrs, doc(cfg(all())))] |
423 | | B460800, |
424 | | #[cfg(any(target_os = "android", target_os = "linux"))] |
425 | | #[cfg_attr(docsrs, doc(cfg(all())))] |
426 | | B500000, |
427 | | #[cfg(any(target_os = "android", target_os = "linux"))] |
428 | | #[cfg_attr(docsrs, doc(cfg(all())))] |
429 | | B576000, |
430 | | #[cfg(any(target_os = "android", |
431 | | target_os = "freebsd", |
432 | | target_os = "illumos", |
433 | | target_os = "linux", |
434 | | target_os = "netbsd", |
435 | | target_os = "solaris"))] |
436 | | #[cfg_attr(docsrs, doc(cfg(all())))] |
437 | | B921600, |
438 | | #[cfg(any(target_os = "android", target_os = "linux"))] |
439 | | #[cfg_attr(docsrs, doc(cfg(all())))] |
440 | | B1000000, |
441 | | #[cfg(any(target_os = "android", target_os = "linux"))] |
442 | | #[cfg_attr(docsrs, doc(cfg(all())))] |
443 | | B1152000, |
444 | | #[cfg(any(target_os = "android", target_os = "linux"))] |
445 | | #[cfg_attr(docsrs, doc(cfg(all())))] |
446 | | B1500000, |
447 | | #[cfg(any(target_os = "android", target_os = "linux"))] |
448 | | #[cfg_attr(docsrs, doc(cfg(all())))] |
449 | | B2000000, |
450 | | #[cfg(any(target_os = "android", all(target_os = "linux", not(target_arch = "sparc64"))))] |
451 | | #[cfg_attr(docsrs, doc(cfg(all())))] |
452 | | B2500000, |
453 | | #[cfg(any(target_os = "android", all(target_os = "linux", not(target_arch = "sparc64"))))] |
454 | | #[cfg_attr(docsrs, doc(cfg(all())))] |
455 | | B3000000, |
456 | | #[cfg(any(target_os = "android", all(target_os = "linux", not(target_arch = "sparc64"))))] |
457 | | #[cfg_attr(docsrs, doc(cfg(all())))] |
458 | | B3500000, |
459 | | #[cfg(any(target_os = "android", all(target_os = "linux", not(target_arch = "sparc64"))))] |
460 | | #[cfg_attr(docsrs, doc(cfg(all())))] |
461 | | B4000000, |
462 | | } |
463 | | impl TryFrom<libc::speed_t> |
464 | | } |
465 | | |
466 | | #[cfg(any( |
467 | | target_os = "freebsd", |
468 | | target_os = "dragonfly", |
469 | | target_os = "ios", |
470 | | target_os = "macos", |
471 | | target_os = "netbsd", |
472 | | target_os = "openbsd" |
473 | | ))] |
474 | | impl From<BaudRate> for u32 { |
475 | | fn from(b: BaudRate) -> u32 { |
476 | | b as u32 |
477 | | } |
478 | | } |
479 | | |
480 | | #[cfg(target_os = "haiku")] |
481 | | impl From<BaudRate> for u8 { |
482 | | fn from(b: BaudRate) -> u8 { |
483 | | b as u8 |
484 | | } |
485 | | } |
486 | | |
487 | | // TODO: Add TCSASOFT, which will require treating this as a bitfield. |
488 | | libc_enum! { |
489 | | /// Specify when a port configuration change should occur. |
490 | | /// |
491 | | /// Used as an argument to `tcsetattr()` |
492 | | #[repr(i32)] |
493 | | #[non_exhaustive] |
494 | | pub enum SetArg { |
495 | | /// The change will occur immediately |
496 | | TCSANOW, |
497 | | /// The change occurs after all output has been written |
498 | | TCSADRAIN, |
499 | | /// Same as `TCSADRAIN`, but will also flush the input buffer |
500 | | TCSAFLUSH, |
501 | | } |
502 | | } |
503 | | |
504 | | libc_enum! { |
505 | | /// Specify a combination of the input and output buffers to flush |
506 | | /// |
507 | | /// Used as an argument to `tcflush()`. |
508 | | #[repr(i32)] |
509 | | #[non_exhaustive] |
510 | | pub enum FlushArg { |
511 | | /// Flush data that was received but not read |
512 | | TCIFLUSH, |
513 | | /// Flush data written but not transmitted |
514 | | TCOFLUSH, |
515 | | /// Flush both received data not read and written data not transmitted |
516 | | TCIOFLUSH, |
517 | | } |
518 | | } |
519 | | |
520 | | libc_enum! { |
521 | | /// Specify how transmission flow should be altered |
522 | | /// |
523 | | /// Used as an argument to `tcflow()`. |
524 | | #[repr(i32)] |
525 | | #[non_exhaustive] |
526 | | pub enum FlowArg { |
527 | | /// Suspend transmission |
528 | | TCOOFF, |
529 | | /// Resume transmission |
530 | | TCOON, |
531 | | /// Transmit a STOP character, which should disable a connected terminal device |
532 | | TCIOFF, |
533 | | /// Transmit a START character, which should re-enable a connected terminal device |
534 | | TCION, |
535 | | } |
536 | | } |
537 | | |
538 | | // TODO: Make this usable directly as a slice index. |
539 | | #[cfg(not(target_os = "haiku"))] |
540 | | libc_enum! { |
541 | | /// Indices into the `termios.c_cc` array for special characters. |
542 | | #[repr(usize)] |
543 | | #[non_exhaustive] |
544 | | pub enum SpecialCharacterIndices { |
545 | | VDISCARD, |
546 | | #[cfg(any(target_os = "dragonfly", |
547 | | target_os = "freebsd", |
548 | | target_os = "illumos", |
549 | | target_os = "macos", |
550 | | target_os = "netbsd", |
551 | | target_os = "openbsd", |
552 | | target_os = "solaris"))] |
553 | | #[cfg_attr(docsrs, doc(cfg(all())))] |
554 | | VDSUSP, |
555 | | VEOF, |
556 | | VEOL, |
557 | | VEOL2, |
558 | | VERASE, |
559 | | #[cfg(any(target_os = "dragonfly", |
560 | | target_os = "freebsd", |
561 | | target_os = "illumos", |
562 | | target_os = "solaris"))] |
563 | | #[cfg_attr(docsrs, doc(cfg(all())))] |
564 | | VERASE2, |
565 | | VINTR, |
566 | | VKILL, |
567 | | VLNEXT, |
568 | | #[cfg(not(any(all(target_os = "linux", target_arch = "sparc64"), |
569 | | target_os = "illumos", target_os = "solaris")))] |
570 | | #[cfg_attr(docsrs, doc(cfg(all())))] |
571 | | VMIN, |
572 | | VQUIT, |
573 | | VREPRINT, |
574 | | VSTART, |
575 | | #[cfg(any(target_os = "dragonfly", |
576 | | target_os = "freebsd", |
577 | | target_os = "illumos", |
578 | | target_os = "macos", |
579 | | target_os = "netbsd", |
580 | | target_os = "openbsd", |
581 | | target_os = "solaris"))] |
582 | | #[cfg_attr(docsrs, doc(cfg(all())))] |
583 | | VSTATUS, |
584 | | VSTOP, |
585 | | VSUSP, |
586 | | #[cfg(target_os = "linux")] |
587 | | #[cfg_attr(docsrs, doc(cfg(all())))] |
588 | | VSWTC, |
589 | | #[cfg(any(target_os = "haiku", target_os = "illumos", target_os = "solaris"))] |
590 | | #[cfg_attr(docsrs, doc(cfg(all())))] |
591 | | VSWTCH, |
592 | | #[cfg(not(any(all(target_os = "linux", target_arch = "sparc64"), |
593 | | target_os = "illumos", target_os = "solaris")))] |
594 | | #[cfg_attr(docsrs, doc(cfg(all())))] |
595 | | VTIME, |
596 | | VWERASE, |
597 | | #[cfg(target_os = "dragonfly")] |
598 | | #[cfg_attr(docsrs, doc(cfg(all())))] |
599 | | VCHECKPT, |
600 | | } |
601 | | } |
602 | | |
603 | | #[cfg(any( |
604 | | all(target_os = "linux", target_arch = "sparc64"), |
605 | | target_os = "illumos", |
606 | | target_os = "solaris" |
607 | | ))] |
608 | | impl SpecialCharacterIndices { |
609 | | pub const VMIN: SpecialCharacterIndices = SpecialCharacterIndices::VEOF; |
610 | | pub const VTIME: SpecialCharacterIndices = SpecialCharacterIndices::VEOL; |
611 | | } |
612 | | |
613 | | pub use libc::NCCS; |
614 | | #[cfg(any( |
615 | | target_os = "android", |
616 | | target_os = "dragonfly", |
617 | | target_os = "freebsd", |
618 | | target_os = "linux", |
619 | | target_os = "macos", |
620 | | target_os = "netbsd", |
621 | | target_os = "openbsd" |
622 | | ))] |
623 | | #[cfg_attr(docsrs, doc(cfg(all())))] |
624 | | pub use libc::_POSIX_VDISABLE; |
625 | | |
626 | | libc_bitflags! { |
627 | | /// Flags for configuring the input mode of a terminal |
628 | | pub struct InputFlags: tcflag_t { |
629 | | IGNBRK; |
630 | | BRKINT; |
631 | | IGNPAR; |
632 | | PARMRK; |
633 | | INPCK; |
634 | | ISTRIP; |
635 | | INLCR; |
636 | | IGNCR; |
637 | | ICRNL; |
638 | | IXON; |
639 | | IXOFF; |
640 | | #[cfg(not(target_os = "redox"))] |
641 | | #[cfg_attr(docsrs, doc(cfg(all())))] |
642 | | IXANY; |
643 | | #[cfg(not(any(target_os = "redox", target_os = "haiku")))] |
644 | | #[cfg_attr(docsrs, doc(cfg(all())))] |
645 | | IMAXBEL; |
646 | | #[cfg(any(target_os = "android", target_os = "linux", target_os = "macos"))] |
647 | | #[cfg_attr(docsrs, doc(cfg(all())))] |
648 | | IUTF8; |
649 | | } |
650 | | } |
651 | | |
652 | | libc_bitflags! { |
653 | | /// Flags for configuring the output mode of a terminal |
654 | | pub struct OutputFlags: tcflag_t { |
655 | | OPOST; |
656 | | #[cfg(any(target_os = "android", |
657 | | target_os = "haiku", |
658 | | target_os = "linux", |
659 | | target_os = "openbsd"))] |
660 | | #[cfg_attr(docsrs, doc(cfg(all())))] |
661 | | OLCUC; |
662 | | ONLCR; |
663 | | OCRNL as tcflag_t; |
664 | | ONOCR as tcflag_t; |
665 | | ONLRET as tcflag_t; |
666 | | #[cfg(any(target_os = "android", |
667 | | target_os = "haiku", |
668 | | target_os = "ios", |
669 | | target_os = "linux", |
670 | | target_os = "macos"))] |
671 | | #[cfg_attr(docsrs, doc(cfg(all())))] |
672 | | OFILL as tcflag_t; |
673 | | #[cfg(any(target_os = "android", |
674 | | target_os = "haiku", |
675 | | target_os = "ios", |
676 | | target_os = "linux", |
677 | | target_os = "macos"))] |
678 | | #[cfg_attr(docsrs, doc(cfg(all())))] |
679 | | OFDEL as tcflag_t; |
680 | | #[cfg(any(target_os = "android", |
681 | | target_os = "haiku", |
682 | | target_os = "ios", |
683 | | target_os = "linux", |
684 | | target_os = "macos"))] |
685 | | #[cfg_attr(docsrs, doc(cfg(all())))] |
686 | | NL0 as tcflag_t; |
687 | | #[cfg(any(target_os = "android", |
688 | | target_os = "haiku", |
689 | | target_os = "ios", |
690 | | target_os = "linux", |
691 | | target_os = "macos"))] |
692 | | #[cfg_attr(docsrs, doc(cfg(all())))] |
693 | | NL1 as tcflag_t; |
694 | | #[cfg(any(target_os = "android", |
695 | | target_os = "haiku", |
696 | | target_os = "ios", |
697 | | target_os = "linux", |
698 | | target_os = "macos"))] |
699 | | #[cfg_attr(docsrs, doc(cfg(all())))] |
700 | | CR0 as tcflag_t; |
701 | | #[cfg(any(target_os = "android", |
702 | | target_os = "haiku", |
703 | | target_os = "ios", |
704 | | target_os = "linux", |
705 | | target_os = "macos"))] |
706 | | #[cfg_attr(docsrs, doc(cfg(all())))] |
707 | | CR1 as tcflag_t; |
708 | | #[cfg(any(target_os = "android", |
709 | | target_os = "haiku", |
710 | | target_os = "ios", |
711 | | target_os = "linux", |
712 | | target_os = "macos"))] |
713 | | #[cfg_attr(docsrs, doc(cfg(all())))] |
714 | | CR2 as tcflag_t; |
715 | | #[cfg(any(target_os = "android", |
716 | | target_os = "haiku", |
717 | | target_os = "ios", |
718 | | target_os = "linux", |
719 | | target_os = "macos"))] |
720 | | #[cfg_attr(docsrs, doc(cfg(all())))] |
721 | | CR3 as tcflag_t; |
722 | | #[cfg(any(target_os = "android", |
723 | | target_os = "freebsd", |
724 | | target_os = "haiku", |
725 | | target_os = "ios", |
726 | | target_os = "linux", |
727 | | target_os = "macos"))] |
728 | | #[cfg_attr(docsrs, doc(cfg(all())))] |
729 | | TAB0 as tcflag_t; |
730 | | #[cfg(any(target_os = "android", |
731 | | target_os = "haiku", |
732 | | target_os = "ios", |
733 | | target_os = "linux", |
734 | | target_os = "macos"))] |
735 | | #[cfg_attr(docsrs, doc(cfg(all())))] |
736 | | TAB1 as tcflag_t; |
737 | | #[cfg(any(target_os = "android", |
738 | | target_os = "haiku", |
739 | | target_os = "ios", |
740 | | target_os = "linux", |
741 | | target_os = "macos"))] |
742 | | #[cfg_attr(docsrs, doc(cfg(all())))] |
743 | | TAB2 as tcflag_t; |
744 | | #[cfg(any(target_os = "android", |
745 | | target_os = "freebsd", |
746 | | target_os = "haiku", |
747 | | target_os = "ios", |
748 | | target_os = "linux", |
749 | | target_os = "macos"))] |
750 | | #[cfg_attr(docsrs, doc(cfg(all())))] |
751 | | TAB3 as tcflag_t; |
752 | | #[cfg(any(target_os = "android", target_os = "linux"))] |
753 | | #[cfg_attr(docsrs, doc(cfg(all())))] |
754 | | XTABS; |
755 | | #[cfg(any(target_os = "android", |
756 | | target_os = "haiku", |
757 | | target_os = "ios", |
758 | | target_os = "linux", |
759 | | target_os = "macos"))] |
760 | | #[cfg_attr(docsrs, doc(cfg(all())))] |
761 | | BS0 as tcflag_t; |
762 | | #[cfg(any(target_os = "android", |
763 | | target_os = "haiku", |
764 | | target_os = "ios", |
765 | | target_os = "linux", |
766 | | target_os = "macos"))] |
767 | | #[cfg_attr(docsrs, doc(cfg(all())))] |
768 | | BS1 as tcflag_t; |
769 | | #[cfg(any(target_os = "android", |
770 | | target_os = "haiku", |
771 | | target_os = "ios", |
772 | | target_os = "linux", |
773 | | target_os = "macos"))] |
774 | | #[cfg_attr(docsrs, doc(cfg(all())))] |
775 | | VT0 as tcflag_t; |
776 | | #[cfg(any(target_os = "android", |
777 | | target_os = "haiku", |
778 | | target_os = "ios", |
779 | | target_os = "linux", |
780 | | target_os = "macos"))] |
781 | | #[cfg_attr(docsrs, doc(cfg(all())))] |
782 | | VT1 as tcflag_t; |
783 | | #[cfg(any(target_os = "android", |
784 | | target_os = "haiku", |
785 | | target_os = "ios", |
786 | | target_os = "linux", |
787 | | target_os = "macos"))] |
788 | | #[cfg_attr(docsrs, doc(cfg(all())))] |
789 | | FF0 as tcflag_t; |
790 | | #[cfg(any(target_os = "android", |
791 | | target_os = "haiku", |
792 | | target_os = "ios", |
793 | | target_os = "linux", |
794 | | target_os = "macos"))] |
795 | | #[cfg_attr(docsrs, doc(cfg(all())))] |
796 | | FF1 as tcflag_t; |
797 | | #[cfg(any(target_os = "freebsd", |
798 | | target_os = "dragonfly", |
799 | | target_os = "ios", |
800 | | target_os = "macos", |
801 | | target_os = "netbsd", |
802 | | target_os = "openbsd"))] |
803 | | #[cfg_attr(docsrs, doc(cfg(all())))] |
804 | | OXTABS; |
805 | | #[cfg(any(target_os = "freebsd", |
806 | | target_os = "dragonfly", |
807 | | target_os = "macos", |
808 | | target_os = "netbsd", |
809 | | target_os = "openbsd"))] |
810 | | #[cfg_attr(docsrs, doc(cfg(all())))] |
811 | | ONOEOT as tcflag_t; |
812 | | |
813 | | // Bitmasks for use with OutputFlags to select specific settings |
814 | | // These should be moved to be a mask once https://github.com/rust-lang-nursery/bitflags/issues/110 |
815 | | // is resolved. |
816 | | |
817 | | #[cfg(any(target_os = "android", |
818 | | target_os = "haiku", |
819 | | target_os = "ios", |
820 | | target_os = "linux", |
821 | | target_os = "macos"))] |
822 | | #[cfg_attr(docsrs, doc(cfg(all())))] |
823 | | NLDLY as tcflag_t; // FIXME: Datatype needs to be corrected in libc for mac |
824 | | #[cfg(any(target_os = "android", |
825 | | target_os = "haiku", |
826 | | target_os = "ios", |
827 | | target_os = "linux", |
828 | | target_os = "macos"))] |
829 | | #[cfg_attr(docsrs, doc(cfg(all())))] |
830 | | CRDLY as tcflag_t; |
831 | | #[cfg(any(target_os = "android", |
832 | | target_os = "freebsd", |
833 | | target_os = "haiku", |
834 | | target_os = "ios", |
835 | | target_os = "linux", |
836 | | target_os = "macos"))] |
837 | | #[cfg_attr(docsrs, doc(cfg(all())))] |
838 | | TABDLY as tcflag_t; |
839 | | #[cfg(any(target_os = "android", |
840 | | target_os = "haiku", |
841 | | target_os = "ios", |
842 | | target_os = "linux", |
843 | | target_os = "macos"))] |
844 | | #[cfg_attr(docsrs, doc(cfg(all())))] |
845 | | BSDLY as tcflag_t; |
846 | | #[cfg(any(target_os = "android", |
847 | | target_os = "haiku", |
848 | | target_os = "ios", |
849 | | target_os = "linux", |
850 | | target_os = "macos"))] |
851 | | #[cfg_attr(docsrs, doc(cfg(all())))] |
852 | | VTDLY as tcflag_t; |
853 | | #[cfg(any(target_os = "android", |
854 | | target_os = "haiku", |
855 | | target_os = "ios", |
856 | | target_os = "linux", |
857 | | target_os = "macos"))] |
858 | | #[cfg_attr(docsrs, doc(cfg(all())))] |
859 | | FFDLY as tcflag_t; |
860 | | } |
861 | | } |
862 | | |
863 | | libc_bitflags! { |
864 | | /// Flags for setting the control mode of a terminal |
865 | | pub struct ControlFlags: tcflag_t { |
866 | | #[cfg(any(target_os = "dragonfly", |
867 | | target_os = "freebsd", |
868 | | target_os = "ios", |
869 | | target_os = "macos", |
870 | | target_os = "netbsd", |
871 | | target_os = "openbsd"))] |
872 | | #[cfg_attr(docsrs, doc(cfg(all())))] |
873 | | CIGNORE; |
874 | | CS5; |
875 | | CS6; |
876 | | CS7; |
877 | | CS8; |
878 | | CSTOPB; |
879 | | CREAD; |
880 | | PARENB; |
881 | | PARODD; |
882 | | HUPCL; |
883 | | CLOCAL; |
884 | | #[cfg(not(target_os = "redox"))] |
885 | | #[cfg_attr(docsrs, doc(cfg(all())))] |
886 | | CRTSCTS; |
887 | | #[cfg(any(target_os = "android", target_os = "linux"))] |
888 | | #[cfg_attr(docsrs, doc(cfg(all())))] |
889 | | CBAUD; |
890 | | #[cfg(any(target_os = "android", all(target_os = "linux", not(target_arch = "mips"))))] |
891 | | #[cfg_attr(docsrs, doc(cfg(all())))] |
892 | | CMSPAR; |
893 | | #[cfg(any(target_os = "android", |
894 | | all(target_os = "linux", |
895 | | not(any(target_arch = "powerpc", target_arch = "powerpc64")))))] |
896 | | CIBAUD; |
897 | | #[cfg(any(target_os = "android", target_os = "linux"))] |
898 | | #[cfg_attr(docsrs, doc(cfg(all())))] |
899 | | CBAUDEX; |
900 | | #[cfg(any(target_os = "dragonfly", |
901 | | target_os = "freebsd", |
902 | | target_os = "macos", |
903 | | target_os = "netbsd", |
904 | | target_os = "openbsd"))] |
905 | | #[cfg_attr(docsrs, doc(cfg(all())))] |
906 | | MDMBUF; |
907 | | #[cfg(any(target_os = "netbsd", target_os = "openbsd"))] |
908 | | #[cfg_attr(docsrs, doc(cfg(all())))] |
909 | | CHWFLOW; |
910 | | #[cfg(any(target_os = "dragonfly", |
911 | | target_os = "freebsd", |
912 | | target_os = "netbsd", |
913 | | target_os = "openbsd"))] |
914 | | #[cfg_attr(docsrs, doc(cfg(all())))] |
915 | | CCTS_OFLOW; |
916 | | #[cfg(any(target_os = "dragonfly", |
917 | | target_os = "freebsd", |
918 | | target_os = "netbsd", |
919 | | target_os = "openbsd"))] |
920 | | #[cfg_attr(docsrs, doc(cfg(all())))] |
921 | | CRTS_IFLOW; |
922 | | #[cfg(any(target_os = "dragonfly", |
923 | | target_os = "freebsd"))] |
924 | | #[cfg_attr(docsrs, doc(cfg(all())))] |
925 | | CDTR_IFLOW; |
926 | | #[cfg(any(target_os = "dragonfly", |
927 | | target_os = "freebsd"))] |
928 | | #[cfg_attr(docsrs, doc(cfg(all())))] |
929 | | CDSR_OFLOW; |
930 | | #[cfg(any(target_os = "dragonfly", |
931 | | target_os = "freebsd"))] |
932 | | #[cfg_attr(docsrs, doc(cfg(all())))] |
933 | | CCAR_OFLOW; |
934 | | |
935 | | // Bitmasks for use with ControlFlags to select specific settings |
936 | | // These should be moved to be a mask once https://github.com/rust-lang-nursery/bitflags/issues/110 |
937 | | // is resolved. |
938 | | |
939 | | CSIZE; |
940 | | } |
941 | | } |
942 | | |
943 | | libc_bitflags! { |
944 | | /// Flags for setting any local modes |
945 | | pub struct LocalFlags: tcflag_t { |
946 | | #[cfg(not(target_os = "redox"))] |
947 | | #[cfg_attr(docsrs, doc(cfg(all())))] |
948 | | ECHOKE; |
949 | | ECHOE; |
950 | | ECHOK; |
951 | | ECHO; |
952 | | ECHONL; |
953 | | #[cfg(not(target_os = "redox"))] |
954 | | #[cfg_attr(docsrs, doc(cfg(all())))] |
955 | | ECHOPRT; |
956 | | #[cfg(not(target_os = "redox"))] |
957 | | #[cfg_attr(docsrs, doc(cfg(all())))] |
958 | | ECHOCTL; |
959 | | ISIG; |
960 | | ICANON; |
961 | | #[cfg(any(target_os = "freebsd", |
962 | | target_os = "dragonfly", |
963 | | target_os = "ios", |
964 | | target_os = "macos", |
965 | | target_os = "netbsd", |
966 | | target_os = "openbsd"))] |
967 | | #[cfg_attr(docsrs, doc(cfg(all())))] |
968 | | ALTWERASE; |
969 | | IEXTEN; |
970 | | #[cfg(not(any(target_os = "redox", target_os = "haiku")))] |
971 | | #[cfg_attr(docsrs, doc(cfg(all())))] |
972 | | EXTPROC; |
973 | | TOSTOP; |
974 | | #[cfg(not(target_os = "redox"))] |
975 | | #[cfg_attr(docsrs, doc(cfg(all())))] |
976 | | FLUSHO; |
977 | | #[cfg(any(target_os = "freebsd", |
978 | | target_os = "dragonfly", |
979 | | target_os = "ios", |
980 | | target_os = "macos", |
981 | | target_os = "netbsd", |
982 | | target_os = "openbsd"))] |
983 | | #[cfg_attr(docsrs, doc(cfg(all())))] |
984 | | NOKERNINFO; |
985 | | #[cfg(not(target_os = "redox"))] |
986 | | #[cfg_attr(docsrs, doc(cfg(all())))] |
987 | | PENDIN; |
988 | | NOFLSH; |
989 | | } |
990 | | } |
991 | | |
992 | | cfg_if! { |
993 | | if #[cfg(any(target_os = "freebsd", |
994 | | target_os = "dragonfly", |
995 | | target_os = "ios", |
996 | | target_os = "macos", |
997 | | target_os = "netbsd", |
998 | | target_os = "openbsd"))] { |
999 | | /// Get input baud rate (see |
1000 | | /// [cfgetispeed(3p)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/cfgetispeed.html)). |
1001 | | /// |
1002 | | /// `cfgetispeed()` extracts the input baud rate from the given `Termios` structure. |
1003 | | // The cast is not unnecessary on all platforms. |
1004 | | #[allow(clippy::unnecessary_cast)] |
1005 | | pub fn cfgetispeed(termios: &Termios) -> u32 { |
1006 | | let inner_termios = termios.get_libc_termios(); |
1007 | | unsafe { libc::cfgetispeed(&*inner_termios) as u32 } |
1008 | | } |
1009 | | |
1010 | | /// Get output baud rate (see |
1011 | | /// [cfgetospeed(3p)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/cfgetospeed.html)). |
1012 | | /// |
1013 | | /// `cfgetospeed()` extracts the output baud rate from the given `Termios` structure. |
1014 | | // The cast is not unnecessary on all platforms. |
1015 | | #[allow(clippy::unnecessary_cast)] |
1016 | | pub fn cfgetospeed(termios: &Termios) -> u32 { |
1017 | | let inner_termios = termios.get_libc_termios(); |
1018 | | unsafe { libc::cfgetospeed(&*inner_termios) as u32 } |
1019 | | } |
1020 | | |
1021 | | /// Set input baud rate (see |
1022 | | /// [cfsetispeed(3p)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/cfsetispeed.html)). |
1023 | | /// |
1024 | | /// `cfsetispeed()` sets the intput baud rate in the given `Termios` structure. |
1025 | | pub fn cfsetispeed<T: Into<u32>>(termios: &mut Termios, baud: T) -> Result<()> { |
1026 | | let inner_termios = unsafe { termios.get_libc_termios_mut() }; |
1027 | | let res = unsafe { libc::cfsetispeed(inner_termios, baud.into() as libc::speed_t) }; |
1028 | | termios.update_wrapper(); |
1029 | | Errno::result(res).map(drop) |
1030 | | } |
1031 | | |
1032 | | /// Set output baud rate (see |
1033 | | /// [cfsetospeed(3p)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/cfsetospeed.html)). |
1034 | | /// |
1035 | | /// `cfsetospeed()` sets the output baud rate in the given termios structure. |
1036 | | pub fn cfsetospeed<T: Into<u32>>(termios: &mut Termios, baud: T) -> Result<()> { |
1037 | | let inner_termios = unsafe { termios.get_libc_termios_mut() }; |
1038 | | let res = unsafe { libc::cfsetospeed(inner_termios, baud.into() as libc::speed_t) }; |
1039 | | termios.update_wrapper(); |
1040 | | Errno::result(res).map(drop) |
1041 | | } |
1042 | | |
1043 | | /// Set both the input and output baud rates (see |
1044 | | /// [termios(3)](https://www.freebsd.org/cgi/man.cgi?query=cfsetspeed)). |
1045 | | /// |
1046 | | /// `cfsetspeed()` sets the input and output baud rate in the given termios structure. Note that |
1047 | | /// this is part of the 4.4BSD standard and not part of POSIX. |
1048 | | pub fn cfsetspeed<T: Into<u32>>(termios: &mut Termios, baud: T) -> Result<()> { |
1049 | | let inner_termios = unsafe { termios.get_libc_termios_mut() }; |
1050 | | let res = unsafe { libc::cfsetspeed(inner_termios, baud.into() as libc::speed_t) }; |
1051 | | termios.update_wrapper(); |
1052 | | Errno::result(res).map(drop) |
1053 | | } |
1054 | | } else { |
1055 | | use std::convert::TryInto; |
1056 | | |
1057 | | /// Get input baud rate (see |
1058 | | /// [cfgetispeed(3p)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/cfgetispeed.html)). |
1059 | | /// |
1060 | | /// `cfgetispeed()` extracts the input baud rate from the given `Termios` structure. |
1061 | 0 | pub fn cfgetispeed(termios: &Termios) -> BaudRate { |
1062 | 0 | let inner_termios = termios.get_libc_termios(); |
1063 | 0 | unsafe { libc::cfgetispeed(&*inner_termios) }.try_into().unwrap() |
1064 | 0 | } |
1065 | | |
1066 | | /// Get output baud rate (see |
1067 | | /// [cfgetospeed(3p)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/cfgetospeed.html)). |
1068 | | /// |
1069 | | /// `cfgetospeed()` extracts the output baud rate from the given `Termios` structure. |
1070 | 0 | pub fn cfgetospeed(termios: &Termios) -> BaudRate { |
1071 | 0 | let inner_termios = termios.get_libc_termios(); |
1072 | 0 | unsafe { libc::cfgetospeed(&*inner_termios) }.try_into().unwrap() |
1073 | 0 | } |
1074 | | |
1075 | | /// Set input baud rate (see |
1076 | | /// [cfsetispeed(3p)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/cfsetispeed.html)). |
1077 | | /// |
1078 | | /// `cfsetispeed()` sets the intput baud rate in the given `Termios` structure. |
1079 | 0 | pub fn cfsetispeed(termios: &mut Termios, baud: BaudRate) -> Result<()> { |
1080 | 0 | let inner_termios = unsafe { termios.get_libc_termios_mut() }; |
1081 | 0 | let res = unsafe { libc::cfsetispeed(inner_termios, baud as libc::speed_t) }; |
1082 | 0 | termios.update_wrapper(); |
1083 | 0 | Errno::result(res).map(drop) |
1084 | 0 | } |
1085 | | |
1086 | | /// Set output baud rate (see |
1087 | | /// [cfsetospeed(3p)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/cfsetospeed.html)). |
1088 | | /// |
1089 | | /// `cfsetospeed()` sets the output baud rate in the given `Termios` structure. |
1090 | 0 | pub fn cfsetospeed(termios: &mut Termios, baud: BaudRate) -> Result<()> { |
1091 | 0 | let inner_termios = unsafe { termios.get_libc_termios_mut() }; |
1092 | 0 | let res = unsafe { libc::cfsetospeed(inner_termios, baud as libc::speed_t) }; |
1093 | 0 | termios.update_wrapper(); |
1094 | 0 | Errno::result(res).map(drop) |
1095 | 0 | } |
1096 | | |
1097 | | /// Set both the input and output baud rates (see |
1098 | | /// [termios(3)](https://www.freebsd.org/cgi/man.cgi?query=cfsetspeed)). |
1099 | | /// |
1100 | | /// `cfsetspeed()` sets the input and output baud rate in the given `Termios` structure. Note that |
1101 | | /// this is part of the 4.4BSD standard and not part of POSIX. |
1102 | | #[cfg(not(target_os = "haiku"))] |
1103 | 0 | pub fn cfsetspeed(termios: &mut Termios, baud: BaudRate) -> Result<()> { |
1104 | 0 | let inner_termios = unsafe { termios.get_libc_termios_mut() }; |
1105 | 0 | let res = unsafe { libc::cfsetspeed(inner_termios, baud as libc::speed_t) }; |
1106 | 0 | termios.update_wrapper(); |
1107 | 0 | Errno::result(res).map(drop) |
1108 | 0 | } |
1109 | | } |
1110 | | } |
1111 | | |
1112 | | /// Configures the port to something like the "raw" mode of the old Version 7 terminal driver (see |
1113 | | /// [termios(3)](https://man7.org/linux/man-pages/man3/termios.3.html)). |
1114 | | /// |
1115 | | /// `cfmakeraw()` configures the termios structure such that input is available character-by- |
1116 | | /// character, echoing is disabled, and all special input and output processing is disabled. Note |
1117 | | /// that this is a non-standard function, but is available on Linux and BSDs. |
1118 | 0 | pub fn cfmakeraw(termios: &mut Termios) { |
1119 | 0 | let inner_termios = unsafe { termios.get_libc_termios_mut() }; |
1120 | 0 | unsafe { |
1121 | 0 | libc::cfmakeraw(inner_termios); |
1122 | 0 | } |
1123 | 0 | termios.update_wrapper(); |
1124 | 0 | } |
1125 | | |
1126 | | /// Configures the port to "sane" mode (like the configuration of a newly created terminal) (see |
1127 | | /// [tcsetattr(3)](https://www.freebsd.org/cgi/man.cgi?query=tcsetattr)). |
1128 | | /// |
1129 | | /// Note that this is a non-standard function, available on FreeBSD. |
1130 | | #[cfg(target_os = "freebsd")] |
1131 | | #[cfg_attr(docsrs, doc(cfg(all())))] |
1132 | | pub fn cfmakesane(termios: &mut Termios) { |
1133 | | let inner_termios = unsafe { termios.get_libc_termios_mut() }; |
1134 | | unsafe { |
1135 | | libc::cfmakesane(inner_termios); |
1136 | | } |
1137 | | termios.update_wrapper(); |
1138 | | } |
1139 | | |
1140 | | /// Return the configuration of a port |
1141 | | /// [tcgetattr(3p)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/tcgetattr.html)). |
1142 | | /// |
1143 | | /// `tcgetattr()` returns a `Termios` structure with the current configuration for a port. Modifying |
1144 | | /// this structure *will not* reconfigure the port, instead the modifications should be done to |
1145 | | /// the `Termios` structure and then the port should be reconfigured using `tcsetattr()`. |
1146 | 0 | pub fn tcgetattr(fd: RawFd) -> Result<Termios> { |
1147 | 0 | let mut termios = mem::MaybeUninit::uninit(); |
1148 | 0 |
|
1149 | 0 | let res = unsafe { libc::tcgetattr(fd, termios.as_mut_ptr()) }; |
1150 | 0 |
|
1151 | 0 | Errno::result(res)?; |
1152 | | |
1153 | 0 | unsafe { Ok(termios.assume_init().into()) } |
1154 | 0 | } |
1155 | | |
1156 | | /// Set the configuration for a terminal (see |
1157 | | /// [tcsetattr(3p)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/tcsetattr.html)). |
1158 | | /// |
1159 | | /// `tcsetattr()` reconfigures the given port based on a given `Termios` structure. This change |
1160 | | /// takes affect at a time specified by `actions`. Note that this function may return success if |
1161 | | /// *any* of the parameters were successfully set, not only if all were set successfully. |
1162 | 0 | pub fn tcsetattr(fd: RawFd, actions: SetArg, termios: &Termios) -> Result<()> { |
1163 | 0 | let inner_termios = termios.get_libc_termios(); |
1164 | 0 | Errno::result(unsafe { |
1165 | 0 | libc::tcsetattr(fd, actions as c_int, &*inner_termios) |
1166 | 0 | }) |
1167 | 0 | .map(drop) |
1168 | 0 | } |
1169 | | |
1170 | | /// Block until all output data is written (see |
1171 | | /// [tcdrain(3p)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/tcdrain.html)). |
1172 | 0 | pub fn tcdrain(fd: RawFd) -> Result<()> { |
1173 | 0 | Errno::result(unsafe { libc::tcdrain(fd) }).map(drop) |
1174 | 0 | } |
1175 | | |
1176 | | /// Suspend or resume the transmission or reception of data (see |
1177 | | /// [tcflow(3p)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/tcflow.html)). |
1178 | | /// |
1179 | | /// `tcflow()` suspends of resumes the transmission or reception of data for the given port |
1180 | | /// depending on the value of `action`. |
1181 | 0 | pub fn tcflow(fd: RawFd, action: FlowArg) -> Result<()> { |
1182 | 0 | Errno::result(unsafe { libc::tcflow(fd, action as c_int) }).map(drop) |
1183 | 0 | } |
1184 | | |
1185 | | /// Discard data in the output or input queue (see |
1186 | | /// [tcflush(3p)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/tcflush.html)). |
1187 | | /// |
1188 | | /// `tcflush()` will discard data for a terminal port in the input queue, output queue, or both |
1189 | | /// depending on the value of `action`. |
1190 | 0 | pub fn tcflush(fd: RawFd, action: FlushArg) -> Result<()> { |
1191 | 0 | Errno::result(unsafe { libc::tcflush(fd, action as c_int) }).map(drop) |
1192 | 0 | } |
1193 | | |
1194 | | /// Send a break for a specific duration (see |
1195 | | /// [tcsendbreak(3p)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/tcsendbreak.html)). |
1196 | | /// |
1197 | | /// When using asynchronous data transmission `tcsendbreak()` will transmit a continuous stream |
1198 | | /// of zero-valued bits for an implementation-defined duration. |
1199 | 0 | pub fn tcsendbreak(fd: RawFd, duration: c_int) -> Result<()> { |
1200 | 0 | Errno::result(unsafe { libc::tcsendbreak(fd, duration) }).map(drop) |
1201 | 0 | } |
1202 | | |
1203 | | feature! { |
1204 | | #![feature = "process"] |
1205 | | /// Get the session controlled by the given terminal (see |
1206 | | /// [tcgetsid(3)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/tcgetsid.html)). |
1207 | 0 | pub fn tcgetsid(fd: RawFd) -> Result<Pid> { |
1208 | 0 | let res = unsafe { libc::tcgetsid(fd) }; |
1209 | 0 |
|
1210 | 0 | Errno::result(res).map(Pid::from_raw) |
1211 | 0 | } |
1212 | | } |
1213 | | |
1214 | | #[cfg(test)] |
1215 | | mod test { |
1216 | | use super::*; |
1217 | | use std::convert::TryFrom; |
1218 | | |
1219 | | #[test] |
1220 | | fn try_from() { |
1221 | | assert_eq!(Ok(BaudRate::B0), BaudRate::try_from(libc::B0)); |
1222 | | #[cfg(not(target_os = "haiku"))] |
1223 | | BaudRate::try_from(999999999).expect_err("assertion failed"); |
1224 | | #[cfg(target_os = "haiku")] |
1225 | | BaudRate::try_from(99).expect_err("assertion failed"); |
1226 | | } |
1227 | | } |