o
    3gQ;                     @  s   d dl mZ d dlZd dlZd dlZd dlmZ d dlmZm	Z	 d dl
mZ d dlmZ d dlmZ d dlmZ d d	lmZ d d
lmZ dd ZG dd dZG dd deZG dd deZdS )    )annotationsN)closing)ProcessExecutionErrorshquote)IS_WIN32)local)BaseRemoteMachine)ShellSession)	LocalPath)
RemotePathc                  C  sJ   t   } t|  | d |  d W  d   S 1 sw   Y  dS )zAttempts to find a free port.)	localhostr      N)socketr   bindgetsockname)s r   T/home/garg/my-data/venv/lib/python3.10/site-packages/plumbum/machines/ssh_machine.py_get_free_port   s
   


$r   c                   @  sd   e Zd ZdZg dZdd Zdd Zdd Zd	d
 Zdd Z	e
dd Ze
dd Ze
dd ZdS )	SshTunnelz{An object representing an SSH tunnel (created by
    :func:`SshMachine.tunnel <plumbum.machines.remote.SshMachine.tunnel>`))_session_lport_dport_reverse__weakref__c                 C  st   || _ || _|| _|| _|r2t|dkr4|jd ur6tdtj}|	|jd }|r8|
d| _d S d S d S d S d S )N0z/^Allocated port (\d+) for remote forward to .+$   r   )r   r   r   r   str_startup_resultrecompile	MULTILINEsearchgroup)selfsessionlportdportreverseregexmatchr   r   r   __init__   s   zSshTunnel.__init__c                 C  s"   | j  r	| j jnd}d| dS )Nz	(defunct)z<SshTunnel >)r   aliveproc)r$   tunnelr   r   r   __repr__-   s   zSshTunnel.__repr__c                 C  s   | S Nr   r$   r   r   r   	__enter__1   s   zSshTunnel.__enter__c                 C  s   |    d S r1   )close)r$   tvtbr   r   r   __exit__4      zSshTunnel.__exit__c                 C  s   | j   dS )zCloses(terminates) the tunnelN)r   r4   r2   r   r   r   r4   7   s   zSshTunnel.closec                 C     | j S )z-Tunneled port or socket on the local machine.)r   r2   r   r   r   r&   ;      zSshTunnel.lportc                 C  r:   )z.Tunneled port or socket on the remote machine.)r   r2   r   r   r   r'   @   r;   zSshTunnel.dportc                 C  r:   )z-Represents if the tunnel is a reverse tunnel.)r   r2   r   r   r   r(   E   r;   zSshTunnel.reverseN)__name__
__module____qualname____doc__	__slots__r+   r0   r3   r8   r4   propertyr&   r'   r(   r   r   r   r   r      s    

r   c                   @  s   e Zd ZdZ											dddZd	d
 Zd ddZdd Zd!ddZd"ddZ					d#ddZ
edd Zdd Zdd ZdS )$
SshMachinea;  
    An implementation of :class:`remote machine <plumbum.machines.remote.BaseRemoteMachine>`
    over SSH. Invoking a remote command translates to invoking it over SSH ::

        with SshMachine("yourhostname") as rem:
            r_ls = rem["ls"]
            # r_ls is the remote `ls`
            # executing r_ls() translates to `ssh yourhostname ls`

    :param host: the host name to connect to (SSH server)

    :param user: the user to connect as (if ``None``, the default will be used)

    :param port: the server's port (if ``None``, the default will be used)

    :param keyfile: the path to the identity file (if ``None``, the default will be used)

    :param ssh_command: the ``ssh`` command to use; this has to be a ``Command`` object;
                        if ``None``, the default ssh client will be used.

    :param scp_command: the ``scp`` command to use; this has to be a ``Command`` object;
                        if ``None``, the default scp program will be used.

    :param ssh_opts: any additional options for ``ssh`` (a list of strings)

    :param scp_opts: any additional options for ``scp`` (a list of strings)

    :param password: the password to use; requires ``sshpass`` be installed. Cannot be used
                     in conjunction with ``ssh_command`` or ``scp_command`` (will be ignored).
                     NOTE: THIS IS A SECURITY RISK!

    :param encoding: the remote machine's encoding (defaults to UTF8)

    :param connect_timeout: specify a connection timeout (the time until shell prompt is seen).
                            The default is 10 seconds. Set to ``None`` to disable

    :param new_session: whether or not to start the background session as a new
                        session leader (setsid). This will prevent it from being killed on
                        Ctrl+C (SIGINT)
    Nr   utf8
   Fc                 C  s"  |d u r|	d urt d d|	df }nt d }|d u r,|	d ur(t d d|	df }nt d }g }g }|| _|r>| d| | _n|| _|rU|dt|g |dt|g |ri|dt|g |dt|g |d || || |t| | _|t| | _t	j
