My slstatus configuration
Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.
 
 
 
 

392 rader
8.9 KiB

  1. /* See LICENSE file for copyright and license details. */
  2. /* global libraries */
  3. #include <alsa/asoundlib.h>
  4. #include <fcntl.h>
  5. #include <stdarg.h>
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8. #include <string.h>
  9. #include <sys/types.h>
  10. #include <sys/stat.h>
  11. #include <time.h>
  12. #include <unistd.h>
  13. #include <X11/Xlib.h>
  14. /* local libraries */
  15. #include "config.h"
  16. /* check file macro */
  17. #define CHECK_FILE(X,Y) do { \
  18. if (stat(X,&Y) < 0) return -1; \
  19. if (!S_ISREG(Y.st_mode)) return -1; \
  20. } while (0);
  21. /* functions */
  22. int config_check();
  23. void setstatus(char *str);
  24. char *smprintf(char *fmt, ...);
  25. char *get_battery();
  26. char *get_cpu_temperature();
  27. char *get_cpu_usage();
  28. char *get_datetime();
  29. char *get_ram_usage();
  30. char *get_volume();
  31. char *get_wifi_signal();
  32. /* global variables */
  33. static Display *dpy;
  34. /* check configured paths */
  35. int
  36. config_check()
  37. {
  38. struct stat fs;
  39. /* check all files in the config.h file */
  40. CHECK_FILE(batterynowfile, fs);
  41. CHECK_FILE(batteryfullfile, fs);
  42. CHECK_FILE(tempfile, fs);
  43. /* check update interval */
  44. if (update_interval < 1)
  45. return -1;
  46. /* exit successfully */
  47. return 0;
  48. }
  49. /* set statusbar (WM_NAME) */
  50. void
  51. setstatus(char *str)
  52. {
  53. XStoreName(dpy, DefaultRootWindow(dpy), str);
  54. XSync(dpy, False);
  55. }
  56. /* smprintf function */
  57. char *
  58. smprintf(char *fmt, ...)
  59. {
  60. va_list fmtargs;
  61. char *ret = NULL;
  62. va_start(fmtargs, fmt);
  63. if (vasprintf(&ret, fmt, fmtargs) < 0)
  64. return NULL;
  65. va_end(fmtargs);
  66. return ret;
  67. }
  68. /* battery percentage */
  69. char *
  70. get_battery()
  71. {
  72. int now, full, perc;
  73. FILE *fp;
  74. /* open battery now file */
  75. if (!(fp = fopen(batterynowfile, "r"))) {
  76. fprintf(stderr, "Error opening battery file.");
  77. return smprintf("n/a");
  78. }
  79. /* read value */
  80. fscanf(fp, "%i", &now);
  81. /* close battery now file */
  82. fclose(fp);
  83. /* open battery full file */
  84. if (!(fp = fopen(batteryfullfile, "r"))) {
  85. fprintf(stderr, "Error opening battery file.");
  86. return smprintf("n/a");
  87. }
  88. /* read value */
  89. fscanf(fp, "%i", &full);
  90. /* close battery full file */
  91. fclose(fp);
  92. /* calculate percent */
  93. perc = now / (full / 100);
  94. /* return perc as string */
  95. return smprintf("%d%%", perc);
  96. }
  97. /* cpu temperature */
  98. char *
  99. get_cpu_temperature()
  100. {
  101. int temperature;
  102. FILE *fp;
  103. /* open temperature file */
  104. if (!(fp = fopen(tempfile, "r"))) {
  105. fprintf(stderr, "Could not open temperature file.\n");
  106. return smprintf("n/a");
  107. }
  108. /* extract temperature */
  109. fscanf(fp, "%d", &temperature);
  110. /* close temperature file */
  111. fclose(fp);
  112. /* return temperature in degrees */
  113. return smprintf("%d°C", temperature / 1000);
  114. }
  115. /* cpu percentage */
  116. char *
  117. get_cpu_usage()
  118. {
  119. int perc;
  120. long double a[4], b[4];
  121. FILE *fp;
  122. /* open stat file */
  123. if (!(fp = fopen("/proc/stat","r"))) {
  124. fprintf(stderr, "Error opening stat file.");
  125. return smprintf("n/a");
  126. }
  127. /* read values */
  128. fscanf(fp, "%*s %Lf %Lf %Lf %Lf", &a[0], &a[1], &a[2], &a[3]);
  129. /* close stat file */
  130. fclose(fp);
  131. /* wait a second (for avg values) */
  132. sleep(1);
  133. /* open stat file */
  134. if (!(fp = fopen("/proc/stat","r"))) {
  135. fprintf(stderr, "Error opening stat file.");
  136. return smprintf("n/a");
  137. }
  138. /* read values */
  139. fscanf(fp, "%*s %Lf %Lf %Lf %Lf", &b[0], &b[1], &b[2], &b[3]);
  140. /* close stat file */
  141. fclose(fp);
  142. /* calculate avg in this second */
  143. 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]));
  144. /* return perc as string */
  145. return smprintf("%d%%", perc);
  146. }
  147. /* date and time */
  148. char *
  149. get_datetime()
  150. {
  151. time_t tm;
  152. size_t bufsize = 64;
  153. char *buf = malloc(bufsize);
  154. /* get time in format */
  155. time(&tm);
  156. if(!strftime(buf, bufsize, timeformat, localtime(&tm))) {
  157. fprintf(stderr, "Strftime failed.\n");
  158. return smprintf("n/a");
  159. }
  160. /* return time */
  161. return smprintf("%s", buf);
  162. }
  163. /* ram percentage */
  164. char *
  165. get_ram_usage()
  166. {
  167. int perc;
  168. long total, free, buffers, cached;
  169. FILE *fp;
  170. /* open meminfo file */
  171. if (!(fp = fopen("/proc/meminfo", "r"))) {
  172. fprintf(stderr, "Error opening meminfo file.");
  173. return smprintf("n/a");
  174. }
  175. /* read the values */
  176. fscanf(fp, "MemTotal: %ld kB\n", &total);
  177. fscanf(fp, "MemFree: %ld kB\n", &free);
  178. fscanf(fp, "MemAvailable: %ld kB\nBuffers: %ld kB\n", &buffers, &buffers);
  179. fscanf(fp, "Cached: %ld kB\n", &cached);
  180. /* close meminfo file */
  181. fclose(fp);
  182. /* calculate percentage */
  183. perc = 100 * ((total - free) - (buffers + cached)) / total;
  184. /* return perc as string */
  185. return smprintf("%d%%", perc);
  186. }
  187. /* alsa volume percentage */
  188. char *
  189. get_volume()
  190. {
  191. int mute = 0;
  192. long vol = 0, max = 0, min = 0;
  193. /* get volume from alsa */
  194. snd_mixer_t *handle;
  195. snd_mixer_elem_t *pcm_mixer, *mas_mixer;
  196. snd_mixer_selem_id_t *vol_info, *mute_info;
  197. snd_mixer_open(&handle, 0);
  198. snd_mixer_attach(handle, soundcard);
  199. snd_mixer_selem_register(handle, NULL, NULL);
  200. snd_mixer_load(handle);
  201. snd_mixer_selem_id_malloc(&vol_info);
  202. snd_mixer_selem_id_malloc(&mute_info);
  203. snd_mixer_selem_id_set_name(vol_info, channel);
  204. snd_mixer_selem_id_set_name(mute_info, channel);
  205. pcm_mixer = snd_mixer_find_selem(handle, vol_info);
  206. mas_mixer = snd_mixer_find_selem(handle, mute_info);
  207. snd_mixer_selem_get_playback_volume_range((snd_mixer_elem_t *)pcm_mixer, &min, &max);
  208. snd_mixer_selem_get_playback_volume((snd_mixer_elem_t *)pcm_mixer, SND_MIXER_SCHN_MONO, &vol);
  209. snd_mixer_selem_get_playback_switch(mas_mixer, SND_MIXER_SCHN_MONO, &mute);
  210. if (vol_info)
  211. snd_mixer_selem_id_free(vol_info);
  212. if (mute_info)
  213. snd_mixer_selem_id_free(mute_info);
  214. if (handle)
  215. snd_mixer_close(handle);
  216. /* return the string (mute) */
  217. if (!mute)
  218. return smprintf("mute");
  219. else
  220. return smprintf("%d%%", (vol * 100) / max);
  221. }
  222. /* wifi percentage */
  223. char *
  224. get_wifi_signal()
  225. {
  226. int bufsize = 255;
  227. int strength;
  228. char buf[bufsize];
  229. char *datastart;
  230. char path_start[16] = "/sys/class/net/";
  231. char path_end[11] = "/operstate";
  232. char path[32];
  233. char status[5];
  234. char needle[sizeof wificard + 1];
  235. FILE *fp;
  236. /* generate the path name */
  237. memset(path, 0, sizeof path);
  238. strcat(path, path_start);
  239. strcat(path, wificard);
  240. strcat(path, path_end);
  241. /* open wifi file */
  242. if(!(fp = fopen(path, "r"))) {
  243. fprintf(stderr, "Error opening wifi operstate file.");
  244. return smprintf("n/a");
  245. }
  246. /* read the status */
  247. fgets(status, 5, fp);
  248. /* close wifi file */
  249. fclose(fp);
  250. /* check if interface down */
  251. if(strcmp(status, "up\n") != 0){
  252. return smprintf("n/a");
  253. }
  254. /* open wifi file */
  255. if (!(fp = fopen("/proc/net/wireless", "r"))) {
  256. fprintf(stderr, "Error opening wireless file.");
  257. return smprintf("n/a");
  258. }
  259. /* extract the signal strength */
  260. strcpy(needle, wificard);
  261. strcat(needle, ":");
  262. fgets(buf, bufsize, fp);
  263. fgets(buf, bufsize, fp);
  264. fgets(buf, bufsize, fp);
  265. if ((datastart = strstr(buf, needle)) != NULL) {
  266. datastart = strstr(buf, ":");
  267. sscanf(datastart + 1, " %*d %d %*d %*d %*d %*d %*d %*d %*d %*d", &strength);
  268. }
  269. /* close wifi file */
  270. fclose(fp);
  271. /* return strength in percent */
  272. return smprintf("%d%%", strength);
  273. }
  274. /* main function */
  275. int
  276. main()
  277. {
  278. char status[1024];
  279. char *battery = NULL;
  280. char *cpu_temperature = NULL;
  281. char *cpu_usage = NULL;
  282. char *datetime = NULL;
  283. char *ram_usage = NULL;
  284. char *volume = NULL;
  285. char *wifi_signal = NULL;
  286. /* check config for sanity */
  287. if (config_check() < 0) {
  288. fprintf(stderr, "Config error, please check paths and interval and recompile!\n");
  289. exit(1);
  290. }
  291. /* open display */
  292. if (!(dpy = XOpenDisplay(0x0))) {
  293. fprintf(stderr, "Cannot open display!\n");
  294. exit(1);
  295. }
  296. /* return status every second */
  297. for (;;) {
  298. /* assign the values */
  299. battery = get_battery();
  300. cpu_temperature = get_cpu_temperature();
  301. cpu_usage = get_cpu_usage();
  302. datetime = get_datetime();
  303. ram_usage = get_ram_usage();
  304. volume = get_volume();
  305. wifi_signal = get_wifi_signal();
  306. /* return the status */
  307. sprintf(status, FORMATSTRING, ARGUMENTS);
  308. setstatus(status);
  309. /* free the values */
  310. free(battery);
  311. free(cpu_temperature);
  312. free(cpu_usage);
  313. free(datetime);
  314. free(ram_usage);
  315. free(volume);
  316. free(wifi_signal);
  317. /* wait, "update_interval - 1" because of get_cpu_usage() which uses 1 second */
  318. sleep(update_interval -1);
  319. }
  320. /* close display */
  321. XCloseDisplay(dpy);
  322. /* exit successfully */
  323. return 0;
  324. }