o
    b1                     @   s   d Z ddlZddlZddlmZ ddlZddlZddlZddlZddl	Z	ddl
Z
ddlZddlZddlmZmZ ddlmZ ddlmZmZmZ ddlmZ e Zde_d	d
 ZG dd dejZdd Zdd ZeeeeG dd dej eZ!dS )z<
Windows Process Management, used with reactor.spawnProcess
    N)implementer)_pollingfileerror)BaseProcess)	IConsumerIProcessTransport	IProducer)quoteArguments   c                 C   s   t |  tj  d S N)printsysstdoutflush)msg r   A/usr/lib/python3/dist-packages/twisted/internet/_dumbwin32proc.pydebug$   s   r   c                   @   s   e Zd Zdd Zdd ZdS )_Reaperc                 C   s
   || _ d S r   )proc)selfr   r   r   r   __init__*   s   
z_Reaper.__init__c                 C   s@   t | jjdt jkrdS t| jj}|   | j| dS Nr   )	
win32eventWaitForSingleObjectr   hProcessWAIT_OBJECT_0win32processGetExitCodeProcess
deactivateprocessEnded)r   exitCoder   r   r   	checkWork-   s   z_Reaper.checkWorkN)__name__
__module____qualname__r   r"   r   r   r   r   r   )   s    r   c                 C   s^   t | !}|ddkr|dd}|W  d   S W d   dS 1 s(w   Y  dS )a   
    Look for a #! line, and return the value following the #! if one exists, or
    None if this file is not a script.

    I don't know if there are any conventions for quoting in Windows shebang
    lines, so this doesn't support any; therefore, you may not pass any
    arguments to scripts invoked as filters.  That's probably wrong, so if
    somebody knows more about the cultural expectations on Windows, please feel
    free to fix.

    This shebang line support was added in support of the CGI tests;
    appropriately enough, I determined that shebang lines are culturally
    accepted in the Windows world through this page::

        http://www.cgi101.com/learn/connect/winxp.html

    @param filename: str representing a filename

    @return: a str representing another filename.
       z#!i   
N)openreadreadlinestrip)filenamefexer   r   r   _findShebang9   s   
"r/   c                 C   s   | j d dkS )z
    Determine if a pywintypes.error is telling us that the given process is
    'not a valid win32 application', i.e. not a PE format executable.

    @param pywinerr: a pywintypes.error instance raised by CreateProcess

    @return: a boolean
    r      )args)pywinerrr   r   r   _invalidWin32AppT   s   r3   c                   @   s   e Zd ZdZdZdd Zdd Zdd Zd	d
 Zdd Z	dd Z
dd Zdd Zdd Zdd Zdd Zdd Zdd Zdd Zdd  Zd!d" Zd#d$ Zd%d& Zd'd( Zd)d* Zd+d, Zd-d. Zd/d0 Zd1efd2d3Zd4S )5Processa  
    A process that integrates with the Twisted event loop.

    If your subprocess is a python program, you need to:

     - Run python.exe with the '-u' command line option - this turns on
       unbuffered I/O. Buffering stdout/err/in can cause problems, see e.g.
       http://support.microsoft.com/default.aspx?scid=kb;EN-US;q1903

     - If you don't want Windows messing with data passed over
       stdin/out/err, set the pipes to be in binary mode::

        import os, sys, mscvrt
        msvcrt.setmode(sys.stdin.fileno(), os.O_BINARY)
        msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)
        msvcrt.setmode(sys.stderr.fileno(), os.O_BINARY)

    r   c                    s
  t j| t| t }d|_t|d\_	}t|d\_
}	t|d\}
_tjtjdd t  | _|	 _|
 _tj _t }t|j	|ddtj}tj	 |_	t|j
|ddtj}tj
 |_
t|j|ddtj}tj |_tj |pi  dd   D dd |D }t!|rt"nrt"n fdd	}z|  W na t#j$y0 } zSt%|st&|t'}|du rt&d
 t(|}|)d t!|}|z|  W n t#j$y% } zt%|rt&d||f t&|d}~ww W Y d}~nd}~ww t|	 t| t|
 t *j	fddj+_,t *j
fddj-_.t /jj0_1j,j.j1fD ]}2| qmj34 2t5 dS )z-
        Create a new child process.
        r
   r   Nc                 S   s"   i | ]\}}t |t |qS r   osfsdecode).0keyvaluer   r   r   
<dictcomp>   s   " z$Process.__init__.<locals>.<dictcomp>c                 S   s   g | ]}t |qS r   r5   )r8   xr   r   r   
<listcomp>   s    z$Process.__init__.<locals>.<listcomp>c                     s2   t j} td d d|  	\___}d S Nr
   )win32conCREATE_NO_WINDOWr   CreateProcessr   hThreadpid)flagsdwTidStartupInfocmdlinecommandenvpathr   r   r   doCreate   s   z"Process.__init__.<locals>.doCreatezD%r is neither a Windows executable, nor a script with a shebang linez<%r has an invalid shebang line: %r is not a valid executablec                        j d| S r>   protochildDataReceiveddatar   r   r   <lambda>       z"Process.__init__.<locals>.<lambda>c                    rM   Nr&   rN   rQ   rS   r   r   rT      rU   )6r   _PollingTimerr   r   win32securitySECURITY_ATTRIBUTESbInheritHandle	win32pipe
