Blame


1 c440ada7 2024-01-04 benni /*
2 c440ada7 2024-01-04 benni * Copyright (c) 2024 Benjamin Stürz <benni@stuerz.xyz>
3 c440ada7 2024-01-04 benni *
4 c440ada7 2024-01-04 benni * Permission to use, copy, modify, and distribute this software for any
5 c440ada7 2024-01-04 benni * purpose with or without fee is hereby granted, provided that the above
6 c440ada7 2024-01-04 benni * copyright notice and this permission notice appear in all copies.
7 c440ada7 2024-01-04 benni *
8 c440ada7 2024-01-04 benni * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 c440ada7 2024-01-04 benni * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 c440ada7 2024-01-04 benni * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 c440ada7 2024-01-04 benni * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 c440ada7 2024-01-04 benni * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 c440ada7 2024-01-04 benni * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 c440ada7 2024-01-04 benni * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 c440ada7 2024-01-04 benni */
16 8f16cb3e 2024-01-04 benni #include <sys/types.h>
17 f6ed57b5 2024-01-04 benni #include <sys/time.h>
18 8f16cb3e 2024-01-04 benni #include <sys/ioctl.h>
19 f6ed57b5 2024-01-04 benni #include <sys/sched.h>
20 8f16cb3e 2024-01-04 benni #include <sys/sensors.h>
21 f6ed57b5 2024-01-04 benni #include <sys/sysctl.h>
22 f6ed57b5 2024-01-04 benni #include <machine/apmvar.h>
23 c440ada7 2024-01-04 benni
24 f6ed57b5 2024-01-04 benni #include <err.h>
25 f6ed57b5 2024-01-04 benni #include <fcntl.h>
26 8f16cb3e 2024-01-04 benni #include <limits.h>
27 f6ed57b5 2024-01-04 benni #include <locale.h>
28 f6ed57b5 2024-01-04 benni #include <ncurses.h>
29 f6ed57b5 2024-01-04 benni #include <stdbool.h>
30 8f16cb3e 2024-01-04 benni #include <stdint.h>
31 8f16cb3e 2024-01-04 benni #include <stdio.h>
32 f6ed57b5 2024-01-04 benni #include <stdlib.h>
33 f6ed57b5 2024-01-04 benni #include <string.h>
34 f6ed57b5 2024-01-04 benni #include <unistd.h>
35 8f16cb3e 2024-01-04 benni
36 8f16cb3e 2024-01-04 benni #define MAXSENSORS 16
37 8f16cb3e 2024-01-04 benni #define LOGLEN 512
38 8f16cb3e 2024-01-04 benni #define MIN(a, b) ((a) < (b) ? (a) : (b))
39 8f16cb3e 2024-01-04 benni
40 8f16cb3e 2024-01-04 benni static int power_sensors[MAXSENSORS];
41 8f16cb3e 2024-01-04 benni static int cputemp_sensor = -1;
42 8f16cb3e 2024-01-04 benni static int num_power_sensors = 0;
43 8f16cb3e 2024-01-04 benni static int entries = 0;
44 8f16cb3e 2024-01-04 benni
45 8f16cb3e 2024-01-04 benni enum {
46 8f16cb3e 2024-01-04 benni G_CPUUSAGE,
47 8f16cb3e 2024-01-04 benni G_CPUSPEED,
48 8f16cb3e 2024-01-04 benni G_CPUTEMP,
49 8f16cb3e 2024-01-04 benni G_BATTERY,
50 8f16cb3e 2024-01-04 benni G_POWER,
51 8f16cb3e 2024-01-04 benni NGRAPH,
52 8f16cb3e 2024-01-04 benni };
53 8f16cb3e 2024-01-04 benni
54 8f16cb3e 2024-01-04 benni struct graph {
55 8f16cb3e 2024-01-04 benni WINDOW *win;
56 8f16cb3e 2024-01-04 benni int log[LOGLEN];
57 8f16cb3e 2024-01-04 benni bool hide;
58 8f16cb3e 2024-01-04 benni };
59 8f16cb3e 2024-01-04 benni
60 8f16cb3e 2024-01-04 benni struct display {
61 8f16cb3e 2024-01-04 benni struct graph g[NGRAPH];
62 8f16cb3e 2024-01-04 benni
63 8f16cb3e 2024-01-04 benni struct cpu_usage *cpus;
64 8f16cb3e 2024-01-04 benni int fd_apm, ncpu;
65 8f16cb3e 2024-01-04 benni int ngraph;
66 8f16cb3e 2024-01-04 benni int width;
67 8f16cb3e 2024-01-04 benni int delay;
68 8f16cb3e 2024-01-04 benni bool running;
69 8f16cb3e 2024-01-04 benni };
70 8f16cb3e 2024-01-04 benni
71 8f16cb3e 2024-01-04 benni struct cpu_usage {
72 8f16cb3e 2024-01-04 benni struct cpustats new;
73 8f16cb3e 2024-01-04 benni struct cpustats old;
74 8f16cb3e 2024-01-04 benni struct cpustats diffs;
75 8f16cb3e 2024-01-04 benni };
76 8f16cb3e 2024-01-04 benni
77 8f16cb3e 2024-01-04 benni static void
78 8f16cb3e 2024-01-04 benni find_sensors (void)
79 8f16cb3e 2024-01-04 benni {
80 8f16cb3e 2024-01-04 benni for (int i = 0; i < MAXSENSORS; ++i) {
81 8f16cb3e 2024-01-04 benni const int mib[3] = { CTL_HW, HW_SENSORS, i };
82 8f16cb3e 2024-01-04 benni struct sensordev dev;
83 8f16cb3e 2024-01-04 benni size_t sdlen = sizeof dev;
84 8f16cb3e 2024-01-04 benni
85 8f16cb3e 2024-01-04 benni if (sysctl (mib, 3, &dev, &sdlen, NULL, 0) == -1)
86 8f16cb3e 2024-01-04 benni continue;
87 8f16cb3e 2024-01-04 benni
88 8f16cb3e 2024-01-04 benni if (dev.maxnumt[SENSOR_WATTS] > 0) {
89 8f16cb3e 2024-01-04 benni power_sensors[num_power_sensors++] = i;
90 8f16cb3e 2024-01-04 benni }
91 8f16cb3e 2024-01-04 benni
92 8f16cb3e 2024-01-04 benni if (dev.maxnumt[SENSOR_TEMP] > 0
93 8f16cb3e 2024-01-04 benni && memcmp (dev.xname, "cpu", 3) == 0
94 8f16cb3e 2024-01-04 benni && cputemp_sensor == -1) {
95 8f16cb3e 2024-01-04 benni cputemp_sensor = i;
96 8f16cb3e 2024-01-04 benni }
97 8f16cb3e 2024-01-04 benni }
98 8f16cb3e 2024-01-04 benni }
99 8f16cb3e 2024-01-04 benni
100 8f16cb3e 2024-01-04 benni static int
101 8f16cb3e 2024-01-04 benni num_cpu (void)
102 8f16cb3e 2024-01-04 benni {
103 8f16cb3e 2024-01-04 benni const int mib[] = { CTL_HW, HW_NCPU };
104 8f16cb3e 2024-01-04 benni int ncpu = 0;
105 8f16cb3e 2024-01-04 benni size_t size = sizeof ncpu;
106 8f16cb3e 2024-01-04 benni
107 8f16cb3e 2024-01-04 benni if (sysctl (mib, 2, &ncpu, &size, NULL, 0) < 0)
108 8f16cb3e 2024-01-04 benni return 1;
109 8f16cb3e 2024-01-04 benni
110 8f16cb3e 2024-01-04 benni return ncpu;
111 8f16cb3e 2024-01-04 benni }
112 8f16cb3e 2024-01-04 benni
113 8f16cb3e 2024-01-04 benni static int64_t
114 8f16cb3e 2024-01-04 benni percentages (struct cpustats *out, struct cpu_usage *cpu)
115 8f16cb3e 2024-01-04 benni {
116 8f16cb3e 2024-01-04 benni int64_t total_change = 0;
117 8f16cb3e 2024-01-04 benni
118 8f16cb3e 2024-01-04 benni for (int i = 0; i < 6; ++i) {
119 8f16cb3e 2024-01-04 benni int64_t change = cpu->new.cs_time[i] - cpu->old.cs_time[i];
120 8f16cb3e 2024-01-04 benni if (change < 0)
121 8f16cb3e 2024-01-04 benni change = INT64_MAX - cpu->old.cs_time[i] - cpu->new.cs_time[i];
122 8f16cb3e 2024-01-04 benni
123 8f16cb3e 2024-01-04 benni cpu->diffs.cs_time[i] = change;
124 8f16cb3e 2024-01-04 benni total_change += change;
125 8f16cb3e 2024-01-04 benni cpu->old.cs_time[i] = cpu->new.cs_time[i];
126 8f16cb3e 2024-01-04 benni }
127 8f16cb3e 2024-01-04 benni
128 8f16cb3e 2024-01-04 benni if (total_change == 0)
129 8f16cb3e 2024-01-04 benni total_change = 1;
130 8f16cb3e 2024-01-04 benni
131 8f16cb3e 2024-01-04 benni for (int i = 0; i < 6; ++i) {
132 8f16cb3e 2024-01-04 benni out->cs_time[i] = (cpu->diffs.cs_time[i] * 1000 + total_change / 2) / total_change;
133 8f16cb3e 2024-01-04 benni }
134 8f16cb3e 2024-01-04 benni
135 8f16cb3e 2024-01-04 benni return total_change;
136 8f16cb3e 2024-01-04 benni }
137 8f16cb3e 2024-01-04 benni
138 8f16cb3e 2024-01-04 benni static int
139 8f16cb3e 2024-01-04 benni cpuspeed (void)
140 8f16cb3e 2024-01-04 benni {
141 8f16cb3e 2024-01-04 benni const int mib[2] = { CTL_HW, HW_CPUSPEED };
142 8f16cb3e 2024-01-04 benni int speed;
143 8f16cb3e 2024-01-04 benni size_t len = sizeof speed;
144 8f16cb3e 2024-01-04 benni
145 8f16cb3e 2024-01-04 benni if (sysctl (mib, 2, &speed, &len, NULL, 0) == -1)
146 8f16cb3e 2024-01-04 benni return -1;
147 8f16cb3e 2024-01-04 benni
148 8f16cb3e 2024-01-04 benni return speed;
149 8f16cb3e 2024-01-04 benni }
150 8f16cb3e 2024-01-04 benni
151 8f16cb3e 2024-01-04 benni static int
152 8f16cb3e 2024-01-04 benni cputemp (void)
153 8f16cb3e 2024-01-04 benni {
154 8f16cb3e 2024-01-04 benni const int mib[5] = { CTL_HW, HW_SENSORS, cputemp_sensor, SENSOR_TEMP, 0 };
155 8f16cb3e 2024-01-04 benni struct sensor sensor;
156 8f16cb3e 2024-01-04 benni size_t len = sizeof sensor;
157 8f16cb3e 2024-01-04 benni int ret;
158 8f16cb3e 2024-01-04 benni
159 8f16cb3e 2024-01-04 benni ret = sysctl (mib, 5, &sensor, &len, NULL, 0);
160 8f16cb3e 2024-01-04 benni
161 caaad6cc 2024-01-11 benni return (ret == -1 || sensor.status & SENSOR_FINVALID) ? -1 : ((sensor.value - 273150000) / 1000000);
162 8f16cb3e 2024-01-04 benni }
163 8f16cb3e 2024-01-04 benni
164 8f16cb3e 2024-01-04 benni static int
165 8f16cb3e 2024-01-04 benni cpu (int ncpu, struct cpu_usage *cpus)
166 8f16cb3e 2024-01-04 benni {
167 8f16cb3e 2024-01-04 benni uint64_t sum = 0;
168 8f16cb3e 2024-01-04 benni
169 8f16cb3e 2024-01-04 benni for (int i = 0; i < ncpu; ++i) {
170 8f16cb3e 2024-01-04 benni const int mib[] = { CTL_KERN, KERN_CPUSTATS, i };
171 8f16cb3e 2024-01-04 benni struct cpustats tmp;
172 8f16cb3e 2024-01-04 benni size_t size = sizeof tmp;
173 8f16cb3e 2024-01-04 benni
174 8f16cb3e 2024-01-04 benni if (sysctl (mib, 3, &cpus[i].new, &size, NULL, 0) < 0)
175 8f16cb3e 2024-01-04 benni continue;
176 8f16cb3e 2024-01-04 benni
177 8f16cb3e 2024-01-04 benni percentages (&tmp, &cpus[i]);
178 8f16cb3e 2024-01-04 benni sum += 1000 - tmp.cs_time[5];
179 8f16cb3e 2024-01-04 benni }
180 8f16cb3e 2024-01-04 benni
181 8f16cb3e 2024-01-04 benni return sum / ncpu / 10;
182 8f16cb3e 2024-01-04 benni }
183 8f16cb3e 2024-01-04 benni
184 8f16cb3e 2024-01-04 benni static int
185 8f16cb3e 2024-01-04 benni bat (int fd)
186 8f16cb3e 2024-01-04 benni {
187 8f16cb3e 2024-01-04 benni struct apm_power_info info;
188 8f16cb3e 2024-01-04 benni
189 8f16cb3e 2024-01-04 benni if (fd < 0 || ioctl (fd, APM_IOC_GETPOWER, &info) != 0)
190 8f16cb3e 2024-01-04 benni return 0;
191 8f16cb3e 2024-01-04 benni
192 8f16cb3e 2024-01-04 benni return info.battery_life;
193 8f16cb3e 2024-01-04 benni }
194 8f16cb3e 2024-01-04 benni
195 8f16cb3e 2024-01-04 benni static int
196 8f16cb3e 2024-01-04 benni power (void)
197 8f16cb3e 2024-01-04 benni {
198 8f16cb3e 2024-01-04 benni int64_t total = 0;
199 8f16cb3e 2024-01-04 benni
200 8f16cb3e 2024-01-04 benni for (int i = 0; i < num_power_sensors; ++i) {
201 8f16cb3e 2024-01-04 benni const int mib[5] = { CTL_HW, HW_SENSORS, power_sensors[i], SENSOR_WATTS, 0 };
202 8f16cb3e 2024-01-04 benni struct sensor sensor;
203 8f16cb3e 2024-01-04 benni size_t slen = sizeof sensor;
204 8f16cb3e 2024-01-04 benni
205 8f16cb3e 2024-01-04 benni if (sysctl (mib, 5, &sensor, &slen, NULL, 0) == -1)
206 8f16cb3e 2024-01-04 benni continue;
207 8f16cb3e 2024-01-04 benni
208 8f16cb3e 2024-01-04 benni if (sensor.flags & SENSOR_FINVALID)
209 8f16cb3e 2024-01-04 benni continue;
210 8f16cb3e 2024-01-04 benni
211 8f16cb3e 2024-01-04 benni total += sensor.value;
212 8f16cb3e 2024-01-04 benni }
213 8f16cb3e 2024-01-04 benni
214 8f16cb3e 2024-01-04 benni return total / 1000;
215 8f16cb3e 2024-01-04 benni }
216 8f16cb3e 2024-01-04 benni
217 8f16cb3e 2024-01-04 benni static void
218 8f16cb3e 2024-01-04 benni create_win (struct display *dpy)
219 8f16cb3e 2024-01-04 benni {
220 8f16cb3e 2024-01-04 benni int j = 0, w, h, wh;
221 8f16cb3e 2024-01-04 benni
222 8f16cb3e 2024-01-04 benni dpy->ngraph = 0;
223 8f16cb3e 2024-01-04 benni for (int i = 0; i < NGRAPH; ++i) {
224 8f16cb3e 2024-01-04 benni if (!dpy->g[i].hide)
225 8f16cb3e 2024-01-04 benni ++dpy->ngraph;
226 8f16cb3e 2024-01-04 benni }
227 8f16cb3e 2024-01-04 benni
228 8f16cb3e 2024-01-04 benni getmaxyx (stdscr, h, w);
229 8f16cb3e 2024-01-04 benni dpy->width = MIN (w - 2, LOGLEN);
230 8f16cb3e 2024-01-04 benni --h;
231 8f16cb3e 2024-01-04 benni wh = h / dpy->ngraph;
232 8f16cb3e 2024-01-04 benni
233 8f16cb3e 2024-01-04 benni if (entries > dpy->width) {
234 8f16cb3e 2024-01-04 benni const int diff = entries - dpy->width;
235 8f16cb3e 2024-01-04 benni for (int i = 0; i < NGRAPH; ++i) {
236 8f16cb3e 2024-01-04 benni struct graph *g = &dpy->g[i];
237 8f16cb3e 2024-01-04 benni memmove (g->log, g->log + diff, dpy->width * sizeof (g->log[0]));
238 8f16cb3e 2024-01-04 benni }
239 8f16cb3e 2024-01-04 benni entries = dpy->width;
240 8f16cb3e 2024-01-04 benni }
241 8f16cb3e 2024-01-04 benni
242 8f16cb3e 2024-01-04 benni for (int i = 0; i < NGRAPH; ++i) {
243 8f16cb3e 2024-01-04 benni struct graph *g = &dpy->g[i];
244 8f16cb3e 2024-01-04 benni if (g->win != NULL)
245 8f16cb3e 2024-01-04 benni delwin (g->win);
246 8f16cb3e 2024-01-04 benni g->win = g->hide ? NULL : newwin (wh, w, 1 + wh * j++, 0);
247 8f16cb3e 2024-01-04 benni }
248 8f16cb3e 2024-01-04 benni }
249 8f16cb3e 2024-01-04 benni
250 8f16cb3e 2024-01-04 benni static void
251 8f16cb3e 2024-01-04 benni draw_graph (struct graph *g, const char *fmt, int min, int max)
252 8f16cb3e 2024-01-04 benni {
253 8f16cb3e 2024-01-04 benni int w, h;
254 8f16cb3e 2024-01-04 benni
255 8f16cb3e 2024-01-04 benni if (g->hide || g->win == NULL)
256 8f16cb3e 2024-01-04 benni return;
257 8f16cb3e 2024-01-04 benni
258 8f16cb3e 2024-01-04 benni getmaxyx (g->win, h, w);
259 8f16cb3e 2024-01-04 benni w -= 2;
260 8f16cb3e 2024-01-04 benni h -= 3;
261 8f16cb3e 2024-01-04 benni
262 caaad6cc 2024-01-11 benni werase (g->win);
263 8f16cb3e 2024-01-04 benni
264 8f16cb3e 2024-01-04 benni for (int i = 0; i < entries; ++i) {
265 8f16cb3e 2024-01-04 benni int v = g->log[i];
266 8f16cb3e 2024-01-04 benni if (v < min)
267 8f16cb3e 2024-01-04 benni min = v;
268 8f16cb3e 2024-01-04 benni if (v > max)
269 8f16cb3e 2024-01-04 benni max = v;
270 8f16cb3e 2024-01-04 benni }
271 8f16cb3e 2024-01-04 benni
272 8f16cb3e 2024-01-04 benni if (min < max) {
273 8f16cb3e 2024-01-04 benni for (int i = 0; i < entries; ++i) {
274 8f16cb3e 2024-01-04 benni int v = g->log[i];
275 8f16cb3e 2024-01-04 benni int y = (int)((float)(v - min) / (max - min) * h);
276 8f16cb3e 2024-01-04 benni mvwaddch (g->win, h - y + 1, i + 1, 'X');
277 8f16cb3e 2024-01-04 benni }
278 8f16cb3e 2024-01-04 benni }
279 8f16cb3e 2024-01-04 benni
280 8f16cb3e 2024-01-04 benni box (g->win, 0, 0);
281 8f16cb3e 2024-01-04 benni
282 8f16cb3e 2024-01-04 benni mvwprintw (g->win, 0, 3, fmt, g->log[entries - 1]);
283 8f16cb3e 2024-01-04 benni wprintw (g->win, " (min: %d/max: %d)", min, max);
284 8f16cb3e 2024-01-04 benni
285 8f16cb3e 2024-01-04 benni }
286 8f16cb3e 2024-01-04 benni
287 8f16cb3e 2024-01-04 benni static void
288 8f16cb3e 2024-01-04 benni draw (struct display *dpy)
289 8f16cb3e 2024-01-04 benni {
290 caaad6cc 2024-01-11 benni erase ();
291 0c9b1cfd 2024-01-06 benni
292 8f16cb3e 2024-01-04 benni draw_graph (&dpy->g[G_CPUUSAGE], "CPU: %d%%", 0, 100);
293 048144dd 2024-01-04 benni draw_graph (&dpy->g[G_CPUTEMP], "CPU: %d C", 0, 100);
294 8f16cb3e 2024-01-04 benni draw_graph (&dpy->g[G_CPUSPEED], "CPU: %d MHz", INT_MAX, INT_MIN);
295 8f16cb3e 2024-01-04 benni draw_graph (&dpy->g[G_BATTERY], "BAT: %d%%", 0, 100);
296 8f16cb3e 2024-01-04 benni draw_graph (&dpy->g[G_POWER], "PWR: %dmW", INT_MAX, INT_MIN);
297 8f16cb3e 2024-01-04 benni
298 8f16cb3e 2024-01-04 benni mvprintw (0, 0, "Panels: ");
299 8f16cb3e 2024-01-04 benni for (int i = 0; i < NGRAPH; ++i) {
300 8f16cb3e 2024-01-04 benni addch (dpy->g[i].hide ? ' ' : ('1' + i));
301 8f16cb3e 2024-01-04 benni }
302 8f16cb3e 2024-01-04 benni
303 8f16cb3e 2024-01-04 benni printw (" %c delay=%d", dpy->running ? 'R' : 'S', dpy->delay);
304 8f16cb3e 2024-01-04 benni
305 caaad6cc 2024-01-11 benni wnoutrefresh (stdscr);
306 8f16cb3e 2024-01-04 benni for (int i = 0; i < NGRAPH; ++i)
307 8f16cb3e 2024-01-04 benni wnoutrefresh (dpy->g[i].win);
308 8f16cb3e 2024-01-04 benni doupdate ();
309 8f16cb3e 2024-01-04 benni }
310 8f16cb3e 2024-01-04 benni
311 8f16cb3e 2024-01-04 benni static void
312 8f16cb3e 2024-01-04 benni update_graph (int w, struct graph *g, int value)
313 8f16cb3e 2024-01-04 benni {
314 8f16cb3e 2024-01-04 benni if (entries == w) {
315 8f16cb3e 2024-01-04 benni memmove (g->log, g->log + 1, (LOGLEN - 1) * sizeof (g->log[0]));
316 8f16cb3e 2024-01-04 benni g->log[entries - 1] = value;
317 8f16cb3e 2024-01-04 benni } else {
318 8f16cb3e 2024-01-04 benni g->log[entries] = value;
319 8f16cb3e 2024-01-04 benni }
320 8f16cb3e 2024-01-04 benni }
321 8f16cb3e 2024-01-04 benni
322 8f16cb3e 2024-01-04 benni static void
323 8f16cb3e 2024-01-04 benni update (struct display *dpy)
324 8f16cb3e 2024-01-04 benni {
325 8f16cb3e 2024-01-04 benni int w = dpy->width;
326 8f16cb3e 2024-01-04 benni
327 8f16cb3e 2024-01-04 benni update_graph (w, &dpy->g[G_CPUUSAGE], cpu (dpy->ncpu, dpy->cpus));
328 8f16cb3e 2024-01-04 benni update_graph (w, &dpy->g[G_CPUTEMP], cputemp ());
329 8f16cb3e 2024-01-04 benni update_graph (w, &dpy->g[G_CPUSPEED], cpuspeed ());
330 8f16cb3e 2024-01-04 benni update_graph (w, &dpy->g[G_BATTERY], bat (dpy->fd_apm));
331 8f16cb3e 2024-01-04 benni update_graph (w, &dpy->g[G_POWER], power ());
332 8f16cb3e 2024-01-04 benni
333 8f16cb3e 2024-01-04 benni entries++;
334 8f16cb3e 2024-01-04 benni if (entries > w)
335 8f16cb3e 2024-01-04 benni entries = w;
336 8f16cb3e 2024-01-04 benni }
337 8f16cb3e 2024-01-04 benni
338 7fd8efc3 2024-01-04 benni static int
339 7fd8efc3 2024-01-04 benni usage (void)
340 7fd8efc3 2024-01-04 benni {
341 7fd8efc3 2024-01-04 benni fputs ("usage: apmtop [-V] [-d delay]\n", stderr);
342 7fd8efc3 2024-01-04 benni return 1;
343 7fd8efc3 2024-01-04 benni }
344 7fd8efc3 2024-01-04 benni
345 8f16cb3e 2024-01-04 benni int
346 8f16cb3e 2024-01-04 benni main (int argc, char *argv[])
347 8f16cb3e 2024-01-04 benni {
348 8f16cb3e 2024-01-04 benni struct display dpy;
349 7fd8efc3 2024-01-04 benni int option;
350 8f16cb3e 2024-01-04 benni
351 c440ada7 2024-01-04 benni // pledge(2) doesn't work, because apmtop(1) needs sysctl(2).
352 c440ada7 2024-01-04 benni unveil ("/usr/share/terminfo", "r");
353 29c14c1d 2024-01-05 benni unveil ("/dev/apm", "r");
354 c440ada7 2024-01-04 benni unveil (NULL, NULL);
355 c440ada7 2024-01-04 benni
356 8f16cb3e 2024-01-04 benni memset (&dpy, 0, sizeof (dpy));
357 7fd8efc3 2024-01-04 benni dpy.delay = 10;
358 7fd8efc3 2024-01-04 benni
359 7fd8efc3 2024-01-04 benni while ((option = getopt (argc, argv, "d:V")) != -1) {
360 7fd8efc3 2024-01-04 benni const char *errstr;
361 7fd8efc3 2024-01-04 benni switch (option) {
362 7fd8efc3 2024-01-04 benni case 'd':
363 7fd8efc3 2024-01-04 benni dpy.delay = (int)strtonum (optarg, 1, 100, &errstr);
364 7fd8efc3 2024-01-04 benni if (errstr != NULL)
365 7fd8efc3 2024-01-04 benni errx (1, "invalid delay '%s': %s", optarg, errstr);
366 7fd8efc3 2024-01-04 benni break;
367 7fd8efc3 2024-01-04 benni case 'V':
368 7fd8efc3 2024-01-04 benni puts ("apmtop-" VERSION);
369 7fd8efc3 2024-01-04 benni return 1;
370 7fd8efc3 2024-01-04 benni default:
371 7fd8efc3 2024-01-04 benni return usage ();
372 7fd8efc3 2024-01-04 benni }
373 7fd8efc3 2024-01-04 benni }
374 7fd8efc3 2024-01-04 benni
375 7fd8efc3 2024-01-04 benni argc -= optind;
376 7fd8efc3 2024-01-04 benni //argv += optind;
377 7fd8efc3 2024-01-04 benni if (argc > 0)
378 7fd8efc3 2024-01-04 benni return usage ();
379 7fd8efc3 2024-01-04 benni
380 7fd8efc3 2024-01-04 benni // Configure the "display".
381 8f16cb3e 2024-01-04 benni dpy.ncpu = num_cpu ();
382 8f16cb3e 2024-01-04 benni dpy.cpus = calloc (dpy.ncpu, sizeof (struct cpu_usage));
383 8f16cb3e 2024-01-04 benni dpy.fd_apm = open ("/dev/apm", O_RDONLY);
384 29c14c1d 2024-01-05 benni if (dpy.fd_apm < 0)
385 29c14c1d 2024-01-05 benni warn ("failed to open /dev/apm");
386 8f16cb3e 2024-01-04 benni dpy.running = true;
387 8f16cb3e 2024-01-04 benni find_sensors ();
388 8f16cb3e 2024-01-04 benni
389 f6ed57b5 2024-01-04 benni // Configure ncurses.
390 8f16cb3e 2024-01-04 benni setlocale (LC_ALL, "");
391 8f16cb3e 2024-01-04 benni initscr ();
392 8f16cb3e 2024-01-04 benni cbreak ();
393 8f16cb3e 2024-01-04 benni noecho ();
394 8f16cb3e 2024-01-04 benni intrflush (stdscr, FALSE);
395 8f16cb3e 2024-01-04 benni keypad (stdscr, TRUE);
396 8f16cb3e 2024-01-04 benni halfdelay (dpy.delay);
397 7dd73432 2024-01-06 benni curs_set (0);
398 8f16cb3e 2024-01-04 benni
399 f6ed57b5 2024-01-04 benni // Bootstrap the process.
400 8f16cb3e 2024-01-04 benni entries = 0;
401 8f16cb3e 2024-01-04 benni create_win (&dpy);
402 8f16cb3e 2024-01-04 benni update (&dpy);
403 8f16cb3e 2024-01-04 benni draw (&dpy);
404 8f16cb3e 2024-01-04 benni
405 8f16cb3e 2024-01-04 benni while (1) {
406 8f16cb3e 2024-01-04 benni struct graph *g;
407 8f16cb3e 2024-01-04 benni int ch;
408 8f16cb3e 2024-01-04 benni
409 8f16cb3e 2024-01-04 benni ch = getch ();
410 8f16cb3e 2024-01-04 benni
411 8f16cb3e 2024-01-04 benni switch (ch) {
412 8f16cb3e 2024-01-04 benni case 'q':
413 8f16cb3e 2024-01-04 benni goto done;
414 8f16cb3e 2024-01-04 benni case KEY_RESIZE:
415 8f16cb3e 2024-01-04 benni create_win (&dpy);
416 8f16cb3e 2024-01-04 benni break;
417 8f16cb3e 2024-01-04 benni case '1':
418 8f16cb3e 2024-01-04 benni case '2':
419 8f16cb3e 2024-01-04 benni case '3':
420 8f16cb3e 2024-01-04 benni case '4':
421 8f16cb3e 2024-01-04 benni case '5':
422 8f16cb3e 2024-01-04 benni g = &dpy.g[ch - '1'];
423 8f16cb3e 2024-01-04 benni if (dpy.ngraph == 1 && !g->hide)
424 8f16cb3e 2024-01-04 benni break;
425 8f16cb3e 2024-01-04 benni g->hide = !g->hide;
426 8f16cb3e 2024-01-04 benni create_win (&dpy);
427 8f16cb3e 2024-01-04 benni break;
428 8f16cb3e 2024-01-04 benni case '+':
429 8f16cb3e 2024-01-04 benni ++dpy.delay;
430 8f16cb3e 2024-01-04 benni halfdelay (dpy.delay);
431 8f16cb3e 2024-01-04 benni break;
432 8f16cb3e 2024-01-04 benni case '-':
433 8f16cb3e 2024-01-04 benni if (dpy.delay > 1)
434 8f16cb3e 2024-01-04 benni --dpy.delay;
435 8f16cb3e 2024-01-04 benni halfdelay (dpy.delay);
436 8f16cb3e 2024-01-04 benni break;
437 8f16cb3e 2024-01-04 benni case ' ':
438 8f16cb3e 2024-01-04 benni dpy.running = !dpy.running;
439 8f16cb3e 2024-01-04 benni break;
440 8f16cb3e 2024-01-04 benni case ERR:
441 8f16cb3e 2024-01-04 benni if (dpy.running)
442 8f16cb3e 2024-01-04 benni update (&dpy);
443 8f16cb3e 2024-01-04 benni break;
444 8f16cb3e 2024-01-04 benni }
445 8f16cb3e 2024-01-04 benni
446 8f16cb3e 2024-01-04 benni draw (&dpy);
447 8f16cb3e 2024-01-04 benni }
448 8f16cb3e 2024-01-04 benni
449 8f16cb3e 2024-01-04 benni done:
450 8f16cb3e 2024-01-04 benni endwin ();
451 048144dd 2024-01-04 benni free (dpy.cpus);
452 8f16cb3e 2024-01-04 benni return 0;
453 8f16cb3e 2024-01-04 benni }