
    d:                        d dl Z d dlZd dlZd dlZd dlmc mZ d dlmZ  e	ed      sd Z
 G d de      Ze
e_
        ee_        	 d Zdd	Zdd
Zd Zd Z G d de      Zd Zddej(                  ej(                  ddddfdZdej(                  ej(                  ddfdZd Zg Z ej2                         ZdZdZd Zd Zd Zy)    Nustrcheck_outputc                     d|v rt        d      t        j                  | dt        j                  i|}|j	                         \  }}|j                         }|r0|j                  d      }|| d   }t        j                  |||      |S )z/Backport from subprocess module from python 2.7stdoutz3stdout argument not allowed, it will be overridden.argsr   output)
ValueError
subprocessPopenPIPEcommunicatepollgetCalledProcessError)	popenargskwargsprocessr
   
unused_errretcodecmds          H/usr/lib/python3/dist-packages/azurelinuxagent/common/utils/shellutil.pyr   r      s    v 6 7 7""IP*//PP$002
,,.**V$C{l//VLL    c                       e Zd ZddZd Zy)r   Nc                 .    || _         || _        || _        y N)
returncoder   r
   )selfr   r   r
   s       r   __init__zCalledProcessError.__init__/   s    (DODH DKr   c                 N    dj                  | j                  | j                        S )Nz/Command '{0}' returned non-zero exit status {1})formatr   r   )r   s    r   __str__zCalledProcessError.__str__4   s     txx9:r   r   )__name__
__module____qualname__r    r#    r   r   r   r   .   s    	!
	:r   r   c                     t        | d       S )z9
    Return True if the given command is on the path
    F)run)r   s    r   has_commandr*   C   s     3r   Tc                 0    |g }t        | ||      \  }}|S )a)  
    Note: Deprecating in favour of `azurelinuxagent.common.utils.shellutil.run_command` function.
    Calls run_get_output on 'cmd', returning only the return code.
    If chk_err=True then errors will be reported in the log.
    If chk_err=False then errors will be suppressed from the log.
    )chk_errexpected_errors)run_get_output)r   r,   r-   r   outs        r   r)   r)   J   s&     !#wXLGSNr   c           	         |g }|rt        j                  d|        	 t        | t        j                  t        j
                  d      }|j                         \  }}t        |j                         t        |      }|j                  dk7  rf|rVdj                  | |j                  |      }|j                  |v rt        j                  |       nt        j                  |       |j                  |fS 	 d|fS # t        $ rG}|r.t        j                  dj                  | t        |                   dt        |      fcY d}~S d}~ww xY w)	a  
    Wrapper for subprocess.check_output.
    Execute 'cmd'.  Returns return code and STDOUT, trapping expected
    exceptions.
    Reports exceptions to Error if chk_err parameter is True

    For new callers, consider using run_command instead as it separates stdout from stderr,
    returns only stdout on success, logs both outputs and return code on error and raises an exception.
    NzCommand: [{0}]T)r   stderrshellr   z1Command: [{0}], return code: [{1}], result: [{2}]0Command [{0}] raised unexpected exception: [{1}])loggerverbose_popenr   r   STDOUTr   _on_command_completedpid__encode_command_outputr   r"   infoerror	Exceptionr   )	r   r,   log_cmdr-   r   r
   _msg	exceptions	            r   r.   r.   W   s%    (#.#Z__Z=N=NVZ['')	gkk*(0"''-vc73E3Ev'N  %%8KK$LL%%%v-- # f9  #LLL &d9o684	?""	#s   CC6 6	E?<E;EEc                     t        | t              rT| rAt        | d   t              r.dj                  | D cg c]  }dj                  |       c}      S dj                  |       S | S c c}w )a  
    Formats the command taken by run_command/run_pipe.

    Examples:
        > __format_command("sort")
        'sort'
        > __format_command(["sort", "-u"])
        'sort -u'
        > __format_command([["sort"], ["unique", "-n"]])
        'sort | unique -n'
    r   z |  )
