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