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