| |
||d	 d S )
Nsshpassz-psshscp@-Pz-iz-r)encodingconnect_timeoutnew_session)r   host_fqhostextendr   appendtuple_ssh_command_scp_commandr   r+   )r$   rM   userportkeyfilessh_commandscp_commandssh_optsscp_optspasswordrJ   rK   rL   scp_argsssh_argsr   r   r   r+   u   s>   



zSshMachine.__init__c                 C     d| j  S )Nzssh://rN   r2   r   r   r   __str__   r9   zSshMachine.__str__c                 K  s   g }| | || j |r`i }t| dr|| j  |r%|| |d u r/t| dd }|r;| dt|dg |rN|d | dd |	 D  t
|ttfr[| | n|| | jt| jdi |S )Nenvcwdcd&&c                 s  s&    | ]\}}| d t | V  qdS )=N)r   ).0kr6   r   r   r   	<genexpr>   s   $ z#SshMachine.popen.<locals>.<genexpr>r   )rO   rP   rN   hasattrupdatera   getdeltagetattrr   items
isinstancerQ   listrR   popen)r$   argsrY   ra   rb   kwargscmdlineenvdeltar   r   r   rp      s(   




zSshMachine.popenc                 C  s(   t jdtdd | j|ddddd dS )z
        Runs the given command using ``nohup`` and redirects std handles,
        allowing the command to run "detached" from its controlling TTY or parent.
        Does not return anything. Depreciated (use command.nohup or daemonic_popen).
        z0Use .nohup on the command or use daemonic_popen)r   )
stacklevel.NF)rb   stdoutstderrrP   )warningswarnFutureWarningdaemonic_popen)r$   commandr   r   r   nohup   s   zSshMachine.nohuprv   Tc           	      C  s
  |du rd}|du rd}t |dkrg ndt |dg}|d ||  ||r-dnd	t | d
|r;|dkr;dnd	 t | dg | j|dgd}| }z#|dkrct|||j |j	 W |j
  |j  |j	  dS |j
  |j  |j	  w )z
        Runs the given command using ``nohup`` and redirects std handles,
        allowing the command to run "detached" from its controlling TTY or parent.
        Does not return anything.

        .. versionadded:: 1.6.0

        Nz	/dev/nullz&1rv   rc   rd   r~   z>>r,   2z
</dev/nullz-f)rY   r   )r   rP   rO   	formulaterp   waitr   rw   readrx   stdinr4   )	r$   r}   rb   rw   rx   rP   rq   r.   rcr   r   r   r|      s6   	




zSshMachine.daemonic_popenc                 C  s2   t | jdg|r
dgndg|d| j|| j| jdS )Nz/bin/shz-tt-TrL   )rM   )r	   rp   custom_encodingrK   rM   r$   isattyrL   r   r   r   r%      s   zSshMachine.sessionr      c                 C  s   |du rdnd| d}|du rdnd| d}t |dkr!t }|s0d| | d| | gnd| | d| | g}	| jd	|	d
d}
tt|
| j| jd|||S )a	  Creates an SSH tunnel from the TCP port (``lport``) of the local machine
        (``lhost``, defaults to ``"localhost"``, but it can be any IP you can ``bind()``)
        to the remote TCP port (``dport``) of the destination machine (``dhost``, defaults
        to ``"localhost"``, which means *this remote machine*). This function also
        supports Unix sockets, in which case the local socket should be passed in as
        ``lport`` and the local bind address should be ``None``. The same can be done
        for a remote socket, by following the same pattern with ``dport`` and ``dhost``.
        The returned :class:`SshTunnel <plumbum.machines.remote.SshTunnel>` object can
        be used as a *context-manager*.

        The more conventional use case is the following::

            +---------+          +---------+
            | Your    |          | Remote  |
            | Machine |          | Machine |
            +----o----+          +---- ----+
                 |                    ^
                 |                    |
               lport                dport
                 |                    |
                 \______SSH TUNNEL____/
                        (secure)

        Here, you wish to communicate safely between port ``lport`` of your machine and
        port ``dport`` of the remote machine. Communication is tunneled over SSH, so the
        connection is authenticated and encrypted.

        The more general case is shown below (where ``dport != "localhost"``)::

            +---------+          +-------------+      +-------------+
            | Your    |          | Remote      |      | Destination |
            | Machine |          | Machine     |      | Machine     |
            +----o----+          +---- ----o---+      +---- --------+
                 |                    ^    |               ^
                 |                    |    |               |
            lhost:lport               |    |          dhost:dport
                 |                    |    |               |
                 \_____SSH TUNNEL_____/    \_____SOCKET____/
                        (secure)              (not secure)

        Usage::

            rem = SshMachine("megazord")

            with rem.tunnel(1234, "/var/lib/mysql/mysql.sock", dhost=None):
                sock = socket.socket()
                sock.connect(("localhost", 1234))
                # sock is now tunneled to the MySQL socket on megazord
        N [z]:r   z-L:z-Rr   T)rY   rL   )rK   )r   r   rp   r   r	   r   rK   )r$   r&   r'   lhostdhostrK   r(   formatted_lhostformatted_dhostrY   r.   r   r   r   r/      s,   :
