o
    +ke,7                     @   sv  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Zd dl	Z	ddl
mZ ddlmZmZmZmZ ddlmZ e ZddlmZmZmZmZ e jdd Zd	d
 Ze jddddZG dd deZG dd deZG dd deZG dd deZ e jdd Z!dd Z"G dd dZ#e# Z$dd Z%d*d e&fd!d"Z'ej(fd#d$Z)d+d%d&Z*e jd,d(d)Z+dS )-    N   )__version__)is_win32is_linux
is_freebsd	is_darwin)create_logger)EXIT_SUCCESSEXIT_WARNINGEXIT_SIGNAL_BASEErrorc               
   c   s@   ddl m}  |  }t }|rKt}z+z|d fV  W n ty/ } z	|j}W Y d }~nd }~ww W td|  t	| ntd|  t	| w t
  t }|rZt	d td td td ttjtj}t|d t|d |  }z||fV  W td t|d d S td t|d w )Nr   )get_process_idz:Daemonizing: Foreground process (%s, %s, %s) is now dying.r   /   )platformr   osforkr	   _ExitCodeException	exit_codeloggerdebug_exitsetsidchdircloseopendevnullO_RDWRdup2)r   old_idpidr   efdnew_id r$   8usr/lib/python3.10/site-packages/borg/helpers/process.py
_daemonize   sD   





r&   c                  C   s6   t  \} }| |fW  d   S 1 sw   Y  dS )zsDetach process from controlling terminal and run in background

    Returns: old and new get_process_id tuples
    N)r&   )r   r#   r$   r$   r%   	daemonize7   s   $r'      )timeoutc                 c   s
   t  u\}}|du rtd|  t}tdtt tdtt tdtt| zvz| dkr8t	
|  W nJ tyB   Y nN tyL   t}Y nI ty_   td|  td }Y n; ty } ztd	d
t|j||j  t}W Y d}~n d}~ww td t}W t|W t|W t|W t|W t|t|1 sw   Y  W d   n1 sw   Y  W d   n1 sw   Y  tj}td|  zbz||fV  W n# ty } ztj}tdd
t|j||j  |d}~ww td|  W z
t|d | W nS ty: } ztdd
t|j||j  W Y d}~n<d}~ww z
t|d | W w  tyi } ztdd
t|j||j  W Y d}~w d}~ww W d   dS W d   dS 1 s~w   Y  dS )aD  Like daemonize(), but as context manager.

    The with-body is executed in the background process,
    while the foreground process survives until the body is left
    or the given timeout is exceeded. In the latter case a warning is
    reported by the foreground.
    Context variable is (old_id, new_id) get_process_id tuples.
    An exception raised in the body is reported by the foreground
    as a warning as well as propagated outside the body in the background.
    In case of a warning, the foreground exits with exit code EXIT_WARNING
    instead of EXIT_SUCCESS.
    NzQDaemonizing: Foreground process (%s, %s, %s) is waiting for background process...SIGINTSIGHUPSIGTERMr   z=Daemonizing: Foreground process (%s, %s, %s) received SIGINT.r   zEDaemonizing: Foreground process received an exception while waiting:
 zGDaemonizing: Background process did not respond (timeout). Is it alive?z;Daemonizing: Background process (%s, %s, %s) is starting...zDDaemonizing: Background process raised an exception while starting:
z9Daemonizing: Background process (%s, %s, %s) has started.r   zHDaemonizing: Trying to kill the foreground process raised an exception:
)r&   r   r   r	   signal_handlerraising_signal_handlerKeyboardInterruptSigHupSigTermtimesleepr
   r   BaseExceptionwarningjoin	tracebackformat_exception	__class____traceback__r   signalr,   r+   r   killerror)r)   r   r#   r   r!   Zsig_to_foregroundr$   r$   r%   daemonizing@   s   

. 4$r?   c                   @   s   e Zd Zdd ZdS )r   c                 C   s
   || _ d S N)r   )selfr   r$   r$   r%   __init__   s   
z_ExitCodeException.__init__N)__name__
__module____qualname__rB   r$   r$   r$   r%   r      s    r   c                   @      e Zd ZdZdS )SignalExceptionz*base class for all signal-based exceptionsNrC   rD   rE   __doc__r$   r$   r$   r%   rG          rG   c                   @   rF   )r1   zraised on SIGHUP signalNrH   r$   r$   r$   r%   r1      rJ   r1   c                   @   rF   )r2   zraised on SIGTERM signalNrH   r$   r$   r$   r%   r2      rJ   r2   c              
   c   sj    t | trtt| d} | durt| |}zdV  W | dur't| | dS dS | dur4t| | w w )a  
    when entering context, set up signal handler <handler> for signal <sig>.
    when leaving context, restore original signal handler.

    <sig> can bei either a str when giving a signal.SIGXXX attribute name (it
    won't crash if the attribute name does not exist as some names are platform
    specific) or a int, when giving a signal number.

    <handler> is any handler value as accepted by the signal.signal(sig, handler).
    N)
