-
Notifications
You must be signed in to change notification settings - Fork 1
/
proc_pid_util.c
141 lines (127 loc) · 3.06 KB
/
proc_pid_util.c
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
/*
* Linux /proc/pid utility module for sftpwrapper
*
* Copyright 2020 Seravo Oy
*
* SPDX short identifier: BSD-2-Clause
*/
#include <errno.h>
#include <limits.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "logger.h"
#include "proc_pid_util.h"
/*
* Get a value from line beginning with attr string in file
* /proc/pid/status. If index == 0, the first value after
* attr is returned. If index == 1, the second value is returned.
* If index is anything else than 0 or 1, returns -1.
* Returns -1 if anything unexpected happens.
*
* Reads /proc/${pid}/status line by line. Scans for attr.
* When attr is found, returns word at a given index as an integer.
*/
static int read_process_attribute(const pid_t pid, const char *attr,
const unsigned index)
{
char path[PATH_MAX];
char line[PATH_MAX];
FILE *f;
char *field = NULL;
char *value = NULL;
int int_value = -1;
int ret = snprintf(path, sizeof path, "/proc/%d/status", (int) pid);
if ((size_t) ret >= sizeof(path)) {
log_error("Unexpected: PATH_MAX exceeded (pid)\n");
goto error;
}
f = fopen(path, "r");
if (f == NULL) {
log_error("Unexpected: Can not open %s\n", path);
goto error;
}
while (1) {
if (fgets(line, sizeof(line), f) == NULL) {
log_error("Unexpected: %s not found (EOF)\n", attr);
goto error;
}
/* Read 2 or 3 words from the line depending on index */
if (index == 0) {
ret = sscanf(line, "%ms %ms", &field, &value);
if (ret < 2) {
log_error("Unexpected: less than 2 words "
"read\n");
goto error;
}
} else if (index == 1) {
char *tmp = NULL;
ret = sscanf(line, "%ms %ms %ms",
&field, &tmp, &value);
free(tmp);
tmp = NULL;
if (ret < 2) {
log_error("Unexpected: less than 2 words "
"read\n");
goto error;
}
if (ret != 3)
continue;
} else {
log_error("Invalid index argument: %d\n", index);
goto error;
}
if (strcmp(field, attr) == 0) {
int_value = atoi(value);
if (int_value < 0) {
log_error("Unexpected negative value: %s %s\n",
attr, value);
goto error;
}
break;
}
free(field);
free(value);
field = NULL;
value = NULL;
}
fclose(f);
free(field);
free(value);
return int_value;
error:
if (f != NULL)
fclose(f);
free(field);
free(value);
return -1;
}
/* Terminates program if something unexpected happens. */
int get_process_exe(char *exe_name, const size_t bufsize, const pid_t pid)
{
char path[PATH_MAX];
ssize_t nbytes;
int ret = snprintf(path, sizeof path, "/proc/%d/exe", (int) pid);
if ((size_t) ret >= sizeof(path)) {
log_error("weird: PATH_MAX exceeded (pid)\n");
return -1;
}
nbytes = readlink(path, exe_name, bufsize);
if (nbytes < 0 || ((size_t) nbytes) == bufsize) {
log_error("Could not read link at %s: %s\n",
path, strerror(errno));
exe_name[0] = 0;
return -1;
}
exe_name[nbytes] = 0;
return 0;
}
pid_t get_process_parent_pid(const pid_t pid)
{
return read_process_attribute(pid, "PPid:", 0);
}
uid_t get_process_euid(const pid_t pid)
{
return read_process_attribute(pid, "Uid:", 1);
}