14c103b47cee90cf77da5a3382824c1b47d2dc49
[monky] / src / freebsd.c
1 /*
2  * freebsd.c
3  * Contains FreeBSD specific stuff
4  *
5  * $Id$
6  */
7
8 #include <sys/dkstat.h>
9 #include <sys/param.h>
10 #include <sys/resource.h>
11 #include <sys/socket.h>
12 #include <sys/sysctl.h>
13 #include <sys/time.h>
14 #include <sys/types.h>
15 #include <sys/vmmeter.h>
16 #include <sys/user.h>
17
18 #include <net/if.h>
19 #include <net/if_mib.h>
20
21 #include <devstat.h>
22 #include <fcntl.h>
23 #include <ifaddrs.h>
24 #include <limits.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <unistd.h>
29
30 #include "conky.h"
31
32 #define GETSYSCTL(name, var)    getsysctl(name, &(var), sizeof (var))
33 #define KELVTOC(x)              ((x - 2732) / 10.0)
34 #define MAXSHOWDEVS             16
35
36 #if 0
37 #define FREEBSD_DEBUG
38 #endif
39
40 inline void proc_find_top(struct process **cpu, struct process **mem);
41
42 u_int64_t diskio_prev = 0;
43 static short cpu_setup = 0;
44 static short diskio_setup = 0;
45
46 static int getsysctl(char *name, void *ptr, size_t len)
47 {
48         size_t nlen = len;
49         if (sysctlbyname(name, ptr, &nlen, NULL, 0) == -1) {
50                 return (-1);
51         }
52
53         if (nlen != len) {
54                 return (-1);
55         }
56
57         return (0);
58 }
59
60 struct ifmibdata *data = NULL;
61 size_t len = 0;
62
63 static int swapmode(int *retavail, int *retfree)
64 {
65         int n;
66         int pagesize = getpagesize();
67         struct kvm_swap swapary[1];
68
69         *retavail = 0;
70         *retfree = 0;
71
72 #define CONVERT(v)      ((quad_t)(v) * pagesize / 1024)
73
74         n = kvm_getswapinfo(kd, swapary, 1, 0);
75         if (n < 0 || swapary[0].ksw_total == 0)
76                 return (0);
77
78         *retavail = CONVERT(swapary[0].ksw_total);
79         *retfree = CONVERT(swapary[0].ksw_total - swapary[0].ksw_used);
80
81         n = (int) ((double) swapary[0].ksw_used * 100.0 /
82                 (double) swapary[0].ksw_total);
83
84         return (n);
85 }
86
87 void
88 prepare_update()
89 {
90 }
91
92 void
93 update_uptime()
94 {
95         int mib[2] = { CTL_KERN, KERN_BOOTTIME };
96         struct timeval boottime;
97         time_t now;
98         size_t size = sizeof (boottime);
99
100         if ((sysctl(mib, 2, &boottime, &size, NULL, 0) != -1) &&
101                         (boottime.tv_sec != 0)) {
102                 time(&now);
103                 info.uptime = now - boottime.tv_sec;
104         } else {
105                 fprintf(stderr, "Could not get uptime\n");
106                 info.uptime = 0;
107         }
108 }
109
110 void
111 update_meminfo()
112 {
113         int total_pages, inactive_pages, free_pages;
114         int swap_avail, swap_free;
115
116         int pagesize = getpagesize();
117
118         if (GETSYSCTL("vm.stats.vm.v_page_count", total_pages))
119                 fprintf(stderr,
120                         "Cannot read sysctl \"vm.stats.vm.v_page_count\"");
121
122         if (GETSYSCTL("vm.stats.vm.v_free_count", free_pages))
123                 fprintf(stderr,
124                         "Cannot read sysctl \"vm.stats.vm.v_free_count\"");
125
126         if (GETSYSCTL("vm.stats.vm.v_inactive_count", inactive_pages))
127                 fprintf(stderr,
128                         "Cannot read sysctl \"vm.stats.vm.v_inactive_count\"");
129
130         info.memmax = (total_pages * pagesize) >> 10;
131         info.mem =
132             ((total_pages - free_pages - inactive_pages) * pagesize) >> 10;
133
134
135         if ((swapmode(&swap_avail, &swap_free)) >= 0) {
136                 info.swapmax = swap_avail;
137                 info.swap = (swap_avail - swap_free);
138         } else {
139                 info.swapmax = 0;
140                 info.swap = 0;
141         }
142 }
143
144 void
145 update_net_stats()
146 {
147         struct net_stat *ns;
148         double delta;
149         long long r, t, last_recv, last_trans;
150         struct ifaddrs *ifap, *ifa;
151         struct if_data *ifd;
152
153
154         /* get delta */
155         delta = current_update_time - last_update_time;
156         if (delta <= 0.0001)
157                 return;
158
159         if (getifaddrs(&ifap) < 0)
160                 return;
161
162         for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
163                 ns = get_net_stat((const char *) ifa->ifa_name);
164
165                 if (ifa->ifa_flags & IFF_UP) {
166                         struct ifaddrs *iftmp;
167
168                         ns->up = 1;
169                         ns->linkstatus = 1;
170                         last_recv = ns->recv;
171                         last_trans = ns->trans;
172
173                         if (ifa->ifa_addr->sa_family != AF_LINK)
174                                 continue;
175
176                         for (iftmp = ifa->ifa_next; iftmp != NULL &&
177                                 strcmp(ifa->ifa_name, iftmp->ifa_name) == 0;
178                                 iftmp = iftmp->ifa_next)
179                                 if (iftmp->ifa_addr->sa_family == AF_INET)
180                                         memcpy(&(ns->addr), iftmp->ifa_addr,
181                                                 iftmp->ifa_addr->sa_len);
182
183                         ifd = (struct if_data *) ifa->ifa_data;
184                         r = ifd->ifi_ibytes;
185                         t = ifd->ifi_obytes;
186
187                         if (r < ns->last_read_recv)
188                                 ns->recv +=
189                                     ((long long) 4294967295U -
190                                         ns->last_read_recv) + r;
191                         else
192                                 ns->recv += (r - ns->last_read_recv);
193
194                         ns->last_read_recv = r;
195
196                         if (t < ns->last_read_trans)
197                                 ns->trans +=
198                                     ((long long) 4294967295U -
199                                         ns->last_read_trans) + t;
200                         else
201                                 ns->trans += (t - ns->last_read_trans);
202
203                         ns->last_read_trans = t;
204
205                         /* calculate speeds */
206                         ns->recv_speed = (ns->recv - last_recv) / delta;
207                         ns->trans_speed = (ns->trans - last_trans) / delta;
208                 } else {
209                         ns->up = 0;
210                         ns->linkstatus = 0;
211                 }
212         }
213
214         freeifaddrs(ifap);
215 }
216
217 void
218 update_total_processes()
219 {
220         int n_processes;
221
222         kvm_getprocs(kd, KERN_PROC_ALL, 0, &n_processes);
223
224         info.procs = n_processes;
225 }
226
227 void
228 update_running_processes()
229 {
230         struct kinfo_proc *p;
231         int n_processes;
232         int i, cnt = 0;
233
234         p = kvm_getprocs(kd, KERN_PROC_ALL, 0, &n_processes);
235         for (i = 0; i < n_processes; i++) {
236 #if __FreeBSD__ < 5
237                 if (p[i].kp_proc.p_stat == SRUN)
238 #else
239                 if (p[i].ki_stat == SRUN)
240 #endif
241                         cnt++;
242         }
243
244         info.run_procs = cnt;
245 }
246
247 struct cpu_load_struct {
248         unsigned long load[5];
249 };
250
251 struct cpu_load_struct fresh = { {0, 0, 0, 0, 0} };
252 long cpu_used, oldtotal, oldused;
253
254 void
255 get_cpu_count()
256 {
257         /* int cpu_count = 0; */
258
259         /*
260          * XXX
261          * FreeBSD doesn't allow to get per CPU load stats
262          * on SMP machines. It's possible to get a CPU count,
263          * but as we fulfil only info.cpu_usage[0], it's better
264          * to report there's only one CPU. It should fix some bugs
265          * (e.g. cpugraph)
266          */
267 #if 0
268         if (GETSYSCTL("hw.ncpu", cpu_count) == 0)
269                 info.cpu_count = cpu_count;
270 #endif
271         info.cpu_count = 1;
272
273         info.cpu_usage = malloc(info.cpu_count * sizeof (float));
274         if (info.cpu_usage == NULL)
275                 CRIT_ERR("malloc");
276 }
277
278 /* XXX: SMP support */
279 void
280 update_cpu_usage()
281 {
282         long used, total;
283         long cp_time[CPUSTATES];
284         size_t len = sizeof (cp_time);
285
286         if (cpu_setup == 0) {
287                 get_cpu_count();
288                 cpu_setup = 1;
289         }
290
291         if (sysctlbyname("kern.cp_time", &cp_time, &len, NULL, 0) < 0) {
292                 (void) fprintf(stderr, "Cannot get kern.cp_time");
293         }
294
295         fresh.load[0] = cp_time[CP_USER];
296         fresh.load[1] = cp_time[CP_NICE];
297         fresh.load[2] = cp_time[CP_SYS];
298         fresh.load[3] = cp_time[CP_IDLE];
299         fresh.load[4] = cp_time[CP_IDLE];
300
301         used = fresh.load[0] + fresh.load[1] + fresh.load[2];
302         total =
303             fresh.load[0] + fresh.load[1] + fresh.load[2] + fresh.load[3];
304
305         if ((total - oldtotal) != 0) {
306                 info.cpu_usage[0] = ((double) (used - oldused)) /
307                         (double) (total - oldtotal);
308         } else {
309                 info.cpu_usage[0] = 0;
310         }
311
312         oldused = used;
313         oldtotal = total;
314 }
315
316 double
317 get_i2c_info(int *fd, int arg, char *devtype, char *type)
318 {
319         return (0);
320 }
321
322 void
323 update_load_average()
324 {
325         double v[3];
326         getloadavg(v, 3);
327
328         info.loadavg[0] = (float) v[0];
329         info.loadavg[1] = (float) v[1];
330         info.loadavg[2] = (float) v[2];
331 }
332
333 double
334 get_acpi_temperature(int fd)
335 {
336         int temp;
337
338         if (GETSYSCTL("hw.acpi.thermal.tz0.temperature", temp)) {
339                 fprintf(stderr,
340                 "Cannot read sysctl \"hw.acpi.thermal.tz0.temperature\"\n");
341                 return (0.0);
342         }
343
344         return (KELVTOC(temp));
345 }
346
347 void
348 get_battery_stuff(char *buf, unsigned int n, const char *bat)
349 {
350         int battime, batcapacity, batstate, ac;
351
352         if (GETSYSCTL("hw.acpi.battery.time", battime))
353                 (void) fprintf(stderr,
354                         "Cannot read sysctl \"hw.acpi.battery.time\"\n");
355         if (GETSYSCTL("hw.acpi.battery.life", batcapacity))
356                 (void) fprintf(stderr,
357                                            "Cannot read sysctl \"hw.acpi.battery.life\"\n");
358
359         if (GETSYSCTL("hw.acpi.battery.state", batstate))
360                 (void) fprintf(stderr,
361                                            "Cannot read sysctl \"hw.acpi.battery.state\"\n");
362
363         if (GETSYSCTL("hw.acpi.acline", ac))
364                 (void) fprintf(stderr,
365                                            "Cannot read sysctl \"hw.acpi.acline\"\n");
366
367         if (batstate == 1) {
368                 if (battime != -1)
369                         snprintf(buf, n, "remaining %d%% (%d:%2.2d)",
370                                         batcapacity, battime / 60, battime % 60);
371                 else
372                         /* no time estimate available yet */
373                         snprintf(buf, n, "remaining %d%%",
374                                         batcapacity);
375                 if (ac == 1)
376                         (void) fprintf(stderr, "Discharging while on AC!\n");
377         } else {
378                 snprintf(buf, n, batstate == 2 ? "charging (%d%%)" : "charged (%d%%)", batcapacity);
379                 if (batstate != 2 && batstate != 0)
380                         (void) fprintf(stderr, "Unknow battery state %d!\n", batstate);
381                 if (ac == 0)
382                         (void) fprintf(stderr, "Charging while not on AC!\n");
383         }
384
385 }
386
387 int
388 open_i2c_sensor(const char *dev, const char *type, int n, int *div,
389                 char *devtype)
390 {
391         return (0);
392 }
393
394 int
395 open_acpi_temperature(const char *name)
396 {
397         return (0);
398 }
399
400 void
401 get_acpi_ac_adapter(char *p_client_buffer, size_t client_buffer_size)
402 {
403         int state;
404
405         if (!p_client_buffer || client_buffer_size <= 0)
406                 return;
407
408         if (GETSYSCTL("hw.acpi.acline", state)) {
409                 fprintf(stderr,
410                         "Cannot read sysctl \"hw.acpi.acline\"\n");
411                 return;
412         }
413
414
415         if (state)
416                 strncpy(p_client_buffer, "Running on AC Power",
417                                 client_buffer_size);
418         else
419                 strncpy(p_client_buffer, "Running on battery",
420                                 client_buffer_size);
421
422 }
423
424 void
425 get_acpi_fan(char *p_client_buffer, size_t client_buffer_size)
426 {
427         if (!p_client_buffer || client_buffer_size <= 0)
428                 return;
429
430         /* not implemented */
431         memset(p_client_buffer, 0, client_buffer_size);
432 }
433
434 void
435 get_adt746x_cpu(char *p_client_buffer, size_t client_buffer_size)
436 {
437         if (!p_client_buffer || client_buffer_size <= 0)
438                 return;
439
440         /* not implemented */
441         memset(p_client_buffer, 0, client_buffer_size);
442 }
443
444 void
445 get_adt746x_fan(char *p_client_buffer, size_t client_buffer_size)
446 {
447         if (!p_client_buffer || client_buffer_size <= 0)
448                 return;
449
450         /* not implemented */
451         memset(p_client_buffer, 0, client_buffer_size);
452 }
453
454 /* rdtsc() and get_freq_dynamic() copied from linux.c */
455
456 #if  defined(__i386) || defined(__x86_64)
457 __inline__ unsigned long long int
458 rdtsc()
459 {
460         unsigned long long int x;
461         __asm__ volatile(".byte 0x0f, 0x31":"=A" (x));
462         return (x);
463 }
464 #endif
465
466 /* return system frequency in MHz (use divisor=1) or GHz (use divisor=1000) */
467 void
468 get_freq_dynamic(char *p_client_buffer, size_t client_buffer_size,
469                 char *p_format, int divisor)
470 {
471 #if  defined(__i386) || defined(__x86_64)
472         struct timezone tz;
473         struct timeval tvstart, tvstop;
474         unsigned long long cycles[2];   /* gotta be 64 bit */
475         unsigned int microseconds;      /* total time taken */
476
477         memset(&tz, 0, sizeof (tz));
478
479         /* get this function in cached memory */
480         gettimeofday(&tvstart, &tz);
481         cycles[0] = rdtsc();
482         gettimeofday(&tvstart, &tz);
483
484         /* we don't trust that this is any specific length of time */
485         usleep(100);
486         cycles[1] = rdtsc();
487         gettimeofday(&tvstop, &tz);
488         microseconds = ((tvstop.tv_sec - tvstart.tv_sec) * 1000000) +
489                 (tvstop.tv_usec - tvstart.tv_usec);
490
491         snprintf(p_client_buffer, client_buffer_size, p_format,
492                 (float)((cycles[1] - cycles[0]) / microseconds) / divisor);
493 #else
494         get_freq(p_client_buffer, client_buffer_size, p_format, divisor);
495 #endif
496 }
497
498 /* return system frequency in MHz (use divisor=1) or GHz (use divisor=1000) */
499 void
500 get_freq(char *p_client_buffer, size_t client_buffer_size,
501                 char *p_format, int divisor)
502 {
503         int freq;
504
505         if (!p_client_buffer || client_buffer_size <= 0 ||
506                         !p_format || divisor <= 0)
507                 return;
508
509         if (GETSYSCTL("dev.cpu.0.freq", freq) == 0)
510                 snprintf(p_client_buffer, client_buffer_size,
511                                 p_format, freq/divisor);
512         else
513                 snprintf(p_client_buffer, client_buffer_size, p_format, 0.0f);
514 }
515
516 void
517 update_top()
518 {
519         proc_find_top(info.cpu, info.memu);
520 }
521
522 void
523 update_wifi_stats()
524 {
525         /* XXX */
526 }
527 void
528 update_diskio()
529 {
530         int devs_count,
531             num_selected,
532             num_selections;
533         struct device_selection *dev_select = NULL;
534         long select_generation;
535         int dn;
536         static struct statinfo  statinfo_cur;
537         u_int64_t diskio_current = 0;
538
539         bzero(&statinfo_cur, sizeof (statinfo_cur));
540         statinfo_cur.dinfo = (struct devinfo *)malloc(sizeof (struct devinfo));
541         bzero(statinfo_cur.dinfo, sizeof (struct devinfo));
542
543         if (devstat_getdevs(NULL, &statinfo_cur) < 0)
544                 return;
545
546         devs_count = statinfo_cur.dinfo->numdevs;
547         if (devstat_selectdevs(&dev_select, &num_selected, &num_selections,
548                         &select_generation, statinfo_cur.dinfo->generation,
549                         statinfo_cur.dinfo->devices, devs_count, NULL, 0,
550                         NULL, 0, DS_SELECT_ONLY, MAXSHOWDEVS, 1) >= 0) {
551                 for (dn = 0; dn < devs_count; ++dn) {
552                         int di;
553                         struct devstat  *dev;
554
555                         di = dev_select[dn].position;
556                         dev = &statinfo_cur.dinfo->devices[di];
557
558                         diskio_current += dev->bytes[DEVSTAT_READ] +
559                                 dev->bytes[DEVSTAT_WRITE];
560                 }
561
562                 free(dev_select);
563         }
564
565         /*
566          * Since we return (diskio_total_current - diskio_total_old), first
567          * frame will be way too high (it will be equal to
568          * diskio_total_current, i.e. all disk I/O since boot). That's why
569          * it is better to return 0 first time;
570          */
571         if (diskio_setup == 0) {
572                 diskio_setup = 1;
573                 diskio_value = 0;
574         } else
575                 diskio_value = (unsigned int)((diskio_current - diskio_prev)/
576                                 1024);
577         diskio_prev = diskio_current;
578
579         free(statinfo_cur.dinfo);
580 }
581
582 /*
583  * While topless is obviously better, top is also not bad.
584  */
585
586 int
587 comparecpu(const void *a, const void *b)
588 {
589         if (((struct process *)a)->amount > ((struct process *)b)->amount)
590                 return (-1);
591
592         if (((struct process *)a)->amount < ((struct process *)b)->amount)
593                 return (1);
594
595         return (0);
596 }
597
598 int
599 comparemem(const void *a, const void *b)
600 {
601         if (((struct process *)a)->totalmem > ((struct process *)b)->totalmem)
602                 return (-1);
603
604         if (((struct process *)a)->totalmem < ((struct process *)b)->totalmem)
605                 return (1);
606
607         return (0);
608 }
609
610 inline void
611 proc_find_top(struct process **cpu, struct process **mem)
612 {
613         struct kinfo_proc *p;
614         int n_processes;
615         int i, j = 0;
616         struct process *processes;
617
618         int total_pages;
619
620         /* we get total pages count again to be sure it is up to date */
621         if (GETSYSCTL("vm.stats.vm.v_page_count", total_pages) != 0)
622                 CRIT_ERR("Cannot read sysctl"
623                         "\"vm.stats.vm.v_page_count\"");
624
625         p = kvm_getprocs(kd, KERN_PROC_PROC, 0, &n_processes);
626         processes = malloc(n_processes * sizeof (struct process));
627
628         for (i = 0; i < n_processes; i++) {
629                 if (!((p[i].ki_flag & P_SYSTEM)) &&
630                                 p[i].ki_comm != NULL) {
631                         processes[j].pid = p[i].ki_pid;
632                         processes[j].name =  strdup(p[i].ki_comm);
633                         processes[j].amount = 100.0 *
634                                 p[i].ki_pctcpu / FSCALE;
635                         processes[j].totalmem = (float)(p[i].ki_rssize /
636                                         (float)total_pages) * 100.0;
637                         j++;
638                 }
639         }
640
641         qsort(processes, j - 1, sizeof (struct process), comparemem);
642         for (i = 0; i < 10; i++) {
643                 struct process *tmp, *ttmp;
644
645                 tmp = malloc(sizeof (struct process));
646                 tmp->pid = processes[i].pid;
647                 tmp->amount = processes[i].amount;
648                 tmp->totalmem = processes[i].totalmem;
649                 tmp->name = strdup(processes[i].name);
650
651                 ttmp = mem[i];
652                 mem[i] = tmp;
653                 if (ttmp != NULL) {
654                         free(ttmp->name);
655                         free(ttmp);
656                 }
657         }
658
659         qsort(processes, j - 1, sizeof (struct process), comparecpu);
660         for (i = 0; i < 10; i++) {
661                 struct process *tmp, *ttmp;
662
663                 tmp = malloc(sizeof (struct process));
664                 tmp->pid = processes[i].pid;
665                 tmp->amount = processes[i].amount;
666                 tmp->totalmem = processes[i].totalmem;
667                 tmp->name = strdup(processes[i].name);
668
669                 ttmp = cpu[i];
670                 cpu[i] = tmp;
671                 if (ttmp != NULL) {
672                         free(ttmp->name);
673                         free(ttmp);
674                 }
675         }
676
677 #if defined(FREEBSD_DEBUG)
678         printf("=====\nmem\n");
679         for (i = 0; i < 10; i++) {
680                 printf("%d: %s(%d) %.2f\n", i, mem[i]->name,
681                                 mem[i]->pid, mem[i]->totalmem);
682         }
683 #endif
684
685         for (i = 0; i < j; free(processes[i++].name));
686         free(processes);
687 }
688
689 #if     defined(i386) || defined(__i386__)
690 #define APMDEV          "/dev/apm"
691 #define APM_UNKNOWN     255
692
693 int
694 apm_getinfo(int fd, apm_info_t aip)
695 {
696         if (ioctl(fd, APMIO_GETINFO, aip) == -1)
697                 return (-1);
698
699         return (0);
700 }
701
702 char
703 *get_apm_adapter()
704 {
705         int fd;
706         struct apm_info info;
707
708         fd = open(APMDEV, O_RDONLY);
709         if (fd < 0)
710                 return ("ERR");
711
712         if (apm_getinfo(fd, &info) != 0) {
713                 close(fd);
714                 return ("ERR");
715         }
716         close(fd);
717
718         switch (info.ai_acline) {
719                 case 0:
720                         return ("off-line");
721                         break;
722                 case 1:
723                         if (info.ai_batt_stat == 3)
724                                 return ("charging");
725                         else
726                                 return ("on-line");
727                         break;
728                 default:
729                         return ("unknown");
730                         break;
731         }
732 }
733
734 char
735 *get_apm_battery_life()
736 {
737         int fd;
738         u_int batt_life;
739         struct apm_info info;
740         char *out;
741
742         out = (char *)calloc(16, sizeof (char));
743
744         fd = open(APMDEV, O_RDONLY);
745         if (fd < 0) {
746                 strncpy(out, "ERR", 16);
747                 return (out);
748         }
749
750         if (apm_getinfo(fd, &info) != 0) {
751                 close(fd);
752                 strncpy(out, "ERR", 16);
753                 return (out);
754         }
755         close(fd);
756
757         batt_life = info.ai_batt_life;
758         if (batt_life == APM_UNKNOWN)
759                 strncpy(out, "unknown", 16);
760         else if (batt_life <= 100) {
761                 snprintf(out, 16, "%d%%", batt_life);
762                 return (out);
763         } else
764                 strncpy(out, "ERR", 16);
765
766         return (out);
767 }
768
769 char
770 *get_apm_battery_time()
771 {
772         int fd;
773         int batt_time;
774         int h, m, s;
775         struct apm_info info;
776         char *out;
777
778         out = (char *)calloc(16, sizeof (char));
779
780         fd = open(APMDEV, O_RDONLY);
781         if (fd < 0) {
782                 strncpy(out, "ERR", 16);
783                 return (out);
784         }
785
786         if (apm_getinfo(fd, &info) != 0) {
787                 close(fd);
788                 strncpy(out, "ERR", 16);
789                 return (out);
790         }
791         close(fd);
792
793         batt_time = info.ai_batt_time;
794
795         if (batt_time == -1)
796                 strncpy(out, "unknown", 16);
797         else {
798                 h = batt_time;
799                 s = h % 60;
800                 h /= 60;
801                 m = h % 60;
802                 h /= 60;
803                 snprintf(out, 16, "%2d:%02d:%02d", h, m, s);
804         }
805
806         return (out);
807 }
808
809 #endif
810
811 /* empty stub so conky links */
812 void
813 free_all_processes(void)
814 {
815 }