diff --git a/include/process.h b/include/process.h index fb55102..55713cb 100644 --- a/include/process.h +++ b/include/process.h @@ -38,9 +38,12 @@ int process_parse_status(pid_t pid, process_status_t* status); // deallocate list with free later int processes_by_name(const char* name, process_status_t** list, size_t* count); -// will determine parent process amongst children and set parent pointer to element in list +// determine parent process amongst children and set parent pointer to element in list // process list must consist of parent and children processes, // obtained from processes_by_name call. of course parent pointer shouldn't be NULL int determine_parent_process(process_status_t* list, size_t count, process_status_t** parent); +// get all process threads. for list and count same rules applies as for processes_by_name +int process_get_threads(pid_t pid, process_status_t** list, size_t* count); + #endif \ No newline at end of file diff --git a/src/main.c b/src/main.c index 8c022eb..2a854b4 100644 --- a/src/main.c +++ b/src/main.c @@ -23,17 +23,34 @@ int main(int argc, char** argv) process_status_t* list = NULL; size_t count = 0; + // find process processes_by_name("dummy_target", &list, &count); + // get real parent process_status_t* parent; if (determine_parent_process(list, count, &parent)) { - fputs("unable to determine parent process. exiting", stderr); + fputs("unable to determine parent process. exiting\n", stderr); free(list); return 1; } print_process(parent); + + // get threads + process_status_t* threads = NULL; + size_t thread_count = 0; + if (process_get_threads(parent->pid, &threads, &thread_count)) + { + fputs("failed to obtain process threads\n", stderr); + free(list); + return 1; + } + + puts("Threads:"); + for (size_t i = 0; i < thread_count; i++) + print_process(&threads[i]); free(list); + free(threads); return 0; } \ No newline at end of file diff --git a/src/process.c b/src/process.c index 1a69600..53931fa 100644 --- a/src/process.c +++ b/src/process.c @@ -136,4 +136,54 @@ int determine_parent_process(process_status_t* list, size_t count, process_statu } return 1; +} + +int process_get_threads(pid_t pid, process_status_t** list, size_t* count) +{ + char taskPath[256] = {0}; + snprintf(taskPath, sizeof(taskPath), "/proc/%d/task", pid); + + DIR* taskDir = opendir(taskPath); + if (!taskDir) return 1; + + struct dirent* entry; + while ((entry = readdir(taskDir))) + { + if (entry->d_type != DT_DIR) continue; + if (!is_numeric(entry->d_name)) continue; + + pid_t pid = strtod(entry->d_name, NULL); + process_status_t status = {}; + if (process_parse_status(pid, &status)) + { + // if we can't some threads, we should fail completely + // failure is better than incomplete info + TRACE("failed to parse %d task status\n", pid); + closedir(taskDir); + return 1; + } + + // add thread to list + process_status_t* _list = *list; + size_t _count = *count; + + if (_count) _list = (process_status_t*)realloc(_list, ++_count * sizeof(process_status_t)); + else _list = (process_status_t*)malloc(++_count * sizeof(process_status_t)); + + if (!_list) + { + TRACE("out of memory for process status!\n"); + closedir(taskDir); + return 1; + } + + // copy thread to list + memcpy(&_list[_count - 1], &status, sizeof(process_status_t)); + + *list = _list; + *count = _count; + } + + closedir(taskDir); + return 0; } \ No newline at end of file