Esempio n. 1
0
    def get_confirmation(self, title, prompt, default='No'):
        '''Display a confirmation dialog'''
        script = '''
            on run argv
              tell application "Alfred 2"
                  activate
                  set alfredPath to (path to application "Alfred 2")
                  set alfredIcon to path to resource "appicon.icns" in bundle ¬
                    (alfredPath as alias)

                  try
                    display dialog "{p}" with title "{t}"  ¬
                      buttons {{"Yes", "No"}} default button "{d}" ¬
                      with icon alfredIcon
                    set answer to (button returned of result)
                  on error number -128
                    set answer to "No"
                  end
              end tell
            end run'''.format(p=prompt, t=title, d=default)

        from subprocess import Popen, PIPE
        p = Popen(['osascript', '-'], stdin=PIPE, stdout=PIPE, stderr=PIPE)
        stdout, stderr = p.communicate(script)
        return stdout.decode('utf-8').rstrip('\n')
Esempio n. 2
0
 def run_script(self, script):
     '''Run an AppleScript, returning its output'''
     from subprocess import Popen, PIPE
     p = Popen(['osascript', '-ss', '-'], stdin=PIPE, stdout=PIPE,
               stderr=PIPE)
     stdout, stderr = p.communicate(script)
     return stdout.decode('utf-8'), stderr.decode('utf-8')
Esempio n. 3
0
    def run(self, mname, is_sys=False, is_demo=False):
        mode_sample = 1
        # create first line in stella files
        for sec in self.Cfg.Sections:
            opts = self.Cfg.Options(sec)
            pattern = None

            if 'mode_sample' in opts:
                mode_sample = int(self.Cfg.get(sec, 'mode_sample'))

            if 'dir' in opts:
                path = os.path.join(self.Cfg.Root, self.Cfg.get(sec, 'dir'))
            else:
                path = self.Cfg.Root
            path = os.path.realpath(path)

            # print("{}: mode_sample= {}".format(sec, mode_sample));

            if 'pattern' in opts:
                pattern = self.Cfg.get(sec, 'pattern')

            if 'file_add_line' in opts:
                fname = os.path.join(self.Cfg.Root,
                                     self.Cfg.get(sec, 'file_add_line'))

                self.add_line(fname, mname, pattern=pattern, is_demo=is_demo)
                logger.info(
                    ' {}: Added new line to {} with pattern= {}'.format(
                        sec, fname, pattern))

            if 'sample' in opts:
                fname = os.path.join(self.Cfg.Root,
                                     self.Cfg.get(sec, 'sample'))
                extension = os.path.splitext(fname)[1]
                fout = os.path.join(os.path.dirname(fname),
                                    '{}{}'.format(mname, extension))
                self.cp_sample(fname, fout, mode=mode_sample, is_demo=is_demo)

            if mode_sample == -1:
                cmd = './delstel.pl  {};'.format(mname)
                return_code, stdout, stderr = self.eval_cmd(cmd,
                                                            path,
                                                            is_demo=is_demo)

            if is_sys and 'cmd' in opts:
                cmd = self.Cfg.get(sec, 'cmd')
                return_code, stdout, stderr = self.eval_cmd(cmd,
                                                            path,
                                                            is_demo=is_demo)
                # return_code, stdout, stderr = self.eval_cmd_log(cmd, path, is_demo=is_demo)

                if stdout:
                    for line in stdout.decode('utf8').strip().split("\n"):
                        logger.info('stdout: {}'.format(line))

                if stderr:
                    for line in stderr.decode('utf8').strip().split("\n"):
                        logger.error('stderr: {}'.format(line))
Esempio n. 4
0
def exec_or_die(cmd):
    print_cmd(shlex.join(cmd))
    proc = subprocess.Popen(cmd, stderr=subprocess.PIPE, stdout=subprocess.PIPE)
    stdout, stderr = proc.communicate()
    result = proc.wait()

    if result != 0:
        for line in stdout.decode('utf-8').split('\n'):
            print_error(line)
        print_error("Command returned %d" % result)
        exit(1)
