Xinqi Bao's Git
   1 /* See LICENSE file for copyright and license details. */ 
   4 #include <alsa/asoundlib.h> 
  14 #include <sys/types.h> 
  16 #include <sys/statvfs.h> 
  17 #include <sys/socket.h> 
  28 setstatus(const char *str
) 
  30     /* set WM_NAME via X11 */ 
  31     XStoreName(dpy
, DefaultRootWindow(dpy
), str
); 
  35 /* smprintf function */ 
  37 smprintf(const char *fmt
, ...) 
  42     va_start(fmtargs
, fmt
); 
  43     if (vasprintf(&ret
, fmt
, fmtargs
) < 0) 
  50 /* battery percentage */ 
  52 battery_perc(const char *battery
) 
  55     char batterynowfile
[64] = ""; 
  56     char batteryfullfile
[64] = ""; 
  59     /* generate battery nowfile path */ 
  60     strcat(batterynowfile
, batterypath
); 
  61     strcat(batterynowfile
, battery
); 
  62     strcat(batterynowfile
, "/"); 
  63     strcat(batterynowfile
, batterynow
); 
  65     /* generate battery fullfile path */ 
  66     strcat(batteryfullfile
, batterypath
); 
  67     strcat(batteryfullfile
, battery
); 
  68     strcat(batteryfullfile
, "/"); 
  69     strcat(batteryfullfile
, batteryfull
); 
  71     /* open battery now file */ 
  72     if (!(fp 
= fopen(batterynowfile
, "r"))) { 
  73         fprintf(stderr
, "Error opening battery file.%s",batterynowfile
); 
  74         return smprintf("n/a"); 
  78     fscanf(fp
, "%i", &now
); 
  80     /* close battery now file */ 
  83     /* open battery full file */ 
  84     if (!(fp 
= fopen(batteryfullfile
, "r"))) { 
  85         fprintf(stderr
, "Error opening battery file."); 
  86         return smprintf("n/a"); 
  90     fscanf(fp
, "%i", &full
); 
  92     /* close battery full file */ 
  95     /* calculate percent */ 
  96     perc 
= now 
/ (full 
/ 100); 
  98     /* return perc as string */ 
  99     return smprintf("%d%%", perc
); 
 104 cpu_perc(const char *null
) 
 107     long double a
[4], b
[4]; 
 111     if (!(fp 
= fopen("/proc/stat","r"))) { 
 112         fprintf(stderr
, "Error opening stat file."); 
 113         return smprintf("n/a"); 
 117     fscanf(fp
, "%*s %Lf %Lf %Lf %Lf", &a
[0], &a
[1], &a
[2], &a
[3]); 
 119     /* close stat file */ 
 122     /* wait a second (for avg values) */ 
 126     if (!(fp 
= fopen("/proc/stat","r"))) { 
 127         fprintf(stderr
, "Error opening stat file."); 
 128         return smprintf("n/a"); 
 132     fscanf(fp
, "%*s %Lf %Lf %Lf %Lf", &b
[0], &b
[1], &b
[2], &b
[3]); 
 134     /* close stat file */ 
 137     /* calculate avg in this second */ 
 138     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])); 
 140     /* return perc as string */ 
 141     return smprintf("%d%%", perc
); 
 146 datetime(const char *timeformat
) 
 150     char *buf 
= malloc(bufsize
); 
 152     /* get time in format */ 
 154     setlocale(LC_TIME
, ""); 
 155     if(!strftime(buf
, bufsize
, timeformat
, localtime(&tm
))) { 
 156         setlocale(LC_TIME
, "C"); 
 157         fprintf(stderr
, "Strftime failed.\n"); 
 158         return smprintf("n/a"); 
 161     setlocale(LC_TIME
, "C"); 
 163     char *ret 
= smprintf("%s", buf
); 
 168 /* disk usage percentage */ 
 170 disk_perc(const char *mountpoint
) 
 175     /* try to open mountpoint */ 
 176     if (statvfs(mountpoint
, &fs
) < 0) { 
 177         fprintf(stderr
, "Could not get filesystem info.\n"); 
 178         return smprintf("n/a"); 
 181     /* calculate percent */ 
 182     perc 
= 100 * (1.0f 
- ((float)fs
.f_bavail 
/ (float)fs
.f_blocks
)); 
 185     return smprintf("%d%%", perc
); 
 188 /* entropy available */ 
 190 entropy(const char *null
) 
 195     /* open entropy file */ 
 196     if (!(fp 
= fopen("/proc/sys/kernel/random/entropy_avail", "r"))) { 
 197         fprintf(stderr
, "Could not open entropy file.\n"); 
 198         return smprintf("n/a"); 
 201     /* extract entropy */ 
 202     fscanf(fp
, "%d", &entropy
); 
 204     /* close entropy file */ 
 208     return smprintf("%d", entropy
); 
 213 ip(const char *interface
) 
 215     struct ifaddrs 
*ifaddr
, *ifa
; 
 217     char host
[NI_MAXHOST
]; 
 219     /* check if getting ip address works */ 
 220     if (getifaddrs(&ifaddr
) == -1) 
 222         fprintf(stderr
, "Error getting IP address."); 
 223         return smprintf("n/a"); 
 226     /* get the ip address */ 
 227     for (ifa 
= ifaddr
; ifa 
!= NULL
; ifa 
= ifa
->ifa_next
) 
 229         if (ifa
->ifa_addr 
== NULL
) 
 232         s 
= getnameinfo(ifa
->ifa_addr
, sizeof(struct sockaddr_in
), host
, NI_MAXHOST
, NULL
, 0, NI_NUMERICHOST
); 
 234         if ((strcmp(ifa
->ifa_name
, interface
) == 0) && (ifa
->ifa_addr
->sa_family 
== AF_INET
)) 
 238                 fprintf(stderr
, "Error getting IP address."); 
 239                 return smprintf("n/a"); 
 241             return smprintf("%s", host
); 
 245     /* free the address */ 
 248     /* return n/a if nothing works */ 
 249     return smprintf("n/a"); 
 254 ram_perc(const char *null
) 
 257     long total
, free
, buffers
, cached
; 
 260     /* open meminfo file */ 
 261     if (!(fp 
= fopen("/proc/meminfo", "r"))) { 
 262         fprintf(stderr
, "Error opening meminfo file."); 
 263         return smprintf("n/a"); 
 266     /* read the values */ 
 267     fscanf(fp
, "MemTotal: %ld kB\n", &total
); 
 268     fscanf(fp
, "MemFree: %ld kB\n", &free
); 
 269     fscanf(fp
, "MemAvailable: %ld kB\nBuffers: %ld kB\n", &buffers
, &buffers
); 
 270     fscanf(fp
, "Cached: %ld kB\n", &cached
); 
 272     /* close meminfo file */ 
 275     /* calculate percentage */ 
 276     perc 
= 100 * ((total 
- free
) - (buffers 
+ cached
)) / total
; 
 278     /* return perc as string */ 
 279     return smprintf("%d%%", perc
); 
 284 temp(const char *file
) 
 289     /* open temperature file */ 
 290     if (!(fp 
= fopen(file
, "r"))) { 
 291         fprintf(stderr
, "Could not open temperature file.\n"); 
 292         return smprintf("n/a"); 
 295     /* extract temperature */ 
 296     fscanf(fp
, "%d", &temperature
); 
 298     /* close temperature file */ 
 301     /* return temperature in degrees */ 
 302     return smprintf("%d°C", temperature 
/ 1000); 
 305 /* alsa volume percentage */ 
 307 vol_perc(const char *soundcard
) 
 310     long vol 
= 0, max 
= 0, min 
= 0; 
 312     /* get volume from alsa */ 
 314     snd_mixer_elem_t 
*pcm_mixer
, *mas_mixer
; 
 315     snd_mixer_selem_id_t 
*vol_info
, *mute_info
; 
 316     snd_mixer_open(&handle
, 0); 
 317     snd_mixer_attach(handle
, soundcard
); 
 318     snd_mixer_selem_register(handle
, NULL
, NULL
); 
 319     snd_mixer_load(handle
); 
 320     snd_mixer_selem_id_malloc(&vol_info
); 
 321     snd_mixer_selem_id_malloc(&mute_info
); 
 322     snd_mixer_selem_id_set_name(vol_info
, channel
); 
 323     snd_mixer_selem_id_set_name(mute_info
, channel
); 
 324     pcm_mixer 
= snd_mixer_find_selem(handle
, vol_info
); 
 325     mas_mixer 
= snd_mixer_find_selem(handle
, mute_info
); 
 326     snd_mixer_selem_get_playback_volume_range((snd_mixer_elem_t 
*)pcm_mixer
, &min
, &max
); 
 327     snd_mixer_selem_get_playback_volume((snd_mixer_elem_t 
*)pcm_mixer
, SND_MIXER_SCHN_MONO
, &vol
); 
 328     snd_mixer_selem_get_playback_switch(mas_mixer
, SND_MIXER_SCHN_MONO
, &mute
); 
 330         snd_mixer_selem_id_free(vol_info
); 
 332         snd_mixer_selem_id_free(mute_info
); 
 334         snd_mixer_close(handle
); 
 336     /* return the string (mute) */ 
 338         return smprintf("mute"); 
 340         return smprintf("%d%%", (vol 
* 100) / max
); 
 343 /* wifi percentage */ 
 345 wifi_perc(const char *wificard
) 
 353     char needle
[sizeof wificard 
+ 1]; 
 356     /* generate the path name */ 
 357     memset(path
, 0, sizeof path
); 
 358     strcat(path
, "/sys/class/net/"); 
 359     strcat(path
, wificard
); 
 360     strcat(path
, "/operstate"); 
 363     if(!(fp 
= fopen(path
, "r"))) { 
 364         fprintf(stderr
, "Error opening wifi operstate file."); 
 365         return smprintf("n/a"); 
 368     /* read the status */ 
 369     fgets(status
, 5, fp
); 
 371     /* close wifi file */ 
 374     /* check if interface down */ 
 375     if(strcmp(status
, "up\n") != 0){ 
 376         return smprintf("n/a"); 
 380     if (!(fp 
= fopen("/proc/net/wireless", "r"))) { 
 381         fprintf(stderr
, "Error opening wireless file."); 
 382         return smprintf("n/a"); 
 385     /* extract the signal strength */ 
 386     strcpy(needle
, wificard
); 
 388     fgets(buf
, bufsize
, fp
); 
 389     fgets(buf
, bufsize
, fp
); 
 390     fgets(buf
, bufsize
, fp
); 
 391     if ((datastart 
= strstr(buf
, needle
)) != NULL
) { 
 392         datastart 
= strstr(buf
, ":"); 
 393         sscanf(datastart 
+ 1, " %*d   %d  %*d  %*d        %*d      %*d      %*d      %*d      %*d        %*d", &strength
); 
 396     /* close wifi file */ 
 399     /* return strength in percent */ 
 400     return smprintf("%d%%", strength
); 
 407     char status_string
[1024]; 
 410     /* try to open display */ 
 411     if (!(dpy 
= XOpenDisplay(0x0))) { 
 412         fprintf(stderr
, "Cannot open display!\n"); 
 416     /* return status every interval */ 
 418         /* clear the string */ 
 419         memset(status_string
, 0, sizeof(status_string
)); 
 421         /* generate status_string */ 
 422         for (size_t i 
= 0; i 
< sizeof(args
) / sizeof(args
[0]); ++i
) { 
 424             char *res 
= argument
.func(argument
.args
); 
 425             char *element 
= smprintf(argument
.format
, res
); 
 426             strcat(status_string
, element
); 
 431         /* return the statusbar */ 
 432         setstatus(status_string
); 
 434         /* wait, "update_interval - 1" because of get_cpu_usage() which uses 1 second */ 
 435         sleep(update_interval 
-1); 
 441     /* exit successfully */