aboutsummaryrefslogtreecommitdiffhomepage
path: root/libs/hbb_common/src/platform/linux.rs
blob: 716025dc7afbeb63df646ba849536eaa17845637 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
use crate::ResultType;

lazy_static::lazy_static! {
    pub static ref DISTRO: Distro = Distro::new();
}

pub struct Distro {
    pub name: String,
    pub version_id: String,
}

impl Distro {
    fn new() -> Self {
        let name = run_cmds("awk -F'=' '/^NAME=/ {print $2}' /etc/os-release".to_owned())
            .unwrap_or_default()
            .trim()
            .trim_matches('"')
            .to_string();
        let version_id =
            run_cmds("awk -F'=' '/^VERSION_ID=/ {print $2}' /etc/os-release".to_owned())
                .unwrap_or_default()
                .trim()
                .trim_matches('"')
                .to_string();
        Self { name, version_id }
    }
}

pub fn get_display_server() -> String {
    let mut session = get_values_of_seat0([0].to_vec())[0].clone();
    if session.is_empty() {
        // loginctl has not given the expected output.  try something else.
        if let Ok(sid) = std::env::var("XDG_SESSION_ID") {
            // could also execute "cat /proc/self/sessionid"
            session = sid;
        }
        if session.is_empty() {
            session = run_cmds("cat /proc/self/sessionid".to_owned()).unwrap_or_default();
        }
    }

    get_display_server_of_session(&session)
}

fn get_display_server_of_session(session: &str) -> String {
    let mut display_server = if let Ok(output) =
        run_loginctl(Some(vec!["show-session", "-p", "Type", session]))
    // Check session type of the session
    {
        let display_server = String::from_utf8_lossy(&output.stdout)
            .replace("Type=", "")
            .trim_end()
            .into();
        if display_server == "tty" {
            // If the type is tty...
            if let Ok(output) = run_loginctl(Some(vec!["show-session", "-p", "TTY", session]))
            // Get the tty number
            {
                let tty: String = String::from_utf8_lossy(&output.stdout)
                    .replace("TTY=", "")
                    .trim_end()
                    .into();
                if let Ok(xorg_results) = run_cmds(format!("ps -e | grep \"{}.\\\\+Xorg\"", tty))
                // And check if Xorg is running on that tty
                {
                    if xorg_results.trim_end() != "" {
                        // If it is, manually return "x11", otherwise return tty
                        return "x11".to_owned();
                    }
                }
            }
        }
        display_server
    } else {
        "".to_owned()
    };
    if display_server.is_empty() || display_server == "tty" {
        // loginctl has not given the expected output.  try something else.
        if let Ok(sestype) = std::env::var("XDG_SESSION_TYPE") {
            display_server = sestype;
        }
    }
    // If the session is not a tty, then just return the type as usual
    display_server
}

pub fn get_values_of_seat0(indices: Vec<usize>) -> Vec<String> {
    if let Ok(output) = run_loginctl(None) {
        for line in String::from_utf8_lossy(&output.stdout).lines() {
            if line.contains("seat0") {
                if let Some(sid) = line.split_whitespace().next() {
                    if is_active(sid) {
                        return indices
                            .into_iter()
                            .map(|idx| line.split_whitespace().nth(idx).unwrap_or("").to_owned())
                            .collect::<Vec<String>>();
                    }
                }
            }
        }
    }

    // some case, there is no seat0 https://github.com/rustdesk/rustdesk/issues/73
    if let Ok(output) = run_loginctl(None) {
        for line in String::from_utf8_lossy(&output.stdout).lines() {
            if let Some(sid) = line.split_whitespace().next() {
                let d = get_display_server_of_session(sid);
                if is_active(sid) && d != "tty" {
                    return indices
                        .into_iter()
                        .map(|idx| line.split_whitespace().nth(idx).unwrap_or("").to_owned())
                        .collect::<Vec<String>>();
                }
            }
        }
    }

    return indices
        .iter()
        .map(|_x| "".to_owned())
        .collect::<Vec<String>>();
}

fn is_active(sid: &str) -> bool {
    if let Ok(output) = run_loginctl(Some(vec!["show-session", "-p", "State", sid])) {
        String::from_utf8_lossy(&output.stdout).contains("active")
    } else {
        false
    }
}

pub fn run_cmds(cmds: String) -> ResultType<String> {
    let output = std::process::Command::new("sh")
        .args(vec!["-c", &cmds])
        .output()?;
    Ok(String::from_utf8_lossy(&output.stdout).to_string())
}

#[cfg(not(feature = "flatpak"))]
fn run_loginctl(args: Option<Vec<&str>>) -> std::io::Result<std::process::Output> {
    let mut cmd = std::process::Command::new("loginctl");
    if let Some(a) = args {
        return cmd.args(a).output();
    }
    cmd.output()
}

#[cfg(feature = "flatpak")]
fn run_loginctl(args: Option<Vec<&str>>) -> std::io::Result<std::process::Output> {
    let mut l_args = String::from("loginctl");
    if let Some(a) = args {
        l_args = format!("{} {}", l_args, a.join(" "));
    }
    std::process::Command::new("flatpak-spawn")
        .args(vec![String::from("--host"), l_args])
        .output()
}