The program reads the proc file system, namely, it must read the stat process files. At me on 3 processes everything falls on segmentation fault. Falls on fopen () when fopen calls malloc; I can not understand what's wrong.
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include <string.h> #include <dirent.h> #include <stdbool.h> #include <errno.h> #define MAX_LENGTH_FILENAME 120 typedef struct proc_info { int pid; char *name; int ppid; } proc_info; typedef struct Node { proc_info *info; struct Node *next; struct Node *prev; } Node; typedef struct List { size_t size; struct Node *head; struct Node *tail; } List; List *createList() { List *tmp = (List *) malloc (sizeof(List)); tmp->head = NULL; tmp->tail = NULL; tmp->size = 0; return tmp; } void copy_proc_info(proc_info *dst, const proc_info *src) { size_t len = strlen(src->name); dst->pid = src->pid; dst->ppid = src->ppid; dst->name = (char *) malloc(len + 1); if (NULL == dst->name) { fprintf(stderr,"Error get new memory.\nNot create new char*!\n"); } else { strncpy(dst->name, src->name, len + 1); } } void push_back(List *list, const proc_info *info) { int rezult = 0; Node *tmp = (Node *) malloc(sizeof(Node)); if (NULL == tmp) { fprintf(stderr,"Error get new memory.\nNot create new Node!\n"); return; } tmp->next = NULL; tmp->prev = list->tail; copy_proc_info(tmp->info, info); if (list->tail) { list->tail->next = tmp; } list->tail = tmp; if (list->head == NULL) { list->head = tmp; } list->size++; } bool cat_stat_file(const char *dir_name, struct proc_info *info) { errno = 0; bool rezult = false; char buf[MAX_LENGTH_FILENAME+1+11]; sprintf(buf, "/proc/%s/stat", dir_name); printf("%s", buf); FILE *f = fopen(buf, "r"); //погибает здесь на 3 вызове if (errno && (NULL == f)) { fprintf(stderr, "Error open file %s\n", buf); perror(""); } else { fscanf(f,"%d %s %*c %d", &info->pid, &buf, &info->ppid); printf("%s\n", buf); if (errno) { fprintf(stderr, "Error read file %s.\n", dir_name); perror(""); errno = 0; } else { size_t len = strlen(buf) + 1; info->name = (char *) malloc(len); strncpy(info->name, buf, len); rezult = true; } fclose(f); if (errno) { fprintf(stderr, "Error close file %s.\n", dir_name); perror(""); errno = 0; } } return rezult; } List *get_dir_list(const char *dir_name) { struct proc_info *dir_list = NULL; DIR *dir; struct dirent *entry; List *list = createList(); if ((dir = opendir(dir_name)) == NULL) { fprintf(stderr, "Error opendir %s\n", dir_name); perror(""); errno = 0; return NULL; } while ( (entry = readdir(dir)) != NULL) { if (errno) { fprintf(stderr, "Error read_dir %s\n", dir_name); perror(""); errno = 0; continue; } if ( (entry->d_type != DT_DIR) || (strlen(entry->d_name) > 5) || !strtol(entry->d_name, NULL, 0)) {continue;} proc_info *info = (struct proc_info *) malloc(sizeof(proc_info)); if (cat_stat_file(entry->d_name, info)) push_back(list, info); else free(info); }; return list; } int main() { List *list = get_dir_list("/proc"); //destroyList(&list); return 0; }
MAX_LENGTH_FILENAMEmay be too small? It’s better for paths to usePATH_MAX, defined instdlib.h(more precisely in/usr/include/linux/limits.h, but it is pulled up viastdlib). / Dynamically allocateproc_infoclearly superfluous. This information can be placed immediately in theNode/ The process name may contain spaces (you have already asked for something like this), but fortunately, it is enclosed in brackets. It is better to read the entire file (or rather its only line)fgets()and localize the name there by callingstrchr/strrchrto search for parentheses. ppid can then be read bysscanf, from the right bracket. - avp