Xinqi Bao's Git
9884aaad128177ecec3cd3e18a35da03d00fd8f7
   1 /* See LICENSE file for copyright and license details. */ 
   4 #include <alsa/asoundlib.h> 
   9 #include <linux/wireless.h> 
  17 #include <sys/ioctl.h> 
  19 #include <sys/statvfs.h> 
  20 #include <sys/socket.h> 
  21 #include <sys/types.h> 
  32 setstatus(const char *str
) 
  34         /* set WM_NAME via X11 */ 
  35         XStoreName(dpy
, DefaultRootWindow(dpy
), str
); 
  39 /* smprintf function */ 
  41 smprintf(const char *fmt
, ...) 
  46         va_start(fmtargs
, fmt
); 
  47         if (vasprintf(&ret
, fmt
, fmtargs
) < 0) { 
  55 /* battery percentage */ 
  57 battery_perc(const char *battery
) 
  60         char batterynowfile
[64] = ""; 
  61         char batteryfullfile
[64] = ""; 
  64         /* generate battery nowfile path */ 
  65         strcat(batterynowfile
, batterypath
); 
  66         strcat(batterynowfile
, battery
); 
  67         strcat(batterynowfile
, "/"); 
  68         strcat(batterynowfile
, batterynow
); 
  70         /* generate battery fullfile path */ 
  71         strcat(batteryfullfile
, batterypath
); 
  72         strcat(batteryfullfile
, battery
); 
  73         strcat(batteryfullfile
, "/"); 
  74         strcat(batteryfullfile
, batteryfull
); 
  76         /* open battery now file */ 
  77         if (!(fp 
= fopen(batterynowfile
, "r"))) { 
  78                 fprintf(stderr
, "Error opening battery file: %s.\n", batterynowfile
); 
  79                 return smprintf(unknowntext
); 
  83         fscanf(fp
, "%i", &now
); 
  85         /* close battery now file */ 
  88         /* open battery full file */ 
  89         if (!(fp 
= fopen(batteryfullfile
, "r"))) { 
  90                 fprintf(stderr
, "Error opening battery file.\n"); 
  91                 return smprintf(unknowntext
); 
  95         fscanf(fp
, "%i", &full
); 
  97         /* close battery full file */ 
 100         /* calculate percent */ 
 101         perc 
= now 
/ (full 
/ 100); 
 103         /* return perc as string */ 
 104         return smprintf("%d%%", perc
); 
 109 cpu_perc(const char *null
) 
 112         long double a
[4], b
[4]; 
 116         if (!(fp 
= fopen("/proc/stat","r"))) { 
 117                 fprintf(stderr
, "Error opening stat file.\n"); 
 118                 return smprintf(unknowntext
); 
 122         fscanf(fp
, "%*s %Lf %Lf %Lf %Lf", &a
[0], &a
[1], &a
[2], &a
[3]); 
 124         /* close stat file */ 
 127         /* wait a second (for avg values) */ 
 131         if (!(fp 
= fopen("/proc/stat","r"))) { 
 132                 fprintf(stderr
, "Error opening stat file.\n"); 
 133                 return smprintf(unknowntext
); 
 137         fscanf(fp
, "%*s %Lf %Lf %Lf %Lf", &b
[0], &b
[1], &b
[2], &b
[3]); 
 139         /* close stat file */ 
 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])); 
 145         /* return perc as string */ 
 146         return smprintf("%d%%", perc
); 
 151 datetime(const char *timeformat
) 
 155         char *buf 
= malloc(bufsize
); 
 157                 fprintf(stderr
, "Failed to get date/time.\n"); 
 158                 return smprintf(unknowntext
); 
 161         /* get time in format */ 
 163         setlocale(LC_TIME
, ""); 
 164         if (!strftime(buf
, bufsize
, timeformat
, localtime(&tm
))) { 
 165                 setlocale(LC_TIME
, "C"); 
 167                 fprintf(stderr
, "Strftime failed.\n"); 
 168                 return smprintf(unknowntext
); 
 171         setlocale(LC_TIME
, "C"); 
 173         char *ret 
= smprintf("%s", buf
); 
 180 disk_free(const char *mountpoint
) 
 184         /* try to open mountpoint */ 
 185         if (statvfs(mountpoint
, &fs
) < 0) { 
 186                 fprintf(stderr
, "Could not get filesystem info.\n"); 
 187                 return smprintf(unknowntext
); 
 191         return smprintf("%f", (float)fs
.f_bsize 
* (float)fs
.f_bfree 
/ 1024 / 1024 / 1024); 
 194 /* disk usage percentage */ 
 196 disk_perc(const char *mountpoint
) 
 201         /* try to open mountpoint */ 
 202         if (statvfs(mountpoint
, &fs
) < 0) { 
 203                 fprintf(stderr
, "Could not get filesystem info.\n"); 
 204                 return smprintf(unknowntext
); 
 207         /* calculate percent */ 
 208         perc 
= 100 * (1.0f 
- ((float)fs
.f_bfree 
/ (float)fs
.f_blocks
)); 
 211         return smprintf("%d%%", perc
); 
 216 disk_total(const char *mountpoint
) 
 220         /* try to open mountpoint */ 
 221         if (statvfs(mountpoint
, &fs
) < 0) { 
 222                 fprintf(stderr
, "Could not get filesystem info.\n"); 
 223                 return smprintf(unknowntext
); 
 227         return smprintf("%f", (float)fs
.f_bsize 
* (float)fs
.f_blocks 
/ 1024 / 1024 / 1024); 
 232 disk_used(const char *mountpoint
) 
 236         /* try to open mountpoint */ 
 237         if (statvfs(mountpoint
, &fs
) < 0) { 
 238                 fprintf(stderr
, "Could not get filesystem info.\n"); 
 239                 return smprintf(unknowntext
); 
 243         return smprintf("%f", (float)fs
.f_bsize 
* ((float)fs
.f_blocks 
- (float)fs
.f_bfree
) / 1024 / 1024 / 1024); 
 246 /* entropy available */ 
 248 entropy(const char *null
) 
 253         /* open entropy file */ 
 254         if (!(fp 
= fopen("/proc/sys/kernel/random/entropy_avail", "r"))) { 
 255                 fprintf(stderr
, "Could not open entropy file.\n"); 
 256                 return smprintf(unknowntext
); 
 259         /* extract entropy */ 
 260         fscanf(fp
, "%d", &entropy
); 
 262         /* close entropy file */ 
 266         return smprintf("%d", entropy
); 
 271 gid(const char *null
) 
 275         if ((gid 
= getgid()) < 0) { 
 276                 fprintf(stderr
, "Could no get gid.\n"); 
 277                 return smprintf(unknowntext
); 
 279                 return smprintf("%d", gid
); 
 282         return smprintf(unknowntext
); 
 287 hostname(const char *null
) 
 289         char hostname
[HOST_NAME_MAX
]; 
 292         /* open hostname file */ 
 293         if (!(fp 
= fopen("/proc/sys/kernel/hostname", "r"))) { 
 294                 fprintf(stderr
, "Could not open hostname file.\n"); 
 295                 return smprintf(unknowntext
); 
 298         /* extract hostname */ 
 299         fscanf(fp
, "%s\n", hostname
); 
 301         /* close hostname file */ 
 305         return smprintf("%s", hostname
); 
 310 ip(const char *interface
) 
 312         struct ifaddrs 
*ifaddr
, *ifa
; 
 314         char host
[NI_MAXHOST
]; 
 316         /* check if getting ip address works */ 
 317         if (getifaddrs(&ifaddr
) == -1) { 
 318                 fprintf(stderr
, "Error getting IP address.\n"); 
 319                 return smprintf(unknowntext
); 
 322         /* get the ip address */ 
 323         for (ifa 
= ifaddr
; ifa 
!= NULL
; ifa 
= ifa
->ifa_next
) { 
 324                 if (ifa
->ifa_addr 
== NULL
) { 
 328                 s 
= getnameinfo(ifa
->ifa_addr
, sizeof(struct sockaddr_in
), host
, NI_MAXHOST
, NULL
, 0, NI_NUMERICHOST
); 
 330                 if ((strcmp(ifa
->ifa_name
, interface
) == 0) && (ifa
->ifa_addr
->sa_family 
== AF_INET
)) { 
 332                                 fprintf(stderr
, "Error getting IP address.\n"); 
 333                                 return smprintf(unknowntext
); 
 335                         return smprintf("%s", host
); 
 339         /* free the address */ 
 342         return smprintf(unknowntext
); 
 347 ram_free(const char *null
) 
 352         /* open meminfo file */ 
 353         if (!(fp 
= fopen("/proc/meminfo", "r"))) { 
 354                 fprintf(stderr
, "Error opening meminfo file.\n"); 
 355                 return smprintf(unknowntext
); 
 358         /* read the values */ 
 359         fscanf(fp
, "MemFree: %ld kB\n", &free
); 
 361         /* close meminfo file */ 
 364         /* return free ram as string */ 
 365         return smprintf("%f", (float)free 
/ 1024 / 1024); 
 370 ram_perc(const char *null
) 
 373         long total
, free
, buffers
, cached
; 
 376         /* open meminfo file */ 
 377         if (!(fp 
= fopen("/proc/meminfo", "r"))) { 
 378                 fprintf(stderr
, "Error opening meminfo file.\n"); 
 379                 return smprintf(unknowntext
); 
 382         /* read the values */ 
 383         fscanf(fp
, "MemTotal: %ld kB\n", &total
); 
 384         fscanf(fp
, "MemFree: %ld kB\n", &free
); 
 385         fscanf(fp
, "MemAvailable: %ld kB\nBuffers: %ld kB\n", &buffers
, &buffers
); 
 386         fscanf(fp
, "Cached: %ld kB\n", &cached
); 
 388         /* close meminfo file */ 
 391         /* calculate percentage */ 
 392         perc 
= 100 * ((total 
- free
) - (buffers 
+ cached
)) / total
; 
 394         /* return perc as string */ 
 395         return smprintf("%d%%", perc
); 
 400 ram_total(const char *null
) 
 405         /* open meminfo file */ 
 406         if (!(fp 
= fopen("/proc/meminfo", "r"))) { 
 407                 fprintf(stderr
, "Error opening meminfo file.\n"); 
 408                 return smprintf(unknowntext
); 
 411         /* read the values */ 
 412         fscanf(fp
, "MemTotal: %ld kB\n", &total
); 
 414         /* close meminfo file */ 
 417         /* return total ram as string */ 
 418         return smprintf("%f", (float)total 
/ 1024 / 1024); 
 423 ram_used(const char *null
) 
 425         long free
, total
, buffers
, cached
, used
; 
 428         /* open meminfo file */ 
 429         if (!(fp 
= fopen("/proc/meminfo", "r"))) { 
 430                 fprintf(stderr
, "Error opening meminfo file.\n"); 
 431                 return smprintf(unknowntext
); 
 434         /* read the values */ 
 435         fscanf(fp
, "MemTotal: %ld kB\n", &total
); 
 436         fscanf(fp
, "MemFree: %ld kB\n", &free
); 
 437         fscanf(fp
, "MemAvailable: %ld kB\nBuffers: %ld kB\n", &buffers
, &buffers
); 
 438         fscanf(fp
, "Cached: %ld kB\n", &cached
); 
 440         /* close meminfo file */ 
 444         used 
= total 
- free 
- buffers 
- cached
; 
 446         /* return used ram as string */ 
 447         return smprintf("%f", (float)used 
/ 1024 / 1024); 
 450 /* custom shell command */ 
 452 run_command(const char* command
) 
 458         /* try to open the command output */ 
 459         if (!(fp 
= popen(command
, "r"))) { 
 460                 fprintf(stderr
, "Could not get command output for: %s.\n", command
); 
 461                 return smprintf(unknowntext
); 
 464         /* get command output text, save it to buffer */ 
 465         fgets(buffer
, sizeof(buffer
) - 1, fp
); 
 470         /* add nullchar at the end */ 
 471         for (int i 
= 0 ; i 
!= sizeof(buffer
); i
++) { 
 472                 if (buffer
[i
] == '\0') { 
 478                 buffer
[strlen(buffer
) - 1] = '\0'; 
 481         /* return the output */ 
 482         return smprintf("%s", buffer
); 
 487 temp(const char *file
) 
 492         /* open temperature file */ 
 493         if (!(fp 
= fopen(file
, "r"))) { 
 494                 fprintf(stderr
, "Could not open temperature file.\n"); 
 495                 return smprintf(unknowntext
); 
 498         /* extract temperature */ 
 499         fscanf(fp
, "%d", &temperature
); 
 501         /* close temperature file */ 
 504         /* return temperature in degrees */ 
 505         return smprintf("%d°C", temperature 
/ 1000); 
 510 username(const char *null
) 
 512         register struct passwd 
*pw
; 
 519         /* if it worked, return */ 
 521                 return smprintf("%s", pw
->pw_name
); 
 523                 fprintf(stderr
, "Could not get username.\n"); 
 524                 return smprintf(unknowntext
); 
 527         return smprintf(unknowntext
); 
 532 uid(const char *null
) 
 539         /* if it worked, return */ 
 541                 return smprintf("%d", uid
); 
 543                 fprintf(stderr
, "Could not get uid.\n"); 
 544                 return smprintf(unknowntext
); 
 547         return smprintf(unknowntext
); 
 551 /* alsa volume percentage */ 
 553 vol_perc(const char *soundcard
) 
 556         long vol 
= 0, max 
= 0, min 
= 0; 
 558         snd_mixer_elem_t 
*pcm_mixer
, *mas_mixer
; 
 559         snd_mixer_selem_id_t 
*vol_info
, *mute_info
; 
 561         /* open everything */ 
 562         snd_mixer_open(&handle
, 0); 
 563         snd_mixer_attach(handle
, soundcard
); 
 564         snd_mixer_selem_register(handle
, NULL
, NULL
); 
 565         snd_mixer_load(handle
); 
 567         /* prepare everything */ 
 568         snd_mixer_selem_id_malloc(&vol_info
); 
 569         snd_mixer_selem_id_malloc(&mute_info
); 
 571         if (vol_info 
== NULL 
|| mute_info 
== NULL
) { 
 572                 fprintf(stderr
, "Could not get alsa volume.\n"); 
 573                 return smprintf(unknowntext
); 
 575         snd_mixer_selem_id_set_name(vol_info
, channel
); 
 576         snd_mixer_selem_id_set_name(mute_info
, channel
); 
 577         pcm_mixer 
= snd_mixer_find_selem(handle
, vol_info
); 
 578         mas_mixer 
= snd_mixer_find_selem(handle
, mute_info
); 
 581         snd_mixer_selem_get_playback_volume_range((snd_mixer_elem_t 
*)pcm_mixer
, &min
, &max
); 
 582         snd_mixer_selem_get_playback_volume((snd_mixer_elem_t 
*)pcm_mixer
, SND_MIXER_SCHN_MONO
, &vol
); 
 583         snd_mixer_selem_get_playback_switch(mas_mixer
, SND_MIXER_SCHN_MONO
, &mute
); 
 587                 snd_mixer_selem_id_free(vol_info
); 
 590                 snd_mixer_selem_id_free(mute_info
); 
 593                 snd_mixer_close(handle
); 
 596         /* return the string (mute) */ 
 598                 return smprintf("mute"); 
 600                 return smprintf("%d%%", (vol 
* 100) / max
); 
 604 /* wifi percentage */ 
 606 wifi_perc(const char *wificard
) 
 614         char needle
[sizeof wificard 
+ 1]; 
 617         /* generate the path name */ 
 618         memset(path
, 0, sizeof path
); 
 619         strcat(path
, "/sys/class/net/"); 
 620         strcat(path
, wificard
); 
 621         strcat(path
, "/operstate"); 
 624         if(!(fp 
= fopen(path
, "r"))) { 
 625                 fprintf(stderr
, "Error opening wifi operstate file.\n"); 
 626                 return smprintf(unknowntext
); 
 629         /* read the status */ 
 630         fgets(status
, 5, fp
); 
 632         /* close wifi file */ 
 635         /* check if interface down */ 
 636         if(strcmp(status
, "up\n") != 0) { 
 637                 return smprintf(unknowntext
); 
 641         if (!(fp 
= fopen("/proc/net/wireless", "r"))) { 
 642                 fprintf(stderr
, "Error opening wireless file.\n"); 
 643                 return smprintf(unknowntext
); 
 646         /* extract the signal strength */ 
 647         strcpy(needle
, wificard
); 
 649         fgets(buf
, bufsize
, fp
); 
 650         fgets(buf
, bufsize
, fp
); 
 651         fgets(buf
, bufsize
, fp
); 
 652         if ((datastart 
= strstr(buf
, needle
)) != NULL
) { 
 653                 datastart 
= strstr(buf
, ":"); 
 654                 sscanf(datastart 
+ 1, " %*d   %d  %*d  %*d                %*d      %*d          %*d              %*d      %*d            %*d", &strength
); 
 657         /* close wifi file */ 
 660         /* return strength in percent */ 
 661         return smprintf("%d%%", strength
); 
 666 wifi_essid(const char *wificard
) 
 668         char id
[IW_ESSID_MAX_SIZE
+1]; 
 673         memset(&wreq
, 0, sizeof(struct iwreq
)); 
 674         wreq
.u
.essid
.length 
= IW_ESSID_MAX_SIZE
+1; 
 676         /* set the interface */ 
 677         sprintf(wreq
.ifr_name
, wificard
); 
 680         if((sockfd 
= socket(AF_INET
, SOCK_DGRAM
, 0)) == -1) { 
 681                 fprintf(stderr
, "Cannot open socket for interface: %s\n", wificard
); 
 682                 return smprintf(unknowntext
); 
 684         wreq
.u
.essid
.pointer 
= id
; 
 685         if (ioctl(sockfd
,SIOCGIWESSID
, &wreq
) == -1) { 
 686                 fprintf(stderr
, "Get ESSID ioctl failed for interface %s\n", wificard
); 
 687                 return smprintf(unknowntext
); 
 690         /* return the essid */ 
 691         if (strcmp((char *)wreq
.u
.essid
.pointer
, "") == 0) { 
 692                 return smprintf(unknowntext
); 
 694                 return smprintf("%s", (char *)wreq
.u
.essid
.pointer
); 
 702         char status_string
[1024]; 
 705         /* try to open display */ 
 706         if (!(dpy 
= XOpenDisplay(0x0))) { 
 707                 fprintf(stderr
, "Cannot open display!\n"); 
 711         /* return status every interval */ 
 713                 /* clear the string */ 
 714                 memset(status_string
, 0, sizeof(status_string
)); 
 716                 /* generate status_string */ 
 717                 for (size_t i 
= 0; i 
< sizeof(args
) / sizeof(args
[0]); ++i
) { 
 719                         char *res 
= argument
.func(argument
.args
); 
 720                         char *element 
= smprintf(argument
.format
, res
); 
 721                         if (element 
== NULL
) { 
 722                                 element 
= smprintf(unknowntext
); 
 723                                 fprintf(stderr
, "Failed to format output.\n"); 
 725                         strcat(status_string
, element
); 
 730                 /* return the statusbar */ 
 731                 setstatus(status_string
); 
 733                 /* wait, "update_interval - 1" because of get_cpu_usage() which uses 1 second */ 
 734                 sleep(update_interval 
-1); 
 740         /* exit successfully */