slstatus.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814
  1. /* See LICENSE file for copyright and license details. */
  2. /* global libraries */
  3. #include <alsa/asoundlib.h>
  4. #include <arpa/inet.h>
  5. #include <fcntl.h>
  6. #include <ifaddrs.h>
  7. #include <limits.h>
  8. #include <linux/wireless.h>
  9. #include <locale.h>
  10. #include <netdb.h>
  11. #include <pwd.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/sysinfo.h>
  21. #include <sys/types.h>
  22. #include <time.h>
  23. #include <unistd.h>
  24. #include <X11/Xlib.h>
  25. /* statusbar configuration type and struct */
  26. typedef char *(*op_fun) (const char *);
  27. struct arg {
  28. op_fun func;
  29. const char *format;
  30. const char *args;
  31. };
  32. /* function declarations */
  33. void setstatus(const char *str);
  34. char *smprintf(const char *fmt, ...);
  35. char *battery_perc(const char *battery);
  36. char *cpu_perc(const char *null);
  37. char *datetime(const char *timeformat);
  38. char *disk_free(const char *mountpoint);
  39. char *disk_perc(const char *mountpoint);
  40. char *disk_total(const char *mountpoint);
  41. char *disk_used(const char *mountpoint);
  42. char *entropy(const char *null);
  43. char *gid(const char *null);
  44. char *hostname(const char *null);
  45. char *ip(const char *interface);
  46. char *load_avg(const char *null);
  47. char *ram_free(const char *null);
  48. char *ram_perc(const char *null);
  49. char *ram_used(const char *null);
  50. char *ram_total(const char *null);
  51. char *run_command(const char *command);
  52. char *temp(const char *file);
  53. char *uid(const char *null);
  54. char *uptime(const char *null);
  55. char *username(const char *null);
  56. char *vol_perc(const char *soundcard);
  57. char *wifi_perc(const char *wificard);
  58. char *wifi_essid(const char *wificard);
  59. /* global variables */
  60. static Display *dpy;
  61. /* configuration header */
  62. #include "config.h"
  63. /* set statusbar */
  64. void
  65. setstatus(const char *str)
  66. {
  67. /* set WM_NAME via X11 */
  68. XStoreName(dpy, DefaultRootWindow(dpy), str);
  69. XSync(dpy, False);
  70. }
  71. /* smprintf function */
  72. char *
  73. smprintf(const char *fmt, ...)
  74. {
  75. va_list fmtargs;
  76. char *ret = NULL;
  77. va_start(fmtargs, fmt);
  78. if (vasprintf(&ret, fmt, fmtargs) < 0) {
  79. return NULL;
  80. }
  81. va_end(fmtargs);
  82. return ret;
  83. }
  84. /* battery percentage */
  85. char *
  86. battery_perc(const char *battery)
  87. {
  88. int now, full, perc;
  89. char batterynowfile[64] = "";
  90. char batteryfullfile[64] = "";
  91. FILE *fp;
  92. /* generate battery nowfile path */
  93. strcat(batterynowfile, batterypath);
  94. strcat(batterynowfile, battery);
  95. strcat(batterynowfile, "/");
  96. strcat(batterynowfile, batterynow);
  97. /* generate battery fullfile path */
  98. strcat(batteryfullfile, batterypath);
  99. strcat(batteryfullfile, battery);
  100. strcat(batteryfullfile, "/");
  101. strcat(batteryfullfile, batteryfull);
  102. /* open battery now file */
  103. if (!(fp = fopen(batterynowfile, "r"))) {
  104. fprintf(stderr, "Error opening battery file: %s.\n", batterynowfile);
  105. return smprintf(unknowntext);
  106. }
  107. /* read value */
  108. fscanf(fp, "%i", &now);
  109. /* close battery now file */
  110. fclose(fp);
  111. /* open battery full file */
  112. if (!(fp = fopen(batteryfullfile, "r"))) {
  113. fprintf(stderr, "Error opening battery file.\n");
  114. return smprintf(unknowntext);
  115. }
  116. /* read value */
  117. fscanf(fp, "%i", &full);
  118. /* close battery full file */
  119. fclose(fp);
  120. /* calculate percent */
  121. perc = now / (full / 100);
  122. /* return perc as string */
  123. return smprintf("%d%%", perc);
  124. }
  125. /* cpu percentage */
  126. char *
  127. cpu_perc(const char *null)
  128. {
  129. int perc;
  130. long double a[4], b[4];
  131. FILE *fp;
  132. /* open stat file */
  133. if (!(fp = fopen("/proc/stat","r"))) {
  134. fprintf(stderr, "Error opening stat file.\n");
  135. return smprintf(unknowntext);
  136. }
  137. /* read values */
  138. fscanf(fp, "%*s %Lf %Lf %Lf %Lf", &a[0], &a[1], &a[2], &a[3]);
  139. /* close stat file */
  140. fclose(fp);
  141. /* wait a second (for avg values) */
  142. sleep(1);
  143. /* open stat file */
  144. if (!(fp = fopen("/proc/stat","r"))) {
  145. fprintf(stderr, "Error opening stat file.\n");
  146. return smprintf(unknowntext);
  147. }
  148. /* read values */
  149. fscanf(fp, "%*s %Lf %Lf %Lf %Lf", &b[0], &b[1], &b[2], &b[3]);
  150. /* close stat file */
  151. fclose(fp);
  152. /* calculate avg in this second */
  153. 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]));
  154. /* return perc as string */
  155. return smprintf("%d%%", perc);
  156. }
  157. /* date and time */
  158. char *
  159. datetime(const char *timeformat)
  160. {
  161. time_t tm;
  162. size_t bufsize = 64;
  163. char *buf = malloc(bufsize);
  164. if (buf == NULL) {
  165. fprintf(stderr, "Failed to get date/time.\n");
  166. return smprintf(unknowntext);
  167. }
  168. /* get time in format */
  169. time(&tm);
  170. setlocale(LC_TIME, "");
  171. if (!strftime(buf, bufsize, timeformat, localtime(&tm))) {
  172. setlocale(LC_TIME, "C");
  173. free(buf);
  174. fprintf(stderr, "Strftime failed.\n");
  175. return smprintf(unknowntext);
  176. }
  177. setlocale(LC_TIME, "C");
  178. /* return time */
  179. char *ret = smprintf("%s", buf);
  180. free(buf);
  181. return ret;
  182. }
  183. /* disk free */
  184. char *
  185. disk_free(const char *mountpoint)
  186. {
  187. struct statvfs fs;
  188. /* try to open mountpoint */
  189. if (statvfs(mountpoint, &fs) < 0) {
  190. fprintf(stderr, "Could not get filesystem info.\n");
  191. return smprintf(unknowntext);
  192. }
  193. /* return free */
  194. return smprintf("%f", (float)fs.f_bsize * (float)fs.f_bfree / 1024 / 1024 / 1024);
  195. }
  196. /* disk usage percentage */
  197. char *
  198. disk_perc(const char *mountpoint)
  199. {
  200. int perc = 0;
  201. struct statvfs fs;
  202. /* try to open mountpoint */
  203. if (statvfs(mountpoint, &fs) < 0) {
  204. fprintf(stderr, "Could not get filesystem info.\n");
  205. return smprintf(unknowntext);
  206. }
  207. /* calculate percent */
  208. perc = 100 * (1.0f - ((float)fs.f_bfree / (float)fs.f_blocks));
  209. /* return perc */
  210. return smprintf("%d%%", perc);
  211. }
  212. /* disk total */
  213. char *
  214. disk_total(const char *mountpoint)
  215. {
  216. struct statvfs fs;
  217. /* try to open mountpoint */
  218. if (statvfs(mountpoint, &fs) < 0) {
  219. fprintf(stderr, "Could not get filesystem info.\n");
  220. return smprintf(unknowntext);
  221. }
  222. /* return total */
  223. return smprintf("%f", (float)fs.f_bsize * (float)fs.f_blocks / 1024 / 1024 / 1024);
  224. }
  225. /* disk used */
  226. char *
  227. disk_used(const char *mountpoint)
  228. {
  229. struct statvfs fs;
  230. /* try to open mountpoint */
  231. if (statvfs(mountpoint, &fs) < 0) {
  232. fprintf(stderr, "Could not get filesystem info.\n");
  233. return smprintf(unknowntext);
  234. }
  235. /* return used */
  236. return smprintf("%f", (float)fs.f_bsize * ((float)fs.f_blocks - (float)fs.f_bfree) / 1024 / 1024 / 1024);
  237. }
  238. /* entropy available */
  239. char *
  240. entropy(const char *null)
  241. {
  242. int entropy = 0;
  243. FILE *fp;
  244. /* open entropy file */
  245. if (!(fp = fopen("/proc/sys/kernel/random/entropy_avail", "r"))) {
  246. fprintf(stderr, "Could not open entropy file.\n");
  247. return smprintf(unknowntext);
  248. }
  249. /* extract entropy */
  250. fscanf(fp, "%d", &entropy);
  251. /* close entropy file */
  252. fclose(fp);
  253. /* return entropy */
  254. return smprintf("%d", entropy);
  255. }
  256. /* gid */
  257. char *
  258. gid(const char *null)
  259. {
  260. gid_t gid;
  261. if ((gid = getgid()) < 0) {
  262. fprintf(stderr, "Could no get gid.\n");
  263. return smprintf(unknowntext);
  264. } else {
  265. return smprintf("%d", gid);
  266. }
  267. return smprintf(unknowntext);
  268. }
  269. /* hostname */
  270. char *
  271. hostname(const char *null)
  272. {
  273. char hostname[HOST_NAME_MAX];
  274. FILE *fp;
  275. /* open hostname file */
  276. if (!(fp = fopen("/proc/sys/kernel/hostname", "r"))) {
  277. fprintf(stderr, "Could not open hostname file.\n");
  278. return smprintf(unknowntext);
  279. }
  280. /* extract hostname */
  281. fscanf(fp, "%s\n", hostname);
  282. /* close hostname file */
  283. fclose(fp);
  284. /* return entropy */
  285. return smprintf("%s", hostname);
  286. }
  287. /* ip address */
  288. char *
  289. ip(const char *interface)
  290. {
  291. struct ifaddrs *ifaddr, *ifa;
  292. int s;
  293. char host[NI_MAXHOST];
  294. /* check if getting ip address works */
  295. if (getifaddrs(&ifaddr) == -1) {
  296. fprintf(stderr, "Error getting IP address.\n");
  297. return smprintf(unknowntext);
  298. }
  299. /* get the ip address */
  300. for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
  301. if (ifa->ifa_addr == NULL) {
  302. continue;
  303. }
  304. s = getnameinfo(ifa->ifa_addr, sizeof(struct sockaddr_in), host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST);
  305. if ((strcmp(ifa->ifa_name, interface) == 0) && (ifa->ifa_addr->sa_family == AF_INET)) {
  306. if (s != 0) {
  307. fprintf(stderr, "Error getting IP address.\n");
  308. return smprintf(unknowntext);
  309. }
  310. return smprintf("%s", host);
  311. }
  312. }
  313. /* free the address */
  314. freeifaddrs(ifaddr);
  315. return smprintf(unknowntext);
  316. }
  317. /* load avg */
  318. char *
  319. load_avg(const char *null)
  320. {
  321. double avgs[3];
  322. /* try to get load avg */
  323. if (getloadavg(avgs, 3) < 0) {
  324. fprintf(stderr, "Error getting load avg.\n");
  325. return smprintf(unknowntext);
  326. }
  327. /* return it */
  328. return smprintf("%.2f %.2f %.2f", avgs[0], avgs[1], avgs[2]);
  329. }
  330. /* ram free */
  331. char *
  332. ram_free(const char *null)
  333. {
  334. long free;
  335. FILE *fp;
  336. /* open meminfo file */
  337. if (!(fp = fopen("/proc/meminfo", "r"))) {
  338. fprintf(stderr, "Error opening meminfo file.\n");
  339. return smprintf(unknowntext);
  340. }
  341. /* read the values */
  342. fscanf(fp, "MemFree: %ld kB\n", &free);
  343. /* close meminfo file */
  344. fclose(fp);
  345. /* return free ram as string */
  346. return smprintf("%f", (float)free / 1024 / 1024);
  347. }
  348. /* ram percentage */
  349. char *
  350. ram_perc(const char *null)
  351. {
  352. int perc;
  353. long total, free, buffers, cached;
  354. FILE *fp;
  355. /* open meminfo file */
  356. if (!(fp = fopen("/proc/meminfo", "r"))) {
  357. fprintf(stderr, "Error opening meminfo file.\n");
  358. return smprintf(unknowntext);
  359. }
  360. /* read the values */
  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. /* close meminfo file */
  366. fclose(fp);
  367. /* calculate percentage */
  368. perc = 100 * ((total - free) - (buffers + cached)) / total;
  369. /* return perc as string */
  370. return smprintf("%d%%", perc);
  371. }
  372. /* ram total */
  373. char *
  374. ram_total(const char *null)
  375. {
  376. long total;
  377. FILE *fp;
  378. /* open meminfo file */
  379. if (!(fp = fopen("/proc/meminfo", "r"))) {
  380. fprintf(stderr, "Error opening meminfo file.\n");
  381. return smprintf(unknowntext);
  382. }
  383. /* read the values */
  384. fscanf(fp, "MemTotal: %ld kB\n", &total);
  385. /* close meminfo file */
  386. fclose(fp);
  387. /* return total ram as string */
  388. return smprintf("%f", (float)total / 1024 / 1024);
  389. }
  390. /* ram used */
  391. char *
  392. ram_used(const char *null)
  393. {
  394. long free, total, buffers, cached, used;
  395. FILE *fp;
  396. /* open meminfo file */
  397. if (!(fp = fopen("/proc/meminfo", "r"))) {
  398. fprintf(stderr, "Error opening meminfo file.\n");
  399. return smprintf(unknowntext);
  400. }
  401. /* read the values */
  402. fscanf(fp, "MemTotal: %ld kB\n", &total);
  403. fscanf(fp, "MemFree: %ld kB\n", &free);
  404. fscanf(fp, "MemAvailable: %ld kB\nBuffers: %ld kB\n", &buffers, &buffers);
  405. fscanf(fp, "Cached: %ld kB\n", &cached);
  406. /* close meminfo file */
  407. fclose(fp);
  408. /* calculate used */
  409. used = total - free - buffers - cached;
  410. /* return used ram as string */
  411. return smprintf("%f", (float)used / 1024 / 1024);
  412. }
  413. /* custom shell command */
  414. char *
  415. run_command(const char* command)
  416. {
  417. int good;
  418. FILE *fp;
  419. char buffer[64];
  420. /* try to open the command output */
  421. if (!(fp = popen(command, "r"))) {
  422. fprintf(stderr, "Could not get command output for: %s.\n", command);
  423. return smprintf(unknowntext);
  424. }
  425. /* get command output text, save it to buffer */
  426. fgets(buffer, sizeof(buffer) - 1, fp);
  427. /* close it again */
  428. pclose(fp);
  429. /* add nullchar at the end */
  430. for (int i = 0 ; i != sizeof(buffer); i++) {
  431. if (buffer[i] == '\0') {
  432. good = 1;
  433. break;
  434. }
  435. }
  436. if (good) {
  437. buffer[strlen(buffer) - 1] = '\0';
  438. }
  439. /* return the output */
  440. return smprintf("%s", buffer);
  441. }
  442. /* temperature */
  443. char *
  444. temp(const char *file)
  445. {
  446. int temperature;
  447. FILE *fp;
  448. /* open temperature file */
  449. if (!(fp = fopen(file, "r"))) {
  450. fprintf(stderr, "Could not open temperature file.\n");
  451. return smprintf(unknowntext);
  452. }
  453. /* extract temperature */
  454. fscanf(fp, "%d", &temperature);
  455. /* close temperature file */
  456. fclose(fp);
  457. /* return temperature in degrees */
  458. return smprintf("%d°C", temperature / 1000);
  459. }
  460. /* uptime */
  461. char *
  462. uptime(const char *null)
  463. {
  464. struct sysinfo info;
  465. int hours = 0;
  466. int minutes = 0;
  467. /* get info */
  468. sysinfo(&info);
  469. hours = info.uptime / 3600;
  470. minutes = (info.uptime - hours * 3600 ) / 60;
  471. /* return it */
  472. return smprintf("%dh %dm", hours, minutes);
  473. }
  474. /* username */
  475. char *
  476. username(const char *null)
  477. {
  478. register struct passwd *pw;
  479. register uid_t uid;
  480. /* get the values */
  481. uid = geteuid();
  482. pw = getpwuid(uid);
  483. /* if it worked, return */
  484. if (pw) {
  485. return smprintf("%s", pw->pw_name);
  486. } else {
  487. fprintf(stderr, "Could not get username.\n");
  488. return smprintf(unknowntext);
  489. }
  490. return smprintf(unknowntext);
  491. }
  492. /* uid */
  493. char *
  494. uid(const char *null)
  495. {
  496. register uid_t uid;
  497. /* get the values */
  498. uid = geteuid();
  499. /* if it worked, return */
  500. if (uid) {
  501. return smprintf("%d", uid);
  502. } else {
  503. fprintf(stderr, "Could not get uid.\n");
  504. return smprintf(unknowntext);
  505. }
  506. return smprintf(unknowntext);
  507. }
  508. /* alsa volume percentage */
  509. char *
  510. vol_perc(const char *soundcard)
  511. {
  512. int mute = 0;
  513. long vol = 0, max = 0, min = 0;
  514. snd_mixer_t *handle;
  515. snd_mixer_elem_t *pcm_mixer, *mas_mixer;
  516. snd_mixer_selem_id_t *vol_info, *mute_info;
  517. /* open everything */
  518. snd_mixer_open(&handle, 0);
  519. snd_mixer_attach(handle, soundcard);
  520. snd_mixer_selem_register(handle, NULL, NULL);
  521. snd_mixer_load(handle);
  522. /* prepare everything */
  523. snd_mixer_selem_id_malloc(&vol_info);
  524. snd_mixer_selem_id_malloc(&mute_info);
  525. /* check */
  526. if (vol_info == NULL || mute_info == NULL) {
  527. fprintf(stderr, "Could not get alsa volume.\n");
  528. return smprintf(unknowntext);
  529. }
  530. snd_mixer_selem_id_set_name(vol_info, channel);
  531. snd_mixer_selem_id_set_name(mute_info, channel);
  532. pcm_mixer = snd_mixer_find_selem(handle, vol_info);
  533. mas_mixer = snd_mixer_find_selem(handle, mute_info);
  534. /* get the info */
  535. snd_mixer_selem_get_playback_volume_range((snd_mixer_elem_t *)pcm_mixer, &min, &max);
  536. snd_mixer_selem_get_playback_volume((snd_mixer_elem_t *)pcm_mixer, SND_MIXER_SCHN_MONO, &vol);
  537. snd_mixer_selem_get_playback_switch(mas_mixer, SND_MIXER_SCHN_MONO, &mute);
  538. /* clean up */
  539. if (vol_info) {
  540. snd_mixer_selem_id_free(vol_info);
  541. }
  542. if (mute_info) {
  543. snd_mixer_selem_id_free(mute_info);
  544. }
  545. if (handle) {
  546. snd_mixer_close(handle);
  547. }
  548. /* return the string (mute) */
  549. if (!mute) {
  550. return smprintf("mute");
  551. } else {
  552. return smprintf("%d%%", (vol * 100) / max);
  553. }
  554. }
  555. /* wifi percentage */
  556. char *
  557. wifi_perc(const char *wificard)
  558. {
  559. int bufsize = 255;
  560. int strength;
  561. char buf[bufsize];
  562. char *datastart;
  563. char path[64];
  564. char status[5];
  565. char needle[sizeof wificard + 1];
  566. FILE *fp;
  567. /* generate the path name */
  568. memset(path, 0, sizeof path);
  569. strcat(path, "/sys/class/net/");
  570. strcat(path, wificard);
  571. strcat(path, "/operstate");
  572. /* open wifi file */
  573. if(!(fp = fopen(path, "r"))) {
  574. fprintf(stderr, "Error opening wifi operstate file.\n");
  575. return smprintf(unknowntext);
  576. }
  577. /* read the status */
  578. fgets(status, 5, fp);
  579. /* close wifi file */
  580. fclose(fp);
  581. /* check if interface down */
  582. if(strcmp(status, "up\n") != 0) {
  583. return smprintf(unknowntext);
  584. }
  585. /* open wifi file */
  586. if (!(fp = fopen("/proc/net/wireless", "r"))) {
  587. fprintf(stderr, "Error opening wireless file.\n");
  588. return smprintf(unknowntext);
  589. }
  590. /* extract the signal strength */
  591. strcpy(needle, wificard);
  592. strcat(needle, ":");
  593. fgets(buf, bufsize, fp);
  594. fgets(buf, bufsize, fp);
  595. fgets(buf, bufsize, fp);
  596. if ((datastart = strstr(buf, needle)) != NULL) {
  597. datastart = strstr(buf, ":");
  598. sscanf(datastart + 1, " %*d %d %*d %*d %*d %*d %*d %*d %*d %*d", &strength);
  599. }
  600. /* close wifi file */
  601. fclose(fp);
  602. /* return strength in percent */
  603. return smprintf("%d%%", strength);
  604. }
  605. /* wifi essid */
  606. char *
  607. wifi_essid(const char *wificard)
  608. {
  609. char id[IW_ESSID_MAX_SIZE+1];
  610. int sockfd;
  611. struct iwreq wreq;
  612. /* prepare */
  613. memset(&wreq, 0, sizeof(struct iwreq));
  614. wreq.u.essid.length = IW_ESSID_MAX_SIZE+1;
  615. /* set the interface */
  616. sprintf(wreq.ifr_name, wificard);
  617. /* check */
  618. if((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
  619. fprintf(stderr, "Cannot open socket for interface: %s\n", wificard);
  620. return smprintf(unknowntext);
  621. }
  622. wreq.u.essid.pointer = id;
  623. if (ioctl(sockfd,SIOCGIWESSID, &wreq) == -1) {
  624. fprintf(stderr, "Get ESSID ioctl failed for interface %s\n", wificard);
  625. return smprintf(unknowntext);
  626. }
  627. /* return the essid */
  628. if (strcmp((char *)wreq.u.essid.pointer, "") == 0) {
  629. return smprintf(unknowntext);
  630. } else {
  631. return smprintf("%s", (char *)wreq.u.essid.pointer);
  632. }
  633. }
  634. /* main function */
  635. int
  636. main(void)
  637. {
  638. char status_string[1024];
  639. struct arg argument;
  640. /* try to open display */
  641. if (!(dpy = XOpenDisplay(0x0))) {
  642. fprintf(stderr, "Cannot open display!\n");
  643. exit(1);
  644. }
  645. /* return status every interval */
  646. for (;;) {
  647. /* clear the string */
  648. memset(status_string, 0, sizeof(status_string));
  649. /* generate status_string */
  650. for (size_t i = 0; i < sizeof(args) / sizeof(args[0]); ++i) {
  651. argument = args[i];
  652. char *res = argument.func(argument.args);
  653. char *element = smprintf(argument.format, res);
  654. if (element == NULL) {
  655. element = smprintf(unknowntext);
  656. fprintf(stderr, "Failed to format output.\n");
  657. }
  658. strcat(status_string, element);
  659. free(res);
  660. free(element);
  661. }
  662. /* return the statusbar */
  663. setstatus(status_string);
  664. /* wait, "update_interval - 1" because of get_cpu_usage() which uses 1 second */
  665. sleep(update_interval -1);
  666. }
  667. /* close display */
  668. XCloseDisplay(dpy);
  669. /* exit successfully */
  670. return 0;
  671. }