#include <stdio.h>
#include <unistd.h>
#include <sys/stat.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <dirent.h>
#include <pwd.h>
#define MAX_LEN 20
struct ps_info *trav_dir(char dir[]);
int read_info(char d_name[],struct ps_info *p1);
void print_ps(struct ps_info *head);
int is_num(char *);
void uid_to_name();
typedef struct ps_info
{
char pname[MAX_LEN];
char user[MAX_LEN];
int pid;
int ppid;
char state;
struct ps_info *next;
}mps;
int main(int ac,char *av[])
{
mps *head,*link;
head=trav_dir("/proc/");
if(head==NULL)
printf("traverse dir error\n");
print_ps(head);
while(head!=NULL) //釋放鏈表
{
link=head;
head=head->next;
free(link);
}
return 0;
}
mps *trav_dir(char dir[])
{
DIR *dir_ptr;
mps *head,*p1,*p2;
struct dirent *direntp;
struct stat infobuf;
if((dir_ptr=opendir(dir))==NULL)
fprintf(stderr,"dir error %s\n",dir);
else
{
head=p1=p2=(struct ps_info *)malloc(sizeof(struct ps_info)); //建立鏈表
while((direntp=readdir(dir_ptr)) != NULL) //遍歷/proc目錄所有進程目錄
{
if((is_num(direntp->d_name))==0) //判斷目錄名字是否為純數字
{
if(p1==NULL)
{
printf("malloc error!\n");
exit(0);
}
if(read_info(direntp->d_name,p1)!=0) //獲取進程信息
{
printf("read_info error\n");
exit(0);
}
p2->next=p1; //插入新節點
p2=p1;
p1=(struct ps_info *)malloc(sizeof(struct ps_info));
}
}
}
p2->next=NULL;
return head;
}
int read_info(char d_name[],struct ps_info *p1)
{
FILE *fd;
char dir[20];
struct stat infobuf;
sprintf(dir,"%s/%s","/proc/",d_name);
chdir("/proc"); //切換至/proc目錄,不然stat返回-1
if(stat(d_name,&infobuf)==-1) //get process USER
fprintf(stderr,"stat error %s\n",d_name);
else
//p1->user=uid_to_name(infobuf.st_uid);
uid_to_name(infobuf.st_uid, p1);
chdir(dir); //切換到/proc/pid目錄
if((fd=fopen("stat","r"))<0)
{
printf("open the file is error!\n");
exit(0);
}
while(4==fscanf(fd,"%d %s %c %d\n",&(p1->pid),p1->pname,&(p1->state),&(p1->ppid))) //讀文件的前四個字段內容,並存放在相關的鏈表成員中
{
break;
}
fclose(fd);
return 0;
}
void uid_to_name(uid_t uid, struct ps_info *p1) //由進程uid得到進程的所有者user
{
struct passwd *getpwuid(), *pw_ptr;
static char numstr[10];
if((pw_ptr=getpwuid(uid)) == NULL)
{
sprintf(numstr,"%d",uid);
strcpy(p1->user, numstr);
}
else
strcpy(p1->user, pw_ptr->pw_name);
}
int is_num(char p_name[])
{
int i,len;
len=strlen(p_name);
if(len==0) return -1;
for(i=0;i<len;i++)
if(p_name[i]<'0' || p_name[i]>'9')
return -1;
return 0;
}
void print_ps(struct ps_info *head)
{
mps *list;
printf("USER\t\tPID\tPPID\tSTATE\tPNAME\n");
for(list=head;list!=NULL;list=list->next)
{
printf("%s\t\t%d\t%d\t%c\t%s\n",list->user,list->pid,list->ppid,list->state,list->pname);
}
}