1 #include <stdio.h>
2 #include <string.h>
3 #include <stdlib.h>
4 
5 #define BUF_SIZ 1024
6 
7 /******************
8 ** output_string **
9 *******************
10 ** Displays a string on the screen.  Also, if the flag
11 ** write_to_file is set, outputs the string to the output file.
12 ** Note, this routine presumes that you've included a carriage
13 ** return at the end of the buffer.
14 */
output_string(const char * buffer,const int write_to_file,FILE * global_ofile)15 static void output_string(const char *buffer, const int write_to_file,
16                           FILE *global_ofile){
17   printf("%s",buffer);
18   if(write_to_file!=0)
19     fprintf(global_ofile,"%s",buffer);
20   return;
21 }
22 
23 
24 /******************
25 ** removeNewLine **
26 *******************
27 ** Removes a trailing newline character if present
28 */
removeNewLine(char * s)29 static void removeNewLine(char * s) {
30   if(strlen(s)>0 && s[strlen(s)-1] == '\n') {
31     s[strlen(s)-1] = '\0';
32   }
33 }
34 
35 
36 /***************
37 ** runCommand **
38 ****************
39 ** Run the system command through a pipe
40 ** The pointer result must point to a pre-allocated array of at least BUF_SIZ
41 */
runCommand(const char * command,char * result)42 static void runCommand (const char *command, char *result) {
43   FILE * pipe;
44 
45   pipe = popen(command, "r");
46   if(pipe == NULL) {
47     /* command failed */
48     result[0] = '\0';
49   } else {
50     if(NULL == fgets(result, BUF_SIZ, pipe)){
51       /* command failed */
52       result[0] = '\0';
53     }
54     pclose(pipe);
55   }
56   removeNewLine(result);
57 }
58 
59 
60 /********************
61 ** readProcCpuInfo **
62 *********************
63 ** Reads and parses /proc/cpuinfo on a Linux system
64 ** The pointers must point to pre-allocated arrays of at least BUF_SIZ
65 */
readProcCpuInfo(char * model,char * cache)66 static void readProcCpuInfo (char *model, char *cache) {
67   FILE * info;
68   char * cp;
69   int cpus = 0;
70   char * buffer_end;
71   char buffer[BUF_SIZ];
72   char vendor_id[BUF_SIZ];
73   char model_name[BUF_SIZ];
74   char cpu_MHz[BUF_SIZ];
75   int i;
76   float f;
77 
78   vendor_id[0] = model_name[0] = cpu_MHz[0] = model[0] = cache[0] = '\0';
79   info = fopen("/proc/cpuinfo", "r");
80   if(info != NULL) {
81     /* command did not fail */
82     while(NULL != fgets(buffer, BUF_SIZ, info)){
83       buffer_end = buffer + strlen(buffer);
84       cp = buffer;
85       if(! strncmp(buffer, "processor", 9)) {
86         cpus++;
87       } else if(! strncmp(buffer, "vendor_id", 9)) {
88         cp+=strlen("vendor_id");
89         while(cp < buffer_end && ( *cp == ' ' || *cp == ':'|| *cp == '\t'))
90           cp++;
91         if(cp<buffer_end) {
92           strcpy(vendor_id, cp);
93         }
94         removeNewLine(vendor_id);
95       } else if(! strncmp(buffer, "model name", 10)) {
96         cp+=strlen("model name");
97         while(cp < buffer_end && ( *cp == ' ' || *cp == ':'|| *cp == '\t'))
98           cp++;
99         if(cp<buffer_end) {
100           strcpy(model_name, cp);
101         }
102         removeNewLine(model_name);
103       } else if(! strncmp(buffer, "cpu MHz", 7)) {
104         cp+=strlen("cpu MHz");
105         while(cp < buffer_end && ( *cp == ' ' || *cp == ':'|| *cp == '\t'))
106           cp++;
107         if(cp<buffer_end) {
108           strcpy(cpu_MHz, cp);
109         }
110         removeNewLine(cpu_MHz);
111       } else if(! strncmp(buffer, "cache size", 10)) {
112         cp+=strlen("cache size");
113         while(cp < buffer_end && ( *cp == ' ' || *cp == ':'|| *cp == '\t'))
114           cp++;
115         if(cp<buffer_end) {
116           strcpy(cache, cp);
117         }
118         removeNewLine(cache);
119       }
120     }
121     if(cpus>1) {
122       if (cpus==2) {
123         strcpy(model, "Dual");
124       } else {
125         sprintf(model, "%d CPU", cpus);
126       }
127     }
128     cp = model + strlen(model);
129     if(vendor_id[0] != '\0'){
130       if(cp != model){
131         *cp++ = ' ';
132       }
133       strcpy(cp, vendor_id);
134       cp += strlen(vendor_id);
135     }
136     if(model_name[0] != '\0'){
137       if(cp != model){
138         *cp++ = ' ';
139       }
140       strcpy(cp, model_name);
141       cp += strlen(model_name);
142     }
143     if(cpu_MHz[0] != '\0'){
144       if(cp != model){
145         *cp++ = ' ';
146       }
147       f = atof(cpu_MHz);
148       i = (int)(f+0.5f);
149       sprintf(cpu_MHz, "%dMHz", i);
150       strcpy(cp, cpu_MHz);
151       cp += strlen(cpu_MHz);
152     }
153     fclose(info);
154   }
155 }
156 
157 
158 /*************
159 ** hardware **
160 **************
161 ** Runs the system command "uname -s -r"
162 ** Reads /proc/cpuinfo if on a linux system
163 ** Writes output
164 */
hardware(const int write_to_file,FILE * global_ofile)165 void hardware(const int write_to_file, FILE *global_ofile) {
166   char buffer[BUF_SIZ];
167   char os[BUF_SIZ];
168   char model[BUF_SIZ];
169   char cache[BUF_SIZ];
170   char os_command[] = "uname -s -r";
171 #ifdef NO_UNAME
172   os[0] = '\0';
173 #else
174   runCommand(os_command, os);
175 #endif
176   if(NULL != strstr(os, "Linux")) {
177     readProcCpuInfo (model, cache);
178   } else {
179     model[0] = '\0';
180     cache[0] = '\0';
181   }
182   sprintf(buffer, "CPU                 : %s\n", model);
183   output_string(buffer, write_to_file, global_ofile);
184   sprintf(buffer, "L2 Cache            : %s\n", cache);
185   output_string(buffer, write_to_file, global_ofile);
186   sprintf(buffer, "OS                  : %s\n", os);
187   output_string(buffer, write_to_file, global_ofile);
188 }
189 
190 
191 /************************
192 ** main for hardware.c **
193 *************************
194 ** For testing of code only
195 ** Should be commented out
196 */
197 /*
198 int main(int argc, char * argv[]) {
199   hardware(0, NULL);
200   return 0;
201 }
202 */
203