/* * UNO Monitor Daemon * Kidacro * * gather_stats.c - retrieves stats from system * */ #include #include #include #include #include #include #define MAX_ENTRIES 10 // from monitor_daemon.c void send_stats(); // local function prototypes void get_stats(); char *trim(char *str); static void get_cpu_load(); void get_cpu_temp(); void get_free_mem(); void get_free_space(); // external vars (monitor_daemon.c) extern const char *cpu_temp_file; extern const char *cpu_fanspeed_file; extern char *drive_free_space[MAX_ENTRIES]; extern int drive_free_space_count; extern FILE *log_stream; extern int debug; extern int line_length; extern int line_count; // stats vars // TODO: make the character sizes dynamic based on line_length // src/gather_stats.c:43:6: error: variably modified ‘freespace’ at file scope <-- damn C // so we have to make a concession and either #define a max or.... no clue... go back to PHP? char cpuload[4]; // line 1 char cputemp[6]; // line 1 char freemem[6]; // line 1 char freespace[16]; // line 2 // sysinfo vars int sysinfo(struct sysinfo *info); // proto: // struct sysinfo { // long uptime; /* Seconds since boot */ // unsigned long loads[3]; /* 1, 5, and 15 minute load averages */ // unsigned long totalram; /* Total usable main memory size */ // unsigned long freeram; /* Available memory size */ // unsigned long sharedram; /* Amount of shared memory */ // unsigned long bufferram; /* Memory used by buffers */ // unsigned long totalswap; /* Total swap space size */ // unsigned long freeswap; /* swap space still available */ // unsigned short procs; /* Number of current processes */ // unsigned long totalhigh; /* Total high memory size */ // unsigned long freehigh; /* Available high memory size */ // unsigned int mem_unit; /* Memory unit size in bytes */ // char _f[20-2*sizeof(long)-sizeof(int)]; /* Padding to 64 bytes */ //}; // trims end of strings char *trim(char *str) { size_t len = 0; char *frontp = str; char *endp = NULL; if( str == NULL ) { return NULL; } if( str[0] == '\0' ) { return str; } len = strlen(str); endp = str + len; /* Move the front and back pointers to address the first non-whitespace * characters from each end. */ while(isspace((unsigned char) *frontp)) { ++frontp; } if(endp != frontp) { while(isspace((unsigned char) *(--endp)) && endp != frontp) {} } if(frontp != str && endp == frontp) { *str = '\0'; } else if(str + len - 1 != endp) { *(endp + 1) = '\0'; } /* Shift the string so that it starts at str so that if it's dynamically * allocated, we can still free it on the returned pointer. Note the reuse * of endp to mean the front of the string buffer now. */ endp = str; if(frontp != str) { while(*frontp) { *endp++ = *frontp++; } *endp = '\0'; } return str; } // get stats (retreive, combine, and send stats) // TODO: force trunication for each line to line_length // no reason to hardcode '24' below when we know the exact line_length void get_stats() { char line_1[24], line_2[24], line_3[24]; get_cpu_load(); get_cpu_temp(); get_free_mem(); get_free_space(); snprintf(line_1,sizeof(line_1),"#1%s%% %sC %sM@",cpuload,cputemp,freemem); snprintf(line_2,sizeof(line_2),"#2%s@",trim(freespace)); snprintf(line_3,sizeof(line_3),"#3%s@",cpuload); send_stats(line_1,line_2,line_3); return; } static void get_cpu_load() { //static unsigned int lastTotalUser, lastTotalUserLow, lastTotalSys, lastTotalIdle; static unsigned long long lastTotalUser, lastTotalUserLow, lastTotalSys, lastTotalIdle; float percent; static float lastPercent; int intPercent, read_result = 0; FILE* file; unsigned long long totalUser, totalUserLow, totalSys, totalIdle, total; file = fopen("/proc/stat", "r"); read_result = fscanf(file, "cpu %llu %llu %llu %llu", &totalUser, &totalUserLow, &totalSys, &totalIdle); fclose(file); // if result cannot be read, set to 0 if(read_result != 4) { snprintf(&*cpuload, sizeof(0), "%d", 0); return; } // we dont have a good value, use old value if(totalUser < lastTotalUser || totalUserLow < lastTotalUserLow || totalSys < lastTotalSys || totalIdle < lastTotalIdle) { percent = -1.0; //percent = lastPercent; } // we have a good value, save it and process it else { total = (totalUser - lastTotalUser) + (totalUserLow - lastTotalUserLow) + (totalSys - lastTotalSys); percent = total * 100; total += (totalIdle - lastTotalIdle); percent /= total; lastPercent = percent; } if(debug) { fprintf(log_stream,"lasttotalUser: %llu - lasttotalUserLow: %llu - lasttotalSys: %llu - lasttotalIdle: %llu - lastpercent: %f\n", lastTotalUser, lastTotalUserLow, lastTotalSys, lastTotalIdle, lastPercent); fprintf(log_stream,"totalUser: %llu - totalUserLow: %llu - totalSys: %llu - totalIdle: %llu - percent: %f\n\n", totalUser,totalUserLow, totalSys, totalIdle, percent); } // save curent values for later comparison lastTotalUser = totalUser; lastTotalUserLow = totalUserLow; lastTotalSys = totalSys; lastTotalIdle = totalIdle; // force percent (float) to int intPercent = percent; snprintf(&*cpuload, sizeof(intPercent), "%d", intPercent); return; } void get_cpu_temp() { FILE* ptr; char str[10]; // opening file in readonly mode ptr = fopen(&*cpu_temp_file, "r"); if(NULL == ptr) { fprintf(log_stream,"File %s can't be opened!\n",cpu_temp_file); return; } while(fgets(str, 10, ptr) != NULL) { if(debug) { fprintf(log_stream,"Raw CPU temp: %s\n", str); } } /* 1 decimal place char a = str[0]; char b = str[1]; char c = str[2]; snprintf(&*cputemp,6,"%c%c.%c",a,b,c); */ // no decimals char a = str[0]; char b = str[1]; snprintf(&*cputemp,6,"%c%c",a,b); fclose(ptr); return; } void get_free_mem() { struct sysinfo info; int myfreemem; if(sysinfo(&info) < 0) { return; } if(debug) { fprintf(log_stream,"RAW free mem: %ld\n",info.freeram); } myfreemem = info.freeram / 1024 / 1024; snprintf(&*freemem,sizeof(freemem),"%d",myfreemem); return; } void get_free_space() { struct statfs info; int n = 0; char *mydrive; char myfree_string[line_length]; long unsigned int mytmpfree; // clear freespace array b4 loop or strcat will keep adding to it causing a buffer overflow memset(freespace, '\0', sizeof(freespace)); for(n = 0; n < drive_free_space_count; n++) { mydrive = drive_free_space[n]; statfs(mydrive, &info); mytmpfree = ((info.f_bavail*4) / 1024 / 1024) + 1; snprintf(myfree_string,10,"%ldG ",mytmpfree); strcat(freespace,myfree_string); if(debug) { fprintf(log_stream, "My Drive: %s\n" " block size : %ld," " total data blocks : %ld," " free blocks for root: %ld," " free blocks for user: %ld," " free space in G: %ld\n\n", mydrive, info.f_bsize, info.f_blocks, info.f_bfree, info.f_bavail, mytmpfree); } } return; }