hare

[hare] The Hare programming language
git clone https://git.torresjrjr.com/hare.git
Log | Files | Refs | README | LICENSE

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 };