bc07703fac5cd8faf1d7e0b458383551394218f5
[monky] / src / netbsd.c
1 /*
2  * Conky, a system monitor, based on torsmo
3  *
4  * Any original torsmo code is licensed under the BSD license
5  *
6  * All code written since the fork of torsmo is licensed under the GPL
7  *
8  * Please see COPYING for details
9  *
10  * Copyright (c) 2004, Hannu Saransaari and Lauri Hakkarainen
11  * Copyright (c) 2005-2007 Brenden Matthews, Philip Kovacs, et. al. (see AUTHORS)
12  * All rights reserved.
13  *
14  * This program is free software: you can redistribute it and/or modify
15  * it under the terms of the GNU General Public License as published by
16  * the Free Software Foundation, either version 3 of the License, or
17  * (at your option) any later version.
18  *
19  * This program is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  * GNU General Public License for more details.
23  * You should have received a copy of the GNU General Public License
24  * along with this program.  If not, see <http://www.gnu.org/licenses/>. 
25  *
26  *  $Id$
27  */
28
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <fcntl.h>
33 #include <time.h>
34 #include <unistd.h>
35 #include <err.h>
36 #include <limits.h>
37 #include <paths.h>
38
39 #include <kvm.h>
40 #include <nlist.h>
41
42 #include <sys/time.h>
43 #include <sys/param.h>
44 #include <sys/sysctl.h>
45 #include <sys/types.h>
46 #include <sys/user.h>
47 #include <sys/socket.h>
48 #include <sys/swap.h>
49 #include <sys/sched.h>
50 #include <sys/envsys.h>
51
52 #include <net/if.h>
53
54 #include <uvm/uvm_extern.h>
55
56 #include <machine/param.h>
57
58 #include "conky.h"
59
60
61 static kvm_t *kd = NULL;
62 int kd_init = 0, nkd_init = 0;
63 u_int32_t sensvalue;
64 char errbuf[_POSIX2_LINE_MAX];
65
66 static int init_kvm(void)
67 {
68         if (kd_init)
69                 return 0;
70
71         kd = kvm_openfiles(NULL, NULL, NULL, KVM_NO_FILES, errbuf);
72         if (kd == NULL) {
73                 (void) warnx("cannot kvm_openfiles: %s", errbuf);
74                 return -1;
75         }
76         kd_init = 1;
77         return 0;
78 }
79
80 static int swapmode(int *retavail, int *retfree)
81 {
82         int n;
83         struct swapent *sep;
84
85         *retavail = 0;
86         *retfree = 0;
87
88         n = swapctl(SWAP_NSWAP, 0, 0);
89
90         if (n < 1) {
91                 (void) warn("could not get swap information");
92                 return 0;
93         }
94
95         sep = (struct swapent *) malloc(n * (sizeof(*sep)));
96
97         if (sep == NULL) {
98                 (void) warn("memory allocation failed");
99                 return 0;
100         }
101
102         if (swapctl(SWAP_STATS, (void *) sep, n) < n) {
103                 (void) warn("could not get swap stats");
104                 return 0;
105         }
106         for (; n > 0; n--) {
107                 *retavail += (int) dbtob(sep[n - 1].se_nblks);
108                 *retfree +=
109                     (int) dbtob(sep[n - 1].se_nblks - sep[n - 1].se_inuse);
110         }
111         *retavail = (int) (*retavail / 1024);
112         *retfree = (int) (*retfree / 1024);
113
114         return 1;
115 }
116
117
118 void prepare_update()
119 {
120 }
121
122 void update_uptime()
123 {
124         int mib[2] = { CTL_KERN, KERN_BOOTTIME };
125         struct timeval boottime;
126         time_t now;
127         int size = sizeof(boottime);
128
129         if ((sysctl(mib, 2, &boottime, &size, NULL, 0) != -1)
130             && (boottime.tv_sec != 0)) {
131                 (void) time(&now);
132                 info.uptime = now - boottime.tv_sec;
133         } else {
134                 (void) warn("could not get uptime");
135                 info.uptime = 0;
136         }
137 }
138
139 int check_mount(char *s)
140 {
141         /* stub */
142         return 0;
143 }
144
145 void update_meminfo()
146 {
147         int mib[] = { CTL_VM, VM_UVMEXP2 };
148         int total_pages, inactive_pages, free_pages;
149         int swap_avail, swap_free;
150         const int pagesize = getpagesize();
151         struct uvmexp_sysctl uvmexp;
152         size_t size = sizeof(uvmexp);
153
154         info.memmax = info.mem = 0;
155         info.swapmax = info.swap = 0;
156
157
158         if (sysctl(mib, 2, &uvmexp, &size, NULL, 0) < 0) {
159                 warn("could not get memory info");
160                 return;
161         }
162
163         total_pages = uvmexp.npages;
164         free_pages = uvmexp.free;
165         inactive_pages = uvmexp.inactive;
166
167         info.memmax = (total_pages * pagesize) >> 10;
168         info.mem =
169             ((total_pages - free_pages - inactive_pages) * pagesize) >> 10;
170
171         if (swapmode(&swap_avail, &swap_free) >= 0) {
172                 info.swapmax = swap_avail;
173                 info.swap = (swap_avail - swap_free);
174         }
175 }
176
177 void update_net_stats()
178 {
179         int i;
180         double delta;
181         struct ifnet ifnet;
182         struct ifnet_head ifhead;       /* interfaces are in a tail queue */
183         u_long ifnetaddr;
184         static struct nlist namelist[] = {
185                 {"_ifnet"},
186                 {NULL},
187         };
188         static kvm_t *nkd;
189
190         if (!nkd_init) {
191                 nkd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, errbuf);
192                 if (nkd == NULL) {
193                         (void) warnx("cannot kvm_openfiles: %s", errbuf);
194                         (void)
195                             warnx
196                             ("maybe you need to setgid kmem this program?");
197                         return;
198                 } else if (kvm_nlist(nkd, namelist) != 0) {
199                         (void) warn("cannot kvm_nlist");
200                         return;
201                 } else
202                         nkd_init = 1;
203         }
204
205         if (kvm_read(nkd, (u_long) namelist[0].n_value, (void *) &ifhead,
206                      sizeof(ifhead)) < 0) {
207                 (void) warn("cannot kvm_read");
208                 return;
209         }
210
211         /* get delta */
212         delta = current_update_time - last_update_time;
213         if (delta <= 0.0001)
214                 return;
215
216         for (i = 0, ifnetaddr = (u_long) ifhead.tqh_first;
217              ifnet.if_list.tqe_next && i < 16;
218              ifnetaddr = (u_long) ifnet.if_list.tqe_next, i++) {
219
220                 struct net_stat *ns;
221                 long long last_recv, last_trans;
222
223                 (void) kvm_read(nkd, (u_long) ifnetaddr, (void *) &ifnet,
224                                 sizeof(ifnet));
225                 ns = get_net_stat(ifnet.if_xname);
226                 ns->up = 1;
227                 last_recv = ns->recv;
228                 last_trans = ns->trans;
229
230                 if (ifnet.if_ibytes < ns->last_read_recv)
231                         ns->recv +=
232                             ((long long) 4294967295U -
233                              ns->last_read_recv) + ifnet.if_ibytes;
234                 else
235                         ns->recv += (ifnet.if_ibytes - ns->last_read_recv);
236
237                 ns->last_read_recv = ifnet.if_ibytes;
238
239                 if (ifnet.if_obytes < ns->last_read_trans)
240                         ns->trans +=
241                             ((long long) 4294967295U -
242                              ns->last_read_trans) + ifnet.if_obytes;
243                 else
244                         ns->trans +=
245                             (ifnet.if_obytes - ns->last_read_trans);
246
247                 ns->last_read_trans = ifnet.if_obytes;
248
249                 ns->recv += (ifnet.if_ibytes - ns->last_read_recv);
250                 ns->last_read_recv = ifnet.if_ibytes;
251                 ns->trans += (ifnet.if_obytes - ns->last_read_trans);
252                 ns->last_read_trans = ifnet.if_obytes;
253
254                 ns->recv_speed = (ns->recv - last_recv) / delta;
255                 ns->trans_speed = (ns->trans - last_trans) / delta;
256         }
257 }
258
259 void update_total_processes()
260 {
261         /* It's easier to use kvm here than sysctl */
262
263         int n_processes;
264
265         info.procs = 0;
266
267         if (init_kvm() < 0)
268                 return;
269         else
270                 kvm_getproc2(kd, KERN_PROC_ALL, 0,
271                              sizeof(struct kinfo_proc2), &n_processes);
272
273         info.procs = n_processes;
274 }
275
276 void update_running_processes()
277 {
278         struct kinfo_proc2 *p;
279         int n_processes;
280         int i, cnt = 0;
281
282         info.run_procs = 0;
283
284         if (init_kvm() < 0)
285                 return;
286         else {
287                 p = kvm_getproc2(kd, KERN_PROC_ALL, 0,
288                                  sizeof(struct kinfo_proc2), &n_processes);
289                 for (i = 0; i < n_processes; i++)
290                         if (p[i].p_stat == LSRUN || p[i].p_stat == LSIDL ||
291                             p[i].p_stat == LSONPROC)
292                                 cnt++;
293         }
294
295         info.run_procs = cnt;
296 }
297
298 struct cpu_load_struct {
299         unsigned long load[5];
300 };
301
302 struct cpu_load_struct fresh = {
303         {0, 0, 0, 0, 0}
304 };
305
306 long cpu_used, oldtotal, oldused;
307
308 void update_cpu_usage()
309 {
310         long used, total;
311         static u_int64_t cp_time[CPUSTATES];
312         size_t len = sizeof(cp_time);
313
314         info.cpu_usage = 0;
315
316         if (sysctlbyname("kern.cp_time", &cp_time, &len, NULL, 0) < 0)
317                 (void) warn("cannot get kern.cp_time");
318
319
320         fresh.load[0] = cp_time[CP_USER];
321         fresh.load[1] = cp_time[CP_NICE];
322         fresh.load[2] = cp_time[CP_SYS];
323         fresh.load[3] = cp_time[CP_IDLE];
324         fresh.load[4] = cp_time[CP_IDLE];
325
326         used = fresh.load[0] + fresh.load[1] + fresh.load[2];
327         total =
328             fresh.load[0] + fresh.load[1] + fresh.load[2] + fresh.load[3];
329
330         if ((total - oldtotal) != 0)
331                 info.cpu_usage =
332                     ((double) (used - oldused)) / (double) (total -
333                                                             oldtotal);
334         else
335                 info.cpu_usage = 0;
336
337         oldused = used;
338         oldtotal = total;
339
340 }
341
342 double get_i2c_info(int *fd, int div, char *devtype)
343 {
344         return -1;
345 }
346
347 void update_load_average()
348 {
349         double v[3];
350         getloadavg(v, 3);
351
352         info.loadavg[0] = (float) v[0];
353         info.loadavg[1] = (float) v[1];
354         info.loadavg[2] = (float) v[2];
355 }
356
357 double get_acpi_temperature(int fd)
358 {
359         return -1;
360 }
361
362 void get_battery_stuff(char *buf, unsigned int n, const char *bat, int item)
363 {
364 }
365
366 int
367 open_i2c_sensor(const char *dev, const char *type, int n, int *div,
368                 char *devtype)
369 {
370         return -1;
371 }
372
373 int open_acpi_temperature(const char *name)
374 {
375         return -1;
376 }
377
378 void get_acpi_ac_adapter( char * p_client_buffer, size_t client_buffer_size )
379 {
380         if ( !p_client_buffer || client_buffer_size <= 0 )
381                 return;
382
383         /* not implemented */
384         memset(p_client_buffer,0,client_buffer_size);
385
386         return;
387 }
388
389 /*char *get_acpi_fan()*/
390 void get_acpi_fan( char * p_client_buffer, size_t client_buffer_size )
391 {
392         if ( !p_client_buffer || client_buffer_size <= 0 )
393                 return;
394
395         /* not implemented */
396         memset(p_client_buffer,0,client_buffer_size);
397
398         return;
399 }
400
401 void update_entropy (void)
402 {
403 }