Esempio n. 5
0
    def get_from_user(self, title, prompt, hidden=False, value=None,
                      extra_buttons=None):
        '''Popup a dialog to request some piece of information.

        The main use for this function is to request information that you don't
        want showing up in Alfred's command history.
        '''
        if value is None:
            value = ''

        buttons = ['Cancel', 'Ok']
        if extra_buttons:
            if isinstance(extra_buttons, (list, tuple)):
                buttons = extra_buttons + buttons
            else:
                buttons.insert(0, extra_buttons)
        buttons = '{%s}' % ', '.join(['"%s"' % b for b in buttons])

        hidden = 'with hidden answer' if hidden else ''

        script = '''
            on run argv
              tell application "Alfred 2"
                  activate
                  set alfredPath to (path to application "Alfred 2")
                  set alfredIcon to path to resource "appicon.icns" in bundle ¬
                    (alfredPath as alias)

                  try
                    display dialog "{p}:" with title "{t}" ¬
                      default answer "{v}" ¬
                      buttons {b} default button "Ok" with icon alfredIcon {h}
                    set answer to (button returned of result) & "|" & ¬
                      (text returned of result)
                  on error number -128
                    set answer to "Cancel|"
                  end
              end tell
            end run'''.format(v=value, p=prompt, t=title, h=hidden, b=buttons)

        from subprocess import Popen, PIPE
        p = Popen(['osascript', '-'], stdin=PIPE, stdout=PIPE, stderr=PIPE)
        stdout, stderr = p.communicate(script)
        response = stdout.decode('utf-8').rstrip('\n')
        button, sep, value = response.partition('|')
        return (button, value)
Esempio n. 6
0
    def get_selection_from_user(cls, title, prompt, choices, default=None):
        '''Popup a dialog to let a user select a value from a list of choices.

        The main use for this function is to request information that you don't
        want showing up in Alfred's command history.
        '''
        if default is None:
            default = ''

        if not isinstance(choices, (tuple, list)):
            choices = [choices]
        choices = '{{"{0}"}}'.format('","'.join(choices))

        with open(os.path.join(BASE_DIR, 'get_selection.scpt')) as sfile:
            script = sfile.read().format(default=default, prompt=prompt,
                                         title=title, choices=choices)
        from subprocess import Popen, PIPE
        p = Popen(['osascript', '-'], stdin=PIPE, stdout=PIPE, stderr=PIPE)
        stdout, stderr = p.communicate(script)
        response = stdout.decode('utf-8').rstrip('\n')
        button, sep, value = response.partition('|')
        return (button, value)
Esempio n. 7
0
def osascript_tell(app, script):
    p = Popen(['osascript'], stdin=PIPE, stdout=PIPE)
    stdout, stderr = p.communicate(
        ('tell application "{}"\n{}\nend tell'.format(app,
                                                      script).encode('utf-8')))
    return stdout.decode('utf-8').rstrip('\n')
