My slstatus configuration
Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.
 
 
 
 

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