
    h                    .   % S r SSKJr  SSKrSSKrSSKrSSKrSSKrSSKrSSK	r	SSK
r
SSKJr  SSKJrJrJrJrJr  S\S'   S\S'   \(       d	   SS	KJrJr  SS
KJr  SSKJrJrJr  SSKJ r   SSK!J"r"  SSK#J$r$J%r%  SSK&J'r'J(r(  SSK)J*r*  SSK+J,r,  \*RZ                  " 5       (       a  \" S5      e SSK.r/\/r. SSK0r1SSK2r2\1r0\Rf                  r30 r4S\S'   S&S jr5S r6S r7 " S S\Rp                  5      r9 " S S\Rp                  5      r: " S S\ 5      r; " S S5      r<\<" 5       r=S  r>          S'S! jr?\" \"5       " S" S#\;5      5       r@\" \"5       " S$ S%\Rp                  \;5      5       rAg! \ a     GNf = f! \ a    Sr. Nf = f! \ a    Sr0 Nf = f)(z
UNIX Process management.

Do NOT use this module directly - use reactor.spawnProcess() instead.

Maintainer: Itamar Shtull-Trauring
    )annotationsN)defaultdict)TYPE_CHECKINGDictListOptionalTupleint	_PS_CLOSE_PS_DUP2)POSIX_SPAWN_CLOSEPOSIX_SPAWN_DUP2)implementer)abstracterrorfdesc)BaseProcess)IProcessTransport)CONNECTION_DONECONNECTION_LOST)failurelog)platform)	switchUIDz^twisted.internet.process does not work on Windows. Use the reactor.spawnProcess() API instead.zDict[int, _BaseProcess]reapProcessHandlersc                 l    [        [        R                  5       5       H  n U R                  5         M     g)z 
Reap all registered processes.
N)listr   valuesreapProcess)processs    _/root/1688_scrapy/alibaba-scraper/venv/lib/python3.13/site-packages/twisted/internet/process.pyreapAllProcessesr"   H   s)     +2245 6    c                N   U [         ;   a  [        S5      e [        R                  " U [        R                  5      u  p#U(       a  UR                  W5        gU[         U '   g! [
         a9    [        R                  " SU  S35        [        R                  " 5         U c   gSn Nef = f)z
Register a process handler for the given pid, in case L{reapAllProcesses}
is called.

@param pid: the pid of the process.
@param process: a process handler.
z.Try to register an already registered process.Failed to reap :N)
r   RuntimeErroroswaitpidWNOHANGBaseExceptionr   msgerrprocessEnded)pidr    auxPIDstatuss       r!   registerReapProcessHandlerr2   R   s     !!KLL	C4 V$ $+C   /#a()	;s   'A! !<B$B$#B$c                V    U [         ;   a  [         U    U:X  d  [        S5      e[         U 	 g)zX
Unregister a process handler previously registered with
L{registerReapProcessHandler}.
z+Try to unregister a process not registered.N)r   r'   )r/   r    s     r!   unregisterReapProcessHandlerr4   m   s.    
 &&+>s+Cw+NHIIC r#   c                  L    \ rS rSrSrSrSrSrSS jrS r	S r
S	 rS
 rS rSrg)ProcessWriterw   a  
(Internal) Helper class to write into a Process's input pipe.

I am a helper which describes a selectable asynchronous writer to a
process's input pipe, including stdin.

@ivar enableReadHack: A flag which determines how readability on this
    write descriptor will be handled.  If C{True}, then readability may
    indicate the reader for this write descriptor has been closed (ie,
    the connection has been lost).  If C{False}, then readability events
    are ignored.
   r   Fc                   [         R                  R                  X5        [        R                  " U5        X l        X0l        X@l        [        R                  " [        R                  " U R                  5       5      R                  5      (       d  SU l        O5U(       a  SU l        O& [        R                  " U R                  5       S5        U R                  (       a  U R#                  5         gg! [          a
    SU l         N6f = f)z:
Initialize, specifying a Process instance to connect to.
FTr   N)r   FileDescriptor__init__r   setNonBlockingprocnamefdstatS_ISFIFOr(   fstatfilenost_modeenableReadHackreadOSErrorstartReading)selfreactorr=   r>   rC   forceReadHacks         r!   r;   ProcessWriter.__init__   s     	((7V$		}}RXXdkkm4<<== #(D"&D+q)
  	  +&*#+s   '%C/ /DDc                    U R                   $ )z,
Return the fileno() of my process's stdin.
r?   rI   s    r!   rC   ProcessWriter.fileno        wwr#   c                    [         R                  " U R                  U5      nU[        U5      :X  a!  U R                  (       a  U R                  5         U$ z&
Write some data to the open process.
)r   	writeToFDr?   lenrE   rH   )rI   datarvs      r!   writeSomeDataProcessWriter.writeSomeData   s>     __TWWd+T?t22 	r#   c                b    U R                  5         [        R                  R                  X5        g N)stopReadingr   r:   writerI   rV   s     r!   r]   ProcessWriter.write   s"    %%d1r#   c                R    U R                   (       a  [        $ U R                  5         g)ad  
The only way a write pipe can become "readable" is at EOF, because the
child has closed it, and we're using a reactor which doesn't
distinguish between readable and closed (such as the select reactor).

