My slstatus configuration
Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

pirms 8 gadiem
pirms 8 gadiem
pirms 8 gadiem
pirms 8 gadiem
pirms 8 gadiem
pirms 8 gadiem
pirms 8 gadiem
pirms 8 gadiem
pirms 8 gadiem
pirms 8 gadiem
pirms 8 gadiem
pirms 8 gadiem
pirms 8 gadiem
pirms 8 gadiem
pirms 8 gadiem
pirms 8 gadiem
pirms 8 gadiem
pirms 8 gadiem
pirms 8 gadiem
pirms 8 gadiem
pirms 8 gadiem
pirms 8 gadiem
pirms 8 gadiem
pirms 8 gadiem
pirms 8 gadiem
pirms 8 gadiem
pirms 8 gadiem
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643
  1. /* See LICENSE file for copyright and license details. */
  2. #include <alsa/asoundlib.h>
  3. #include <arpa/inet.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 <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/sysinfo.h>
  20. #include <sys/types.h>
  21. #include <time.h>
  22. #include <unistd.h>
  23. #include <X11/Xlib.h>
  24. #undef strlcat
  25. #undef strlcpy
  26. #include "strlcat.h"
  27. #include "strlcpy.h"
  28. typedef char *(*op_fun)();
  29. struct arg {
  30. op_fun func;
  31. const char *format;
  32. const char *args;
  33. };
  34. static void setstatus(const char *);
  35. static char *smprintf(const char *, ...);
  36. static char *battery_perc(const char *);
  37. static char *cpu_perc(void);
  38. static char *datetime(const char *);
  39. static char *disk_free(const char *);
  40. static char *disk_perc(const char *);
  41. static char *disk_total(const char *);
  42. static char *disk_used(const char *);
  43. static char *entropy(void);
  44. static char *gid(void);
  45. static char *hostname(void);
  46. static char *ip(const char *);
  47. static char *load_avg(void);
  48. static char *ram_free(void);
  49. static char *ram_perc(void);
  50. static char *ram_used(void);
  51. static char *ram_total(void);
  52. static char *run_command(const char *);
  53. static char *temp(const char *);
  54. static char *uid(void);
  55. static char *uptime(void);
  56. static char *username(void);
  57. static char *vol_perc(const char *);
  58. static char *wifi_perc(const char *);
  59. static char *wifi_essid(const char *);
  60. static Display *dpy;
  61. #include "config.h"
  62. static void
  63. setstatus(const char *str)
  64. {
  65. /* set WM_NAME via X11 */
  66. XStoreName(dpy, DefaultRootWindow(dpy), str);
  67. XSync(dpy, False);
  68. }
  69. static char *
  70. smprintf(const char *fmt, ...)
  71. {
  72. va_list fmtargs;
  73. char *ret = NULL;
  74. va_start(fmtargs, fmt);
  75. if (vasprintf(&ret, fmt, fmtargs) < 0)
  76. return NULL;
  77. va_end(fmtargs);
  78. return ret;
  79. }
  80. static char *
  81. battery_perc(const char *battery)
  82. {
  83. int now, full, perc;
  84. char batterynowfile[64] = "";
  85. char batteryfullfile[64] = "";
  86. FILE *fp;
  87. strlcat(batterynowfile, batterypath, sizeof(batterynowfile));
  88. strlcat(batterynowfile, battery, sizeof(batterynowfile));
  89. strlcat(batterynowfile, "/", sizeof(batterynowfile));
  90. strlcat(batterynowfile, batterynow, sizeof(batterynowfile));
  91. strlcat(batteryfullfile, batterypath, sizeof(batteryfullfile));
  92. strlcat(batteryfullfile, battery, sizeof(batteryfullfile));
  93. strlcat(batteryfullfile, "/", sizeof(batteryfullfile));
  94. strlcat(batteryfullfile, batteryfull, sizeof(batteryfullfile));
  95. if (!(fp = fopen(batterynowfile, "r"))) {
  96. fprintf(stderr, "Error opening battery file: %s.\n", batterynowfile);
  97. return smprintf(unknowntext);
  98. }
  99. fscanf(fp, "%i", &now);
  100. fclose(fp);
  101. if (!(fp = fopen(batteryfullfile, "r"))) {
  102. fprintf(stderr, "Error opening battery file.\n");
  103. return smprintf(unknowntext);
  104. }
  105. fscanf(fp, "%i", &full);
  106. fclose(fp);
  107. perc = now / (full / 100);
  108. return smprintf("%d%%", perc);
  109. }
  110. static char *
  111. cpu_perc(void)
  112. {
  113. int perc;
  114. long double a[4], b[4];
  115. FILE *fp;
  116. if (!(fp = fopen("/proc/stat","r"))) {
  117. fprintf(stderr, "Error opening stat file.\n");
  118. return smprintf(unknowntext);
  119. }
  120. fscanf(fp, "%*s %Lf %Lf %Lf %Lf", &a[0], &a[1], &a[2], &a[3]);
  121. fclose(fp);
  122. /* wait a second (for avg values) */
  123. sleep(1);
  124. if (!(fp = fopen("/proc/stat","r"))) {
  125. fprintf(stderr, "Error opening stat file.\n");
  126. return smprintf(unknowntext);
  127. }
  128. fscanf(fp, "%*s %Lf %Lf %Lf %Lf", &b[0], &b[1], &b[2], &b[3]);
  129. fclose(fp);
  130. 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]));
  131. return smprintf("%d%%", perc);
  132. }
  133. static char *
  134. datetime(const char *timeformat)
  135. {
  136. time_t tm;
  137. size_t bufsize = 64;
  138. char *buf = malloc(bufsize);
  139. if (buf == NULL) {
  140. fprintf(stderr, "Failed to get date/time.\n");
  141. return smprintf(unknowntext);
  142. }
  143. time(&tm);
  144. setlocale(LC_TIME, "");
  145. if (!strftime(buf, bufsize, timeformat, localtime(&tm))) {
  146. setlocale(LC_TIME, "C");
  147. free(buf);
  148. fprintf(stderr, "Strftime failed.\n");
  149. return smprintf(unknowntext);
  150. }
  151. setlocale(LC_TIME, "C");
  152. char *ret = smprintf("%s", buf);
  153. free(buf);
  154. return ret;
  155. }
  156. static char *
  157. disk_free(const char *mountpoint)
  158. {
  159. struct statvfs fs;
  160. if (statvfs(mountpoint, &fs) < 0) {
  161. fprintf(stderr, "Could not get filesystem info.\n");
  162. return smprintf(unknowntext);
  163. }
  164. return smprintf("%f", (float)fs.f_bsize * (float)fs.f_bfree / 1024 / 1024 / 1024);
  165. }
  166. static char *
  167. disk_perc(const char *mountpoint)
  168. {
  169. int perc = 0;
  170. struct statvfs fs;
  171. if (statvfs(mountpoint, &fs) < 0) {
  172. fprintf(stderr, "Could not get filesystem info.\n");
  173. return smprintf(unknowntext);
  174. }
  175. perc = 100 * (1.0f - ((float)fs.f_bfree / (float)fs.f_blocks));
  176. return smprintf("%d%%", perc);
  177. }
  178. static char *
  179. disk_total(const char *mountpoint)
  180. {
  181. struct statvfs fs;
  182. if (statvfs(mountpoint, &fs) < 0) {
  183. fprintf(stderr, "Could not get filesystem info.\n");
  184. return smprintf(unknowntext);
  185. }
  186. return smprintf("%f", (float)fs.f_bsize * (float)fs.f_blocks / 1024 / 1024 / 1024);
  187. }
  188. static char *
  189. disk_used(const char *mountpoint)
  190. {
  191. struct statvfs fs;
  192. if (statvfs(mountpoint, &fs) < 0) {
  193. fprintf(stderr, "Could not get filesystem info.\n");
  194. return smprintf(unknowntext);
  195. }
  196. return smprintf("%f", (float)fs.f_bsize * ((float)fs.f_blocks - (float)fs.f_bfree) / 1024 / 1024 / 1024);
  197. }
  198. static char *
  199. entropy(void)
  200. {
  201. int entropy = 0;
  202. FILE *fp;
  203. if (!(fp = fopen("/proc/sys/kernel/random/entropy_avail", "r"))) {
  204. fprintf(stderr, "Could not open entropy file.\n");
  205. return smprintf(unknowntext);
  206. }
  207. fscanf(fp, "%d", &entropy);
  208. fclose(fp);
  209. return smprintf("%d", entropy);
  210. }
  211. static char *
  212. gid(void)
  213. {
  214. gid_t gid = getgid();
  215. return smprintf("%d", gid);
  216. }
  217. static char *
  218. hostname(void)
  219. {
  220. char hostname[HOST_NAME_MAX];
  221. FILE *fp;
  222. if (!(fp = fopen("/proc/sys/kernel/hostname", "r"))) {
  223. fprintf(stderr, "Could not open hostname file.\n");
  224. return smprintf(unknowntext);
  225. }
  226. fscanf(fp, "%s\n", hostname);
  227. fclose(fp);
  228. return smprintf("%s", hostname);
  229. }
  230. static char *
  231. ip(const char *interface)
  232. {
  233. struct ifaddrs *ifaddr, *ifa;
  234. int s;
  235. char host[NI_MAXHOST];
  236. if (getifaddrs(&ifaddr) == -1) {
  237. fprintf(stderr, "Error getting IP address.\n");
  238. return smprintf(unknowntext);
  239. }
  240. /* get the ip address */
  241. for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
  242. if (ifa->ifa_addr == NULL)
  243. continue;
  244. s = getnameinfo(ifa->ifa_addr, sizeof(struct sockaddr_in), host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST);
  245. if ((strcmp(ifa->ifa_name, interface) == 0) && (ifa->ifa_addr->sa_family == AF_INET)) {
  246. if (s != 0) {
  247. fprintf(stderr, "Error getting IP address.\n");
  248. return smprintf(unknowntext);
  249. }
  250. return smprintf("%s", host);
  251. }
  252. }
  253. /* free the address */
  254. freeifaddrs(ifaddr);
  255. return smprintf(unknowntext);
  256. }
  257. static char *
  258. load_avg(void)
  259. {
  260. double avgs[3];
  261. if (getloadavg(avgs, 3) < 0) {
  262. fprintf(stderr, "Error getting load avg.\n");
  263. return smprintf(unknowntext);
  264. }
  265. return smprintf("%.2f %.2f %.2f", avgs[0], avgs[1], avgs[2]);
  266. }
  267. static char *
  268. ram_free(void)
  269. {
  270. long free;
  271. FILE *fp;
  272. if (!(fp = fopen("/proc/meminfo", "r"))) {
  273. fprintf(stderr, "Error opening meminfo file.\n");
  274. return smprintf(unknowntext);
  275. }
  276. fscanf(fp, "MemFree: %ld kB\n", &free);
  277. fclose(fp);
  278. return smprintf("%f", (float)free / 1024 / 1024);
  279. }
  280. static char *
  281. ram_perc(void)
  282. {
  283. int perc;
  284. long total, free, buffers, cached;
  285. FILE *fp;
  286. if (!(fp = fopen("/proc/meminfo", "r"))) {
  287. fprintf(stderr, "Error opening meminfo file.\n");
  288. return smprintf(unknowntext);
  289. }
  290. fscanf(fp, "MemTotal: %ld kB\n", &total);
  291. fscanf(fp, "MemFree: %ld kB\n", &free);
  292. fscanf(fp, "MemAvailable: %ld kB\nBuffers: %ld kB\n", &buffers, &buffers);
  293. fscanf(fp, "Cached: %ld kB\n", &cached);
  294. fclose(fp);
  295. perc = 100 * ((total - free) - (buffers + cached)) / total;
  296. return smprintf("%d%%", perc);
  297. }
  298. static char *
  299. ram_total(void)
  300. {
  301. long total;
  302. FILE *fp;
  303. if (!(fp = fopen("/proc/meminfo", "r"))) {
  304. fprintf(stderr, "Error opening meminfo file.\n");
  305. return smprintf(unknowntext);
  306. }
  307. fscanf(fp, "MemTotal: %ld kB\n", &total);
  308. fclose(fp);
  309. return smprintf("%f", (float)total / 1024 / 1024);
  310. }
  311. static char *
  312. ram_used(void)
  313. {
  314. long free, total, buffers, cached, used;
  315. FILE *fp;
  316. if (!(fp = fopen("/proc/meminfo", "r"))) {
  317. fprintf(stderr, "Error opening meminfo file.\n");
  318. return smprintf(unknowntext);
  319. }
  320. fscanf(fp, "MemTotal: %ld kB\n", &total);
  321. fscanf(fp, "MemFree: %ld kB\n", &free);
  322. fscanf(fp, "MemAvailable: %ld kB\nBuffers: %ld kB\n", &buffers, &buffers);
  323. fscanf(fp, "Cached: %ld kB\n", &cached);
  324. fclose(fp);
  325. used = total - free - buffers - cached;
  326. return smprintf("%f", (float)used / 1024 / 1024);
  327. }
  328. static char *
  329. run_command(const char* command)
  330. {
  331. int good;
  332. FILE *fp;
  333. char buffer[64];
  334. if (!(fp = popen(command, "r"))) {
  335. fprintf(stderr, "Could not get command output for: %s.\n", command);
  336. return smprintf(unknowntext);
  337. }
  338. fgets(buffer, sizeof(buffer) - 1, fp);
  339. pclose(fp);
  340. for (int i = 0 ; i != sizeof(buffer); i++) {
  341. if (buffer[i] == '\0') {
  342. good = 1;
  343. break;
  344. }
  345. }
  346. if (good)
  347. buffer[strlen(buffer) - 1] = '\0';
  348. return smprintf("%s", buffer);
  349. }
  350. static char *
  351. temp(const char *file)
  352. {
  353. int temperature;
  354. FILE *fp;
  355. if (!(fp = fopen(file, "r"))) {
  356. fprintf(stderr, "Could not open temperature file.\n");
  357. return smprintf(unknowntext);
  358. }
  359. fscanf(fp, "%d", &temperature);
  360. fclose(fp);
  361. return smprintf("%d°C", temperature / 1000);
  362. }
  363. static char *
  364. uptime(void)
  365. {
  366. struct sysinfo info;
  367. int hours = 0;
  368. int minutes = 0;
  369. sysinfo(&info);
  370. hours = info.uptime / 3600;
  371. minutes = (info.uptime - hours * 3600 ) / 60;
  372. return smprintf("%dh %dm", hours, minutes);
  373. }
  374. static char *
  375. username(void)
  376. {
  377. register struct passwd *pw;
  378. register uid_t uid;
  379. uid = geteuid();
  380. pw = getpwuid(uid);
  381. if (pw)
  382. return smprintf("%s", pw->pw_name);
  383. else {
  384. fprintf(stderr, "Could not get username.\n");
  385. return smprintf(unknowntext);
  386. }
  387. return smprintf(unknowntext);
  388. }
  389. static char *
  390. uid(void)
  391. {
  392. register uid_t uid;
  393. uid = geteuid();
  394. if (uid)
  395. return smprintf("%d", uid);
  396. else {
  397. fprintf(stderr, "Could not get uid.\n");
  398. return smprintf(unknowntext);
  399. }
  400. return smprintf(unknowntext);
  401. }
  402. static char *
  403. vol_perc(const char *soundcard)
  404. {
  405. int mute = 0;
  406. long vol = 0, max = 0, min = 0;
  407. snd_mixer_t *handle;
  408. snd_mixer_elem_t *pcm_mixer, *mas_mixer;
  409. snd_mixer_selem_id_t *vol_info, *mute_info;
  410. snd_mixer_open(&handle, 0);
  411. snd_mixer_attach(handle, soundcard);
  412. snd_mixer_selem_register(handle, NULL, NULL);
  413. snd_mixer_load(handle);
  414. snd_mixer_selem_id_malloc(&vol_info);
  415. snd_mixer_selem_id_malloc(&mute_info);
  416. if (vol_info == NULL || mute_info == NULL) {
  417. fprintf(stderr, "Could not get alsa volume.\n");
  418. return smprintf(unknowntext);
  419. }
  420. snd_mixer_selem_id_set_name(vol_info, channel);
  421. snd_mixer_selem_id_set_name(mute_info, channel);
  422. pcm_mixer = snd_mixer_find_selem(handle, vol_info);
  423. mas_mixer = snd_mixer_find_selem(handle, mute_info);
  424. snd_mixer_selem_get_playback_volume_range(pcm_mixer, &min, &max);
  425. snd_mixer_selem_get_playback_volume(pcm_mixer, SND_MIXER_SCHN_MONO, &vol);
  426. snd_mixer_selem_get_playback_switch(mas_mixer, SND_MIXER_SCHN_MONO, &mute);
  427. if (vol_info)
  428. snd_mixer_selem_id_free(vol_info);
  429. if (mute_info)
  430. snd_mixer_selem_id_free(mute_info);
  431. if (handle)
  432. snd_mixer_close(handle);
  433. if (!mute)
  434. return smprintf("mute");
  435. else
  436. return smprintf("%d%%", (vol * 100) / max);
  437. }
  438. static char *
  439. wifi_perc(const char *wificard)
  440. {
  441. int bufsize = 255;
  442. int strength;
  443. char buf[bufsize];
  444. char *datastart;
  445. char path[64];
  446. char status[5];
  447. char needle[sizeof wificard + 1];
  448. FILE *fp;
  449. memset(path, 0, sizeof path);
  450. strlcat(path, "/sys/class/net/", sizeof(path));
  451. strlcat(path, wificard, sizeof(path));
  452. strlcat(path, "/operstate", sizeof(path));
  453. if(!(fp = fopen(path, "r"))) {
  454. fprintf(stderr, "Error opening wifi operstate file.\n");
  455. return smprintf(unknowntext);
  456. }
  457. fgets(status, 5, fp);
  458. fclose(fp);
  459. if(strcmp(status, "up\n") != 0)
  460. return smprintf(unknowntext);
  461. if (!(fp = fopen("/proc/net/wireless", "r"))) {
  462. fprintf(stderr, "Error opening wireless file.\n");
  463. return smprintf(unknowntext);
  464. }
  465. strlcpy(needle, wificard, sizeof(needle));
  466. strlcat(needle, ":", sizeof(needle));
  467. fgets(buf, bufsize, fp);
  468. fgets(buf, bufsize, fp);
  469. fgets(buf, bufsize, fp);
  470. if ((datastart = strstr(buf, needle)) != NULL) {
  471. datastart = strstr(buf, ":");
  472. sscanf(datastart + 1, " %*d %d %*d %*d %*d %*d %*d %*d %*d %*d", &strength);
  473. }
  474. fclose(fp);
  475. return smprintf("%d%%", strength);
  476. }
  477. static char *
  478. wifi_essid(const char *wificard)
  479. {
  480. char id[IW_ESSID_MAX_SIZE+1];
  481. int sockfd;
  482. struct iwreq wreq;
  483. memset(&wreq, 0, sizeof(struct iwreq));
  484. wreq.u.essid.length = IW_ESSID_MAX_SIZE+1;
  485. sprintf(wreq.ifr_name, wificard);
  486. if((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
  487. fprintf(stderr, "Cannot open socket for interface: %s\n", wificard);
  488. return smprintf(unknowntext);
  489. }
  490. wreq.u.essid.pointer = id;
  491. if (ioctl(sockfd,SIOCGIWESSID, &wreq) == -1) {
  492. fprintf(stderr, "Get ESSID ioctl failed for interface %s\n", wificard);
  493. return smprintf(unknowntext);
  494. }
  495. if (strcmp((char *)wreq.u.essid.pointer, "") == 0)
  496. return smprintf(unknowntext);
  497. else
  498. return smprintf("%s", (char *)wreq.u.essid.pointer);
  499. }
  500. int
  501. main(void)
  502. {
  503. size_t i;
  504. char status_string[4096];
  505. char *res, *element;
  506. struct arg argument;
  507. if (!(dpy = XOpenDisplay(0x0))) {
  508. fprintf(stderr, "Cannot open display!\n");
  509. exit(1);
  510. }
  511. for (;;) {
  512. memset(status_string, 0, sizeof(status_string));
  513. for (i = 0; i < sizeof(args) / sizeof(args[0]); ++i) {
  514. argument = args[i];
  515. if (argument.args == NULL)
  516. res = argument.func();
  517. else
  518. res = argument.func(argument.args);
  519. element = smprintf(argument.format, res);
  520. if (element == NULL) {
  521. element = smprintf(unknowntext);
  522. fprintf(stderr, "Failed to format output.\n");
  523. }
  524. strlcat(status_string, element, sizeof(status_string));
  525. free(res);
  526. free(element);
  527. }
  528. setstatus(status_string);
  529. sleep(update_interval -1);
  530. }
  531. XCloseDisplay(dpy);
  532. return 0;
  533. }