diff --git a/src/process.h b/src/process.h index 822483f..d640bc0 100644 --- a/src/process.h +++ b/src/process.h @@ -15,6 +15,8 @@ typedef struct st_process { int tgid; int level; char label[128]; + char cpuset[128]; + char lxcname[128]; int iskernel; // statistics - each outputs 1 line per process uint64_t cpuTime; diff --git a/src/server.c b/src/server.c index 4aa64b1..b7458aa 100644 --- a/src/server.c +++ b/src/server.c @@ -129,8 +129,8 @@ int parseIOFile(Process *proc, char *filedata) { return 0; } -int readProcesses(char *procdir) { - int len, rc = 1; +char *readProcesses(char *procdir) { + int len; struct dirent *pDirent; DIR *pDir; @@ -139,7 +139,7 @@ int readProcesses(char *procdir) { pDir = opendir(procdir); if (pDir == NULL) { printf("Cannot open directory '%s'\n", procdir); - return 1; + return NULL; } // Process each entry. @@ -174,7 +174,8 @@ int readProcesses(char *procdir) { fclose(file); if (parseStatFile(cur, buffer)) continue; - + + sprintf(fname, "/proc/%s/io", pDirent->d_name); file = fopen(fname, "rb"); if (file == NULL) continue; fread(buffer, 1, 4096, file); @@ -182,6 +183,34 @@ int readProcesses(char *procdir) { if (parseIOFile(cur, buffer)) continue; + sprintf(fname, "/proc/%s/cpuset", pDirent->d_name); + file = fopen(fname, "rb"); + if (file == NULL) goto nextProcess; + fread(cur->cpuset, 1, sizeof(cur->cpuset), file); + fclose(file); + + strtok(cur->cpuset, "\n\t "); + char *lxcTag = "/lxc/"; + if (memcmp(cur->cpuset, lxcTag, strlen(lxcTag)) == 0) { + // Resides in LXC -- read file and tag + sscanf(cur->cpuset, "/lxc/%d/ns", &cur->lxc); + sprintf(fname, "/etc/pve/lxc/%d.conf", cur->lxc); + file = fopen(fname, "rb"); + if (file == NULL) goto nextProcess; + fread(buffer, 1, 4096, file); + fclose(file); + + char *ptr = strstr(buffer, "hostname:"); + ptr += strlen("hostname:"); + while (*ptr == ' ') ptr++; + strtok(ptr, "\n\t "); + strcpy(cur->lxcname, ptr); + } else { + cur->lxcname[0] = 0; + cur->lxc = -1; + } + +nextProcess: cur->next = malloc(sizeof(Process)); cur->next->prev = cur; cur = cur->next; @@ -193,24 +222,23 @@ int readProcesses(char *procdir) { cur->next = NULL; int clocks = sysconf(_SC_CLK_TCK); + char *output = malloc(8*1024*1024); + char *ptr = output; cur = head; while (cur != NULL) { // create process descriptor - sprintf(buffer, "pid=\"%d\",ppid=\"%d\",label=\"%s\",kernel=\"%d\"", cur->pid, cur->ppid, cur->label, cur->iskernel); - printf("proc_cpu_time{%s} %f\n", buffer, (double) cur->cpuTime / clocks); - printf("proc_child_cpu_time{%s} %f\n", buffer, (double) cur->childCpuTime / clocks); - printf("proc_num_threads{%s} %llu\n", buffer, cur->nThreads); - printf("proc_resident_bytes{%s} %llu\n", buffer, cur->resident); - printf("proc_swap_bytes{%s} %llu\n", buffer, cur->swap); - printf("proc_fileio_bytes_written{%s} %llu\n", buffer, cur->written); - printf("proc_fileio_bytes_read{%s} %llu\n", buffer, cur->read); + sprintf(buffer, "pid=\"%d\",ppid=\"%d\",label=\"%s\",kernel=\"%d\",ctid=\"%d\",lxc=\"%s\"", cur->pid, cur->ppid, cur->label, cur->iskernel, cur->lxc, cur->lxcname); + ptr += sprintf(ptr, "proc_cpu_time{%s} %f\n", buffer, (double) cur->cpuTime / clocks); + ptr += sprintf(ptr, "proc_child_cpu_time{%s} %f\n", buffer, (double) cur->childCpuTime / clocks); + ptr += sprintf(ptr, "proc_num_threads{%s} %llu\n", buffer, cur->nThreads); + ptr += sprintf(ptr, "proc_resident_bytes{%s} %llu\n", buffer, cur->resident); + ptr += sprintf(ptr, "proc_swap_bytes{%s} %llu\n", buffer, cur->swap); + ptr += sprintf(ptr, "proc_fileio_bytes_written{%s} %llu\n", buffer, cur->written); + ptr += sprintf(ptr, "proc_fileio_bytes_read{%s} %llu\n", buffer, cur->read); cur = cur->next; } - rc = 0; - -freeChain: cur = head; while (cur != NULL) { Process *prev = cur; @@ -222,35 +250,50 @@ freeChain: closedir(pDir); free(buffer); free(fname); - return rc; + return output; } -#define PORT 9101 #define BUFFER_SIZE 1024 void handle_client(int client_socket) { + char *data = readProcesses("/proc"); + int length = strlen(data); + printf("Got data of length: %d\n", length); + // HTTP response - const char *http_response = + const char *http_response_fmt = "HTTP/1.1 200 OK\r\n" "Content-Type: text/plain\r\n" - "Content-Length: 25\r\n" + "Content-Length: %d\r\n" "Connection: close\r\n" - "\r\n" - "test{data=\"something\"} 25"; + "\r\n%s"; + char *http_response = malloc(length + strlen(http_response_fmt) + 20); + if (http_response == NULL) perror("Failed to allocate HTTP response\n"); + sprintf(http_response, http_response_fmt, length, data); // Send the response to the client send(client_socket, http_response, strlen(http_response), 0); // Close the client socket close(client_socket); + + free(http_response); + free(data); } int main(int argc, char *argv[]) { + int port = 9101; + if (argc == 1) { - int rc = readProcesses("/proc"); - return rc; - } + char *buf = readProcesses("/proc"); + if (buf == NULL) return 4; + printf(buf); + return 0; + + } else { + port = atoi(argv[1]); + } int server_socket, client_socket; struct sockaddr_in server_addr, client_addr; @@ -265,7 +308,7 @@ int main(int argc, char *argv[]) { // Configure the server address server_addr.sin_family = AF_INET; server_addr.sin_addr.s_addr = INADDR_ANY; - server_addr.sin_port = htons(PORT); + server_addr.sin_port = htons(port); // Bind the socket to the specified port if (bind(server_socket, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1) { @@ -281,7 +324,7 @@ int main(int argc, char *argv[]) { exit(EXIT_FAILURE); } - printf("Server is listening on port %d\n", PORT); + printf("Server is listening on port %d\n", port); // Accept and handle incoming connections while (1) {