| 9 | |
| 10 | #[test] |
| 11 | fn openpty_basic() { |
| 12 | // Use `CLOEXEC` if we can. |
| 13 | #[cfg(any(linux_kernel, target_os = "freebsd", target_os = "netbsd"))] |
| 14 | let flags = OpenptFlags::RDWR | OpenptFlags::NOCTTY | OpenptFlags::CLOEXEC; |
| 15 | #[cfg(not(any(linux_kernel, target_os = "freebsd", target_os = "netbsd")))] |
| 16 | let flags = OpenptFlags::RDWR | OpenptFlags::NOCTTY; |
| 17 | |
| 18 | let controller = openpt(flags).unwrap(); |
| 19 | |
| 20 | grantpt(&controller).unwrap(); |
| 21 | unlockpt(&controller).unwrap(); |
| 22 | |
| 23 | let name = match ptsname(&controller, Vec::new()) { |
| 24 | Ok(name) => name, |
| 25 | #[cfg(target_os = "freebsd")] |
| 26 | Err(rustix::io::Errno::NOSYS) => return, // FreeBSD 12 doesn't support this |
| 27 | Err(err) => panic!("{:?}", err), |
| 28 | }; |
| 29 | let user = openat( |
| 30 | CWD, |
| 31 | name, |
| 32 | OFlags::RDWR | OFlags::NOCTTY | OFlags::CLOEXEC, |
| 33 | Mode::empty(), |
| 34 | ) |
| 35 | .unwrap(); |
| 36 | |
| 37 | let mut controller = File::from(controller); |
| 38 | let mut user = File::from(user); |
| 39 | |
| 40 | // The `'\x04'` is Ctrl-D, the default EOF control code. |
| 41 | controller.write_all(b"Hello, world!\n\x04").unwrap(); |
| 42 | |
| 43 | let mut s = String::new(); |
| 44 | |
| 45 | // Read the string back. Our `\x04` above ended the stream, so we can |
| 46 | // read to the end of the stream. |
| 47 | #[cfg(not(target_os = "illumos"))] |
| 48 | { |
| 49 | user.read_to_string(&mut s).unwrap(); |
| 50 | } |
| 51 | |
| 52 | // Except on illumos, where the `\0x04` doesn't seem to translate into an |
| 53 | // EOF, so we didn't end the stream, so just the line. |
| 54 | #[cfg(target_os = "illumos")] |
| 55 | use std::io::{BufRead, BufReader}; |
| 56 | #[cfg(target_os = "illumos")] |
| 57 | let mut user = BufReader::new(user); |
| 58 | #[cfg(target_os = "illumos")] |
| 59 | { |
| 60 | user.read_line(&mut s).unwrap(); |
| 61 | } |
| 62 | |
| 63 | assert_eq!(s, "Hello, world!\n"); |
| 64 | } |
| 65 | |
| 66 | // Like `openpty_basic` but use `ioctl_tiocgptpeer` instead of `ptsname`. |
| 67 | #[cfg(target_os = "linux")] |