1/*** 2 This file is part of systemd. 3 4 Copyright 2010 Lennart Poettering 5 6 systemd is free software; you can redistribute it and/or modify it 7 under the terms of the GNU Lesser General Public License as published by 8 the Free Software Foundation; either version 2.1 of the License, or 9 (at your option) any later version. 10 11 systemd is distributed in the hope that it will be useful, but 12 WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 Lesser General Public License for more details. 15 16 You should have received a copy of the GNU Lesser General Public License 17 along with systemd; If not, see <http://www.gnu.org/licenses/>. 18***/ 19 20#include <stdbool.h> 21#include <sys/types.h> 22#include <string.h> 23#include <stdio.h> 24#include <assert.h> 25#include <errno.h> 26#include <unistd.h> 27#include <sys/wait.h> 28#include <signal.h> 29#include <ctype.h> 30 31#include "process-util.h" 32#include "fileio.h" 33#include "util.h" 34#include "log.h" 35 36int get_process_comm(pid_t pid, char **name) { 37 const char *p; 38 int r; 39 40 assert(name); 41 assert(pid >= 0); 42 43 p = procfs_file_alloca(pid, "comm"); 44 45 r = read_one_line_file(p, name); 46 if (r == -ENOENT) 47 return -ESRCH; 48 49 return r; 50} 51 52int get_process_cmdline(pid_t pid, size_t max_length, bool comm_fallback, char **line) { 53 _cleanup_fclose_ FILE *f = NULL; 54 char *r = NULL, *k; 55 const char *p; 56 int c; 57 58 assert(line); 59 assert(pid >= 0); 60 61 p = procfs_file_alloca(pid, "cmdline"); 62 63 f = fopen(p, "re"); 64 if (!f) 65 return -errno; 66 67 if (max_length == 0) { 68 size_t len = 0, allocated = 0; 69 70 while ((c = getc(f)) != EOF) { 71 72 if (!GREEDY_REALLOC(r, allocated, len+2)) { 73 free(r); 74 return -ENOMEM; 75 } 76 77 r[len++] = isprint(c) ? c : ' '; 78 } 79 80 if (len > 0) 81 r[len-1] = 0; 82 83 } else { 84 bool space = false; 85 size_t left; 86 87 r = new(char, max_length); 88 if (!r) 89 return -ENOMEM; 90 91 k = r; 92 left = max_length; 93 while ((c = getc(f)) != EOF) { 94 95 if (isprint(c)) { 96 if (space) { 97 if (left <= 4) 98 break; 99 100 *(k++) = ' '; 101 left--; 102 space = false; 103 } 104 105 if (left <= 4) 106 break; 107 108 *(k++) = (char) c; 109 left--; 110 } else 111 space = true; 112 } 113 114 if (left <= 4) { 115 size_t n = MIN(left-1, 3U); 116 memcpy(k, "...", n); 117 k[n] = 0; 118 } else 119 *k = 0; 120 } 121 122 /* Kernel threads have no argv[] */ 123 if (isempty(r)) { 124 _cleanup_free_ char *t = NULL; 125 int h; 126 127 free(r); 128 129 if (!comm_fallback) 130 return -ENOENT; 131 132 h = get_process_comm(pid, &t); 133 if (h < 0) 134 return h; 135 136 r = strjoin("[", t, "]", NULL); 137 if (!r) 138 return -ENOMEM; 139 } 140 141 *line = r; 142 return 0; 143} 144 145int get_process_environ(pid_t pid, char **env) { 146 _cleanup_fclose_ FILE *f = NULL; 147 _cleanup_free_ char *outcome = NULL; 148 int c; 149 const char *p; 150 size_t allocated = 0, sz = 0; 151 152 assert(pid >= 0); 153 assert(env); 154 155 p = procfs_file_alloca(pid, "environ"); 156 157 f = fopen(p, "re"); 158 if (!f) 159 return -errno; 160 161 while ((c = fgetc(f)) != EOF) { 162 if (!GREEDY_REALLOC(outcome, allocated, sz + 5)) 163 return -ENOMEM; 164 165 if (c == '\0') 166 outcome[sz++] = '\n'; 167 else 168 sz += cescape_char(c, outcome + sz); 169 } 170 171 outcome[sz] = '\0'; 172 *env = outcome; 173 outcome = NULL; 174 175 return 0; 176} 177