
    2e*                     ~    d dl Z d dlZd dlZd dlZd dlZd
dZddZ G d de      Z G d de      Z	 G d d	e      Z
y)    Nc                 "   t        j                   | t         j                        }|r|t        j                   z  }n|t        j                  z  }t        j                   | t         j                  |       t        |t        j                  z         S )zl
    Set the given file-descriptor blocking or non-blocking.

    Returns the original blocking status.
    )fcntlF_GETFLos
O_NONBLOCKF_SETFLbool)fdblockingold_flagnew_flags       ./usr/lib/python3/dist-packages/dockerpty/io.pyset_blockingr      sd     {{2u}}-Ho-bmm+	KKEMM8,Hr}},---    c                     g }	 t        j                  | |||      dd S # t         j                  $ r/}|j                  }|t        j                  k(  r	g g fcY d}~S |d}~ww xY w)z
    Select the streams from `read_streams` that are ready for reading, and
    streams from `write_streams` ready for writing.

    Uses `select.select()` internally but only returns two lists of ready streams.
    r      N)builtin_selectselecterrorerrnoEINTR)read_streamswrite_streamstimeoutexception_streamsenos         r   r   r   +   su     $$	

 A 	  WW8OGs     A!"AA!AA!c                       e Zd ZdZ	 ej
                  ej                  ej                  gZd Z	d Z
d ZddZd Zd Zd Zd	 Zd
 Zy)Streamz
    Generic Stream class.

    This is a file-like abstraction on top of os.read() and os.write(), which
    add consistency to the reading of sockets and files alike.
    c                 <    || _         d| _        d| _        d| _        y)z}
        Initialize the Stream for the file descriptor `fd`.

        The `fd` object must have a `fileno()` method.
        r   FN)r
   bufferclose_requestedclosed)selfr
   s     r   __init__zStream.__init__V   s!     $r   c                 6    | j                   j                         S )z=
        Return the fileno() of the file descriptor.
        )r
   filenor$   s    r   r'   zStream.filenoa   s    
 ww~~r   c                     t        | j                  d      r| j                  j                  |       yt        | j                  |      S )NsetblockingT)hasattrr
   r*   r   r$   values     r   r   zStream.set_blockingh   s6    477M*GG&//r   c                 .   	 	 t        | j                  d      r| j                  j                  |      S t        j                  | j                  j                         |      S # t        $ r(}|j                  t        j                  vr|Y d}~nd}~ww xY w)zU
        Return `n` bytes of data from the Stream, or None at end of stream.
        recvN)
r+   r
   r/   r   readr'   EnvironmentErrorr   r   ERRNO_RECOVERABLE)r$   nr   s      r   r0   zStream.reado   sy    
 477F+77<<?*wwtww~~/33# 77&":"::G ; s   0A" -A" "	B+BBc                 h    |sy| xj                   |z  c_         | j                          t        |      S )z
        Write `data` to the Stream. Not all data may be written right away.
        Use select to find when the stream is writeable, and call do_write()
        to flush the internal buffer.
        N)r!   do_writelenr$   datas     r   writezStream.write~   s+     t4yr   c                    	 	 d}t        | j                  d      r&| j                  j                  | j                        }n8t	        j
                  | j                  j                         | j                        }| j                  |d | _        | j                  r(t        | j                        dk(  r| j                          |S # t        $ r(}|j                  t        j                  vr|Y d}~nd}~ww xY w)zZ
        Flushes as much pending data from the internal write buffer as possible.
        r   sendN)r+   r
   r;   r!   r   r9   r'   r"   r6   closer1   r   r   r2   )r$   writtenr   s      r   r5   zStream.do_write   s     477F+"ggll4;;7G hhtww~~'7EG"kk'(3 ''C,<,AJJL# 77&":"::G ;! s   B?C 	C4C//C4c                 2    t        | j                        dkD  S )zL
        Returns True if the stream has data waiting to be written.
        r   )r6   r!   r(   s    r   needs_writezStream.needs_write   s     4;;!##r   c                 (   d| _         | j                  st        | j                        dk(  rfd| _        t	        | j
                  d      r| j
                  j                          y t        j                  | j
                  j                                y y y )NTr   r<   )	r"   r#   r6   r!   r+   r
   r<   r   r'   r(   s    r   r<   zStream.close   sc    # {{s4;;/14DKtww()*  5{r   c                 b    dj                  t        |       j                  | j                        S )Nz{cls}({fd}))clsr
   )formattype__name__r
   r(   s    r   __repr__zStream.__repr__   s&    ##T
(;(;#HHr   Ni   )rE   
__module____qualname____doc__r   r   EDEADLKEWOULDBLOCKr2   r%   r'   r   r0   r9   r5   r?   r<   rF    r   r   r   r   E   s[     		 00$
+Ir   r   c                   P    e Zd ZdZd Zd Zd ZddZd Zd Z	d Z
d	 Zdd
Zd Zy)Demuxera8  
    Wraps a multiplexed Stream to read in data demultiplexed.

    Docker multiplexes streams together when there is no PTY attached, by
    sending an 8-byte header, followed by a chunk of data.

    The first 4 bytes of the header denote the stream from which the data came
    (i.e. 0x01 = stdout, 0x02 = stderr). Only the first byte of these initial 4
    bytes is used.

    The next 4 bytes indicate the length of the following chunk of data as an
    integer in big endian format. This much data must be consumed before the
    next 8-byte header is read.
    c                      || _         d| _        y)zA
        Initialize a new Demuxer reading from `stream`.
        r   N)streamremain)r$   rQ   s     r   r%   zDemuxer.__init__   s    
 r   c                 6    | j                   j                         S )zn
        Returns the fileno() of the underlying Stream.

        This is useful for select() to work.
        )rQ   r'   r(   s    r   r'   zDemuxer.fileno   s     {{!!##r   c                 8    | j                   j                  |      S N)rQ   r   r,   s     r   r   zDemuxer.set_blocking   s    {{''..r   c                     | j                  |      }|dk  ryd}t        |      |k  r?| j                  j                  |t        |      z
        }|s|S ||z   }t        |      |k  r?|S )a  
        Read up to `n` bytes of data from the Stream, after demuxing.

        Less than `n` bytes of data may be returned depending on the available
        payload, but the number of bytes returned will never exceed `n`.

        Because demuxing involves scanning 8-byte headers, the actual amount of
        data read from the underlying stream may be greater than `n`.
        r   Nr   )_next_packet_sizer6   rQ   r0   )r$   r3   sizer8   nxts        r   r0   zDemuxer.read   sr     %%a(19Dd)d"kk&&tc$i'78Kcz d)d" Kr   c                 8    | j                   j                  |      S )z6
        Delegates the the underlying Stream.
        )rQ   r9   r7   s     r   r9   zDemuxer.write   s    
 {{  &&r   c                 d    t        | j                  d      r| j                  j                         S y)1
        Delegates to underlying Stream.
        r?   F)r+   rQ   r?   r(   s    r   r?   zDemuxer.needs_write   s(    
 4;;.;;**,,r   c                 d    t        | j                  d      r| j                  j                         S y)r\   r5   F)r+   rQ   r5   r(   s    r   r5   zDemuxer.do_write	  s(    
 4;;
+;;''))r   c                 6    | j                   j                         S )r\   )rQ   r<   r(   s    r   r<   zDemuxer.close  s    
 {{  ""r   c                    d}| j                   dkD  r-t        || j                         }| xj                   |z  c_         |S d}t        |      dk  r>| j                  j	                  dt        |      z
        }|sy||z   }t        |      dk  r>|yt        |      dk(  r/t        j                  d|      \  }}t        ||      }||z
  | _         |S )Nr   r      z>BxxxL)rR   minr6   rQ   r0   structunpack)r$   r3   rX   r8   rY   __actuals          r   rW   zDemuxer._next_packet_size  s    ;;?q$++&DKK4K"  Dd)a-kk&&q3t9}5cz d)a- |4yA~#]]8T:
