ladish_control: Expose all current methods
[ladish.git] / daemon / procfs.c
blob9c37af621e926f52f021415763aa11aaca8d1cd2
1 /* -*- Mode: C ; c-basic-offset: 2 -*- */
2 /*
3 * LADI Session Handler (ladish)
5 * Copyright (C) 2009 Nedko Arnaudov <nedko@arnaudov.name>
7 **************************************************************************
8 * This file contains the code that interfaces procfs
9 **************************************************************************
11 * LADI Session Handler is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * LADI Session Handler is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with LADI Session Handler. If not, see <http://www.gnu.org/licenses/>
23 * or write to the Free Software Foundation, Inc.,
24 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
27 #include <stdbool.h>
28 #include <string.h>
29 #include <assert.h>
30 #include <stdlib.h>
31 #include <sys/types.h>
32 #include <sys/stat.h>
33 #include <fcntl.h>
34 #include <stdio.h>
35 #include <unistd.h>
37 #include "procfs.h"
38 #include "../common/debug.h"
40 #define BUFFER_SIZE 4096
42 static char g_buffer[BUFFER_SIZE];
44 static
45 bool
46 procfs_get_process_file(
47 unsigned long long pid,
48 const char * filename,
49 char ** buffer_ptr_ptr,
50 size_t * size_ptr)
52 int fd;
53 ssize_t ret;
54 size_t max;
55 char * buffer_ptr;
56 char * read_ptr;
57 size_t buffer_size;
58 size_t used_size;
60 sprintf(g_buffer, "/proc/%llu/%s", pid, filename);
62 fd = open(g_buffer, O_RDONLY);
63 if (fd == -1)
65 return false;
68 buffer_size = BUFFER_SIZE;
69 buffer_ptr = malloc(buffer_size);
70 if (buffer_ptr == NULL)
72 lash_error("malloc failed to allocate buffer with size %zu", buffer_size);
73 return false;
76 used_size = 0;
77 read_ptr = buffer_ptr;
78 loop:
79 max = buffer_size - used_size;
80 if (max < BUFFER_SIZE / 4)
82 buffer_size = used_size + BUFFER_SIZE;
83 read_ptr = realloc(buffer_ptr, buffer_size);
84 if (read_ptr == NULL)
86 lash_error("realloc failed to allocate buffer with size %zu", buffer_size);
87 free(buffer_ptr);
88 close(fd);
89 return false;
92 buffer_ptr = read_ptr;
93 read_ptr = buffer_ptr + used_size;
94 max = BUFFER_SIZE;
97 ret = read(fd, read_ptr, max);
98 if (ret > 0)
100 assert(ret <= max);
101 read_ptr += ret;
102 used_size += ret;
103 assert(used_size <= buffer_size);
104 goto loop;
107 close(fd);
109 if (ret < 0)
111 assert(ret == -1);
112 close(fd);
113 return false;
116 *buffer_ptr_ptr = buffer_ptr;
117 *size_ptr = used_size;
119 return true;
122 static
123 char *
124 procfs_get_process_link(
125 unsigned long long pid,
126 const char * filename)
128 int fd;
129 ssize_t ret;
130 char * buffer_ptr;
132 sprintf(g_buffer, "/proc/%llu/%s", pid, filename);
134 fd = open(g_buffer, O_RDONLY);
135 if (fd == -1)
137 return NULL;
140 ret = readlink(g_buffer, g_buffer, sizeof(g_buffer));
141 if (ret != 0)
143 g_buffer[ret] = 0;
144 buffer_ptr = strdup(g_buffer);
145 lash_debug("process %llu %s symlink points to \"%s\"", pid, filename, buffer_ptr);
147 else
149 assert(ret == -1);
150 buffer_ptr = NULL;
153 close(fd);
155 return buffer_ptr;
158 bool
159 procfs_get_process_cmdline(
160 unsigned long long pid,
161 int * argc_ptr,
162 char *** argv_ptr)
164 char * cmdline_ptr;
165 char * temp_ptr;
166 size_t cmdline_size;
167 int i;
168 int argc;
169 char ** argv;
171 if (!procfs_get_process_file(pid, "cmdline", &cmdline_ptr, &cmdline_size))
173 return false;
176 argc = 0;
177 temp_ptr = cmdline_ptr;
179 while (temp_ptr - cmdline_ptr < cmdline_size)
181 if (*temp_ptr == 0)
183 argc++;
186 temp_ptr++;
189 assert(*(temp_ptr - 1) == 0); /* the last nul char */
191 argv = malloc((argc + 1) * sizeof(char *));
192 if (argv == NULL)
194 free(cmdline_ptr);
195 return false;
198 temp_ptr = cmdline_ptr;
200 for (i = 0; i < argc; i++)
202 assert(temp_ptr - cmdline_ptr < cmdline_size);
204 argv[i] = strdup(temp_ptr);
205 if (argv[i] == NULL)
207 /* rollback */
208 while (i > 0)
210 i--;
211 free(argv[i]);
214 free(argv);
215 free(cmdline_ptr);
216 return false;
219 temp_ptr += strlen(temp_ptr) + 1;
222 /* Make sure that the array is NULL terminated */
223 argv[argc] = NULL;
225 *argc_ptr = argc;
226 *argv_ptr = argv;
228 free(cmdline_ptr);
230 return true;
233 char *
234 procfs_get_process_cwd(
235 unsigned long long pid)
237 return procfs_get_process_link(pid, "cwd");