isinstancelistjoin)commandr   s     r   __format_commandrI      sZ     '4 z'!*d3::@sxx}@AAxx  N As   A'c                 &    t        | | nddd      S )zH
    Encodes the stdout/stderr returned by subprocess.communicate()
    r   zutf-8backslashreplace)encodingerrorsr   r	   s    r   r;   r;      s     &,#Pbccr   c                   2     e Zd ZdZed        Z fdZ xZS )CommandErrorzT
    Exception raised by run_command/run_pipe when the command returns an error
    c                     t        | t              rt        |       dkD  r| d   n| }dj                  |||j	                               S )Nr   z'{0}' failed: {1} ({2}))rE   rF   lenr"   rstrip)rH   return_coder1   command_names       r   _get_messagezCommandError._get_message   s>    %/%>3w<RSCSwqzY`(//k6==?[[r   c                     t         t        |   t        j	                  |||             || _        || _        || _        || _        y r   )	superr>   r    rO   rU   rH   r   r   r1   )r   rH   rS   r   r1   	__class__s        r   r    zCommandError.__init__   s>    i'(A(A';X^(_`%r   )r$   r%   r&   __doc__staticmethodrU   r    __classcell__)rX   s   @r   rO   rO      s(     \ \ r   rO   c                 \   	  |        \  }}}|rt        |      }t        |      }|dk7  r<|r"t        j                  dt        |      |||       t	        t        |      |||      |S # t        $ r  t
        $ r1}|r)t        j                  dt        |      t        |              d}~ww xY w)a  
    Executes the given command_action and returns its stdout. The command_action is a function that executes a command/pipe
    and returns its exit code, stdout, and stderr.

    If there are any errors executing the command it raises a RunCommandException; if 'log_error'
    is True, it also logs details about the error.

    If encode_output is True the stdout is returned as a string, otherwise it is returned as a bytes object.
    r   z?Command: [{0}], return code: [{1}], stdout: [{2}] stderr: [{3}])rH   rS   r   r1   r3   N)r;   r5   r=   rI   rO   r>   r   )command_actionrH   	log_errorencode_outputrS   r   r1   rB   s           r   __run_commandr`      s    &4&6#VV,V4F,V4F!U$W- '7'@kbhqwxx  LLLN^_fNgimnwixys   A%A( (B+:,B&&B+Fc	                 b     t        d       fd}	t        |	 ||      S )aV  
        Executes the given command and returns its stdout.

        If there are any errors executing the command it raises a RunCommandException; if 'log_error'
        is True, it also logs details about the error.

        If encode_output is True the stdout is returned as a string, otherwise it is returned as a bytes object.

        If track_process is False the command is not added to list of running commands

        This function is a thin wrapper around Popen/communicate in the subprocess module:
           * The 'input' parameter corresponds to the same parameter in communicate
           * The 'stdin' parameter corresponds to the same parameters in Popen
           * Only one of 'input' and 'stdin' can be specified
           * The 'stdout' and 'stderr' parameters correspond to the same parameters in Popen, except that they
             default to subprocess.PIPE instead of None
           * If the output of the command is redirected using the 'stdout' or 'stderr' parameters (i.e. if the
             value for these parameters is anything other than the default (subprocess.PIPE)), then the corresponding
             values returned by this function or the CommandError exception will be empty strings.

        Note: This is the preferred method to execute shell commands over `azurelinuxagent.common.utils.shellutil.run` function.
    z4The input and stdin arguments are mutually exclusivec                  T   d x} }4t         j                  } r t        t              rj	                         n}		} d }rt        | 
d      }nt        j                  | 
d      }|j                  |      \  }}rt        |j                         |j                  ||fS )NF)stdinr   r1   r2   )input)r   r   rE   strencoder7   r   r   r9   r:   r   )popen_stdincommunicate_inputr   command_stdoutcommand_stderrrH   encode_inputrd   r1   rc   r   track_processs        r   r]   z#run_command.<locals>.command_action   s    *..'$//K2>:eUXCY_dK $WKv]bcG &&wk&Y_glmG)0)<)<CT)<)U&!'++.!!>>AAr   r]   rH   r^   r_   )r   r`   )
rH   rd   rc   r   r1   r^   rk   r_   rl   r]   s
   ````` ` ` r   run_commandrn      s=    . U.OPPB B( S\lyzzr   c                 j     t               dk  rt        d       fd}t        | ||      S )aN  
        Executes the given commands as a pipe and returns its stdout as a string.

        The pipe is a list of commands, which in turn are a list of strings, e.g.

            [["sort"], ["uniq", "-n"]] represents 'sort | unique -n'

        If there are any errors executing the command it raises a RunCommandException; if 'log_error'
        is True, it also logs details about the error.

        If encode_output is True the stdout is returned as a string, otherwise it is returned as a bytes object.

        This function is a thin wrapper around Popen/communicate in the subprocess module:
           * The 'stdin' parameter is used as input for the first command in the pipe
           * The 'stdout', and 'stderr' can be used to redirect the output of the pipe
           * If the output of the pipe is redirected using the 'stdout' or 'stderr' parameters (i.e. if the
             value for these parameters is anything other than the default (subprocess.PIPE)), then the corresponding
             values returned by this function or the CommandError exception will be empty strings.
       z,The pipe must consist of at least 2 commandsc                  .   d } 	 
}	t         j                  k(  rt        j                         } | }n	}g }d}|t	              dz
  k  rU|j                  t        |   |t         j                  |             ||   j                  }|dz  }|t	              dz
  k  rU|j                  t        |   ||             d}|t	        |      dz
  k  r4||   j                  j                          |dz  }|t	        |      dz
  k  r4||   j                         \  }}|D ]  }t        |j                          | !| j                  d       | j                         }||   j                  ||f| | j                          S S # | | j                          w w xY w)Nr      )rc   r   r1   )r   r   tempfileTemporaryFilerQ   appendr7   r   closer   r9   r:   seekreadr   )stderr_filerg   popen_stderr	processesipipe_stdoutpipe_stderrprocpiper1   rc   r   s           r   r]   z run_pipe.<locals>.command_action  s   $	$K (&446*%IAc$i!m#  Q{:??co!pq'l11Q c$i!m#
 VDG;vVbcdAc)nq((!##))+Q c)nq(( (1|'?'?'A$K! 0%dhh/0 &  #)..0Q<**KD&!!# '{&!!# 's   BE? A'E? A&E? ?Frm   )rQ   r   r`   )r   rc   r   r1   r^   r_   r]   s   ````   r   run_piper     s7    ( 4y1}GHH'$R PYivwwr   c                 v    t        | t        t        f      s| f} dj                  t        d | D                    S )a  
    Quote a list or tuple of strings for Unix Shell as words, using the
    byte-literal single quote.

    The resulting string is safe for use with ``shell=True`` in ``subprocess``,
    and in ``os.system``. ``assert shlex.split(ShellQuote(wordList)) == wordList``.

    See POSIX.1:2013 Vol 3, Chap 2, Sec 2.2.2:
    http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_02_02
    rD   c              3   ^   K   | ]%  }d j                  |j                  dd             ' yw)z'{0}''z'\''N)r"   replace).0ss     r   	<genexpr>zquote.<locals>.<genexpr>S  s$     TQ		#w(?@Ts   +-)rE   tuplerF   rG   )	word_lists    r   quoter   E  s3     i%/L	88DT)TTUUr   %AZURE_GUEST_AGENT_PARENT_PROCESS_NAMEAZURE_GUEST_AGENTc                  >   t         5  i }d|v r|j                  |d          n|j                  t        j                         t        |t
        <   ||d<   t        j                  | i |}t        j                  |j                         |cd d d        S # 1 sw Y   y xY w)Nenv)_running_commands_lockupdateosenvironr   PARENT_PROCESS_NAMEr   r   _running_commandsru   r:   )r   r   r   r   s       r   r7   r7   `  s    	 F?JJve}%JJrzz" $5 u""D3F3  -  s   BBBc                 d    t         5  t        j                  |        d d d        y # 1 sw Y   y xY wr   )r   r   remove)r:   s    r   r9   r9   r  s(    	 &  %& & &s   &/c                  L    t         5  t        dd cddd       S # 1 sw Y   yxY w)ar  
    Returns the commands started by run/run_get_output/run_command/run_pipe that are currently running.

    NOTE: This function is not synchronized with process completion, so the returned array may include processes that have
    already completed. Also, keep in mind that by the time this function returns additional processes may have
    started or completed.
    N)r   r   r'   r   r   get_running_commandsr   w  s$     
  $ #$ $ $s   	#)TN)TTN) r   r   rs   	threadingazurelinuxagent.common.loggercommonr5   azurelinuxagent.common.futurer   hasattrr   r>   r   r*   r)   r.   rI   r;   rO   r`   r   rn   r   r   r   RLockr   r   r   r7   r9   r   r'   r   r   <module>r      s	  & 
    . . . z>*":Y : +J$6J!
&R&d9 ""L  $4
PZP_P_kp  @D  TX  hl .{b joojooY^nr @xFV*  (* = ' $&
	$r   