// statline by shockrah // Inspired by barM // barM is a great tool but formats information in a really ugly fashion // This version mainly aims to ve a visual overhaul of both code and output over barM // Dependancies: cat grep awk #include #include #include #include #include #include #include #include #include #define BASIC_MSG "/comfy/ o clock | " #define TIME_FORMAT "%I:%M%p - %d %b %Y" // Time in seconds #define TIME_DELAY 5 #define MAXSTR 1024 #define SMALL_BUF 32 #define MEM_BREAD_SIZE 32 #define STD_IO // `man date` should give you some more info on what the format specs do // This format give the form ยป 05:13 PM - 20 Jul 2019 static char* date_time(void) { static char date[MAXSTR]; time_t now = time(0); strftime(date, sizeof(date), TIME_FORMAT, localtime(&now)); return date; } char* ram_usage(void) { struct sysinfo info; sysinfo(&info); static char buf[MAXSTR]; long sum; // TODO: fix the Lazily reading through /proc/meminfo FILE* res = popen("cat /proc/meminfo | grep -e ^Cached -e Buffers -e Slab | awk '{print $2}'", "r"); if(res) { sum = 0; while(fgets(buf, sizeof(buf)-1, res) != NULL) { sum += atoi(buf); } sum *= 1000; // KB to B } double used = (info.totalram - info.freeram - sum) / 1000000000.; double total = info.totalram / 1000000000.; snprintf(buf, sizeof(buf), "%.2f G/ %.1f G", used, total); pclose(res); return buf; } #ifdef LAPTOP #define BATTERY_STATUS_BUFFER 50 #define REDUCER 1000 static char* battery_percentage(void) { unsigned long total, curr; static char buf[BATTERY_STATUS_BUFFER]; FILE* file_max = fopen("/sys/class/power_supply/BAT0/energy_full","r"); if(file_max) { fgets(buf, BATTERY_STATUS_BUFFER, file_max); fclose(file_max); total = atoi(buf)/REDUCER; } FILE* file_curr = fopen("/sys/class/power_supply/BAT0/energy_now", "r"); if(file_curr) { fgets(buf, BATTERY_STATUS_BUFFER, file_max); fclose(file_curr); curr = atoi(buf)/REDUCER; } float level = (float)curr / (float)total; snprintf(buf, BATTERY_STATUS_BUFFER, "Battery: %.2f%%", level*100); return buf; } #endif #ifdef CPU_USAGE // stat(2) -> #define CPU_PROC_BASE #define TOTAL "head /proc/stat -n 1 | cut -c 6- | sed 's/ /\\+/g' | bc" #define IDLE "head /proc/stat -n 1 | cut -c 6- | awk '{print $4}'" static char* cpu_usage(void) { // NOTE: not accounting for the query so this may be somewhat off by some metric // Grabbing the total usage FILE* query_p; static char buf[SMALL_BUF]; unsigned total, idle; // get the total time query_p = popen(TOTAL, "r"); fgets(buf, sizeof(buf)-1, query_p); total = atoi(buf); pclose(query_p); // get the idle time query_p = popen(IDLE, "r"); fgets(buf, sizeof(buf)-1, query_p); idle = atoi(buf); pclose(query_p); double usage = 1.00 - ((double)idle / (double)total); #ifdef DEBUG printf("IDLE/TOTAL = %.02f\n", usage); #endif sprintf(buf, "CPU: %.02f % ", usage); return buf; } #endif static void XSetRoot(char* name) { Display *display; if (( display = XOpenDisplay(0x0)) == NULL ) { fprintf(stderr, "[barM] cannot open display!\n"); exit(1); } XStoreName(display, DefaultRootWindow(display), name); XSync(display, 0); XCloseDisplay(display); } int main(void) { // Here you can put the functions you create as they should be executed from here static char* (*func_table[])(void) = { ram_usage, date_time, #ifdef LAPTOP battery_percentage, #endif #ifdef CPU_USAGE cpu_usage, #endif }; char stat_output[MAXSTR]; // First things that don't need updating like ever int base_len = snprintf(stat_output, sizeof(stat_output), BASIC_MSG); char* base_offset = stat_output + base_len; // Make sure we didn't go past the end of our buffer if(base_offset >= sizeof(stat_output)+stat_output) { XSetRoot(stat_output); return 1; } // Now the regularly updated stuff like date/time cpu usage etc. int len; for(;;) { int remainder = sizeof(stat_output) - base_len; // starting position for 'dynamic text' char* tmp_base_ptr = base_offset; for(int i = 0; i < sizeof(func_table)/sizeof(func_table[0]); ++i) { if(tmp_base_ptr > (stat_output+MAXSTR)) { break; } int written = snprintf(tmp_base_ptr, remainder, "%s | ", func_table[i]()); tmp_base_ptr += written; remainder -= written; } XSetRoot(stat_output); sleep(TIME_DELAY); } return 0; }