My slstatus configuration
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

912 line
18 KiB

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