* Use timed_thread for mpd
[monky] / src / common.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 "conky.h"
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <ctype.h>
34 #include <errno.h>
35 #include <sys/time.h>
36 #include <pthread.h>
37
38 struct information info;
39
40 void update_uname()
41 {
42         uname(&info.uname_s);
43 }
44
45 double get_time()
46 {
47         struct timeval tv;
48         gettimeofday(&tv, 0);
49         return tv.tv_sec + (tv.tv_usec / 1000000.0);
50 }
51
52 FILE *open_file(const char *file, int *reported)
53 {
54         FILE *fp = fopen(file, "r");
55         if (!fp) {
56                 if (!reported || *reported == 0) {
57                         ERR("can't open %s: %s", file, strerror(errno));
58                         if (reported)
59                                 *reported = 1;
60                 }
61                 return 0;
62         }
63
64         return fp;
65 }
66
67 void variable_substitute(const char *s, char *dest, unsigned int n)
68 {
69         while (*s && n > 1) {
70                 if (*s == '$') {
71                         s++;
72                         if (*s != '$') {
73                                 char buf[256];
74                                 const char *a, *var;
75                                 unsigned int len;
76
77                                 /* variable is either $foo or ${foo} */
78                                 if (*s == '{') {
79                                         s++;
80                                         a = s;
81                                         while (*s && *s != '}')
82                                                 s++;
83                                 } else {
84                                         a = s;
85                                         while (*s && (isalnum((int) *s)
86                                                       || *s == '_'))
87                                                 s++;
88                                 }
89
90                                 /* copy variable to buffer and look it up */
91                                 len = (s - a > 255) ? 255 : (s - a);
92                                 strncpy(buf, a, len);
93                                 buf[len] = '\0';
94
95                                 if (*s == '}')
96                                         s++;
97
98                                 var = getenv(buf);
99
100                                 if (var) {
101                                         /* add var to dest */
102                                         len = strlen(var);
103                                         if (len >= n)
104                                                 len = n - 1;
105                                         strncpy(dest, var, len);
106                                         dest += len;
107                                         n -= len;
108                                 }
109                                 continue;
110                         }
111                 }
112
113                 *dest++ = *s++;
114                 n--;
115         }
116
117         *dest = '\0';
118 }
119
120 /* network interface stuff */
121
122 static struct net_stat netstats[16];
123
124 struct net_stat *get_net_stat(const char *dev)
125 {
126         unsigned int i;
127
128         if (!dev)
129                 return 0;
130
131         /* find interface stat */
132         for (i = 0; i < 16; i++) {
133                 if (netstats[i].dev && strcmp(netstats[i].dev, dev) == 0)
134                         return &netstats[i];
135         }
136
137         /* wasn't found? add it */
138         if (i == 16) {
139                 for (i = 0; i < 16; i++) {
140                         if (netstats[i].dev == 0) {
141                                 netstats[i].dev = strdup(dev);
142                                 return &netstats[i];
143                         }
144                 }
145         }
146
147         CRIT_ERR("too many interfaces used (limit is 16)");
148         return 0;
149 }
150
151 void clear_net_stats (void)
152 {
153   memset (netstats, 0, sizeof(netstats));
154 }
155
156 void format_seconds(char *buf, unsigned int n, long t)
157 {
158         if (t >= 24 * 60 * 60)  /* hours necessary when there are days? */
159                 snprintf(buf, n, "%ldd %ldh %ldm", t / 60 / 60 / 24,
160                          (t / 60 / 60) % 24, (t / 60) % 60);
161         else if (t >= 60 * 60)
162                 snprintf(buf, n, "%ldh %ldm", (t / 60 / 60) % 24,
163                          (t / 60) % 60);
164         else
165                 snprintf(buf, n, "%ldm %lds", t / 60, t % 60);
166 }
167
168 void format_seconds_short(char *buf, unsigned int n, long t)
169 {
170         if (t >= 24 * 60 * 60)
171                 snprintf(buf, n, "%ldd %ldh", t / 60 / 60 / 24,
172                          (t / 60 / 60) % 24);
173         else if (t >= 60 * 60)
174                 snprintf(buf, n, "%ldh %ldm", (t / 60 / 60) % 24,
175                          (t / 60) % 60);
176         else
177                 snprintf(buf, n, "%ldm", t / 60);
178 }
179
180 static double last_meminfo_update;
181 static double last_fs_update;
182
183 unsigned long long need_mask;
184 #define NEED(a) ((need_mask & (1 << a)) && ((info.mask & (1 << a)) == 0))
185
186 void update_stuff()
187 {
188         unsigned int i;
189         info.mask = 0;
190
191         if (no_buffers)
192                 need_mask |= 1 << INFO_BUFFERS;
193
194         /* clear speeds and up status in case device was removed and doesn't get
195            updated */
196
197         for (i = 0; i < 16; i++) {
198                 if (netstats[i].dev) {
199                         netstats[i].up = 0;
200                         netstats[i].recv_speed = 0.0;
201                         netstats[i].trans_speed = 0.0;
202                 }
203         }
204
205         prepare_update();
206
207         if (NEED(INFO_UPTIME))
208                 update_uptime();
209
210         if (NEED(INFO_PROCS))
211                 update_total_processes();
212
213         if (NEED(INFO_RUN_PROCS))
214                 update_running_processes();
215
216         if (NEED(INFO_CPU))
217                 update_cpu_usage();
218
219         if (NEED(INFO_NET))
220                 update_net_stats();
221
222         if (NEED(INFO_DISKIO))
223                 update_diskio();
224
225         if (NEED(INFO_MAIL))
226                 update_mail_count();
227
228 #if defined(__linux__)
229         if (NEED(INFO_I8K))
230                 update_i8k();
231 #endif /* __linux__ */
232         
233 #ifdef MPD
234         if (NEED(INFO_MPD)) {
235                 if (!mpd_timed_thread) {
236                         mpd_timed_thread = timed_thread_create((void*)update_mpd, (void*) NULL, update_interval * 1000000);
237                 }
238         }
239 #endif
240
241 #ifdef XMMS2
242         if (NEED(INFO_XMMS2))
243                 update_xmms2();
244 #endif
245
246 #ifdef AUDACIOUS
247         if (NEED(INFO_AUDACIOUS))
248                 update_audacious();
249 #endif
250
251 #ifdef BMPX
252         if (NEED(INFO_BMPX))
253                 update_bmpx();
254 #endif
255
256         if (NEED(INFO_LOADAVG))
257                 update_load_average();
258
259
260         if ((NEED(INFO_MEM) || NEED(INFO_BUFFERS) || NEED(INFO_TOP)) &&
261             current_update_time - last_meminfo_update > 6.9) {
262                 update_meminfo();
263                 if (no_buffers) {
264                         info.mem -= info.bufmem;
265                 }
266                 last_meminfo_update = current_update_time;
267         }
268
269         if (NEED(INFO_TOP))
270                 update_top();
271
272         /* update_fs_stat() won't do anything if there aren't fs -things */
273         if (NEED(INFO_FS) && current_update_time - last_fs_update > 12.9) {
274                 update_fs_stats();
275                 last_fs_update = current_update_time;
276         }
277 #ifdef TCP_PORT_MONITOR
278         if (NEED(INFO_TCP_PORT_MONITOR))
279                 update_tcp_port_monitor_collection( info.p_tcp_port_monitor_collection );
280 #endif
281         if (NEED(INFO_ENTROPY))
282                 update_entropy();
283 }
284
285 int round_to_int(float f)
286 {
287     int intval = (int)f;
288     double delta = f - intval;
289     if (!(delta < 0.5)) {
290         ++intval;
291     }
292
293     return intval;
294 }