Update memory sizes to 64 bit and fix compilation warnings.
[lxde/lxtask.git] / src / xfce-taskmanager-linux.c
1 /* $Id: xfce-taskmanager-linux.c 3940 2008-02-10 22:48:45Z nebulon $
2 *
3 * Copyright (c) 2006 Johannes Zellner, <webmaster@nebulon.de>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU Library General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 */
19
20 #ifdef HAVE_CONFIG_H
21 #include <config.h>
22 #endif
23
24 #include <errno.h>
25 #include <unistd.h>
26 #include <fcntl.h>
27
28 #include <glib/gi18n.h>
29 #include <glib/gprintf.h>
30 #include "xfce-taskmanager-linux.h"
31
32
33 void get_task_details(pid_t pid,struct task *task)
34 {
35 int fd;
36 gchar line[256];
37 gulong t_size, t_rss;
38 ssize_t ret;
39
40 task->pid=-1;
41 task->checked=FALSE;
42 task->size=0;
43
44 sprintf(line,"/proc/%d/statm",(int)pid);
45 fd=open(line,O_RDONLY);
46 if(fd==-1) return;
47 ret = read(fd,line,255);
48 if (ret <= 0)
49 {
50 close(fd);
51 return;
52 }
53 line[ret] = '\0';
54 sscanf(line,"%lu %lu",&t_size,&t_rss);
55 close(fd);
56 if(t_size == 0) return;
57 task->size = t_size * PAGE_SIZE;
58 task->rss = t_rss * PAGE_SIZE;
59
60 sprintf(line,"/proc/%d/stat",(gint)pid);
61 fd=open(line,O_RDONLY);
62 if(fd!=-1)
63 {
64 struct passwd *passwdp;
65 struct stat st;
66 char buf[2048],*p;
67 size_t len;
68 gint utime = 0;
69 gint stime = 0;
70 glong ppid;
71
72 task->pid=pid;
73
74 ret=read(fd,buf,2048-1);
75 if(ret<=0)
76 {
77 close(fd);
78 return;
79 }
80 buf[ret]=0;
81 p=strchr(buf,'(');
82 if(p==NULL)
83 {
84 close(fd);
85 return;
86 }
87 p++;
88 for(len=0;*p!=')';len++) task->name[len]=*p++;
89 task->name[len]=0;p++;
90 if(show_full_path)
91 {
92 FILE *fp;
93 sprintf(line,"/proc/%d/cmdline",(int)pid);
94 fp=fopen(line,"r");
95 if(fp)
96 {
97 size_t size;
98 size=fread(task->name,1,sizeof(task->name)-1,fp);
99 if(size>0)
100 {
101 size_t x;
102 task->name[size]=0;
103 for(x=0;x<size;x++)
104 {
105 if(task->name[x]=='\0')
106 {
107 if(task->name[x+1]=='\n')
108 break;
109 task->name[x]=' ';
110 }
111 }
112 }
113 fclose(fp);
114 }
115 }
116 else if(len>=15)
117 {
118 FILE *fp;
119 sprintf(line,"/proc/%d/cmdline",(int)pid);
120 fp=fopen(line,"r");
121 if(fp)
122 {
123 char *p;
124 if (fscanf(fp, "%255s", line) > 0)
125 {
126 p=strrchr(line,'/');
127 if(p != NULL)
128 strncpy(task->name, p+1, sizeof(task->name)-1);
129 else
130 strncpy(task->name, line, sizeof(task->name)-1);
131 task->name[sizeof(task->name)-1] = '\0';
132 }
133 fclose(fp);
134 }
135 }
136
137 sscanf(p, "%1s %ld %s %s %s %s %s %s %s %s %s %i %i %s %s %s %i",
138 task->state, // processstate
139 &ppid, // parentid
140 line, // processs groupid
141
142 line, // session id
143 line, // tty id
144 line, // tpgid: The process group ID of the process running on tty of the process
145 line, // flags
146 line, // minflt minor faults the process has maid
147
148 line, // cminflt
149 line, // majflt
150 line, // cmajflt
151 &utime, // utime the number of jiffies that this process has scheduled in user mode
152 &stime, // stime " kernel mode
153
154 line, // cutime " waited for children in user
155 line, // cstime " kernel mode
156 line, // priority (nice value + fifteen)
157 &task->prio // nice range from 19 to -19 /* my change */
158 );
159 task->time = stime + utime;
160 task->old_time = task->time;
161 task->time_percentage = 0;
162 task->ppid = ppid;
163
164 fstat(fd,&st);
165 task->uid=st.st_uid;
166 passwdp = getpwuid(task->uid);
167 if( passwdp != NULL && passwdp->pw_name != NULL)
168 g_strlcpy(task->uname, passwdp->pw_name, sizeof task->uname);
169
170 close(fd);
171 }
172 }
173
174 static int proc_filter(const struct dirent *d)
175 {
176 int c=d->d_name[0];
177 return c>='1' && c<='9';
178 }
179
180 GArray *get_task_list(void)
181 {
182 GArray *task_list;
183 struct dirent **namelist;
184 int n;
185 int count=0;
186
187
188 task_list = g_array_new(FALSE, FALSE, sizeof (struct task));
189 n=scandir("/proc",&namelist,proc_filter,0);
190 if(n<0) return task_list;
191
192 g_array_set_size(task_list,n);
193 while(n--)
194 {
195 pid_t pid = atol(namelist[n]->d_name);
196 struct task *task=&g_array_index(task_list, struct task, count);
197 free(namelist[n]);
198 get_task_details(pid,task);
199 if(task->pid > 0 && task->size > 0) // don't show error or kenerl threads
200 {
201 count++;
202 }
203 }
204 task_list->len=count;
205 free(namelist);
206 return task_list;
207 }
208
209 gboolean get_cpu_usage_from_proc(system_status *sys_stat)
210 {
211 const gchar *file_name = "/proc/stat";
212 FILE *file;
213
214 if ( sys_stat->valid_proc_reading == TRUE ) {
215 sys_stat->cpu_old_jiffies =
216 sys_stat->cpu_user +
217 sys_stat->cpu_nice +
218 sys_stat->cpu_system+
219 sys_stat->cpu_idle;
220 sys_stat->cpu_old_used =
221 sys_stat->cpu_user +
222 sys_stat->cpu_nice +
223 sys_stat->cpu_system;
224 } else {
225 sys_stat->cpu_old_jiffies = 0;
226 }
227
228 sys_stat->valid_proc_reading = FALSE;
229
230 file = fopen (file_name, "rb");
231 if(!file) return FALSE;
232 if ( fscanf (file, "cpu\t%u %u %u %u",
233 &sys_stat->cpu_user,
234 &sys_stat->cpu_nice,
235 &sys_stat->cpu_system,
236 &sys_stat->cpu_idle
237 ) == 4 )
238 {
239 sys_stat->valid_proc_reading = TRUE;
240 }
241 fclose( file );
242 return TRUE;
243 }
244
245 gboolean get_system_status (system_status *sys_stat)
246 {
247 FILE *file;
248 gchar buffer[100];
249 int reach;
250 static int cpu_count;
251
252 file = fopen ("/proc/meminfo", "r");
253 if(!file) return FALSE;
254 reach=0;
255 while (fgets (buffer, 100, file) != NULL)
256 {
257 if(!strncmp(buffer,"MemTotal:",9))
258 sys_stat->mem_total=atoi(buffer+10),reach++;
259 else if(!strncmp(buffer,"MemFree:",8))
260 sys_stat->mem_free=atoi(buffer+9),reach++;
261 else if(!strncmp(buffer,"Cached:",7))
262 sys_stat->mem_cached=atoi(buffer+8),reach++;
263 else if(!strncmp(buffer,"Buffers:",8))
264 sys_stat->mem_buffered=atoi(buffer+9),reach++;
265 if(reach==4) break;
266 }
267 fclose (file);
268
269 if(!cpu_count)
270 {
271 file = fopen ("/proc/cpuinfo", "r");
272 if(!file) return FALSE;
273 while (fgets (buffer, 100, file) != NULL)
274 {
275 if(buffer[0]!='p') continue;
276 if(!strncmp(buffer,"processor",9))
277 {
278 cpu_count++;
279 }
280 }
281 fclose (file);
282 if(!cpu_count) cpu_count++; /* cpu_count should be at least 1 */
283 }
284 sys_stat->cpu_count=cpu_count;
285 return TRUE;
286 }
287
288 void send_signal_to_task(gint task_id, gint signal)
289 {
290 if(task_id > 0 && signal != 0)
291 {
292 gint ret = 0;
293
294 ret = kill(task_id, signal);
295
296 if(ret != 0)
297 show_error(_("Couldn't send signal %d to the task with ID %d\n\n%s"), signal, task_id, g_strerror(errno) );
298 }
299 }
300
301
302 void set_priority_to_task(gint task_id, gint prio)
303 {
304 if(task_id > 0)
305 {
306 int status = 0;
307 gchar command[128] = "";
308 g_sprintf(command, "renice %d %d > /dev/null", prio, task_id);
309
310 if( ! g_spawn_command_line_sync(command, NULL, NULL, &status, NULL) ||status )
311 show_error(_("Couldn't set priority %d to the task with ID %d"), prio, task_id);
312 }
313 }
314