zSshMachine.tunnelc                 C  s,   t | } d| v rd| dddd S | S )Nr   /r   \)r   replace)pathr   r   r   _translate_drive_letterQ  s   z"SshMachine._translate_drive_letterc                 C  s   t |trtd|t |tr|j| krtd|dt |tr*td|tr6| |}| |}| | j dt	| | d S )Nzsrc of download cannot be zsrc % points to a different remote machinezdst of download cannot be r   )
rn   r
   	TypeErrorr   remoter   r   rS   rN   r   r$   srcdstr   r   r   downloadY  s   



 zSshMachine.downloadc                 C  s   t |trtd|t |trtd|t |tr*|j| kr*td|dtr6| |}| |}| || j dt	|  d S )Nzsrc of upload cannot be zdst of upload cannot be zdst r   r   )
rn   r   r   r
   r   r   r   rS   rN   r   r   r   r   r   uploade  s   



 zSshMachine.upload)NNNNNr   r   NrC   rD   F)r   NN)rv   NNTFF)r   r   r   F)r<   r=   r>   r?   r+   r`   rp   r~   r|   r%   r/   staticmethodr   r   r   r   r   r   r   rB   K   s8    ,
3


$
S
rB   c                   @  sH   e Zd ZdZ										dddZd	d
 Zdd ZdddZdS )PuttyMachinea   
    PuTTY-flavored SSH connection. The programs ``plink`` and ``pscp`` are expected to
    be in the path (or you may provide your own ``ssh_command`` and ``scp_command``)

    Arguments are the same as for :class:`plumbum.machines.remote.SshMachine`
    Nr   rC   rD   Fc                 C  s   |d u rt d }|d u rt d }|sdg}|d u rt jj}|d ur8|dt|g g t|dt|}d }tj| |||||||||	|
|d d S )Nplinkpscpz-sshrI   )rV   rW   rX   rY   rZ   rJ   rK   rL   )r   ra   rT   rO   r   ro   rB   r+   )r$   rM   rT   rU   rV   rW   rX   rY   rZ   rJ   rK   rL   r   r   r   r+   z  s4   
zPuttyMachine.__init__c                 C  r^   )Nzputty-ssh://r_   r2   r   r   r   r`     r9   zPuttyMachine.__str__c                 C  s   |S r1   r   )r$   r   r   r   r   r     s   z$PuttyMachine._translate_drive_letterc                 C  s*   t | jd|r	dgndg|d| j|| jS )Nr   z-tr   r   )r	   rp   r   rK   r   r   r   r   r%     s   zPuttyMachine.session)
NNNNNr   r   rC   rD   Fr   )r<   r=   r>   r?   r+   r`   r   r%   r   r   r   r   r   r  s     

)r   )
__future__r   r   r   ry   
contextlibr   plumbum.commandsr   r   plumbum.libr   plumbum.machines.localr   plumbum.machines.remoter   plumbum.machines.sessionr	   plumbum.path.localr
   plumbum.path.remoter   r   r   rB   r   r   r   r   r   <module>   s$    2  )