/* Ċ Ġ* ĠCopyright Ġ 2 0 1 9 ĠF elix ĠTree de Ċ Ġ* Ċ Ġ* ĠLicensed Ġunder Ġthe ĠApache ĠLicense , ĠVersion Ġ 2 . 0 Ġ( the Ġ" License "); Ċ Ġ* Ġyou Ġmay Ġnot Ġuse Ġthis Ġfile Ġexcept Ġin Ġcompliance Ġwith Ġthe ĠLicense . Ċ Ġ* ĠYou Ġmay Ġobtain Ġa Ġcopy Ġof Ġthe ĠLicense Ġat Ċ Ġ* Ċ Ġ* ĠĠĠ Ġhttp :// www . apache . org / licenses / LICENSE - 2 . 0 Ċ Ġ* Ċ Ġ* ĠUnless Ġrequired Ġby Ġapplicable Ġlaw Ġor Ġagreed Ġto Ġin Ġwriting , Ġsoftware Ċ Ġ* Ġdistributed Ġunder Ġthe ĠLicense Ġis Ġdistributed Ġon Ġan Ġ" AS ĠIS " ĠBASIS , Ċ Ġ* ĠWITHOUT ĠWARRANTIES ĠOR ĠCONDITIONS ĠOF ĠANY ĠKIND , Ġeither Ġexpress Ġor Ġimplied . Ċ Ġ* ĠSee Ġthe ĠLicense Ġfor Ġthe Ġspecific Ġlanguage Ġgoverning Ġpermissions Ġand Ċ Ġ* Ġlimitations Ġunder Ġthe ĠLicense . Ċ Ġ*/ Ċ package Ġd rew car l son . k subprocess Ċ Ċ import Ġio . ktor . utils . io . char sets .* Ċ import Ġio . ktor . utils . io . core .* Ċ import Ġkotlin . time .* Ċ Ċ /** Ċ Ġ* ĠResult Ġtuple Ġof ĠProcess . com municate (). Ċ Ġ* Ċ Ġ* Ġ@ param Ġexit Code Ġprocess Ġexit Ġcode . ĠIs Ġ 0 Ġif Ġthe Ġprocess Ġterminated Ġnormally Ċ Ġ* Ġ@ param Ġoutput Ġstdout Ġpipe Ġoutput , Ġor Ġempty Ġif Ġstdout Ġwasn 't Ġa Ġpipe Ċ Ġ* Ġ@ param Ġerrors Ġstderr Ġpipe Ġoutput , Ġor Ġempty Ġif Ġstderr Ġwasn 't Ġa Ġpipe Ċ Ġ*/ Ċ data Ġclass ĠCom municate Result ( ĊĠĠĠ Ġval Ġexit Code : ĠInt , ĊĠĠĠ Ġval Ġoutput : ĠString , ĊĠĠĠ Ġval Ġerrors : ĠString Ċ ) Ġ{ ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠCheck Ġthat Ġthe Ġprocess Ġexited Ġnormally , Ġie Ġwith Ġ[ exit Code ] Ġ 0 . ĠIf Ġnot , Ġthrow Ġ[ Process Exit Exception ]. ĊĠĠĠĠ Ġ* ĊĠĠĠĠ Ġ* Ġ@ throws ĠProcess Exit Exception Ġif Ġ` exit Code Ġ!= Ġ 0 ` ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġfun Ġcheck () Ġ{ ĊĠĠĠĠĠĠĠ Ġif Ġ( exit Code Ġ!= Ġ 0 ) Ġthrow ĠProcess Exit Exception ( this ) ĊĠĠĠ Ġ} Ċ } Ċ Ċ /** Ċ Ġ* ĠCom municate Ġwith Ġthe Ġprocess Ġand Ġwait Ġfor Ġit 's Ġtermination . Ċ Ġ* Ċ Ġ* ĠIf Ġstdin Ġis Ġa Ġpipe , Ġinput Ġwill Ġbe Ġwritten Ġto Ġit . ĠAfter wards , Ġstdin Ġwill Ġbe Ġclosed Ġto Ġsignal Ġend - of - input . Ċ Ġ* Ċ Ġ* ĠIf Ġstdout Ġor Ġstderr Ġare Ġpipes , Ġtheir Ġoutput Ġwill Ġbe Ġcollected Ġand Ġreturned Ġon Ġcompletion . ĠThe Ġpipes Ġwill Ġbe Ġclosed Ċ Ġ* Ġon Ġtermination . ĠThe Ġpipe Ġcollection Ġruns Ġin Ġbackground Ġthreads Ġto Ġavoid Ġbuffer Ġoverflow s Ġin Ġthe Ġpipe . Ċ Ġ* Ċ Ġ* ĠIf Ġa Ġtimeout Ġis Ġset , Ġthe Ġchild Ġwill Ġbe Ġ[ terminated ][ Process . terminate ] Ġif Ġit Ġdoesn 't Ġfinish Ġsoon Ġenough . ĠAn Ġextra Ċ Ġ* Ġtimeout Ġfor Ġgrace ful Ġtermination Ġcan Ġbe Ġset , Ġafterwards Ġthe Ġchild Ġwill Ġbe Ġ[ k illed ][ Process . kill ]. ĠThe Ġkill Ġtimeout Ċ Ġ* Ġcan Ġalso Ġbe Ġset Ġto Ġ[ Duration . ZERO ] Ġto Ġskip Ġthe Ġgrace ful Ġtermination Ġattempt Ġand Ġkill Ġthe Ġchild Ġdirectly . Ċ Ġ* Ċ Ġ* Ċ Ġ* Ġ@ param Ġinput Ġstdin Ġpipe Ġinput . ĠIgnore d Ġif Ġstdin Ġisn 't Ġa Ġpipe Ċ Ġ* Ġ@ param Ġcharset Ġcharset Ġto Ġuse Ġfor Ġtext Ġcommunication . ĠDefaults Ġto ĠUTF - 8 Ċ Ġ* Ġ@ param Ġtimeout Ġtimeout Ġfor Ġchild Ġprocess Ġif Ġdesired Ċ Ġ* Ġ@ param Ġkill Timeout Ġextra Ġtimeout Ġbefore Ġthe Ġterminated Ġchild Ġis Ġkilled . ĠMay Ġbe ĠZERO Ġto Ġkill Ġdirectly Ċ Ġ* Ċ Ġ* Ġ@ return Ġresult Ġof Ġcommunication Ċ Ġ* Ċ Ġ* Ġ@ throws ĠProcess Exception Ġif Ġanother Ġprocess Ġerror Ġoccurs Ċ Ġ* Ġ@ throws ĠIOException Ġif Ġan ĠIO Ġerror Ġoccurs Ġin Ġthe Ġpipes Ċ Ġ*/ Ċ fun ĠProcess . com municate ( ĊĠĠĠ Ġinput : ĠString Ġ= Ġ"", ĊĠĠĠ Ġcharset : ĠCharset Ġ= ĠChar sets . UTF _ 8 , ĊĠĠĠ Ġtimeout : ĠDuration ? Ġ= Ġnull , ĊĠĠĠ Ġkill Timeout : ĠDuration ? Ġ= Ġnull Ċ ): ĠCom municate Result Ġ{ ĊĠĠĠ Ġ// Ġstart Ġoutput Ġpipe Ġcollect ors ĊĠĠĠ Ġval Ġstdout Collector Ġ= ĊĠĠĠĠĠĠĠ Ġif Ġ( args . stdout Ġ== ĠRedirect . Pipe ) ĠBackground Pipe Collector ( this , Ġfalse , Ġcharset ) ĊĠĠĠĠĠĠĠ Ġelse Ġnull ĊĠĠĠ Ġval Ġstderr Collector Ġ= ĊĠĠĠĠĠĠĠ Ġif Ġ( args . stderr Ġ== ĠRedirect . Pipe ) ĠBackground Pipe Collector ( this , Ġtrue , Ġcharset ) ĊĠĠĠĠĠĠĠ Ġelse Ġnull ĊĊĠĠĠ Ġ// Ġpush Ġout Ġthe Ġinput Ġdata ĊĠĠĠ Ġstdin ?. let Ġ{ ĊĠĠĠĠĠĠĠ Ġit . write Text ( input , Ġcharset Ġ= Ġcharset ) ĊĠĠĠĠĠĠĠ Ġ// Ġclose Ġinput Ġstream Ġto Ġnotify Ġchild Ġof Ġinput Ġend ĊĠĠĠĠĠĠĠ Ġit . close () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ// Ġwait Ġwith Ġtimeout Ġif Ġneeded ĊĠĠĠ Ġif Ġ( timeout Ġ!= Ġnull Ġ&& ĠwaitFor ( timeout ) Ġ== Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠ Ġ// Ġdidn 't Ġexit Ġin Ġtimeout , Ġso Ġterminate Ġexplicitly ĊĠĠĠĠĠĠĠ Ġif Ġ( kill Timeout Ġ== ĠDuration . ZERO ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġkill Ġdirectly ĊĠĠĠĠĠĠĠĠĠĠĠ Ġkill () ĊĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġtry Ġg ently Ġfirst ĊĠĠĠĠĠĠĠĠĠĠĠ Ġterminate () ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġwait Ġa Ġlittle Ġmore Ġand Ġkill Ġif Ġrequested ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( kill Timeout Ġ!= Ġnull Ġ&& ĠwaitFor ( kill Timeout ) Ġ== Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġkill () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ// Ġwait Ġfor Ġthe Ġprocess Ġto Ġactually Ġdie ĊĠĠĠ Ġval Ġexit Code Ġ= ĠwaitFor () ĊĊĠĠĠ Ġ// Ġwait Ġfor Ġoutput Ġcollect ors ĊĠĠĠ ĠBackground Pipe Collector . await All ( listOf NotNull ( stdout Collector , Ġstderr Collector )) ĊĊĠĠĠ Ġ// Ġreturn Ġresult ĊĠĠĠ Ġreturn ĠCom municate Result ( ĊĠĠĠĠĠĠĠ Ġexit Code , ĊĠĠĠĠĠĠĠ Ġstdout Collector ?. result Ġ?: Ġ"", ĊĠĠĠĠĠĠĠ Ġstderr Collector ?. result Ġ?: Ġ"" ĊĠĠĠ Ġ) Ċ } Ċ Ċ /** ĠReads Ġthe Ġgiven Ġstream 's Ġtext Ġin Ġthe Ġbackground , Ġused Ġby Ġcommunicate . Ġ*/ Ċ internal Ġexpect Ġclass ĠBackground Pipe Collector ( ĊĠĠĠ Ġprocess : ĠProcess , ĊĠĠĠ Ġis Stderr : ĠBoolean , ĊĠĠĠ Ġcharset : ĠCharset Ċ ) Ġ{ ĊĠĠĠ Ġ// Ġwait Ġfor Ġthe Ġstream Ġto Ġreach ĠEOF ĊĠĠĠ Ġfun Ġawait () ĊĊĠĠĠ Ġ// Ġget Ġresult . Ġresult Ġof Ġcalling Ġbefore ĠEOF Ġis Ġunspecified ĊĠĠĠ Ġval Ġresult : ĠString ĊĊĠĠĠ Ġcompanion Ġobject Ġ{ ĊĠĠĠĠĠĠĠ Ġ// Ġwait Ġfor Ġall Ġstreams Ġin Ġlist ĊĠĠĠĠĠĠĠ Ġfun Ġawait All ( readers : ĠList < Background Pipe Collector >) ĊĠĠĠ Ġ} Ċ } ĊĊ