Except that's not true on linux < 2.6.11. It has the following
characteristics: write pipe is completely empty => POLLOUT (writable in
select), write pipe is not completely empty => POLLIN (readable in
select), write pipe's reader closed => POLLIN|POLLERR (readable and
writable in select)

That's what this funky code is for. If linux was not broken, this
function could be simply "return CONNECTION_LOST".
N)rE   r   r\   rO   s    r!   doReadProcessWriter.doRead   s     ""r#   c                    [         R                  " U R                  5        [        R                  R                  X5        U R                  R                  U R                  U5        g)z-
See abstract.FileDescriptor.connectionLost.
N)	r   setBlockingr?   r   r:   connectionLostr=   childConnectionLostr>   rI   reasons     r!   re   ProcessWriter.connectionLost   sB     	$''"..t<		%%dii8r#   )rE   r?   r>   r=   N)F)__name__
__module____qualname____firstlineno____doc__	connectedicrE   r;   rC   rX   r]   ra   re   __static_attributes__ r#   r!   r6   r6   w   s6     I	
BN >
2(
9r#   r6   c                  F    \ rS rSrSrSrS rS rS rS r	S r
S	 rS
 rSrg)ProcessReader   zh
ProcessReader

I am a selectable representation of a process's output pipe, such as
stdout and stderr.
Tc                    [         R                  R                  X5        [        R                  " U5        X l        X0l        X@l        U R                  5         g)z1
Initialize, specifying a process to connect to.
N)	r   r:   r;   r   r<   r=   r>   r?   rH   )rI   rJ   r=   r>   rC   s        r!   r;   ProcessReader.__init__   sA     	((7V$		r#   c                    U R                   $ )z-
Return the fileno() of my process's stderr.
rN   rO   s    r!   rC   ProcessReader.fileno   rQ   r#   c                    US:X  d   e[         $ )Nr#   )r   r^   s     r!   rX   ProcessReader.writeSomeData   s     s{{r#   c                X    [         R                  " U R                  U R                  5      $ )z0
This is called when the pipe becomes readable.
)r   
readFromFDr?   dataReceivedrO   s    r!   ra   ProcessReader.doRead  s!     ):):;;r#   c                P    U R                   R                  U R                  U5        g r[   )r=   childDataReceivedr>   r^   s     r!   r~   ProcessReader.dataReceived  s    		##DIIt4r#   c                    U R                   (       ai  U R                  (       dW  SU l        U R                  5         U R                  R	                  SU R
                  [        R                  " [        5      5        g g g )Nr8   r   )	ro   disconnectingr\   rJ   	callLaterre   r   Failurer   rO   s    r!   loseConnectionProcessReader.loseConnection
  sT    >>$"4"4!"DLL""4&&(H #5>r#   c                    [         R                  R                  X5        U R                  R	                  U R
                  U5        g)zS
Close my end of the pipe, signal the Process (which signals the
ProcessProtocol).
N)r   r:   re   r=   rf   r>   rg   s     r!   re   ProcessReader.connectionLost  s0    
 	..t<		%%dii8r#   )r   r?   r>   r=   N)rj   rk   rl   rm   rn   ro   r;   rC   rX   ra   r~   r   re   rq   rr   r#   r!   rt   rt      s1     I	<59r#   rt   c                  f    \ rS rSr% SrSrS\S'   SrS rS r	S r
