forked from posborne/linux-programming-interface-exercises
-
Notifications
You must be signed in to change notification settings - Fork 0
/
pstree.c
183 lines (160 loc) · 4.29 KB
/
pstree.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
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
/*
Write a program that draws a tree showing the hierarchical
parent-child relationships of all processes on the system, going all
the way back to init. For each process, the program should display
the process ID and the command being executed. The output of the
program should be similar to that produced by pstree(1), although it
does need not to be as sophisticated. The parent of each process on
the system can be found by inspecing the PPid: line of all of the
/proc/PID/status files on the system. Be careful to handle the
possibilty that a process's parent (and thus its /proc/PID directory)
disappears during the scan of all /proc/PID directories.
---
Providing this output consists of two main steps:
1) Build the process tree based on information from the proc filesystem.
2) Render the tree using a recursion (pre-order traversal)
*/
#define _DEFAULT_SOURCE
#define _BSD_SOURCE
#include "proclib.h"
#include <dirent.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <string.h>
#include <pwd.h>
#define PROCFS_ROOT "/proc"
/* acts as node in both linked list and tree */
struct pstree_node {
char name[128];
pid_t pid;
pid_t ppid;
struct pstree_node * parent;
struct pstree_node * children[128];
struct pstree_node * next;
};
static struct pstree_node * ll_head;
int ll_create_and_insert(char *procname, pid_t pid, pid_t ppid)
{
struct pstree_node *node;
node = (struct pstree_node*)malloc(sizeof(struct pstree_node));
if (node == NULL) {
printf("Unable to allocate memory for node\n");
return 1;
}
strcpy(node->name, procname);
node->pid = pid;
node->ppid = ppid;
node->children[0] = NULL;
node->parent = NULL;
node->next = ll_head; /* could be null, that is fine */
ll_head = node;
return 0;
}
int catalog_process(char *dirname)
{
char filename[256];
char linebuf[256];
char procname[256];
char pid[32];
char ppid[32];
char *key;
char *value;
FILE *p_file;
strcpy(filename, dirname);
strcat(filename, "/status");
p_file = fopen(filename, "r");
if (p_file == NULL) {
return 1; /* just ignore, this is fine I guess */
}
while (fgets(linebuf, sizeof(linebuf), p_file) != NULL) {
key = strtok(linebuf, ":");
value = strtok(NULL, ":");
if (key != NULL && value != NULL) {
trim(key); trim(value);
if (strcmp(key, "Pid") == 0) {
strcpy(pid, value);
} else if (strcmp(key, "PPid") == 0) {
strcpy(ppid, value);
} else if (strcmp(key, "Name") == 0) {
strcpy(procname, value);
}
}
}
return ll_create_and_insert(&procname[0], atoi(pid), atoi(ppid));
}
struct pstree_node * find_node_with_pid(pid_t pid)
{
struct pstree_node *node;
for (node = ll_head; node != NULL; node = node->next) {
if (node->pid == pid) {
return node;
}
}
return NULL;
}
int make_tree(void)
{
int i;
struct pstree_node *node, *pnode;
/* now we have a valid linked list, make a tree */
for (node = ll_head; node != NULL; node = node->next) {
i = 0;
pnode = find_node_with_pid(node->ppid);
if (pnode != NULL) {
node->parent = pnode;
while (pnode->children[i++] != NULL);
pnode->children[i - 1] = node;
pnode->children[i] = NULL;
}
}
return 0;
}
int print_tree(struct pstree_node * root, int level)
{
int i;
struct pstree_node *node;
for (i = 0; i < level; i++) {
printf(" ");
}
printf("%s (pid: %d, ppid: %d)\n", root->name, root->pid, root->ppid);
/* recurse on children */
while ((node = root->children[i++]) != NULL) {
print_tree(node, level + 1);
}
return 0;
}
int main(int argc, char **argv)
{
(void)argc;
(void)argv;
DIR *dirp;
struct dirent *directory_entry;
char dirname[256];
/* now, walk directories in /proc fs to create nodes */
if ((dirp = opendir(PROCFS_ROOT)) == NULL) {
perror("Unabled to open /proc");
return 1;
}
do {
if ((directory_entry = readdir(dirp)) != NULL) {
if (directory_entry->d_type == DT_DIR) {
strcpy(&dirname[0], PROCFS_ROOT);
strcat(&dirname[0], "/");
strcat(&dirname[0], directory_entry->d_name);
catalog_process(dirname);
}
}
} while (directory_entry != NULL);
/* turn the list into a tree */
make_tree();
/* print the tree */
struct pstree_node *node;
for (node = ll_head; node != NULL; node = node->next) {
// printf("node: %s, pid: %d, ppid: %d\n", node->name, node->pid, node->ppid);
if (node->parent == NULL) {
print_tree(node, 0);
}
}
return 0;
}