1 module socat; 2 3 version (Posix) {} 4 else static assert(0, "support only posix platform"); 5 6 import std.process; 7 import std.string; 8 import std.exception; 9 10 import core.sys.posix.unistd : getuid; 11 12 auto runSocat(uint bufferSize=1024) 13 { 14 struct Result 15 { 16 ProcessPipes pipe; 17 string port1, port2; 18 19 string[2] ports() const @property 20 { return [port1, port2]; } 21 22 this(int bufsz) 23 { 24 enforce(getuid() == 0, "you must be a root"); 25 auto cmd = ("socat -d -d -b%d pty,raw,"~ 26 "echo=0 pty,raw,echo=0").format(bufsz); 27 import std.stdio; 28 writeln(cmd); 29 pipe = pipeShell(cmd); 30 31 port1 = parsePort(pipe.stderr.readln.strip); 32 port2 = parsePort(pipe.stderr.readln.strip); 33 } 34 35 string parsePort(string ln) 36 { 37 import std.file : exists; 38 auto p = parseSocatPort(ln); 39 enforce(p.exists, "%s doesn't exists".format(p)); 40 return p; 41 } 42 43 ~this() { kill(pipe.pid); } 44 } 45 46 return Result(bufferSize); 47 } 48 49 string parseSocatPort(string ln) 50 { 51 // 52 auto ret = ln.split[$-1]; 53 enforce(ret.startsWith("/dev/pts/"), 54 "unexpected last word in output line '%s'".format(ln)); 55 return ret; 56 } 57 58 unittest 59 { 60 assert("2018/03/08 02:56:58 socat[30331] N PTY is /dev/pts/1" 61 .parseSocatPort == "/dev/pts/1"); 62 63 assertThrown("some string".parseSocatPort); 64 }