#!/usr/bin/python3

# Copyright (c) 2017, NVIDIA CORPORATION.  All rights reserved.
#
# NVIDIA CORPORATION and its licensors retain all intellectual property
# and proprietary rights in and to this software, related documentation
# and any modifications thereto.  Any use, reproduction, disclosure or
# distribution of this software and related documentation without an express
# license agreement from NVIDIA CORPORATION is strictly prohibited.

#
# Module used for running shell command, based on SubPorcess
#

import os
import sys
import subprocess 
import time

sps_list = []

class SubPs:

    @staticmethod
    def check_timeout(kill_it):

        rc = 0
        cur_time = time.time()
        last = len(sps_list) - 1
        
        while last >= 0:
            sps = sps_list[last]

            if sps.start_time == 0:
                last -= 1
                continue

            elapsed = cur_time - sps.start_time
            if elapsed > sps.timeout:
                rc += 1 
                if kill_it:
                    try:
                        sps.proc.kill()
                    except:
                        pass
                    del sps_list[last]
            last -= 1

        return rc

    def __init__(self):
        self.output = ""
        self.error_output = ""
        self.error_code = 0xff
        self.os_errno = 0
        self.os_err_str = ""
        self.timeout = 0
        self.start_time = 0
        self.proc = None

    def log_cmd_status(self):

        print(self.output)
        print(self.error_output)

    def run_cmd(self, cmd, timeout = 15):
        self.timeout = timeout 
        tmpout = ""

        if not self.timeout == 0:
            self.start_time = time.time()
            sps_list.append(self)

        try:
            cmd_str = ''.join((str(i) + ' ') for i in cmd)

            self.proc = subprocess.Popen(cmd, stdout = subprocess.PIPE,
                                    stderr = subprocess.PIPE, preexec_fn = os.setpgrp)

            (tmpout, stderr) = self.proc.communicate()
            self.output = tmpout.decode('utf-8', errors='ignore')

            self.error_output = stderr

            self.error_code = self.proc.returncode

            sys.stdout.flush()

        except OSError as e:
            self.os_errno = e.errno
            self.os_err_str = e.strerror
            self.error_code = 0xff
        
        return self.error_code

    def get_error_str(self, prefix_str):
        err_str = ". Error code: " + str(self.error_code) +  ", OS error: " + self.os_err_str + ", errno " + str(self.os_errno)

        return prefix_str + err_str

