a hG@sdZddlZddlZddlZddlZddlZddlZddlZddlZddl Z ddl Z ddl Z ddl Z ddl mZmZmZddlmZmZedjZeddddZdZeeZd ZGd d d ejZGd d d ejZ GdddZ!Gdddeej"Z"GdddeZ#GdddZ$dS)zKBi-directional asyncio.Transport implementations based on file descriptors.N)AnyClassVarSequence) JsonObjectget_int)argsreturncGst|dkrtddS)Nrzprctl() failed) sys_prctlOSError)rr 6/usr/lib/python3.9/site-packages/cockpit/transports.pyprctl's ricseZdZUdZeeed<ejed<ej ed<ded<eed<eed<e ed <e ed <e ed <d Z e ed <dHejej eeddfdd Z ddddZ e dddZddddZddddZddddZdddd ZdId!dd"d#d$Ze dd%d&Zddd'd(Zedd)d*Zd+dd,d-ZdJd.d.dd/d0d1Zddd2d3Zddd4d5Zddd6d7Zedd8d9d:Zedd8d;d<Zddd=d>Zej dd?d@Z!e ddAdBZ"ej ddCdDdEZ#dddFdGZ$Z%S)K _Transporti BLOCK_SIZE_loop _protocolzcollections.deque[bytes] | None_queue_in_fd_out_fd_closing _is_reading_eofF _eio_is_eofNzdict[str, object] | None)loopprotocolin_fdout_fdextracst|||_||_td||||d|_d|_d|_d|_ ||_ ||_ t |d||krnt |d|j||dS)Nz/Created transport %s for protocol %s, fds %d %dF)super__init__rrloggerdebugrrrrrros set_blockingZconnection_maderesume_reading)selfrrrrr __class__r r r!Bs    z_Transport.__init__r c Cstd||j|jzt|jtj}Wnfty<YdSt y}z<|j rb|j t j krbd}n| |WYd}~dSWYd}~n d}~00|dkrtdt||j|n(td||j}|s|dS)NzRead ready on %s %s %dz read %d bytesz got EOF)r"r#rrr$readrrBlockingIOErrorr rerrnoZEIOabortlenZ data_received _close_readerZ eof_receivedclose)r'dataexcZ keep_openr r r _read_ready]s$  $  z_Transport._read_readycCs|jSN)rr'r r r is_readingvsz_Transport.is_readingcCs|d|_dSNr) pause_readingrr7r r r r1ysz_Transport._close_readercCs|jr|j|jd|_dSNF)rr remove_readerrr7r r r r:}sz_Transport.pause_readingcCs,|js(|jdkr(|j|j|jd|_dS)NrT)rrr add_readerr5r7r r r r&sz_Transport.resume_readingcCsdSr6r r7r r r _closesz_Transport._closezException | None)r4r cCs4d|_|||j|jj||dSNT)rr1_remove_write_queuerZ call_soonrZconnection_lostr>)r'r4r r r r/s z_Transport.abortcCstdSr6NotImplementedErrorr7r r r can_write_eofsz_Transport.can_write_eofcCs@|jr Jd|_|jdur0td||n td|dS)NTz%s got EOF. closing backend.z,%s got EOF. bytes in queue, deferring close)rrr"r#_write_eof_nowr7r r r write_eofs     z_Transport.write_eofcCs"|jdurdStdd|jDS)Nrcss|]}t|VqdSr6)r0).0blockr r r r+z3_Transport.get_write_buffer_size..)rsumr7r r r get_write_buffer_sizes z _Transport.get_write_buffer_sizeztuple[int, int]cCsdS)N)rrr r7r r r get_write_buffer_limitssz"_Transport.get_write_buffer_limits int | None)highlowr cCs,|dus|dksJ|dus(|dks(JdSNrr )r'rMrNr r r set_write_buffer_limitssz"_Transport.set_write_buffer_limitscCstdSr6rAr7r r r rDsz_Transport._write_eof_nowc Cstd||jdusJzt|j|j}WnDtyDd}Yn0tyr}z||WYd}~dSd}~00td||r|j }t ||krtd|j ||dq|t |8}td|q|jstd| |j rtd||jr|dS)Nz%s _write_readyrz, successfully wrote %d bytes from the queuez incomplete block. Stop.z& removed complete block. %d remains.z%s queue drained.z'%s queue drained. closing backend now.)r"r#rr$writevrr-r r/popleftr0 appendleftr@rrDr)r'n_bytesr4rGr r r _write_readys4          z_Transport._write_readycCs,|jdur(|j|j|jd|_dSr6)rrZresume_writingrZ remove_writerrr7r r r r@s  z_Transport._remove_write_queue)r3r cCsLtd||j|jdusJ|j|j|jt|f|_|j dS)Nz!%s creating write queue for fd %s) r"r#rrrZ add_writerrU collectionsdequerZ pause_writingr'r3r r r _create_write_queues z_Transport._create_write_queuec Cs|jrtd|jdS|jr"J|jdurl|j|t|jtkrhd |j}|j |j|dSzt |j|}WnDt yd}Yn0ty}z||WYd}~dSd}~00|t|kr|||ddS)Nz+ignoring write() to closing transport fd %ir+r)rr"r#rrrappendr0IOV_MAXjoinclearr$writer-r r/rY)r'r3Zall_datarTr4r r r r^s(         z_Transport.writecCs2|jr dSd|_||jdur&dS|dSr?)rr1rr/r7r r r r2s z_Transport.closecCs|jSr6)rr7r r r get_protocol sz_Transport.get_protocolcCs|jSr6)rr7r r r is_closing sz_Transport.is_closing)rr cCstdSr6rA)r'rr r r set_protocolsz_Transport.set_protocolcCs |dSr6)r>r7r r r __del__sz_Transport.__del__)rrN)N)NN)&__name__ __module__ __qualname__rrint__annotations__asyncioAbstractEventLoopProtocolboolrr!r5r8r1r:r&r>r/rCrErJrKrPrDrUr@bytesrYr^r2Z BaseProtocolr_r`rarb __classcell__r r r(r r3sP     !  rc@seZdZdZddddZdS)SubprocessProtocolzBAn extension to asyncio.Protocol for use with SubprocessTransport.Nr*cCstdS)z"Called when subprocess has exited.NrAr7r r r process_exitedsz!SubprocessProtocol.process_exited)rcrdre__doc__ror r r r rnsrnc@seZdZedddZdS) WindowSize)valuecCst|d|_t|d|_dS)Nrowscols)rrsrt)r'rrr r r r!s zWindowSize.__init__N)rcrdrerr!r r r r rqsrqcs(eZdZUdZdZded<dZded<dZded<ded <d d ee d d dZ dddddZ d dde j eee ededfddZeddddZedddZddddZedd d!Zddd"d#Zee jd$d%d&Zejdd'd(d)Zddd*d+Zddd,d-Zddd.d/Z Z!S)0SubprocessTransportaA bi-directional transport speaking with stdin/out of a subprocess. Note: this is not really a normal SubprocessTransport. Although it implements the entire API of asyncio.SubprocessTransport, it is not designed to be used with asyncio.SubprocessProtocol objects. Instead, it pair with normal Protocol objects which also implement the SubprocessProtocol defined in this module (which only has a process_exited() method). Whatever the protocol writes is sent to stdin, and whatever comes from stdout is given to the Protocol via the .data_received() function. If stderr is configured as a pipe, the transport will separately collect data from it, making it available via the .get_stderr() method. NrL_pty_fdzsubprocess.Popen[bytes] | None_process _returncodezSpooler | None_stderrFresetr{r cCs(|jdur |jj|djddSdSdS)Nrzreplace)errors)rygetdecode)r'r{r r r get_stderr9s zSubprocessTransport.get_stderrzsubprocess.Popen[bytes])processr c sddfdd ddfdd }ttddfdd }ztjj|Wn`ttfyd }tj|d}|durt }| jt j||| j|Yn0dS) Nr*cs2tjtsJtdjjs.jdS)NzProcess exited with status %d) isinstancerrnr"r#rxrror r7r r flag_exit@sz1SubprocessTransport.watch_exit..flag_exitcsjtjd\}}|jks Jzt|_WntyH|_Yn0jtdSrO) r$waitpidpidwaitstatus_to_exitcoderx ValueErrorrr<r2)rstatusrZpidfdrr'r r pidfd_readyFs    z3SubprocessTransport.watch_exit..pidfd_ready)rcoder csj|ksJ|_dSr6)rrx)rr)rrr'r r child_watch_firedQsz9SubprocessTransport.watch_exit..child_watch_firedZ!_cockpit_transports_child_watcher)rfr$ pidfd_openrrr=AttributeErrorr getattrrhZSafeChildWatcherZ attach_loopsetattrZadd_child_handler)r'rrrZquarkZwatcherr rr watch_exit?s    zSubprocessTransport.watch_exit)ptywindowzWindowSize | None)rrrrrkwargsc  sddfdd }r|t\|_}|dur6||||d<tj|f|||dd||_t||j|j} } d|_nPtj|ftj tj |d||_|jj sJ|jj sJ|jj } |jj } |jj durt||jj |_nd|_t||| | ||jdS)Nr*cs$tttjr tdtjddSrO)r SET_PDEATHSIGsignalSIGTERMfcntlioctltermiosZ TIOCSCTTYr rr r preexec_fnts z0SubprocessTransport.__init__..preexec_fnstderrT)stdinstdoutrZstart_new_session)rrr)r$openptyrvset_window_size subprocessPopenrwr2rPIPErrfilenorSpoolerryr r!r) r'rrrrrrrZ session_fdrrr(rr r!js:        zSubprocessTransport.__init__)sizer c Cs2|jdusJt|jtjtd|j|jdS)NZ2H4x) rvrrrZ TIOCSWINSZstructpackrsrt)r'rr r r rsz#SubprocessTransport.set_window_sizer*cCs|jdusJ|jjduSr6)rwrr7r r r rCsz!SubprocessTransport.can_write_eofcCs4|jdusJ|jjdusJ|jjd|_dSr9)rwrr2rr7r r r rDs z"SubprocessTransport._write_eof_nowcCs|jdusJ|jjSr6)rwrr7r r r get_pidszSubprocessTransport.get_pidcCs|jSr6)rxr7r r r get_returncodesz"SubprocessTransport.get_returncode)fdr cCstdSr6rA)r'rr r r get_pipe_transportsz&SubprocessTransport.get_pipe_transport)sigr cCs~|jdusJ|jdur.td||jjdSz&t|jj|td||jjWn$tyxtd||jjYn0dS)Nz3won't attempt %s to process %i. It exited already.zsent %s to process %iz3can't send %s to process %i. It's exited just now.)rwrxr"r#rr$killProcessLookupError)r'rr r r send_signals  zSubprocessTransport.send_signalcCs|tjdSr6)rrrr7r r r terminateszSubprocessTransport.terminatecCs|tjdSr6)rrSIGKILLr7r r r rszSubprocessTransport.killcCsz|jdurt|jd|_|jdurv|jjdurF|jjd|j_z |Wn"tyttd|jj Yn0dS)Nzcan't kill %i due to EPERM) rvr$r2rwrrPermissionErrorr"r#rr7r r r r>s       zSubprocessTransport._close)"rcrdrerprvrgrwrxrkstrrrrhrirnrrr!rqrrCrDrfrr TransportrrZSignalsrrrr>rmr r r(r ru$s6    0.rucsNeZdZdZd ejejeedfdd Ze ddd Z d dd d Z Z S)StdioTransportzA bi-directional transport that corresponds to stdin/out. Can talk to just about anything: - files - pipes - character devices (including terminals) - sockets rr)rrrrcst||||dSr6)r r!)r'rrrrr(r r r!szStdioTransport.__init__r*cCsdSr;r r7r r r rCszStdioTransport.can_write_eofNcCs tddS)NzCan't write EOF to stdout) RuntimeErrorr7r r r rDszStdioTransport._write_eof_now)rr) rcrdrerprhrirjrfr!rkrCrDrmr r r(r rs rc@seZdZUdZejed<eed<ded<ejedddZd d d d Z e d d dZ dde e dddZ d d ddZd d ddZd S)rzConsumes data from an fd, storing it in a buffer. This makes a copy of the fd, so you don't have to worry about holding it open. r_fdz list[bytes] _contents)rrcCs@||_d|_g|_t||_t|jd||j|jdS)NrF)rrrr$dupr%r=r5)r'rrr r r r!s  zSpooler.__init__Nr*cCs^zt|jd}Wn(ty&YdSty:d}Yn0|dkrR|j|n|dS)Ni r+)r$r,rr-r rrZr2rXr r r r5s   zSpooler._read_readycCs,|jdkrdSt|jgggdgggfkS)NrFr)rselectr7r r r _is_readys zSpooler._is_readyFrzr|cCs,|r|qd|j}|r(g|_|S)Nr+)rr5r\r)r'r{resultr r r rs   z Spooler.getcCs.|jdkr*|j|jt|jd|_dSr9)rrr<r$r2r7r r r r2"s  z Spooler.closecCs |dSr6)r2r7r r r rb(szSpooler.__del__)rcrdrerprhrirgrfr!r5rkrrlrr2rbr r r r rs    r)%rprhrVZctypesr.rZloggingr$rrrrrtypingrrrZjsonutilrrZCDLLrr rfrZ getLoggerrcr"r[rrrjrnrqrurrr r r r s6  e: