use nprocs() function instead of /proc/cpuinfo
[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 #include <sys/sysinfo.h>
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,*e;
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 e = strrchr(p, ')');
89 if (e == NULL || e >= &p[sizeof(task->name)])
90 {
91 close(fd);
92 return;
93 }
94 len = e - p;
95 strncpy(task->name, p, len);
96 task->name[len]=0;
97 p = &e[1];
98 if(show_full_path)
99 {
100 FILE *fp;
101 sprintf(line,"/proc/%d/cmdline",(int)pid);
102 fp=fopen(line,"r");
103 if(fp)
104 {
105 size_t size;
106 size=fread(task->name,1,sizeof(task->name)-1,fp);
107 if(size>0)
108 {
109 size_t x;
110 task->name[size]=0;
111 for(x=0;x<size;x++)
112 {
113 if(task->name[x]=='\0')
114 {
115 if(task->name[x+1]=='\n')
116 break;
117 task->name[x]=' ';
118 }
119 }
120 }
121 fclose(fp);
122 }
123 }
124 else if(len>=15)
125 {
126 FILE *fp;
127 sprintf(line,"/proc/%d/cmdline",(int)pid);
128 fp=fopen(line,"r");
129 if(fp)
130 {
131 char *p;
132 if (fscanf(fp, "%255s", line) > 0)
133 {
134 p=strrchr(line,'/');
135 if(p != NULL)
136 strncpy(task->name, p+1, sizeof(task->name)-1);
137 else
138 strncpy(task->name, line, sizeof(task->name)-1);
139 task->name[sizeof(task->name)-1] = '\0';
140 }
141 fclose(fp);
142 }
143 }
144
145 sscanf(p, "%1s %ld %s %s %s %s %s %s %s %s %s %i %i %s %s %s %i",
146 task->state, // processstate
147 &ppid, // parentid
148 line, // processs groupid
149
150 line, // session id
151 line, // tty id
152 line, // tpgid: The process group ID of the process running on tty of the process
153 line, // flags
154 line, // minflt minor faults the process has maid
155
156 line, // cminflt
157 line, // majflt
158 line, // cmajflt
159 &utime, // utime the number of jiffies that this process has scheduled in user mode
160 &stime, // stime " kernel mode
161
162 line, // cutime " waited for children in user
163 line, // cstime " kernel mode
164 line, // priority (nice value + fifteen)
165 &task->prio // nice range from 19 to -19 /* my change */
166 );
167 task->time = stime + utime;
168 task->old_time = task->time;
169 task->time_percentage = 0;
170 task->ppid = ppid;
171
172 fstat(fd,&st);
173 task->uid=st.st_uid;
174 passwdp = getpwuid(task->uid);
175 if( passwdp != NULL && passwdp->pw_name != NULL)
176 g_strlcpy(task->uname, passwdp->pw_name, sizeof task->uname);
177
178 close(fd);
179 }
180 }
181
182 static int proc_filter(const struct dirent *d)
183 {
184 int c=d->d_name[0];
185 return c>='1' && c<='9';
186 }
187
188 GArray *get_task_list(void)
189 {
190 GArray *task_list;
191 struct dirent **namelist;
192 int n;
193 int count=0;
194
195
196 task_list = g_array_new(FALSE, FALSE, sizeof (struct task));
197 n=scandir("/proc",&namelist,proc_filter,0);
198 if(n<0) return task_list;
199
200 g_array_set_size(task_list,n);
201 while(n--)
202 {
203 pid_t pid = atol(namelist[n]->d_name);
204 struct task *task=&g_array_index(task_list, struct task, count);
205 free(namelist[n]);
206 get_task_details(pid,task);
207 if(task->pid > 0 && task->size > 0) // don't show error or kenerl threads
208 {
209 count++;
210 }
211 }
212 task_list->len=count;
213 free(namelist);
214 return task_list;
215 }
216
217 gboolean get_cpu_usage_from_proc(system_status *sys_stat)
218 {
219 const gchar *file_name = "/proc/stat";
220 FILE *file;
221
222 if ( sys_stat->valid_proc_reading == TRUE ) {
223 sys_stat->cpu_old_jiffies =
224 sys_stat->cpu_user +
225 sys_stat->cpu_nice +
226 sys_stat->cpu_system+
227 sys_stat->cpu_idle;
228 sys_stat->cpu_old_used =
229 sys_stat->cpu_user +
230 sys_stat->cpu_nice +
231 sys_stat->cpu_system;
232 } else {
233 sys_stat->cpu_old_jiffies = 0;
234 }
235
236 sys_stat->valid_proc_reading = FALSE;
237
238 file = fopen (file_name, "rb");
239 if(!file) return FALSE;
240 if ( fscanf (file, "cpu\t%u %u %u %u",
241 &sys_stat->cpu_user,
242 &sys_stat->cpu_nice,
243 &sys_stat->cpu_system,
244 &sys_stat->cpu_idle
245 ) == 4 )
246 {
247 sys_stat->valid_proc_reading = TRUE;
248 }
249 fclose( file );
250 return TRUE;
251 }
252
253 gboolean get_system_status (system_status *sys_stat)
254 {
255 FILE *file;
256 gchar buffer[100];
257 int reach;
258 static int cpu_count;
259
260 file = fopen ("/proc/meminfo", "r");
261 if(!file) return FALSE;
262 reach=0;
263 while (fgets (buffer, 100, file) != NULL)
264 {
265 if(!strncmp(buffer,"MemTotal:",9))
266 sys_stat->mem_total=atoi(buffer+10),reach++;
267 else if(!strncmp(buffer,"MemFree:",8))
268 sys_stat->mem_free=atoi(buffer+9),reach++;
269 else if(!strncmp(buffer,"Cached:",7))
270 sys_stat->mem_cached=atoi(buffer+8),reach++;
271 else if(!strncmp(buffer,"Buffers:",8))
272 sys_stat->mem_buffered=atoi(buffer+9),reach++;
273 if(reach==4) break;
274 }
275 fclose (file);
276
277 if(!cpu_count)
278 {
279 cpu_count=get_nprocs();
280 }
281 sys_stat->cpu_count=cpu_count;
282 return TRUE;
283 }
284
285 void send_signal_to_task(gint task_id, gint signal)
286 {
287 if(task_id > 0 && signal != 0)
288 {
289 gint ret = 0;
290
291 ret = kill(task_id, signal);
292
293 if(ret != 0)
294 show_error(_("Couldn't send signal %d to the task with ID %d\n\n%s"), signal, task_id, g_strerror(errno) );
295 }
296 }
297
298
299 void set_priority_to_task(gint task_id, gint prio)
300 {
301 if(task_id > 0)
302 {
303 int status = 0;
304 gchar command[128] = "";
305 g_sprintf(command, "renice %d %d > /dev/null", prio, task_id);
306
307 if( ! g_spawn_command_line_sync(command, NULL, NULL, &status, NULL) ||status )
308 show_error(_("Couldn't set priority %d to the task with ID %d"), prio, task_id);
309 }
310 }
311