Esempio n. 8
0
def index():
    """
    Main WSGI application entry.
    """
    path = normpath(abspath(dirname(__file__)))

    # Only POST is implemented
    if request.method != 'POST':
        abort(501)

    # Load config
    with open(join(path, 'config.json'), 'r') as cfg:
        config = loads(cfg.read())

    hooks = config.get('hooks_path', join(path, 'hooks'))

    # Allow Github IPs only
    if config.get('github_ips_only', True):
        src_ip = ip_address(u'{}'.format(
            request.remote_addr)  # Fix stupid ipaddress issue
                            )
        whitelist = requests.get('https://api.github.com/meta').json()['hooks']

        for valid_ip in whitelist:
            if src_ip in ip_network(valid_ip):
                break
        else:
            abort(403)

    # Enforce secret
    secret = config.get('enforce_secret', '')
    if secret:
        # Only SHA1 is supported
        header_signature = request.headers.get('X-Hub-Signature')
        if header_signature is None:
            abort(403)

        sha_name, signature = header_signature.split('=')
        if sha_name != 'sha1':
            abort(501)

        # HMAC requires the key to be bytes, but data is string
        mac = hmac.new(str(secret), msg=request.data, digestmod=sha1)

        # Python prior to 2.7.7 does not have hmac.compare_digest
        if hexversion >= 0x020707F0:
            if not hmac.compare_digest(str(mac.hexdigest()), str(signature)):
                abort(403)
        else:
            # What compare_digest provides is protection against timing
            # attacks; we can live without this protection for a web-based
            # application
            if not str(mac.hexdigest()) == str(signature):
                abort(403)

    # Implement ping
    event = request.headers.get('X-GitHub-Event', 'ping')
    if event == 'ping':
        return dumps({'msg': 'pong'})

    # Gather data
    try:
        payload = request.get_json()
    except:
        app.logger.error("Loading payload failed.")
        abort(400)

    # Determining the branch is tricky, as it only appears for certain event
    # types an at different levels
    branch = None
    try:
        # Case 1: a ref_type indicates the type of ref.
        # This true for create and delete events.
        if 'ref_type' in payload:
            if payload['ref_type'] == 'branch':
                branch = payload['ref']

        # Case 2: a pull_request object is involved. This is pull_request and
        # pull_request_review_comment events.
        elif 'pull_request' in payload:
            # This is the TARGET branch for the pull-request, not the source
            # branch
            branch = payload['pull_request']['base']['ref']

        elif event in ['push']:
            # Push events provide a full Git ref in 'ref' and not a 'ref_type'.
            branch = payload['ref'].split('/')[2]

    except KeyError:
        # If the payload structure isn't what we expect, we'll live without
        # the branch name
        pass

    # All current events have a repository, but some legacy events do not,
    # so let's be safe
    name = payload['repository']['name'] if 'repository' in payload else None

    meta = {'name': name, 'branch': branch, 'event': event}
    app.logger.info('Metadata: {}'.format(dumps(meta)))

    # Possible hooks
    scripts = []
    if branch and name:
        scripts.append(join(hooks, '{event}-{name}-{branch}'.format(**meta)))
    if name:
        scripts.append(join(hooks, '{event}-{name}'.format(**meta)))
    scripts.append(join(hooks, '{event}'.format(**meta)))
    scripts.append(join(hooks, 'all'))

    # Check permissions
    scripts = [s for s in scripts if isfile(s) and access(s, X_OK)]
    if not scripts:
        app.logger.error("No scripts to run.")
        return ''

    # Save payload to temporal file
    osfd, tmpfile = mkstemp()
    with fdopen(osfd, 'w') as pf:
        pf.write(dumps(payload))

    # If the process does not terminate after timeout seconds,
    # an empty response will be sent without output, while the
    # script finishes in the background.
    execution_timeout = config.get('execution_timeout', 10)

    # Run scripts
    ran = {}
    for s in scripts:
        proc = Popen([s, tmpfile, event],
                     env={'PATH': getenv('PATH')},
                     stdout=PIPE,
                     stderr=PIPE)
        try:
            stdout, stderr = proc.communicate(timeout=execution_timeout)

            ran[basename(s)] = {
                'returncode': proc.returncode,
                'stdout': stdout.decode('utf-8'),
                'stderr': stderr.decode('utf-8'),
            }

            # Log errors if a hook failed
            if proc.returncode != 0:
                app.logger.error('{} : {} \n{}'.format(s, proc.returncode,
                                                       stderr))
        except TimeoutExpired:
            ran[basename(s)] = {
                'returncode': None,
                'stdout':
                "Script took to long to finish. Will finish in background.",
                'stderr': None,
            }
    # Remove temporal file
    remove(tmpfile)

    info = config.get('return_scripts_info', False)
    if not info:
        return ''

    output = jsonify(ran)
    app.logger.info(output)
    return output
