199ca880aSopenharmony_ci/***
299ca880aSopenharmony_ci  This file is part of systemd.
399ca880aSopenharmony_ci
499ca880aSopenharmony_ci  Copyright 2010 Lennart Poettering
599ca880aSopenharmony_ci
699ca880aSopenharmony_ci  systemd is free software; you can redistribute it and/or modify it
799ca880aSopenharmony_ci  under the terms of the GNU Lesser General Public License as published by
899ca880aSopenharmony_ci  the Free Software Foundation; either version 2.1 of the License, or
999ca880aSopenharmony_ci  (at your option) any later version.
1099ca880aSopenharmony_ci
1199ca880aSopenharmony_ci  systemd is distributed in the hope that it will be useful, but
1299ca880aSopenharmony_ci  WITHOUT ANY WARRANTY; without even the implied warranty of
1399ca880aSopenharmony_ci  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1499ca880aSopenharmony_ci  Lesser General Public License for more details.
1599ca880aSopenharmony_ci
1699ca880aSopenharmony_ci  You should have received a copy of the GNU Lesser General Public License
1799ca880aSopenharmony_ci  along with systemd; If not, see <http://www.gnu.org/licenses/>.
1899ca880aSopenharmony_ci***/
1999ca880aSopenharmony_ci
2099ca880aSopenharmony_ci#include <stdbool.h>
2199ca880aSopenharmony_ci#include <sys/types.h>
2299ca880aSopenharmony_ci#include <string.h>
2399ca880aSopenharmony_ci#include <stdio.h>
2499ca880aSopenharmony_ci#include <assert.h>
2599ca880aSopenharmony_ci#include <errno.h>
2699ca880aSopenharmony_ci#include <unistd.h>
2799ca880aSopenharmony_ci#include <sys/wait.h>
2899ca880aSopenharmony_ci#include <signal.h>
2999ca880aSopenharmony_ci#include <ctype.h>
3099ca880aSopenharmony_ci
3199ca880aSopenharmony_ci#include "process-util.h"
3299ca880aSopenharmony_ci#include "fileio.h"
3399ca880aSopenharmony_ci#include "util.h"
3499ca880aSopenharmony_ci#include "log.h"
3599ca880aSopenharmony_ci
3699ca880aSopenharmony_ciint get_process_comm(pid_t pid, char **name) {
3799ca880aSopenharmony_ci        const char *p;
3899ca880aSopenharmony_ci        int r;
3999ca880aSopenharmony_ci
4099ca880aSopenharmony_ci        assert(name);
4199ca880aSopenharmony_ci        assert(pid >= 0);
4299ca880aSopenharmony_ci
4399ca880aSopenharmony_ci        p = procfs_file_alloca(pid, "comm");
4499ca880aSopenharmony_ci
4599ca880aSopenharmony_ci        r = read_one_line_file(p, name);
4699ca880aSopenharmony_ci        if (r == -ENOENT)
4799ca880aSopenharmony_ci                return -ESRCH;
4899ca880aSopenharmony_ci
4999ca880aSopenharmony_ci        return r;
5099ca880aSopenharmony_ci}
5199ca880aSopenharmony_ci
5299ca880aSopenharmony_ciint get_process_cmdline(pid_t pid, size_t max_length, bool comm_fallback, char **line) {
5399ca880aSopenharmony_ci        _cleanup_fclose_ FILE *f = NULL;
5499ca880aSopenharmony_ci        char *r = NULL, *k;
5599ca880aSopenharmony_ci        const char *p;
5699ca880aSopenharmony_ci        int c;
5799ca880aSopenharmony_ci
5899ca880aSopenharmony_ci        assert(line);
5999ca880aSopenharmony_ci        assert(pid >= 0);
6099ca880aSopenharmony_ci
6199ca880aSopenharmony_ci        p = procfs_file_alloca(pid, "cmdline");
6299ca880aSopenharmony_ci
6399ca880aSopenharmony_ci        f = fopen(p, "re");
6499ca880aSopenharmony_ci        if (!f)
6599ca880aSopenharmony_ci                return -errno;
6699ca880aSopenharmony_ci
6799ca880aSopenharmony_ci        if (max_length == 0) {
6899ca880aSopenharmony_ci                size_t len = 0, allocated = 0;
6999ca880aSopenharmony_ci
7099ca880aSopenharmony_ci                while ((c = getc(f)) != EOF) {
7199ca880aSopenharmony_ci
7299ca880aSopenharmony_ci                        if (!GREEDY_REALLOC(r, allocated, len+2)) {
7399ca880aSopenharmony_ci                                free(r);
7499ca880aSopenharmony_ci                                return -ENOMEM;
7599ca880aSopenharmony_ci                        }
7699ca880aSopenharmony_ci
7799ca880aSopenharmony_ci                        r[len++] = isprint(c) ? c : ' ';
7899ca880aSopenharmony_ci                }
7999ca880aSopenharmony_ci
8099ca880aSopenharmony_ci                if (len > 0)
8199ca880aSopenharmony_ci                        r[len-1] = 0;
8299ca880aSopenharmony_ci
8399ca880aSopenharmony_ci        } else {
8499ca880aSopenharmony_ci                bool space = false;
8599ca880aSopenharmony_ci                size_t left;
8699ca880aSopenharmony_ci
8799ca880aSopenharmony_ci                r = new(char, max_length);
8899ca880aSopenharmony_ci                if (!r)
8999ca880aSopenharmony_ci                        return -ENOMEM;
9099ca880aSopenharmony_ci
9199ca880aSopenharmony_ci                k = r;
9299ca880aSopenharmony_ci                left = max_length;
9399ca880aSopenharmony_ci                while ((c = getc(f)) != EOF) {
9499ca880aSopenharmony_ci
9599ca880aSopenharmony_ci                        if (isprint(c)) {
9699ca880aSopenharmony_ci                                if (space) {
9799ca880aSopenharmony_ci                                        if (left <= 4)
9899ca880aSopenharmony_ci                                                break;
9999ca880aSopenharmony_ci
10099ca880aSopenharmony_ci                                        *(k++) = ' ';
10199ca880aSopenharmony_ci                                        left--;
10299ca880aSopenharmony_ci                                        space = false;
10399ca880aSopenharmony_ci                                }
10499ca880aSopenharmony_ci
10599ca880aSopenharmony_ci                                if (left <= 4)
10699ca880aSopenharmony_ci                                        break;
10799ca880aSopenharmony_ci
10899ca880aSopenharmony_ci                                *(k++) = (char) c;
10999ca880aSopenharmony_ci                                left--;
11099ca880aSopenharmony_ci                        }  else
11199ca880aSopenharmony_ci                                space = true;
11299ca880aSopenharmony_ci                }
11399ca880aSopenharmony_ci
11499ca880aSopenharmony_ci                if (left <= 4) {
11599ca880aSopenharmony_ci                        size_t n = MIN(left-1, 3U);
11699ca880aSopenharmony_ci                        memcpy(k, "...", n);
11799ca880aSopenharmony_ci                        k[n] = 0;
11899ca880aSopenharmony_ci                } else
11999ca880aSopenharmony_ci                        *k = 0;
12099ca880aSopenharmony_ci        }
12199ca880aSopenharmony_ci
12299ca880aSopenharmony_ci        /* Kernel threads have no argv[] */
12399ca880aSopenharmony_ci        if (isempty(r)) {
12499ca880aSopenharmony_ci                _cleanup_free_ char *t = NULL;
12599ca880aSopenharmony_ci                int h;
12699ca880aSopenharmony_ci
12799ca880aSopenharmony_ci                free(r);
12899ca880aSopenharmony_ci
12999ca880aSopenharmony_ci                if (!comm_fallback)
13099ca880aSopenharmony_ci                        return -ENOENT;
13199ca880aSopenharmony_ci
13299ca880aSopenharmony_ci                h = get_process_comm(pid, &t);
13399ca880aSopenharmony_ci                if (h < 0)
13499ca880aSopenharmony_ci                        return h;
13599ca880aSopenharmony_ci
13699ca880aSopenharmony_ci                r = strjoin("[", t, "]", NULL);
13799ca880aSopenharmony_ci                if (!r)
13899ca880aSopenharmony_ci                        return -ENOMEM;
13999ca880aSopenharmony_ci        }
14099ca880aSopenharmony_ci
14199ca880aSopenharmony_ci        *line = r;
14299ca880aSopenharmony_ci        return 0;
14399ca880aSopenharmony_ci}
14499ca880aSopenharmony_ci
14599ca880aSopenharmony_ciint get_process_environ(pid_t pid, char **env) {
14699ca880aSopenharmony_ci        _cleanup_fclose_ FILE *f = NULL;
14799ca880aSopenharmony_ci        _cleanup_free_ char *outcome = NULL;
14899ca880aSopenharmony_ci        int c;
14999ca880aSopenharmony_ci        const char *p;
15099ca880aSopenharmony_ci        size_t allocated = 0, sz = 0;
15199ca880aSopenharmony_ci
15299ca880aSopenharmony_ci        assert(pid >= 0);
15399ca880aSopenharmony_ci        assert(env);
15499ca880aSopenharmony_ci
15599ca880aSopenharmony_ci        p = procfs_file_alloca(pid, "environ");
15699ca880aSopenharmony_ci
15799ca880aSopenharmony_ci        f = fopen(p, "re");
15899ca880aSopenharmony_ci        if (!f)
15999ca880aSopenharmony_ci                return -errno;
16099ca880aSopenharmony_ci
16199ca880aSopenharmony_ci        while ((c = fgetc(f)) != EOF) {
16299ca880aSopenharmony_ci                if (!GREEDY_REALLOC(outcome, allocated, sz + 5))
16399ca880aSopenharmony_ci                        return -ENOMEM;
16499ca880aSopenharmony_ci
16599ca880aSopenharmony_ci                if (c == '\0')
16699ca880aSopenharmony_ci                        outcome[sz++] = '\n';
16799ca880aSopenharmony_ci                else
16899ca880aSopenharmony_ci                        sz += cescape_char(c, outcome + sz);
16999ca880aSopenharmony_ci        }
17099ca880aSopenharmony_ci
17199ca880aSopenharmony_ci        outcome[sz] = '\0';
17299ca880aSopenharmony_ci        *env = outcome;
17399ca880aSopenharmony_ci        outcome = NULL;
17499ca880aSopenharmony_ci
17599ca880aSopenharmony_ci        return 0;
17699ca880aSopenharmony_ci}
177