slstatus.c 17 KB

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