F1f~$tmr   c                 b    dj                  t        |       j                  | j                        S )Nz{cls}({stream}))rB   rQ   )rC   rD   rE   rQ   r(   s    r   rF   zDemuxer.__repr__2  s-     ''DJ,?,?/3{{ ( < 	<r   NrG   r   )rE   rH   rI   rJ   r%   r'   r   r0   r9   r?   r5   r<   rW   rF   rM   r   r   rO   rO      s9    $/2'#0<r   rO   c                   <    e Zd ZdZ	 	 d	dZd Zd Zd
dZd Zd Z	y)Pumpa  
    Stream pump class.

    A Pump wraps two Streams, reading from one and and writing its data into
    the other, much like a pipe but manually managed.

    This abstraction is used to facilitate piping data between the file
    descriptors associated with the tty and those associated with a container's
    allocated pty.

    Pumps are selectable based on the 'read' end of the pipe.
    c                 J    || _         || _        d| _        || _        || _        y)z
        Initialize a Pump with a Stream to read from and another to write to.

        `wait_for_output` is a flag that says that we need to wait for EOF
        on the from_stream in order to consider this pump as "done".
        FN)from_stream	to_streameofwait_for_outputpropagate_close)r$   rk   rl   rn   ro   s        r   r%   zPump.__init__E  s*     '"..r   c                 6    | j                   j                         S )z
        Returns the `fileno()` of the reader end of the Pump.

        This is useful to allow Pumps to function with `select()`.
        )rk   r'   r(   s    r   r'   zPump.filenoW  s     &&((r   c                 8    | j                   j                  |      S rU   )rk   r   r,   s     r   r   zPump.set_blocking`  s    ,,U33r   c                 V   	 | j                   j                  |      }|t        |      dk(  r.d| _        | j                  r| j
                  j                          y| j
                  j                  |      S # t        $ r)}|j                  t        j                  k7  r|Y d}~yd}~ww xY w)z
        Flush `n` bytes of data from the reader Stream to the writer Stream.

        Returns the number of bytes that were actually flushed. A return value
        of zero is not an error.

        If EOF has been reached, `None` is returned.
        Nr   T)rk   r0   r6   rm   ro   rl   r<   r9   OSErrorr   EPIPE)r$   r3   r0   r   s       r   flushz
Pump.flushc  s    	##((+D|s4yA~''NN((*>>''-- 	ww%++% &	s   AA6 A6 6	B(?B##B(c                     | j                    xs | j                  xr3 t        | j                  d      xr | j                  j	                          S )z
        Returns True if the read stream is done (either it's returned EOF or
        the pump doesn't have wait_for_output set), and the write
        side does not have pending bytes to send.
        r?   )rn   rm   r+   rl   r?   r(   s    r   is_donezPump.is_done{  sH     (((4DHH ^T^^];\@Z@Z@\]	^r   c                 x    dj                  t        |       j                  | j                  | j                        S )Nz){cls}(from={from_stream}, to={to_stream}))rB   rk   rl   )rC   rD   rE   rk   rl   r(   s    r   rF   zPump.__repr__  s8    :AAT
##((nn B & 	&r   N)TTrG   )
rE   rH   rI   rJ   r%   r'   r   ru   rw   rF   rM   r   r   ri   ri   7  s.      "&!%	/$)40^&r   ri   )Trg   )r   r   r   rb   r   r   r   objectr   rO   ri   rM   r   r   <module>rz      sN   " 
    .&4sIV sIly<f y<xR&6 R&r   