My slstatus configuration
Nie możesz wybrać więcej, niż 25 tematów Tematy muszą się zaczynać od litery lub cyfry, mogą zawierać myślniki ('-') i mogą mieć do 35 znaków.
 
 
 
 

918 wiersze
18 KiB

  1. /* See LICENSE file for copyright and license details. */
  2. #include <dirent.h>
  3. #include <err.h>
  4. #include <fcntl.h>
  5. #include <ifaddrs.h>
  6. #include <limits.h>
  7. #include <linux/wireless.h>
  8. #include <locale.h>
  9. #include <netdb.h>
  10. #include <pwd.h>
  11. #include <signal.h>
  12. #include <stdarg.h>
  13. #include <stdio.h>
  14. #include <stdlib.h>
  15. #include <string.h>
  16. #include <sys/ioctl.h>
  17. #include <sys/stat.h>
  18. #include <sys/statvfs.h>
  19. #include <sys/socket.h>
  20. #include <sys/soundcard.h>
  21. #include <sys/sysinfo.h>
  22. #include <sys/types.h>
  23. #include <sys/utsname.h>
  24. #include <time.h>
  25. #include <unistd.h>
  26. #include <X11/Xlib.h>
  27. #include "arg.h"
  28. struct arg {
  29. const char *(*func)();
  30. const char *fmt;
  31. const char *args;
  32. };
  33. static const char *bprintf(const char *fmt, ...);
  34. static const char *battery_perc(const char *bat);
  35. static const char *battery_power(const char *bat);
  36. static const char *battery_state(const char *bat);
  37. static const char *cpu_freq(void);
  38. static const char *cpu_perc(void);
  39. static const char *datetime(const char *fmt);
  40. static const char *disk_free(const char *mnt);
  41. static const char *disk_perc(const char *mnt);
  42. static const char *disk_total(const char *mnt);
  43. static const char *disk_used(const char *mnt);
  44. static const char *entropy(void);
  45. static const char *gid(void);
  46. static const char *hostname(void);
  47. static const char *ip(const char *iface);
  48. static const char *kernel_release(void);
  49. static const char *keyboard_indicators(void);
  50. static const char *load_avg(void);
  51. static const char *num_files(const char *dir);
  52. static const char *ram_free(void);
  53. static const char *ram_perc(void);
  54. static const char *ram_used(void);
  55. static const char *ram_total(void);
  56. static const char *run_command(const char *cmd);
  57. static const char *swap_free(void);
  58. static const char *swap_perc(void);
  59. static const char *swap_used(void);
  60. static const char *swap_total(void);
  61. static const char *temp(const char *file);
  62. static const char *uid(void);
  63. static const char *uptime(void);
  64. static const char *username(void);
  65. static const char *vol_perc(const char *card);
  66. static const char *wifi_perc(const char *iface);
  67. static const char *wifi_essid(const char *iface);
  68. static void sighandler(const int signo);
  69. static void usage(void);
  70. char *argv0;
  71. static unsigned short int delay = 0;
  72. static unsigned short int done;
  73. static Display *dpy;
  74. #include "config.h"
  75. static char buf[MAXLEN];
  76. static const char *
  77. bprintf(const char *fmt, ...)
  78. {
  79. va_list ap;
  80. size_t len;
  81. va_start(ap, fmt);
  82. len = vsnprintf(buf, sizeof(buf) - 1, fmt, ap);
  83. va_end(ap);
  84. if (len >= sizeof(buf))
  85. buf[sizeof(buf)-1] = '\0';
  86. return buf;
  87. }
  88. static const char *
  89. battery_perc(const char *bat)
  90. {
  91. int n, perc;
  92. char path[PATH_MAX];
  93. FILE *fp;
  94. snprintf(path, sizeof(path), "%s%s%s", "/sys/class/power_supply/", bat, "/capacity");
  95. fp = fopen(path, "r");
  96. if (fp == NULL) {
  97. warn("Failed to open file %s", path);
  98. return UNKNOWN_STR;
  99. }
  100. n = fscanf(fp, "%i", &perc);
  101. fclose(fp);
  102. if (n != 1)
  103. return UNKNOWN_STR;
  104. return bprintf("%d", perc);
  105. }
  106. static const char *
  107. battery_power(const char *bat)
  108. {
  109. char path[PATH_MAX];
  110. FILE *fp;
  111. int n, watts;
  112. snprintf(path, sizeof(path), "%s%s%s", "/sys/class/power_supply/", bat, "/power_now");
  113. fp = fopen(path, "r");
  114. if (fp == NULL) {
  115. warn("Failed to open file %s", path);
  116. return UNKNOWN_STR;
  117. }
  118. n = fscanf(fp, "%i", &watts);
  119. fclose(fp);
  120. if (n != 1)
  121. return UNKNOWN_STR;
  122. return bprintf("%d", (watts + 500000) / 1000000);
  123. }
  124. static const char *
  125. battery_state(const char *bat)
  126. {
  127. char path[PATH_MAX];
  128. char state[12];
  129. FILE *fp;
  130. int n;
  131. snprintf(path, sizeof(path), "%s%s%s", "/sys/class/power_supply/", bat, "/status");
  132. fp = fopen(path, "r");
  133. if (fp == NULL) {
  134. warn("Failed to open file %s", path);
  135. return UNKNOWN_STR;
  136. }
  137. n = fscanf(fp, "%12s", state);
  138. fclose(fp);
  139. if (n != 1)
  140. return UNKNOWN_STR;
  141. if (strcmp(state, "Charging") == 0) {
  142. return "+";
  143. } else if (strcmp(state, "Discharging") == 0) {
  144. return "-";
  145. } else if (strcmp(state, "Full") == 0) {
  146. return "=";
  147. } else if (strcmp(state, "Unknown") == 0) {
  148. return "/";
  149. } else {
  150. return "?";
  151. }
  152. }
  153. static const char *
  154. cpu_freq(void)
  155. {
  156. int n, freq;
  157. FILE *fp;
  158. fp = fopen("/sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq", "r");
  159. if (fp == NULL) {
  160. warn("Failed to open file /sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq");
  161. return UNKNOWN_STR;
  162. }
  163. n = fscanf(fp, "%i", &freq);
  164. fclose(fp);
  165. if (n != 1)
  166. return UNKNOWN_STR;
  167. return bprintf("%d", (freq + 500) / 1000);
  168. }
  169. static const char *
  170. cpu_perc(void)
  171. {
  172. int n, perc;
  173. long double a[4], b[4];
  174. FILE *fp;
  175. fp = fopen("/proc/stat", "r");
  176. if (fp == NULL) {
  177. warn("Failed to open file /proc/stat");
  178. return UNKNOWN_STR;
  179. }
  180. n = fscanf(fp, "%*s %Lf %Lf %Lf %Lf", &a[0], &a[1], &a[2], &a[3]);
  181. fclose(fp);
  182. if (n != 4)
  183. return UNKNOWN_STR;
  184. delay++;
  185. sleep(delay);
  186. fp = fopen("/proc/stat", "r");
  187. if (fp == NULL) {
  188. warn("Failed to open file /proc/stat");
  189. return UNKNOWN_STR;
  190. }
  191. n = fscanf(fp, "%*s %Lf %Lf %Lf %Lf", &b[0], &b[1], &b[2], &b[3]);
  192. fclose(fp);
  193. if (n != 4)
  194. return UNKNOWN_STR;
  195. perc = 100 * ((b[0]+b[1]+b[2]) - (a[0]+a[1]+a[2])) / ((b[0]+b[1]+b[2]+b[3]) - (a[0]+a[1]+a[2]+a[3]));
  196. return bprintf("%d", perc);
  197. }
  198. static const char *
  199. datetime(const char *fmt)
  200. {
  201. time_t t;
  202. t = time(NULL);
  203. if (strftime(buf, sizeof(buf), fmt, localtime(&t)) == 0)
  204. return UNKNOWN_STR;
  205. return buf;
  206. }
  207. static const char *
  208. disk_free(const char *mnt)
  209. {
  210. struct statvfs fs;
  211. if (statvfs(mnt, &fs) < 0) {
  212. warn("Failed to get filesystem info");
  213. return UNKNOWN_STR;
  214. }
  215. return bprintf("%f", (float)fs.f_bsize * (float)fs.f_bfree / 1024 / 1024 / 1024);
  216. }
  217. static const char *
  218. disk_perc(const char *mnt)
  219. {
  220. int perc;
  221. struct statvfs fs;
  222. if (statvfs(mnt, &fs) < 0) {
  223. warn("Failed to get filesystem info");
  224. return UNKNOWN_STR;
  225. }
  226. perc = 100 * (1.0f - ((float)fs.f_bfree / (float)fs.f_blocks));
  227. return bprintf("%d", perc);
  228. }
  229. static const char *
  230. disk_total(const char *mnt)
  231. {
  232. struct statvfs fs;
  233. if (statvfs(mnt, &fs) < 0) {
  234. warn("Failed to get filesystem info");
  235. return UNKNOWN_STR;
  236. }
  237. return bprintf("%f", (float)fs.f_bsize * (float)fs.f_blocks / 1024 / 1024 / 1024);
  238. }
  239. static const char *
  240. disk_used(const char *mnt)
  241. {
  242. struct statvfs fs;
  243. if (statvfs(mnt, &fs) < 0) {
  244. warn("Failed to get filesystem info");
  245. return UNKNOWN_STR;
  246. }
  247. return bprintf("%f", (float)fs.f_bsize * ((float)fs.f_blocks - (float)fs.f_bfree) / 1024 / 1024 / 1024);
  248. }
  249. static const char *
  250. entropy(void)
  251. {
  252. int n, num;
  253. FILE *fp;
  254. fp= fopen("/proc/sys/kernel/random/entropy_avail", "r");
  255. if (fp == NULL) {
  256. warn("Failed to open file /proc/sys/kernel/random/entropy_avail");
  257. return UNKNOWN_STR;
  258. }
  259. n = fscanf(fp, "%d", &num);
  260. fclose(fp);
  261. if (n != 1)
  262. return UNKNOWN_STR;
  263. return bprintf("%d", num);
  264. }
  265. static const char *
  266. gid(void)
  267. {
  268. return bprintf("%d", getgid());
  269. }
  270. static const char *
  271. hostname(void)
  272. {
  273. if (gethostname(buf, sizeof(buf)) == -1) {
  274. warn("hostname");
  275. return UNKNOWN_STR;
  276. }
  277. return buf;
  278. }
  279. static const char *
  280. ip(const char *iface)
  281. {
  282. struct ifaddrs *ifaddr, *ifa;
  283. int s;
  284. char host[NI_MAXHOST];
  285. if (getifaddrs(&ifaddr) == -1) {
  286. warn("Failed to get IP address for interface %s", iface);
  287. return UNKNOWN_STR;
  288. }
  289. for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
  290. if (ifa->ifa_addr == NULL) {
  291. continue;
  292. }
  293. s = getnameinfo(ifa->ifa_addr, sizeof(struct sockaddr_in), host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST);
  294. if ((strcmp(ifa->ifa_name, iface) == 0) && (ifa->ifa_addr->sa_family == AF_INET)) {
  295. if (s != 0) {
  296. warnx("Failed to get IP address for interface %s", iface);
  297. return UNKNOWN_STR;
  298. }
  299. return bprintf("%s", host);
  300. }
  301. }
  302. freeifaddrs(ifaddr);
  303. return UNKNOWN_STR;
  304. }
  305. static const char *
  306. kernel_release(void)
  307. {
  308. struct utsname udata;
  309. if (uname(&udata) < 0) {
  310. return UNKNOWN_STR;
  311. }
  312. return bprintf("%s", udata.release);
  313. }
  314. static const char *
  315. keyboard_indicators(void)
  316. {
  317. Display *dpy = XOpenDisplay(NULL);
  318. XKeyboardState state;
  319. XGetKeyboardControl(dpy, &state);
  320. XCloseDisplay(dpy);
  321. switch (state.led_mask) {
  322. case 1:
  323. return "c";
  324. case 2:
  325. return "n";
  326. case 3:
  327. return "cn";
  328. default:
  329. return "";
  330. }
  331. }
  332. static const char *
  333. load_avg(void)
  334. {
  335. double avgs[3];
  336. if (getloadavg(avgs, 3) < 0) {
  337. warnx("Failed to get the load avg");
  338. return UNKNOWN_STR;
  339. }
  340. return bprintf("%.2f %.2f %.2f", avgs[0], avgs[1], avgs[2]);
  341. }
  342. static const char *
  343. num_files(const char *dir)
  344. {
  345. struct dirent *dp;
  346. DIR *fd;
  347. int num = 0;
  348. if ((fd = opendir(dir)) == NULL) {
  349. warn("Failed to get number of files in directory %s", dir);
  350. return UNKNOWN_STR;
  351. }
  352. while ((dp = readdir(fd)) != NULL) {
  353. if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, ".."))
  354. continue; /* skip self and parent */
  355. num++;
  356. }
  357. closedir(fd);
  358. return bprintf("%d", num);
  359. }
  360. static const char *
  361. ram_free(void)
  362. {
  363. long free;
  364. FILE *fp;
  365. int n;
  366. fp = fopen("/proc/meminfo", "r");
  367. if (fp == NULL) {
  368. warn("Failed to open file /proc/meminfo");
  369. return UNKNOWN_STR;
  370. }
  371. n = fscanf(fp, "MemFree: %ld kB\n", &free);
  372. fclose(fp);
  373. if (n != 1)
  374. return UNKNOWN_STR;
  375. return bprintf("%f", (float)free / 1024 / 1024);
  376. }
  377. static const char *
  378. ram_perc(void)
  379. {
  380. long total, free, buffers, cached;
  381. FILE *fp;
  382. fp = fopen("/proc/meminfo", "r");
  383. if (fp == NULL) {
  384. warn("Failed to open file /proc/meminfo");
  385. return UNKNOWN_STR;
  386. }
  387. if (fscanf(fp, "MemTotal: %ld kB\n", &total) != 1 ||
  388. fscanf(fp, "MemFree: %ld kB\n", &free) != 1 ||
  389. fscanf(fp, "MemAvailable: %ld kB\nBuffers: %ld kB\n",
  390. &buffers, &buffers) != 2 ||
  391. fscanf(fp, "Cached: %ld kB\n", &cached) != 1)
  392. goto scanerr;
  393. fclose(fp);
  394. return bprintf("%d", 100 * ((total - free) - (buffers + cached)) / total);
  395. scanerr:
  396. fclose(fp);
  397. return UNKNOWN_STR;
  398. }
  399. static const char *
  400. ram_total(void)
  401. {
  402. long total;
  403. FILE *fp;
  404. int n;
  405. fp = fopen("/proc/meminfo", "r");
  406. if (fp == NULL) {
  407. warn("Failed to open file /proc/meminfo");
  408. return UNKNOWN_STR;
  409. }
  410. n = fscanf(fp, "MemTotal: %ld kB\n", &total);
  411. fclose(fp);
  412. if (n != 1)
  413. return UNKNOWN_STR;
  414. return bprintf("%f", (float)total / 1024 / 1024);
  415. }
  416. static const char *
  417. ram_used(void)
  418. {
  419. long free, total, buffers, cached;
  420. FILE *fp;
  421. fp = fopen("/proc/meminfo", "r");
  422. if (fp == NULL) {
  423. warn("Failed to open file /proc/meminfo");
  424. return UNKNOWN_STR;
  425. }
  426. if (fscanf(fp, "MemTotal: %ld kB\n", &total) != 1 ||
  427. fscanf(fp, "MemFree: %ld kB\n", &free) != 1 ||
  428. fscanf(fp, "MemAvailable: %ld kB\nBuffers: %ld kB\n",
  429. &buffers, &buffers) != 2 ||
  430. fscanf(fp, "Cached: %ld kB\n", &cached) != 1)
  431. goto scanerr;
  432. fclose(fp);
  433. return bprintf("%f", (float)(total - free - buffers - cached) / 1024 / 1024);
  434. scanerr:
  435. fclose(fp);
  436. return UNKNOWN_STR;
  437. }
  438. static const char *
  439. run_command(const char *cmd)
  440. {
  441. char *p;
  442. FILE *fp;
  443. fp = popen(cmd, "r");
  444. if (fp == NULL) {
  445. warn("Failed to get command output for %s", cmd);
  446. return UNKNOWN_STR;
  447. }
  448. p = fgets(buf, sizeof(buf) - 1, fp);
  449. pclose(fp);
  450. if (!p)
  451. return UNKNOWN_STR;
  452. if ((p = strrchr(buf, '\n')) != NULL)
  453. p[0] = '\0';
  454. return buf[0] ? buf : UNKNOWN_STR;
  455. }
  456. static const char *
  457. swap_free(void)
  458. {
  459. long total, free;
  460. FILE *fp;
  461. size_t bytes_read;
  462. char *match;
  463. fp = fopen("/proc/meminfo", "r");
  464. if (fp == NULL) {
  465. warn("Failed to open file /proc/meminfo");
  466. return UNKNOWN_STR;
  467. }
  468. if ((bytes_read = fread(buf, sizeof(char), sizeof(buf) - 1, fp)) == 0) {
  469. warn("swap_free: read error");
  470. fclose(fp);
  471. return UNKNOWN_STR;
  472. }
  473. fclose(fp);
  474. if ((match = strstr(buf, "SwapTotal")) == NULL)
  475. return UNKNOWN_STR;
  476. sscanf(match, "SwapTotal: %ld kB\n", &total);
  477. if ((match = strstr(buf, "SwapFree")) == NULL)
  478. return UNKNOWN_STR;
  479. sscanf(match, "SwapFree: %ld kB\n", &free);
  480. return bprintf("%f", (float)free / 1024 / 1024);
  481. }
  482. static const char *
  483. swap_perc(void)
  484. {
  485. long total, free, cached;
  486. FILE *fp;
  487. size_t bytes_read;
  488. char *match;
  489. fp = fopen("/proc/meminfo", "r");
  490. if (fp == NULL) {
  491. warn("Failed to open file /proc/meminfo");
  492. return UNKNOWN_STR;
  493. }
  494. if ((bytes_read = fread(buf, sizeof(char), sizeof(buf) - 1, fp)) == 0) {
  495. warn("swap_perc: read error");
  496. fclose(fp);
  497. return UNKNOWN_STR;
  498. }
  499. fclose(fp);
  500. if ((match = strstr(buf, "SwapTotal")) == NULL)
  501. return UNKNOWN_STR;
  502. sscanf(match, "SwapTotal: %ld kB\n", &total);
  503. if ((match = strstr(buf, "SwapCached")) == NULL)
  504. return UNKNOWN_STR;
  505. sscanf(match, "SwapCached: %ld kB\n", &cached);
  506. if ((match = strstr(buf, "SwapFree")) == NULL)
  507. return UNKNOWN_STR;
  508. sscanf(match, "SwapFree: %ld kB\n", &free);
  509. return bprintf("%d", 100 * (total - free - cached) / total);
  510. }
  511. static const char *
  512. swap_total(void)
  513. {
  514. long total;
  515. FILE *fp;
  516. size_t bytes_read;
  517. char *match;
  518. fp = fopen("/proc/meminfo", "r");
  519. if (fp == NULL) {
  520. warn("Failed to open file /proc/meminfo");
  521. return UNKNOWN_STR;
  522. }
  523. if ((bytes_read = fread(buf, sizeof(char), sizeof(buf) - 1, fp)) == 0) {
  524. warn("swap_total: read error");
  525. fclose(fp);
  526. return UNKNOWN_STR;
  527. }
  528. fclose(fp);
  529. if ((match = strstr(buf, "SwapTotal")) == NULL)
  530. return UNKNOWN_STR;
  531. sscanf(match, "SwapTotal: %ld kB\n", &total);
  532. return bprintf("%f", (float)total / 1024 / 1024);
  533. }
  534. static const char *
  535. swap_used(void)
  536. {
  537. long total, free, cached;
  538. FILE *fp;
  539. size_t bytes_read;
  540. char *match;
  541. fp = fopen("/proc/meminfo", "r");
  542. if (fp == NULL) {
  543. warn("Failed to open file /proc/meminfo");
  544. return UNKNOWN_STR;
  545. }
  546. if ((bytes_read = fread(buf, sizeof(char), sizeof(buf) - 1, fp)) == 0) {
  547. warn("swap_used: read error");
  548. fclose(fp);
  549. return UNKNOWN_STR;
  550. }
  551. fclose(fp);
  552. if ((match = strstr(buf, "SwapTotal")) == NULL)
  553. return UNKNOWN_STR;
  554. sscanf(match, "SwapTotal: %ld kB\n", &total);
  555. if ((match = strstr(buf, "SwapCached")) == NULL)
  556. return UNKNOWN_STR;
  557. sscanf(match, "SwapCached: %ld kB\n", &cached);
  558. if ((match = strstr(buf, "SwapFree")) == NULL)
  559. return UNKNOWN_STR;
  560. sscanf(match, "SwapFree: %ld kB\n", &free);
  561. return bprintf("%f", (float)(total - free - cached) / 1024 / 1024);
  562. }
  563. static const char *
  564. temp(const char *file)
  565. {
  566. int n, temp;
  567. FILE *fp;
  568. fp = fopen(file, "r");
  569. if (fp == NULL) {
  570. warn("Failed to open file %s", file);
  571. return UNKNOWN_STR;
  572. }
  573. n = fscanf(fp, "%d", &temp);
  574. fclose(fp);
  575. if (n != 1)
  576. return UNKNOWN_STR;
  577. return bprintf("%d", temp / 1000);
  578. }
  579. static const char *
  580. uptime(void)
  581. {
  582. struct sysinfo info;
  583. int h = 0;
  584. int m = 0;
  585. sysinfo(&info);
  586. h = info.uptime / 3600;
  587. m = (info.uptime - h * 3600 ) / 60;
  588. return bprintf("%dh %dm", h, m);
  589. }
  590. static const char *
  591. username(void)
  592. {
  593. struct passwd *pw = getpwuid(geteuid());
  594. if (pw == NULL) {
  595. warn("Failed to get username");
  596. return UNKNOWN_STR;
  597. }
  598. return bprintf("%s", pw->pw_name);
  599. }
  600. static const char *
  601. uid(void)
  602. {
  603. return bprintf("%d", geteuid());
  604. }
  605. static const char *
  606. vol_perc(const char *card)
  607. {
  608. unsigned int i;
  609. int v, afd, devmask;
  610. char *vnames[] = SOUND_DEVICE_NAMES;
  611. afd = open(card, O_RDONLY | O_NONBLOCK);
  612. if (afd == -1) {
  613. warn("Cannot open %s", card);
  614. return UNKNOWN_STR;
  615. }
  616. if (ioctl(afd, SOUND_MIXER_READ_DEVMASK, &devmask) == -1) {
  617. warn("Cannot get volume for %s", card);
  618. close(afd);
  619. return UNKNOWN_STR;
  620. }
  621. for (i = 0; i < (sizeof(vnames) / sizeof((vnames[0]))); i++) {
  622. if (devmask & (1 << i) && !strcmp("vol", vnames[i])) {
  623. if (ioctl(afd, MIXER_READ(i), &v) == -1) {
  624. warn("vol_perc: ioctl");
  625. close(afd);
  626. return UNKNOWN_STR;
  627. }
  628. }
  629. }
  630. close(afd);
  631. return bprintf("%d", v & 0xff);
  632. }
  633. static const char *
  634. wifi_perc(const char *iface)
  635. {
  636. int i, perc;
  637. char *p, *datastart;
  638. char path[PATH_MAX];
  639. char status[5];
  640. FILE *fp;
  641. snprintf(path, sizeof(path), "%s%s%s", "/sys/class/net/", iface, "/operstate");
  642. fp = fopen(path, "r");
  643. if (fp == NULL) {
  644. warn("Failed to open file %s", path);
  645. return UNKNOWN_STR;
  646. }
  647. p = fgets(status, 5, fp);
  648. fclose(fp);
  649. if(!p || strcmp(status, "up\n") != 0) {
  650. return UNKNOWN_STR;
  651. }
  652. fp = fopen("/proc/net/wireless", "r");
  653. if (fp == NULL) {
  654. warn("Failed to open file /proc/net/wireless");
  655. return UNKNOWN_STR;
  656. }
  657. for (i = 0; i < 3; i++) {
  658. if (!(p = fgets(buf, sizeof(buf) - 1, fp)))
  659. break;
  660. }
  661. fclose(fp);
  662. if (i < 2 || !p)
  663. return UNKNOWN_STR;
  664. if ((datastart = strstr(buf, iface)) == NULL)
  665. return UNKNOWN_STR;
  666. datastart = (datastart+(strlen(iface)+1));
  667. sscanf(datastart + 1, " %*d %d %*d %*d %*d %*d %*d %*d %*d %*d", &perc);
  668. return bprintf("%d", perc);
  669. }
  670. static const char *
  671. wifi_essid(const char *iface)
  672. {
  673. static char id[IW_ESSID_MAX_SIZE+1];
  674. int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
  675. struct iwreq wreq;
  676. memset(&wreq, 0, sizeof(struct iwreq));
  677. wreq.u.essid.length = IW_ESSID_MAX_SIZE+1;
  678. snprintf(wreq.ifr_name, sizeof(wreq.ifr_name), "%s", iface);
  679. if (sockfd == -1) {
  680. warn("Failed to get ESSID for interface %s", iface);
  681. return UNKNOWN_STR;
  682. }
  683. wreq.u.essid.pointer = id;
  684. if (ioctl(sockfd,SIOCGIWESSID, &wreq) == -1) {
  685. warn("Failed to get ESSID for interface %s", iface);
  686. return UNKNOWN_STR;
  687. }
  688. close(sockfd);
  689. if (strcmp(id, "") == 0)
  690. return UNKNOWN_STR;
  691. else
  692. return id;
  693. }
  694. static void
  695. sighandler(const int signo)
  696. {
  697. if (signo == SIGTERM || signo == SIGINT) {
  698. done = 1;
  699. }
  700. }
  701. static void
  702. usage(void)
  703. {
  704. fprintf(stderr, "usage: %s [-s]\n", argv0);
  705. exit(1);
  706. }
  707. int
  708. main(int argc, char *argv[])
  709. {
  710. struct arg argument;
  711. struct sigaction act;
  712. size_t i, len;
  713. int sflag = 0;
  714. char status_string[MAXLEN];
  715. char *element;
  716. ARGBEGIN {
  717. case 's':
  718. sflag = 1;
  719. break;
  720. default:
  721. usage();
  722. } ARGEND
  723. if (argc) {
  724. usage();
  725. }
  726. memset(&act, 0, sizeof(act));
  727. act.sa_handler = sighandler;
  728. sigaction(SIGINT, &act, 0);
  729. sigaction(SIGTERM, &act, 0);
  730. if (!sflag) {
  731. dpy = XOpenDisplay(NULL);
  732. }
  733. setlocale(LC_ALL, "");
  734. while (!done) {
  735. status_string[0] = '\0';
  736. for (element = status_string, i = len = 0;
  737. i < sizeof(args) / sizeof(args[0]);
  738. ++i, element += len) {
  739. argument = args[i];
  740. len = snprintf(element, sizeof(status_string)-1 - len,
  741. argument.fmt,
  742. argument.func(argument.args));
  743. if (len >= sizeof(status_string)) {
  744. status_string[sizeof(status_string)-1] = '\0';
  745. break;
  746. }
  747. }
  748. if (sflag) {
  749. printf("%s\n", status_string);
  750. } else {
  751. XStoreName(dpy, DefaultRootWindow(dpy), status_string);
  752. XSync(dpy, False);
  753. }
  754. if ((UPDATE_INTERVAL - delay) <= 0) {
  755. delay = 0;
  756. continue;
  757. } else {
  758. sleep(UPDATE_INTERVAL - delay);
  759. delay = 0;
  760. }
  761. }
  762. if (!sflag) {
  763. XStoreName(dpy, DefaultRootWindow(dpy), NULL);
  764. XCloseDisplay(dpy);
  765. }
  766. return 0;
  767. }