Esempio n. 9
0
def perform_inventory(args):
    Variables = dict()

    # Parse command line arguments
    optlist = []

    command_line_length = len(args)
    argIndex = 0
    inArgument = False
    currentArgument = ""
    arg = ""

    while argIndex < command_line_length:
        arg = args[argIndex]
        if argIndex == 0:
            # skip the program name
            argIndex += 1
            continue

        if inArgument:
            Variables[currentArgument] = arg
            inArgument = False
        else:
            if arg[0:2] == "--":
                inArgument = True
                currentArgument = arg[2:].lower()
            else:
                # The rest are not options
                args = args[argIndex:]
                break
        argIndex += 1

    if inArgument:
        Variables[currentArgument] = arg

    AcceptableOptions = ["inmof", "outxml", "help"]

    if "help" in Variables:
        usage()
        exit(0)

    optionsValid = True
    for arg in Variables.keys():
        if arg.lower() not in AcceptableOptions:
            optionsValid = False
            exitWithError("Error: %s is not a valid option" % arg)

    if optionsValid == False:
        usage()
        exit(1)

    dsc_sysconfdir = join(helperlib.CONFIG_SYSCONFDIR, helperlib.CONFIG_SYSCONFDIR_DSC)
    dsc_reportdir = join(dsc_sysconfdir, 'InventoryReports')
    omicli_path = join(helperlib.CONFIG_BINDIR, 'omicli')
    dsc_host_base_path = helperlib.DSC_HOST_BASE_PATH
    dsc_host_path = join(dsc_host_base_path, 'bin/dsc_host')
    dsc_host_output_path = join(dsc_host_base_path, 'output')
    dsc_host_lock_path = join(dsc_host_base_path, 'dsc_host_lock')
    dsc_host_switch_path = join(dsc_host_base_path, 'dsc_host_ready')
    dsc_configuration_path = join(dsc_sysconfdir, 'configuration')
    temp_report_path = join(dsc_configuration_path, 'Inventory.xml.temp')
    report_path = join(dsc_configuration_path, 'Inventory.xml')
    inventorylock_path = join(dsc_sysconfdir, 'inventory_lock')

    if ("omsconfig" in helperlib.DSC_SCRIPT_PATH):
        write_omsconfig_host_switch_event(pathToCurrentScript, isfile(dsc_host_switch_path))

    if ("omsconfig" in helperlib.DSC_SCRIPT_PATH) and (isfile(dsc_host_switch_path)):
        use_omsconfig_host = True
    else:
        use_omsconfig_host = False

    if "outxml" in Variables:
        report_path = Variables["outxml"]

    parameters = []

    if use_omsconfig_host:
        parameters.append(dsc_host_path)
        parameters.append(dsc_host_output_path)

        if "inmof" in Variables:
            parameters.append("PerformInventoryOOB")
            parameters.append(Variables["inmof"])
        else:
            parameters.append("PerformInventory")
    else:
        parameters.append(omicli_path)
        parameters.append("iv")
        parameters.append(helperlib.DSC_NAMESPACE)
        parameters.append("{")
        parameters.append("MSFT_DSCLocalConfigurationManager")
        parameters.append("}")

        if "inmof" in Variables:
            parameters.append("PerformInventoryOOB")
            parameters.append("{")
            parameters.append("InventoryMOFPath")
            parameters.append(Variables["inmof"])
            parameters.append("}")
        else:
            parameters.append("PerformInventory")

    # Ensure inventory lock file permission is set correctly before opening
    operationStatusUtility.ensure_file_permissions(inventorylock_path, '644')

    # Open the inventory lock file. This also creates a file if it does not exist.
    inventorylock_filehandle = open(inventorylock_path, 'w')
    printVerboseMessage("Opened the inventory lock file at the path '" + inventorylock_path + "'")
    retval = 0
    inventorylock_acquired = True
    dschostlock_filehandle = None
    inmof_file = ''
    if "inmof" in Variables:
        inmof_file = Variables["inmof"]

    try:
        # Acquire inventory file lock
        try:
            flock(inventorylock_filehandle, LOCK_EX | LOCK_NB)
            write_omsconfig_host_log('Inventory lock is acquired by : ' + inmof_file, pathToCurrentScript)
        except IOError:
            inventorylock_acquired = False
            write_omsconfig_host_log('Failed to acquire inventory lock.', pathToCurrentScript, 'WARNING')

        if inventorylock_acquired:
            dschostlock_acquired = False
            
            if use_omsconfig_host:
                if isfile(dsc_host_lock_path):
                    stop_old_host_instances(dsc_host_lock_path)
                    # Open the dsc host lock file. This also creates a file if it does not exist.
                    dschostlock_filehandle = open(dsc_host_lock_path, 'w')
                    printVerboseMessage("Opened the dsc host lock file at the path '" + dsc_host_lock_path + "'")

                    # Acquire dsc host file lock
                    for retry in range(10):
                        try:
                            flock(dschostlock_filehandle, LOCK_EX | LOCK_NB)
                            dschostlock_acquired = True
                            write_omsconfig_host_log('dsc_host lock file is acquired by : ' + inmof_file, pathToCurrentScript)
                            break
                        except IOError:
                            write_omsconfig_host_log('dsc_host lock file not acquired. retry (#' + str(retry) + ') after 60 seconds...', pathToCurrentScript)
                            sleep(60)
                else:
                    write_omsconfig_host_log('dsc_host lock file does not exist. Skipping this operation until next consistency hits.', pathToCurrentScript, 'WARNING')

            if dschostlock_acquired or (not use_omsconfig_host):
                try:
                    system("rm -f " + dsc_reportdir + "/*")

                    process = Popen(parameters, stdout = PIPE, stderr = PIPE)
                    stdout, stderr = process.communicate()
                    retval = process.returncode

                    stdout = stdout.decode() if isinstance(stdout, bytes) else stdout
                    stderr = stderr.decode() if isinstance(stderr, bytes) else stderr
                    printVerboseMessage(stdout)

                    if (retval > 0):
                        write_omsconfig_host_log('dsc_host failed with code = ' + str(retval), pathToCurrentScript)
                        exit(retval)

                    # Combine reports together
                    reportFiles = listdir(dsc_reportdir)

                    final_xml_report = '<INSTANCE CLASSNAME="Inventory"><PROPERTY.ARRAY NAME="Instances" TYPE="string" EmbeddedObject="object"><VALUE.ARRAY>'
                    values = []
                    for reportFileName in reportFiles:
                        reportFilePath = join(dsc_reportdir, reportFileName)

                        if not isfile(reportFilePath):
                            continue
                        report = parse(reportFilePath)
                        for valueNode in report.getElementsByTagName('VALUE'):
                            values.append(valueNode.toxml())

                    final_xml_report = final_xml_report + "".join(values) + "</VALUE.ARRAY></PROPERTY.ARRAY></INSTANCE>"

                    # Ensure temporary inventory report file permission is set correctly before opening
                    operationStatusUtility.ensure_file_permissions(temp_report_path, '644')

                    tempReportFileHandle = open(temp_report_path, 'w')
                    try:
                        tempReportFileHandle.write(final_xml_report)
                    finally:
                        if (tempReportFileHandle):
                            tempReportFileHandle.close()

                    # Ensure temporary inventory report file permission is set correctly after opening
                    operationStatusUtility.ensure_file_permissions(temp_report_path, '644')

                    system("rm -f " + dsc_reportdir + "/*")
                    move(temp_report_path, report_path)

                    # Ensure inventory report file permission is set correctly
                    operationStatusUtility.ensure_file_permissions(report_path, '644')
                finally:
                    if (dschostlock_filehandle):
                        # Release inventory file lock
                        flock(inventorylock_filehandle, LOCK_UN)

                        # Release dsc host file lock
                        if isfile(dsc_host_lock_path) and use_omsconfig_host:
                            try:
                                flock(dschostlock_filehandle, LOCK_UN)
                            except:
                                pass
    finally:
        if (inventorylock_filehandle):
            # Close inventory lock file handle
            inventorylock_filehandle.close()
        
        if (dschostlock_filehandle):
            # Close dsc host lock file handle
            if use_omsconfig_host:
                try:
                    dschostlock_filehandle.close()
                except:
                    pass

    # Ensure inventory lock file permission is set correctly after opening
    operationStatusUtility.ensure_file_permissions(inventorylock_path, '644')

    # Ensure dsc host lock file permission is set correctly after opening
    if use_omsconfig_host:
        operationStatusUtility.ensure_file_permissions(dsc_host_lock_path, '644')

    exit(retval)