isinstancestrgetattrr<   )sighandlerZorig_handlerr$   r$   r%   r.      s   
r.   c                    s    fdd}|S )Nc                    s   t  | t j  r@   )r<   SIG_IGN)sig_noframeexc_clsr$   r%   rO      s   z'raising_signal_handler.<locals>.handlerr$   )rT   rO   r$   rS   r%   r/      s   r/   c                   @   sL   e 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S )SigIntManagerc                 C   s$   d| _ d| _d| _td| j| _d S )NFr*   )_sig_int_triggered_action_triggered_action_doner.   rO   ctxrA   r$   r$   r%   rB      s   zSigIntManager.__init__c                 C      | j S r@   )rV   rZ   r$   r$   r%   __bool__      zSigIntManager.__bool__c                 C   r[   r@   )rW   rZ   r$   r$   r%   action_triggered   r]   zSigIntManager.action_triggeredc                 C   r[   r@   )rX   rZ   r$   r$   r%   action_done   r]   zSigIntManager.action_donec                 C   s   d| _ d| _d S )NFT)rW   rX   rZ   r$   r$   r%   action_completed   s   
zSigIntManager.action_completedc                 C   s   |  d d d  d| _d| _d S )NT)__exit__rV   rW   )rA   rQ   stackr$   r$   r%   rO      s   
zSigIntManager.handlerc                 C   s   | j   d S r@   )rY   	__enter__rZ   r$   r$   r%   rc      s   zSigIntManager.__enter__c                 C   s$   | j r| j ||| d | _ d S d S r@   )rY   ra   )rA   Zexception_typeZexception_valuer8   r$   r$   r%   ra      s   
zSigIntManager.__exit__N)rC   rD   rE   rB   r\   r^   r_   r`   rO   rc   ra   r$   r$   r$   r%   rU      s    rU   c                   C   s   t  t jt j dS )aW  
    Ignore SIGINT, see also issue #6912.

    Ctrl-C will send a SIGINT to both the main process (borg) and subprocesses
    (e.g. ssh for remote ssh:// repos), but often we do not want the subprocess
    getting killed (e.g. because it is still needed to cleanly shut down borg).

    To avoid that: Popen(..., preexec_fn=ignore_sigint)
    N)r<   r*   rP   r$   r$   r$   r%   ignore_sigint   s   
rd   r-   cmd_linec              
   K   s   | dr	J dzt| }|stdW n ty0 } ztd|| W Y d}~dS d}~ww td|| z
tj|fi |W S  t	yU   td||d  Y dS  t
yg   td	||d  Y dS w )
as  
    Handle typical errors raised by subprocess.Popen. Return None if an error occurred,
    otherwise return the Popen object.

    *cmd_line* is split using shlex (e.g. 'gzip -9' => ['gzip', '-9']).

    Log messages will be prefixed with *log_prefix*; if set, it should end with a space
    (e.g. log_prefix='--some-option: ').

    Does not change the exit code.
    shellz Sorry pal, shell mode is a no-noz&an empty command line is not permittedz%s%sNz%scommand line: %sz%sexecutable not found: %sr   z%spermission denied: %s)getshlexsplit
ValueErrorr   r>   r   
subprocessPopenFileNotFoundErrorPermissionError)re   
log_prefixkwargscommandver$   r$   r%   popen_with_error_handling   s*   
rs   c                 C   s"   t | do|  ot pdtjv S )NisattyZANSICON)hasattrrt   r   r   environ)r"   r$   r$   r%   is_terminal  s   "rw   c                 C   s   t |dur|ntj}| r8d}||d }|dur|||< n||}|dur8ttddr8ttdr8|| |dd t|d< |S )	a  
    Prepare the environment for a subprocess we are going to create.

    :param system: True for preparing to invoke system-installed binaries,
                   False for stuff inside the pyinstaller environment (like borg, python).
    :param env: optionally give a environment dict here. if not given, default to os.environ.
    :return: a modified copy of the environment
    NZLD_LIBRARY_PATHZ_ORIGfrozenFZ_MEIPASSZBORG_PASSPHRASEZBORG_VERSION)	dictr   rv   rg   rM   sysru   popr   )systemenvZlp_keyZlp_origlpr$   r$   r%   prepare_subprocess_env  s   	



r   Tc           
   
   c   sd   | r:|}|}t dd}|rt| tj|d|td}nt| tj|d|td}|s/td|  d|r4|jn|j}| }zMz|V  W n tyU   t	
d | rR|  d	} w d}W |r_|  | rt	
d
 | }	t	
d|	 |rv|  |r|	rtd| |	f d S d S d S |r|  | rt	
d
 | }	t	
d|	 |r|  |r|	rtd| |	f w )NT)r|   zfilter-process: )stdoutstdinro   r}   
preexec_fn)r   r   ro   r}   r   zfilter z: process creation failedz Exception, killing the filter...Fz"Done, waiting for filter to die...zfilter cmd exited with code %dzfilter %s failed, rc=%d)r   rs   rk   PIPErd   r   r   r   	Exceptionr   r   r=   r   wait)
cmdstreamZstream_closeZinboundZfilter_streamZfilter_stream_closer}   procZborg_succeededrcr$   r$   r%   create_filter_process=  s`   






r   )r-   r@   )T),
contextlibr   os.pathrerh   r<   rk   rz   r3   r8   r-   r   Zplatformflagsr   r   r   r   r   r   helpersr	   r
   r   r   contextmanagerr&   r'   r?   r5   r   rG   r1   r2   r.   r/   rU   Zsig_intrd   rL   rs   r   rw   r   r   r$   r$   r$   r%   <module>   sF    
!	E
+
&