S	 rS
 rS rS rS rSS jrSrg)_BaseProcessi  z(
Base class for Process and PTYProcess.
NzOptional[int]r1   c                     [         R                  " U R                  [         R                  5      u  pU(       a  [        X5        U R                  W5        gg! [         a+  nUR
                  [
        R                  :X  a  Sn SnANTe SnAff = f! [         a>    [        R                  " SU R                   S35        [        R                  " 5         Sn Nf = f)a  
Try to reap a process (without blocking) via waitpid.

This is called when sigchild is caught or a Process object loses its
"connection" (stdout is closed) This ought to result in reaping all
zombie processes, since it will be called twice as often as it needs
to be.

(Unfortunately, this is a slightly experimental approach, since
UNIX has no way to be really sure that your process is going to
go away w/o blocking.  I don't want to block.)
Nr%   r&   )r(   r)   r/   r*   rG   errnoECHILDr+   r   r,   r-   r4   r.   )rI   r/   r1   es       r!   r   _BaseProcess.reapProcess#  s    	 jj2::> (3f%   77ell*C  	GGodhhZq12GGIC	s6   1A 
B# B	B B		BB ACCc                   S =p#[         R                  " U5      (       a  [         R                  " U5      nO[         R                  " U5      nU(       d  U(       a  [        R
                  " X#U5      $ [        R                  " U5      $ r[   )r(   	WIFEXITEDWEXITSTATUSWTERMSIGr   ProcessTerminatedProcessDone)rI   r1   exitCodesigs       r!   
_getReason_BaseProcess._getReasonA  s^    <<~~f-H++f%Cs**8&AA  ((r#   c                   US;   a  [        [        SU 35      nU R                  c
  [        5       e [        R
                  " U R                  U5        g! [         a.  nUR                  [        R                  :X  a
  [        5       ee SnAff = f)z
Send the given signal C{signalID} to the process. It'll translate a
few signals ('HUP', 'STOP', 'INT', 'KILL', 'TERM') from a string
representation to its int value, otherwise it'll pass directly the
value provided

@type signalID: C{str} or C{int}
)HUPSTOPINTKILLTERMSIGN)	getattrsignalr/   ProcessExitedAlreadyr(   killrG   r   ESRCH)rI   signalIDr   s      r!   signalProcess_BaseProcess.signalProcessK  sv     ==vXJ'78H88&((	GGDHHh' 	ww%++%*,,		s   !A 
B)BBc                    [        S[        R                  5       HR  n[        R                  " U5      [        R                  :X  d  M-  [        R                  " U[        R
                  5        MT     g Nr8   )ranger   NSIG	getsignalSIG_IGNSIG_DFL)rI   	signalnums     r!   _resetSignalDisposition$_BaseProcess._resetSignalDisposition`  sB     q&++.I	*fnn<i8 /r#   c                    g)a  
Try to use posix_spawnp() instead of fork(), if possible.

This implementation returns False because the non-PTY subclass
implements the actual logic; we can't yet use this for pty processes.

@return: a boolean indicating whether posix_spawnp() was used or not.
Frr   )rI   pathuidgid
executableargsenvironmentkwargss           r!   _trySpawnInsteadOfFork#_BaseProcess._trySpawnInsteadOfForkk  s     r#   c           	        U R                  XX4XVU5      (       a  g[        R                  " 5       n[        R                  " 5          [        R
                  " 5       U l        U R                  S:X  aR   [        R                  " S5        U R                  " S0 UD6  U R                  XX4XV5        [        R0                  " S
5        U(       a  [        R2                  " 5         SU l        g! [         a     [        R                  " [        R                  " SS5      SS9n	SR                  U[!        U5      [#        U5      5      n
U	R%                  U
5        [&        R(                  " U	S9  U	R+                  5         [-        S	5       H  n[        R.                  " U5        M      N! [         a      GNf = ff = f! [         a    U(       a  [        R2                  " 5         e f = f)aN  
Fork and then exec sub-process.

@param path: the path where to run the new process.
@type path: L{bytes} or L{unicode}

@param uid: if defined, the uid used to run the new process.
@type uid: L{int}

@param gid: if defined, the gid used to run the new process.
@type gid: L{int}

@param executable: the executable to run in a new process.
@type executable: L{str}

@param args: arguments used to create the new process.
@type args: L{list}.

@param environment: environment used for the new process.
@type environment: L{dict}.

@param kwargs: keyword arguments to L{_setupChild} method.
Nr      wbzutf-8)encodingz)Upon execvpe {} {} in environment id {}
:file   r8   rr   )r   gc	isenableddisabler(   forkr/   syssettrace_setupChild
_execChildr+   ioTextIOWrapperfdopenformatstridr]   	traceback	print_excflushr   close_exitenabler1   )rI   r   r   r   r   r   r   r   collectorEnabledstderrr,   r?   s               r!   _fork_BaseProcess._forkx  sv   2 &&s6
 
 <<>


D	wwyDH xx1}+LL&$$.v.OODsRV  IIK_ % &" "$!1!1"))At2Dw!WNVV&D	2k? S)!++8"'(BHHRL #+(  G&1  					s7   F5 1;C& &
F21B,F
F.)F2-F..F25(Gc                    [        5       e)z2
Setup the child process. Override in subclasses.
NotImplementedError)rI   r   r   s      r!   r   _BaseProcess._setupChild  s     "##r#   c                F   U(       a  [         R                  " U5        Uc  Ubg  Uc  [         R                  " 5       nUc  [         R                  " 5       n[         R                  " S5        [         R
                  " S5        [        X#5        [         R                  " XEU5        g)z/
The exec() which is done in the forked child.
Nr   )r(   chdirgeteuidgetegidsetuidsetgidr   execvpe)rI   r   r   r   r   r   r   s          r!   r   _BaseProcess._execChild  sg     HHTN?co{jjl{jjlIIaLIIaLc


:[1r#   c                x    SR                  U R                  R                  U R                  U R                  5      $ )z%
String representation of a process.
z<{} pid={} status={}>)r   	__class__rj   r/   r1   rO   s    r!   __repr___BaseProcess.__repr__  s2     '--NN##HHKK
 	
r#   )r/   r1   )returnr   )rj   rk   rl   rm   rn   r1   __annotations__r/   r   r   r   r   r   r   r   r   r   rq   rr   r#   r!   r   r     sG     !FM 
C&<)*	9iV$2"
r#   r   c                  p    \ rS rSrSr\R                  r\R                  r\r	S r
S rS rS rS rS rS	rg
)_FDDetectori  aF  
This class contains the logic necessary to decide which of the available
system techniques should be used to detect the open file descriptors for
the current process. The chosen technique gets monkey-patched into the
_listOpenFDs method of this class so that the detection only needs to occur
once.

@ivar listdir: The implementation of listdir to use. This gets overwritten
    by the test cases.
@ivar getpid: The implementation of getpid to use, returns the PID of the
    running process.
@ivar openfile: The implementation of open() to use, by default the Python
    builtin.
c                T    U R                   U R                  U R                  /U l        g r[   )_procFDImplementation_devFDImplementation_fallbackFDImplementation_implementationsrO   s    r!   r;   _FDDetector.__init__  s'    &&%%**!
r#   c                L    U R                  5       U l        U R                  5       $ )z
Return an iterable of file descriptors which I{may} be open in this
process.

This will try to return the fewest possible descriptors without missing
any.
)_getImplementation_listOpenFDsrO   s    r!   r   _FDDetector._listOpenFDs!  s$     !335  ""r#   c                    U R                    H7  n U" 5       nU R                  SS5         U" 5       nSSS5        UW:w  d  M5  Us  $    W$ ! [         a     MJ  f = f! , (       d  f       N/= f)a  
Pick a method which gives correct results for C{_listOpenFDs} in this
runtime environment.

This involves a lot of very platform-specific checks, some of which may
be relatively expensive.  Therefore the returned method should be saved
and re-used, rather than always calling this method to determine what it
is.

See the implementation for the details of how a method is selected.
z	/dev/nullrN)r   r+   openfile)rI   implbeforeafters       r!   r   _FDDetector._getImplementation,  sj     ))D {C0 1 *  ! 00s   A
A

AA
A)	c                h    SnU R                  U5       Vs/ s H  n[        U5      PM     nnU$ s  snf )zq
Simple implementation for systems where /dev/fd actually works.
See: http://www.freebsd.org/cgi/man.cgi?fdescfs
z/dev/fd)listdirr
   )rI   dnamer?   results       r!   r    _FDDetector._devFDImplementationI  s6    
 $(LL$78$7b#b'$78 9s   /c                    SU R                  5       4-  nU R                  U5       Vs/ s H  n[        U5      PM     sn$ s  snf )zS
Simple implementation for systems where /proc/pid/fd exists (we assume
it works).
z/proc/%d/fd)getpidr  r
   )rI   r  r?   s      r!   r   !_FDDetector._procFDImplementationR  s>    
  00"&,,u"56"5BB"5666s   A c                     SSK n[        SUR                  UR                  5      S   5      n[        U5      $ ! [         a    Sn Nf = f)aE  
Fallback implementation where either the resource module can inform us
about the upper bound of how many FDs to expect, or where we just guess
a constant maximum if there is no resource module.

All possible file descriptors from 0 to that upper bound are returned
with no attempt to exclude invalid file descriptor values.
r   Ni   r8   )resourcemin	getrlimitRLIMIT_NOFILEImportErrorr   )rI   r  maxfdss      r!   r   %_FDDetector._fallbackFDImplementationZ  sO    	N x11(2H2HI!LMFV}  	F	s   9 AA)r   r   N)rj   rk   rl   rm   rn   r(   r  r
  openr   r;   r   r   r   r   r   rq   rr   r#   r!   r   r     s>      jjGYYFH
	#:7r#   r   c                 *    [         R                  5       $ )zN
Use the global detector object to figure out which FD implementation to
use.
)detectorr   rr   r#   r!   r   r   r  s    
   ""r#   c                l  ^^ [        U 5      n[        [        5      nUR                  5        H  u  pgXW   R	                  U5        M     [        U5      mT[        UR                  5       5      -  mT[        UR                  5       5      -  mSmSUU4S jjn/ n	0 n
[        UR                  5       5       H  u  pgXW   R                  U5        XV   (       a  U" 5       =oU'   U	R	                  X6U45        Xz;   a8  U	R	                  X:U   U45        XW   (       d  U	R	                  X*U   45        Mz  M|  Xv:X  a-  XG   (       a"  U" 5       nU	R                  X7U4X<U4X,4/5        M  M  U	R	                  X7U45        M     UR                  5        H'  u  pX;  d  M  U(       a  M  U	R	                  X-45        M)     U	$ )aD  
Get the C{file_actions} parameter for C{posix_spawn} based on the
parameters describing the current process state.

@param fdState: A list of 2-tuples of (file descriptor, close-on-exec
    flag).

@param doClose: the integer to use for the 'close' instruction

@param doDup2: the integer to use for the 'dup2' instruction
r   c                 P   > TT ;   a  TS-  mTT ;   a  M  T R                  T5        T$ r   )add)	allocatednextFDs   r!   
allocateFD#_getFileActions.<locals>.allocateFD  s/    	!aKF 	!fr#   )r   r
   )dictr   r   itemsappendsetr   keyssortedremoveextend)fdStatechildToParentFDdoClosedoDup2fdStateDictparentToChildreninChildinParentr  r  relocationsnewtempFDeachFDuninheritabler  r  s                  @@r!   _getFileActionsr3  z  s   " w-K-8->,224"))'2 5K I_++-..I_))+,,IF  %'FK#O$9$9$;<"))'2$)35Cg&MM6C01"MM6x#8'BC#-wH(=>? . "(
 (\F MM#v6#W5$- )* v9:C =F "-!2!2!4(MM7+, "5 Mr#   c                      \ rS rSrSrSrSrSrSr\	r
\r   SS jrS r\" \SS5      c  CS	 rS
 rS rS rS rS rS rS rS rS rS rS rS rS rS rS r S r!S r"Sr#g)Processi  a  
An operating-system Process.

This represents an operating-system process with arbitrary input/output
pipes connected to it.  Those pipes may represent standard input, standard
output, and standard error, or any other file descriptor.

On UNIX, this is implemented using posix_spawnp() when possible (or fork(),
exec(), pipe() and fcntl() when not).  These calls may not exist elsewhere
so this code is not cross-platform.  (also, windows can only select on
sockets...)
Fr   Nc
           
     .  ^ Xl         U(       d,  SU	R                  5       ;  d   eSU	R                  5       ;  d   e[        R                  X5        0 U l        0 n
U	c  SSSS.n	U R
                  nU(       a  [        SU	5        / mU4S jn0 n U	R                  5        H  u  pU(       a  [        SU-  U5        US:X  a+  U" 5       u  nnU(       a  [        SUU4-  5        UX'   UX'   ML  US:X  a+  U" 5       u  nnU(       a  [        SUU4-  5        UX'   UX'   M}  [        U5      [        :X  d   U< S	35       eXU'   M     U(       a  [        S
U5        U(       a  [        SU
5        U R                  XWXX4US9  X`l        U
R                  5        Hs  u  nn[        R                  " X   5        X   S:X  a"  U R                  XUU5      nUU R                  U'   X   S:X  d  MR  U R!                  XUUSS9nUU R                  U'   Mu      U R                  b  U R                  R#                  U 5        [)        U R*                  U 5        g! [         a!    T H  n[        R                  " U5        M     e f = f! [         a    [$        R&                  " 5          Nff = f)  
Spawn an operating-system process.

This is where the hard work of disconnecting all currently open
files / forking / executing the new process happens.  (This is
executed automatically when a Process is instantiated.)

This will also run the subprocess as a given user ID and group ID, if
specified.  (Implementation Note: this doesn't support all the arcane
nuances of setXXuid on UNIX: it will assume that either your effective
or real UID is 0.)
r   wN)r   r8   r   childFDsc                 \   > [         R                  " 5       u  pTR                  X/5        X4$ r[   )r(   piper%  )r   r8  _openedPipess     r!   r;  Process.__init__.<locals>.pipe  s'    779DA'4Kr#   z[%d]zreadFD=%d, writeFD=%dz should be an intfdmaphelpers)r>  T)rK   )_reactorr   r   r;   pipesdebugprintr  typer
   r   r+   r(   r   protoprocessReaderFactoryprocessWriterFactorymakeConnectionr   r-   r2   r/   )rI   rJ   r   r   r   r   rE  r   r   r9  r?  rB  r;  r>  childFDtargetreadFDwriteFDparentFDreaderwriterr<  s                        @r!   r;   Process.__init__  s   0  hoo////hoo////d*
  H 

*h'	 	#+>>#3&7*F3S=&*fOFG58IIJ%,EN'-G$s]&*fOFG58IIJ%+EN'.G$<3.N6*<M0NN.%+'N' $4( gu%i) JJt#4EJR 
 ")GXHHU^$ C'227'8T&,

7# C'227HD 3  '-

7# "1	zz%

))$/ 	#488T2A  	$ %	2  	GGI	s   C+I (I2 +I/2JJc                   Ucb  Uc_  Ub@  [         R                  R                  U5      [         R                  R                  S5      :w  d  [        U R                  SS5      (       a  gUR                  S5      n/ n	[        5        HI  n
 [        R                  U
[        R                  [        R                  5      nU	R                  X45        MK     Uc  [         R                  n[        S[        R                  5       Vs/ s H/  n[        R                   " U5      [        R"                  :X  d  M-  UPM1     nn[         R$                  " UUU['        X[(        [*        S9US9U l        SU l        g	! [         a     M  f = fs  snf )
z
Try to use posix_spawnp() instead of fork(), if possible.

@return: a boolean indicating whether posix_spawnp() was used or not.
._neverUseSpawnFr>  r8   )r(  r)  )file_actions	setsigdefr   T)r(   r   abspathr   r@  getr   fcntlF_GETFD
FD_CLOEXECr   rG   environr   r   r   r   r   posix_spawnpr3  r   r   r/   r1   )rI   r   r   r   r   r   r   r   r>  r&  r1  isCloseOnExeceverySignal	setSigDefs                 r!   r   Process._trySpawnInsteadOfForkW  sF    _!(=QTAU(Ut}}&6>>

7#"nF8 %FEMM5CSCS T 67 % **K  %Q4
4,> 4 	 
 ??(	(  
 /  
s   3E. ,E?0E?.
E<;E<r\  c                |   U R                   nU(       a!  [        R                  nUR                  S5        UR	                  5       n[        5        H>  nXT;   a  M
  U(       a  UWR                  5       :X  a  M'   [        R                  " U5        M@     U(       a  [        SUWS9  [        UR                  5       5       H  nX   nXv:X  a,  U(       a  [        SU-  WS9  [        R                  " U5        M8  XaR	                  5       ;   an  [        R                  " U5      nU(       a  [        SXh4-  WS9  [        R                  " U5        [!        UR#                  5       5       H  u  pX:X  d  M  XU	'   M     U(       a  [        SXv4-  WS9  [        R$                  " Xv5        M     / nUR	                  5        H0  nX[;  d  M
  XQR                  5       ;  d  M  UR'                  U5        M2     U(       a  [        SUWS9  U H  n[        R                  " U5        M     U R)                  5         g! [         a     GM  f = f)	al  
fdmap[childFD] = parentFD

The child wants to end up with 'childFD' attached to what used to be
the parent's parentFD. As an example, a bash command run like
'command 2>&1' would correspond to an fdmap of {0:0, 1:1, 2:1}.
'command >foo.txt' would be {0:0, 1:os.open('foo.txt'), 2:2}.

This is accomplished in two steps::

    1. close all file descriptors that aren't values of fdmap.  This
       means 0 .. maxfds (or just the open fds within that range, if
       the platform supports '/proc/<pid>/fd').

    2. for each childFD::

         - if fdmap[childFD] == childFD, the descriptor is already in
           place.  Make sure the CLOEXEC flag is not set, then delete
           the entry from fdmap.

         - if childFD is in fdmap.values(), then the target descriptor
           is busy. Use os.dup() to move it elsewhere, update all
           fdmap[childFD] items that point to it, then close the
           original. Then fall through to the next case.

         - now fdmap[childFD] is not in fdmap.values(), and is free.
           Use os.dup2() to move it to the right place, then close the
           original.
zstarting _setupChild
r>  r   z%d already in placezos.dup(%d) -> %dzos.dup2(%d,%d)oldN)debug_childr   r   r]   r   r   rC   r(   r   r+   rC  r#  r"  r   _unsetCloseOnExecdupr   r  dup2r   r   )rI   r>  rB  errfddestListr?   childrJ  	newtargetcprb  s               r!   r   Process._setupChild  s   <   JJEKK01<<>.B~u||~- ! '5u-EJJL)E\F/&8uE''.LLN* !#uI0E3EEERHHUO $U[[] 3:'0!H !4 *f_<5I&- *@ ,,.B}ZZ\)JJrN ! %5)BHHRL  	$$&g ! s   7H,,
H;:H;c                @    U R                   U   R                  U5        g r[   rA  r]   rI   rI  rV   s      r!   writeToChildProcess.writeToChild  s    

7!!$'r#   c                ^    XR                   ;   a  U R                   U   R                  5         g g r[   )rA  r   )rI   rI  s     r!   closeChildFDProcess.closeChildFD  s(    
 jj JJw..0 !r#   c                    U R                   R                  5        H*  n[        U[        5      (       d  M  UR	                  5         M,     g r[   )rA  r   
isinstancert   r\   rI   rl  s     r!   pauseProducingProcess.pauseProducing  s/    ""$A!]++ %r#   c                    U R                   R                  5        H*  n[        U[        5      (       d  M  UR	                  5         M,     g r[   )rA  r   rw  rt   rH   rx  s     r!   resumeProducingProcess.resumeProducing  s0    ""$A!]++  %r#   c                &    U R                  S5        g)z4
Call this to close standard input on this process.
r   Nrt  rO   s    r!   
closeStdinProcess.closeStdin   s     	!r#   c                &    U R                  S5        g r   r  rO   s    r!   closeStdoutProcess.closeStdout      !r#   c                &    U R                  S5        g Nr   r  rO   s    r!   closeStderrProcess.closeStderr	  r  r#   c                d    U R                  5         U R                  5         U R                  5         g r[   )r  r  r  rO   s    r!   r   Process.loseConnection  s$    r#   c                b    SU R                   ;   a  U R                   S   R                  U5        ggzz
Call this to write to standard input on this process.

NOTE: This will silently lose data if there is no standard input.
r   Nro  r^   s     r!   r]   Process.write  s*     

?JJqM% r#   c                    SU R                   ;   a  U R                   S   R                  X5        gUR                  5         g)z
Call this to register producer for standard input.

If there is no standard input producer.stopProducing() will
be called immediately.
r   N)rA  registerProducerstopProducing)rI   producer	streamings      r!   r  Process.registerProducer  s1     

?JJqM**8?""$r#   c                `    SU R                   ;   a  U R                   S   R                  5         gg)z5
Call this to unregister producer for standard input.r   N)rA  unregisterProducerrO   s    r!   r  Process.unregisterProducer&  s(     

?JJqM,,. r#   c                b    SU R                   ;   a  U R                   S   R                  U5        ggr  )rA  writeSequence)rI   seqs     r!   r  Process.writeSequence,  s*     

?JJqM'', r#   c                :    U R                   R                  X5        g r[   rE  r   )rI   r>   rV   s      r!   r   Process.childDataReceived5  s    

$$T0r#   c                "   [         R                  " U R                  U   R                  5       5        U R                  U	  U R                  R                  U5        U R                  5         g ! [         a    [        R                  " 5          N2f = fr[   )
r(   r   rA  rC   rE  rf   r+   r   r-   maybeCallProcessEnded)rI   rI  rh   s      r!   rf   Process.childConnectionLost8  sm     	G$++-.JJw	JJ**73 	""$  	GGI	s    A, ,BBc                    U R                   (       a  g U R                  (       d  U R                  5         g [        R	                  U 5        g r[   )rA  lostProcessr   r   r  rO   s    r!   r  Process.maybeCallProcessEndedC  s4     ::**40r#   c                    [        5       er[   r   rO   s    r!   getHostProcess.getHostP      !##r#   c                    [        5       er[   r   rO   s    r!   getPeerProcess.getPeerT  r  r#   )r@  r/   rA  rE  r1   NNN)$rj   rk   rl   rm   rn   rB  rc  r1   r/   r6   rG  rt   rF  r;   r   r   r(   r   rq  rt  ry  r|  r  r  r  r   r]   r  r  r  r   rf   r  r  r  rq   rr   r#   r!   r5  r5    s     EKF
C(( v3p-^ r>4(0"^'@(1 
!
&
%/-1	%1$$r#   r5  c                  r    \ rS rSrSrSrSr   SS jrS rS r	S r
S	 rS
 rS rS rS rS rS rS rSrg)
PTYProcessiY  z4
An operating-system Process that uses PTY support.
r   Nc
                \   [         c&  [        U	[        [        45      (       d  [	        S5      e[
        R                  R                  X5        [        R                  X5        [        U	[        [        45      (       a  U	u  pnO[         R                  5       u  p U R                  UUUUUUU
US9  [        R                  " U5        [        R                  " U
5        Xl        U R#                  5         SU l        SU l         U R(                  R+                  U 5        [1        U R2                  U 5        g! [         aI    [        U	[        [        45      (       d,  [        R                  " U
5        [        R                  " U5        e f = f! [         a    [,        R.                  " 5          Nf = f)r7  Nz:cannot use PTYProcess on platforms without the pty module.)masterfdslavefdr8   r   )ptyrw  tupler   r   r   r:   r;   r   openptyr   r+   r(   r   r   r<   r?   rH   ro   r1   rE  rH  r   r-   r2   r/   )rI   rJ   r   r   r   r   rE  r   r   usePTYr  r  _s                r!   r;   PTYProcess.__init__b  s\   0 ;z&5$-@@%L  	((7d*fudm,,#) Hq #H	JJ!  	" 	X&	JJ%%d+ 	#488T2#  	fudm44"!		  	GGI	s   D3 F	 3AF	F+*F+c                .   [         R                  " U5        [         R                  " 5         [        R	                  U[
        R                  S5        [        S5       H   nX2:w  d  M
  [         R                  " U5        M"     [         R                  " US5        [         R                  " US5        [         R                  " US5        [        5        H"  nUS:  d  M   [         R                  " U5        M$     U R                  5         g! [         a     MD  f = f)a  
Set up child process after C{fork()} but before C{exec()}.

This involves:

    - closing C{masterfd}, since it is not used in the subprocess

    - creating a new session with C{os.setsid}

    - changing the controlling terminal of the process (and the new
      session) to point at C{slavefd}

    - duplicating C{slavefd} to standard input, output, and error

    - closing all other open file descriptors (according to
      L{_listOpenFDs})

    - re-setting all signal handlers to C{SIG_DFL}

@param masterfd: The master end of a PTY file descriptors opened with
    C{openpty}.
@type masterfd: L{int}

@param slavefd: The slave end of a PTY opened with C{openpty}.
@type slavefd: L{int}
 r   r   r8   r   N)r(   r   setsidrX  ioctltermios	TIOCSCTTYr   rf  r   r+   r   )rI   r  r  r?   s       r!   r   PTYProcess._setupChild  s    6 	
		GW..3(B}  	

.BAvHHRL ! 	$$& % s   D
DDc                    g r[   rr   rO   s    r!   r  PTYProcess.closeStdin  s     	r#   c                    g r[   rr   rO   s    r!   r  PTYProcess.closeStdout      r#   c                    g r[   rr   rO   s    r!   r  PTYProcess.closeStderr  r  r#   c                N   ^  [         R                  " T R                  U 4S j5      $ )z=
Called when my standard output stream is ready for reading.
c                <   > TR                   R                  SU 5      $ r   r  )rV   rI   s    r!   <lambda>#PTYProcess.doRead.<locals>.<lambda>  s    $**">">q$"Gr#   )r   r}   r?   rO   s   `r!   ra   PTYProcess.doRead  s"     GGG
 	
r#   c                    U R                   $ )zB
This returns the file number of standard output on this process.
rN   rO   s    r!   rC   PTYProcess.fileno  rQ   r#   c                P    U R                   S:X  a  [        R                  U 5        g g r  )r  r   r  rO   s    r!   r   PTYProcess.maybeCallProcessEnded  s%     q ..t4 !r#   c                    [         R                  R                  X5        [        R                  " U R
                  5        U =R                  S-  sl        U R                  5         g)zE
I call this to clean up when one or all of my connections has died.
r8   N)r   r:   re   r(   r   r?   r  r  rg   s     r!   re   PTYProcess.connectionLost  sE     	..t<
A""$r#   c                D    [         R                  " U R                  U5      $ rS   )r   rT   r?   r^   s     r!   rX   PTYProcess.writeSomeData  s     tww--r#   c                    [        5       er[   r   )rI   
descriptors     r!   rt  PTYProcess.closeChildFD  r  r#   c                    [        5       er[   r   rp  s      r!   rq  PTYProcess.writeToChild  r  r#   )ro   r?   r1   r  )rj   rk   rl   rm   rn   r1   r/   r;   r   r  r  r  ra   rC   r  re   rX   rt  rq  rq   rr   r#   r!   r  r  Y  s]     F
C A3F.'`

5%.$$r#   r  )r   None)
r&  zList[Tuple[int, bool]]r'  zDict[int, int]r(  r
   r)  r
   r   zList[Tuple[int, ...]])Brn   
__future__r   r   r   r   r(   r   r@   r   r   collectionsr   typingr   r   r   r   r	   r   r   r   r   r   r  zope.interfacer   twisted.internetr   r   r   twisted.internet._baseprocessr   twisted.internet.interfacesr   twisted.internet.mainr   r   twisted.pythonr   r   twisted.python.runtimer   twisted.python.utilr   	isWindowsr  _ptyrX  _fcntlr  r   r   r"   r2   r4   r:   r6   rt   r   r   r  r   r3  r5  r  rr   r#   r!   <module>r     s  
 #  	 	 	   
  # = =
S ' 3 3 5 9 B ' + )
	6 
 C E 11 /1 , 1+6!e9H++ e9P99H++ 99xg
; g
Tg gT =#J#J#J J 	J
 JZ N$l N$  N$b s$((, s$  s$w!  *  
C  Es6   E. /E; 6F	 .E87E8;FF	FF