CreatePipehStdoutRhStderrRhStdinWSetNamedPipeHandleStatePIPE_NOWAITr   STARTUPINFO
hStdOutput	hStdError	hStdInputSTARTF_USESTDHANDLESdwFlagswin32apiGetCurrentProcessDuplicateHandler?   DUPLICATE_SAME_ACCESS	win32fileCloseHandler6   environcopyupdateitemsr	   r7   
pywintypesr   r3   OSErrorr/   listinsert_PollableReadPipeoutConnectionLostr   errConnectionLoststderr_PollableWritePipeinConnectionLoststdin_addPollableResourcerO   makeConnectionr   )r   reactorprotocolrI   r1   environmentrK   sAttrshStdoutWhStderrWhStdinR
currentPidtmprL   pwtesheborigcmdpwte2pipewatcherr   rF   r   r   |   s   




!



zProcess.__init__c                 C   s0   | j d u r	t |dv rt| jd d S d S )N)INTTERMKILLr
   )rC   r   ProcessExitedAlreadyr   TerminateProcessr   )r   signalIDr   r   r   signalProcess  s
   
zProcess.signalProcessc                 C   s   |dkr	t |S t |S r   )r   ProcessDoneProcessTerminated)r   statusr   r   r   
_getReason
  s   

zProcess._getReasonc                 C      | j | dS )zQ
        Write data to the process' stdin.

        @type data: C{bytes}
        N)r|   write)r   rR   r   r   r   r        zProcess.writec                 C   r   )z[
        Write data to the process' stdin.

        @type seq: C{list} of C{bytes}
        N)r|   writeSequence)r   seqr   r   r   r     r   zProcess.writeSequencec                 C   s    |dkr| j | dS t|)a;  
        Similar to L{ITransport.write} but also allows the file descriptor in
        the child process which will receive the bytes to be specified.

        This implementation is limited to writing to the child's standard input.

        @param fd: The file descriptor to which to write.  Only stdin (C{0}) is
            supported.
        @type fd: C{int}

        @param data: The bytes to write.
        @type data: C{bytes}

        @return: L{None}

        @raise KeyError: If C{fd} is anything other than the stdin file
            descriptor (C{0}).
        r   N)r|   r   KeyError)r   fdrR   r   r   r   writeToChild  s   zProcess.writeToChildc                 C   sD   |dkr
|    d S |dkr|   d S |dkr|   d S td)Nr   r
   r&   z4Only standard-IO file descriptors available on win32)
closeStdincloseStdoutcloseStderrNotImplementedError)r   r   r   r   r   closeChildFD7  s   zProcess.closeChildFDc                 C   s   | j   dS )zClose the process' stdin.N)r|   closerS   r   r   r   r   C  s   zProcess.closeStdinc                 C      | j   d S r   )ry   r   rS   r   r   r   r   G     zProcess.closeStderrc                 C   r   r   )r   r   rS   r   r   r   r   J  r   zProcess.closeStdoutc                 C   s   |    |   |   dS )z8
        Close the process' stdout, in and err.
        N)r   r   r   rS   r   r   r   loseConnectionM  s   zProcess.loseConnectionc                 C      | j d |   d S r>   rO   childConnectionLostconnectionLostNotifyrS   r   r   r   rw   U     zProcess.outConnectionLostc                 C   r   rV   r   rS   r   r   r   rx   Y  r   zProcess.errConnectionLostc                 C   r   r   r   rS   r   r   r   r{   ]  r   zProcess.inConnectionLostc                 C   s   |  j d7  _ |   dS )zS
        Will be called 3 times, by stdout/err threads and process handle.
        r
   N)closedNotifiesmaybeCallProcessEndedrS   r   r   r   r   a  s   zProcess.connectionLostNotifyc                 C   sJ   | j dkr!| jr#t| j t| j d | _d | _t|  d S d S d S )N   )r   lostProcessrl   rm   r   rB   r   r   rS   r   r   r   r   h  s   zProcess.maybeCallProcessEndedc                 C   s   | j || d S r   )r|   registerProducer)r   producer	streamingr   r   r   r   q  s   zProcess.registerProducerc                 C   r   r   )r|   unregisterProducerrS   r   r   r   r   t  r   zProcess.unregisterProducerc                 C      |    d S r   )_pauserS   r   r   r   pauseProducingx     zProcess.pauseProducingc                 C   r   r   )_unpauserS   r   r   r   resumeProducing{  r   zProcess.resumeProducingc                 C   r   r   )r   rS   r   r   r   stopProducing~  r   zProcess.stopProducingc                 C      t d)NzUnimplemented: Process.getHostr   rS   r   r   r   getHost     zProcess.getHostc                 C   r   )NzUnimplemented: Process.getPeerr   rS   r   r   r   getPeer  r   zProcess.getPeerreturnc                 C   s   d| j j d| j dS )z@
        Return a string representation of the process.
        <z pid=>)	__class__r#   rC   rS   r   r   r   __repr__  s   zProcess.__repr__N)r#   r$   r%   __doc__r   r   r   r   r   r   r   r   r   r   r   r   rw   rx   r{   r   r   r   r   r   r   r   r   r   strr   r   r   r   r   r4   e   s8     		r4   )"r   r6   r   zope.interfacer   rr   rh   r?   r   rl   r[   r   rX   twisted.internetr   r   twisted.internet._baseprocessr   twisted.internet.interfacesr   r   r   twisted.python.win32r	   rY   PIPE_ATTRS_INHERITABLErZ   r   _PollableResourcer   r/   r3   rW   r4   r   r   r   r   <module>   s0   
