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