Test Failed
Push — master ( aea994...69b639 )
by Nicolas
03:44 queued 10s
created

glances.secure   A

Complexity

Total Complexity 10

Size/Duplication

Total Lines 88
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 38
dl 0
loc 88
rs 10
c 0
b 0
f 0
wmc 10

2 Functions

Rating   Name   Duplication   Size   Complexity  
A secure_popen() 0 13 2
B __secure_popen() 0 47 8
1
# -*- coding: utf-8 -*-
2
#
3
# This file is part of Glances.
4
#
5
# Copyright (C) 2021 Nicolargo <[email protected]>
6
#
7
# Glances is free software; you can redistribute it and/or modify
8
# it under the terms of the GNU Lesser General Public License as published by
9
# the Free Software Foundation, either version 3 of the License, or
10
# (at your option) any later version.
11
#
12
# Glances is distributed in the hope that it will be useful,
13
# but WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
# GNU Lesser General Public License for more details.
16
#
17
# You should have received a copy of the GNU Lesser General Public License
18
# along with this program. If not, see <http://www.gnu.org/licenses/>.
19
20
"""Secures functions for Glances"""
21
22
from glances.compat import nativestr
23
from subprocess import Popen, PIPE
24
25
26
def secure_popen(cmd):
27
    """A more or less secure way to execute system commands
28
    Multiple command should be seprated with a &&
29
30
    Return: the result of the commands
31
    """
32
    ret = ''
33
34
    # Split by multiple commands '&&'
35
    for c in cmd.split('&&'):
36
        ret += __secure_popen(c)
37
38
    return ret
39
40
41
def __secure_popen(cmd):
42
    """A more or less secure way to execute system command
43
    Manage redirection (>) and pipes (|)
44
    """
45
    ret = ''
46
47
    # Split by redirection '>'
48
    cmd_split_redirect = cmd.split('>')
49
    if len(cmd_split_redirect) > 2:
50
        return 'Glances error: Only one file redirection allowed ({})'.format(cmd)
51
    elif len(cmd_split_redirect) == 2:
52
        stdout_redirect = cmd_split_redirect[1].strip()
53
        cmd = cmd_split_redirect[0]
54
    else:
55
        stdout_redirect = None
56
57
    sub_cmd_stdin = None
58
    p_last = None
59
    # Split by pipe '|'
60
    for sub_cmd in cmd.split('|'):
61
        # Split by space ' '
62
        sub_cmd_split = [i for i in sub_cmd.split(' ') if i]
63
        p = Popen(sub_cmd_split,
64
                  shell=False,
65
                  stdin=sub_cmd_stdin,
66
                  stdout=PIPE,
67
                  stderr=PIPE)
68
        if p_last is not None:
69
            # Allow p_last to receive a SIGPIPE if p exits.
70
            p_last.stdout.close()
71
        p_last = p
72
        sub_cmd_stdin = p.stdout
73
74
    p_ret = p_last.communicate()
75
76
    if nativestr(p_ret[1]) == '':
77
        # No error
78
        ret = nativestr(p_ret[0])
79
        if stdout_redirect is not None:
80
            # Write result to redirection file
81
            with open(stdout_redirect, "w") as stdout_redirect_file:
82
                stdout_redirect_file.write(ret)
83
    else:
84
        # Error
85
        ret = nativestr(p_ret[1])
86
87
    return ret
88