pty.ha (1962B)
1 // SPDX-License-Identifier: MPL-2.0 2 // (c) Hare authors <https://harelang.org> 3 4 use errors; 5 use fs; 6 use io; 7 use rt; 8 use types::c; 9 10 // Opens an available pseudoterminal and returns the file descriptors of the 11 // master and slave. 12 export fn openpty() ((io::file, io::file) | fs::error) = { 13 let master = open_master()?; 14 defer io::close(master)!; 15 16 let ptm = rt::ptmget { ... }; 17 match (rt::ioctl(master, rt::PTMGET, &ptm)) { 18 case let e: rt::errno => 19 return errors::errno(e); 20 case => void; 21 }; 22 23 return (ptm.cfd, ptm.sfd); 24 }; 25 26 // Opens an available pseudoterminal master. 27 fn open_master() (io::file | fs::error) = { 28 match (rt::open(rt::PATH_PTMDEV, rt::O_RDWR, 0)) { 29 case let e: rt::errno => 30 return errors::errno(e); 31 case let i: int => 32 return io::fdopen(i); 33 }; 34 }; 35 36 // Returns the filename of the pseudoterminal slave. 37 export fn ptsname(master: io::file) (str | error) = { 38 static let path_buf: [rt::PATH_MAX]u8 = [0...]; 39 40 let name = match (rt::ptsname(master)) { 41 case let name: *u8 => 42 yield name: *[*]u8; 43 case let err: rt::errno => 44 switch (err) { 45 // master is not a pseudo-terminal device 46 case rt::EINVAL => 47 return errors::unsupported; 48 // master is not an open valid file descriptor 49 case rt::EBADF => 50 return errors::invalid; 51 case => 52 abort("Unexpected error from ptsname"); 53 }; 54 }; 55 let namelen = c::strlen(name: *const c::char); 56 path_buf[..namelen] = name[..namelen]; 57 58 return c::tostrn(&path_buf: *const c::char, namelen)!; 59 }; 60 61 // Sets the dimensions of the underlying pseudoterminal for an [[io::file]]. 62 export fn set_winsize(pty: io::file, sz: ttysize) (void | error) = { 63 let wsz = rt::winsize { ws_row = sz.rows, ws_col = sz.columns, ... }; 64 match (rt::ioctl(pty, rt::TIOCSWINSZ, &wsz)) { 65 case let e: rt::errno => 66 switch (e) { 67 case rt::EBADF, rt::EINVAL => 68 return errors::invalid; 69 case rt::ENOTTY => 70 return errors::unsupported; 71 case => 72 abort("Unexpected error from ioctl"); 73 }; 74 case => void; 75 }; 76 };