Esempio n. 10
0
def osascript_tell(app, script):
    p = Popen(['osascript'], stdin=PIPE, stdout=PIPE)
    stdout, stderr = p.communicate(
        ('tell application "{}"\n{}\nend tell'.format(app, script)
         .encode('utf-8')))
    return stdout.decode('utf-8').rstrip('\n')
Esempio n. 11
0
def index():
    """
    Main WSGI application entry.
    """

    path = normpath(abspath(dirname(__file__)))

    # Only POST is implemented - same effect as removing 'GET' in methods above
    if request.method != 'POST':
        logging.warning("We got a {} request, this isn't supported".format(
            request.method))
        abort(405)

    # Load config
    if isfile(join(path, 'config.json')):
        with open(join(path, 'config.json'), 'r') as cfg:
            config = loads(cfg.read())
    else:
        # abort(503, 'Configuration file config.json is missing.')
        config = {
            "github_ips_only": False,
            "enforce_secret": "",
            "return_scripts_info": False,
        }

    hooks = config.get('hooks_path', join(path, 'hooks'))

    logging.info("Config loaded, handling request")

    # Allow Github IPs only
    if config.get('github_ips_only', True):
        src_ip = ip_address(u'{}'.format(
            request.access_route[0])  # Fix stupid ipaddress issue
                            )
        whitelist = requests.get('https://api.github.com/meta').json()['hooks']

        for valid_ip in whitelist:
            if src_ip in ip_network(valid_ip):
                break
        else:
            logging.warning("We got a request from unauthorized IP: %s",
                            src_ip)
            abort(403)

    # Enforce secret
    secret = config.get('enforce_secret', '')
    if secret:
        # Only SHA1 is supported
        header_signature = request.headers.get('X-Hub-Signature')
        if header_signature is None:
            logging.warning("No signature found when expecting one")
            abort(403)

        sha_name, signature = header_signature.split('=')
        if sha_name != 'sha1':
            logging.warning("Unsupported signature mech: %s", sha_name)
            abort(501)

        # HMAC requires the key to be bytes, but data is string
        # Convert key to ascii in unicode environment
        # https://stackoverflow.com/questions/33455463/python-3-sign-a-message-with-key-sha512
        mac = hmac.new(bytearray(secret, "ASCII"),
                       msg=request.data,
                       digestmod=sha1)

        if not constant_time_compare(str(mac.hexdigest()), str(signature)):
            abort(403)

    # Implement ping
    event = request.headers.get('X-GitHub-Event', 'ping')
    if event == 'ping':
        logging.warning("Ping Pong")
        return dumps({'msg': 'pong'})

    # Gather data
    try:
        payload = request.get_json()
    except Exception:
        logging.warning('Request parsing failed with exception %s', Exception)
        abort(400)

    # Determining the branch is tricky, as it only appears for certain event
    # types an at different levels
    branch = None
    try:
        # Case 1: a ref_type indicates the type of ref.
        # This true for create and delete events.
        if 'ref_type' in payload:
            if payload['ref_type'] == 'branch':
                branch = payload['ref']

        # Case 2: a pull_request object is involved. This is pull_request and
        # pull_request_review_comment events.
        elif 'pull_request' in payload:
            # This is the TARGET branch for the pull-request, not the source
            # branch
            branch = payload['pull_request']['base']['ref']

        elif event in ['push']:
            # Push events provide a full Git ref in 'ref' and not a 'ref_type'.
            branch = payload['ref'].split('/', 2)[2]

    except KeyError:
        # If the payload structure isn't what we expect, we'll live without
        # the branch name
        pass

    # All current events have a repository, but some legacy events do not,
    # so let's be safe
    name = payload['repository']['name'] if 'repository' in payload else None

    meta = {'name': name, 'branch': branch, 'event': event}
    logging.info('Metadata:\n{}'.format(dumps(meta)))

    # Skip push-delete
    if event == 'push' and payload['deleted']:
        logging.info('Skipping push-delete event for {}'.format(dumps(meta)))
        return jsonify({'status': 'skipped'})

    # Possible hooks
    scripts = []
    if branch and name:
        scripts.append(join(hooks, '{event}-{name}-{branch}'.format(**meta)))
        scripts.append(
            join(hooks, '{event}-{name}-{branch}-background'.format(**meta)))
    if name:
        scripts.append(join(hooks, '{event}-{name}'.format(**meta)))
    scripts.append(join(hooks, '{event}'.format(**meta)))
    scripts.append(join(hooks, '{event}-background'.format(**meta)))
    scripts.append(join(hooks, 'all'))
    scripts.append(join(hooks, 'all-background'))

    # Check permissions
    scripts = [s for s in scripts if isfile(s) and access(s, X_OK)]
    if not scripts:
        return jsonify({'status': 'nop'})

    # Save payload to temporal file
    osfd, tmpfile = mkstemp()
    with fdopen(osfd, 'w') as pf:
        pf.write(dumps(payload))

    # Run scripts
    ran = {}
    for s in scripts:

        if s.endswith('-background'):
            # each backgrounded script gets its own tempfile
            # in this case, the backgrounded script MUST clean up after this!!!
            # the per-job tempfile will NOT be deleted here!
            osfd2, tmpfile2 = mkstemp()
            with fdopen(osfd2, 'w') as pf2:
                pf2.write(dumps(payload))

            proc = Popen([s, tmpfile2, event], stdout=PIPE, stderr=PIPE)

            ran[basename(s)] = {'backgrounded': 'yes'}

        else:
            proc = Popen([s, tmpfile, event], stdout=PIPE, stderr=PIPE)
            stdout, stderr = proc.communicate()

            ran[basename(s)] = {
                'returncode': proc.returncode,
                'stdout': stdout.decode('utf-8'),
                'stderr': stderr.decode('utf-8'),
            }

            # Log errors if a hook failed
            if proc.returncode != 0:
                logging.error('{} : {} \n{}'.format(s, proc.returncode,
                                                    stderr))

    # Remove temporal file
    remove(tmpfile)

    info = config.get('return_scripts_info', False)
    if not info:
        return jsonify({'status': 'done'})

    output = dumps(ran, sort_keys=True, indent=4)
    logging.info(output)
    return jsonify(ran)