Update memory sizes to 64 bit and fix compilation warnings.
[lxde/lxtask.git] / src / xfce-taskmanager-linux.c
CommitLineData
580e78c2
HJYP
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
a4a3fc0a 24#include <errno.h>
ac6cc864 25#include <unistd.h>
bdc67cb1 26#include <fcntl.h>
a4a3fc0a 27
580e78c2 28#include <glib/gi18n.h>
e3568c63 29#include <glib/gprintf.h>
580e78c2
HJYP
30#include "xfce-taskmanager-linux.h"
31
ac6cc864 32
4ab5f812 33void get_task_details(pid_t pid,struct task *task)
0284f607 34{
bdc67cb1 35 int fd;
ac6cc864 36 gchar line[256];
4ab5f812
AG
37 gulong t_size, t_rss;
38 ssize_t ret;
0284f607 39
ac6cc864 40 task->pid=-1;
41 task->checked=FALSE;
2dbcf129 42 task->size=0;
ac6cc864 43
4ab5f812 44 sprintf(line,"/proc/%d/statm",(int)pid);
bdc67cb1 45 fd=open(line,O_RDONLY);
46 if(fd==-1) return;
4ab5f812
AG
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);
2dbcf129 55 close(fd);
4ab5f812
AG
56 if(t_size == 0) return;
57 task->size = t_size * PAGE_SIZE;
58 task->rss = t_rss * PAGE_SIZE;
0284f607 59
4ab5f812 60 sprintf(line,"/proc/%d/stat",(gint)pid);
bdc67cb1 61 fd=open(line,O_RDONLY);
62 if(fd!=-1)
0284f607 63 {
ac6cc864 64 struct passwd *passwdp;
65 struct stat st;
a94565c9 66 char buf[2048],*p;
ac6cc864 67 size_t len;
0284f607 68 gint utime = 0;
69 gint stime = 0;
4ab5f812 70 glong ppid;
0284f607 71
bdc67cb1 72 task->pid=pid;
73
5f1c09bf 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++;
626fdf69 88 for(len=0;*p!=')';len++) task->name[len]=*p++;
89 task->name[len]=0;p++;
5ff47b84 90 if(show_full_path)
91 {
92 FILE *fp;
4ab5f812 93 sprintf(line,"/proc/%d/cmdline",(int)pid);
5ff47b84 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 {
4ab5f812 101 size_t x;
5ff47b84 102 task->name[size]=0;
4ab5f812 103 for(x=0;x<size;x++)
5ff47b84 104 {
4ab5f812 105 if(task->name[x]=='\0')
5ff47b84 106 {
4ab5f812 107 if(task->name[x+1]=='\n')
5ff47b84 108 break;
4ab5f812 109 task->name[x]=' ';
5ff47b84 110 }
111 }
112 }
113 fclose(fp);
114 }
115 }
116 else if(len>=15)
626fdf69 117 {
118 FILE *fp;
4ab5f812 119 sprintf(line,"/proc/%d/cmdline",(int)pid);
626fdf69 120 fp=fopen(line,"r");
121 if(fp)
122 {
123 char *p;
4ab5f812
AG
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 }
626fdf69 133 fclose(fp);
626fdf69 134 }
135 }
bdc67cb1 136
4ab5f812 137 sscanf(p, "%1s %ld %s %s %s %s %s %s %s %s %s %i %i %s %s %s %i",
ac6cc864 138 task->state, // processstate
4ab5f812 139 &ppid, // parentid
0284f607 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)
ac6cc864 157 &task->prio // nice range from 19 to -19 /* my change */
0284f607 158 );
ac6cc864 159 task->time = stime + utime;
160 task->old_time = task->time;
161 task->time_percentage = 0;
4ab5f812 162 task->ppid = ppid;
ac6cc864 163
bdc67cb1 164 fstat(fd,&st);
ac6cc864 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);
0284f607 169
bdc67cb1 170 close(fd);
0284f607 171 }
0284f607 172}
173
bdc67cb1 174static int proc_filter(const struct dirent *d)
175{
176 int c=d->d_name[0];
177 return c>='1' && c<='9';
178}
179
180GArray *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 {
4ab5f812 195 pid_t pid = atol(namelist[n]->d_name);
bdc67cb1 196 struct task *task=&g_array_index(task_list, struct task, count);
a58111b0 197 free(namelist[n]);
bdc67cb1 198 get_task_details(pid,task);
4ab5f812 199 if(task->pid > 0 && task->size > 0) // don't show error or kenerl threads
bdc67cb1 200 {
201 count++;
202 }
203 }
204 task_list->len=count;
205 free(namelist);
206 return task_list;
207}
580e78c2
HJYP
208
209gboolean get_cpu_usage_from_proc(system_status *sys_stat)
210{
211 const gchar *file_name = "/proc/stat";
580e78c2
HJYP
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
bdc67cb1 230 file = fopen (file_name, "rb");
ac6cc864 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 )
580e78c2 238 {
ac6cc864 239 sys_stat->valid_proc_reading = TRUE;
580e78c2 240 }
ac6cc864 241 fclose( file );
242 return TRUE;
580e78c2
HJYP
243}
244
245gboolean get_system_status (system_status *sys_stat)
246{
247 FILE *file;
ac6cc864 248 gchar buffer[100];
249 int reach;
250 static int cpu_count;
580e78c2 251
ac6cc864 252 file = fopen ("/proc/meminfo", "r");
253 if(!file) return FALSE;
254 reach=0;
255 while (fgets (buffer, 100, file) != NULL)
580e78c2 256 {
ac6cc864 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++;
3022c6ce 263 else if(!strncmp(buffer,"Buffers:",8))
264 sys_stat->mem_buffered=atoi(buffer+9),reach++;
265 if(reach==4) break;
580e78c2 266 }
ac6cc864 267 fclose (file);
580e78c2 268
ac6cc864 269 if(!cpu_count)
580e78c2 270 {
ac6cc864 271 file = fopen ("/proc/cpuinfo", "r");
272 if(!file) return FALSE;
580e78c2
HJYP
273 while (fgets (buffer, 100, file) != NULL)
274 {
ac6cc864 275 if(buffer[0]!='p') continue;
276 if(!strncmp(buffer,"processor",9))
277 {
278 cpu_count++;
279 }
580e78c2
HJYP
280 }
281 fclose (file);
963dea39 282 if(!cpu_count) cpu_count++; /* cpu_count should be at least 1 */
580e78c2 283 }
ac6cc864 284 sys_stat->cpu_count=cpu_count;
580e78c2
HJYP
285 return TRUE;
286}
287
288void 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)
a4a3fc0a 297 show_error(_("Couldn't send signal %d to the task with ID %d\n\n%s"), signal, task_id, g_strerror(errno) );
580e78c2
HJYP
298 }
299}
300
301
302void set_priority_to_task(gint task_id, gint prio)
303{
304 if(task_id > 0)
305 {
a4a3fc0a 306 int status = 0;
580e78c2
HJYP
307 gchar command[128] = "";
308 g_sprintf(command, "renice %d %d > /dev/null", prio, task_id);
309
a4a3fc0a 310 if( ! g_spawn_command_line_sync(command, NULL, NULL, &status, NULL) ||status )
580e78c2
HJYP
311 show_error(_("Couldn't set priority %d to the task with ID %d"), prio, task_id);
312 }
313}
314