Code:
/*This program will scan through a directory
if it finds subdirectories within it, it will
check if the name of the directory is a digit
if it is it will return 1, otherwise a 0. Based
upon the return value, the program will print the
details of the process that was matched (a match
being a 1). These details are obtained by opening
a file stream to the processes stat file, and then
scanning through the details using the fscanf function.
This program is in essence a mimmick of the ps command.
This code will only work if your version of linux uses the /proc
directory.
Fortunately there are only a few things to iron out now
here goes.
1. The tty that the process uses seems to report back
incorecctly, infact the only one it seems to recognise
is pts/0 it never once mentions ttyx (where x is a number),
Also some of the time it comes back as null, where as if
I use the ps command normally those that are null in my version
have value in the proper version. Here are the lines associated
with tty.
t_name = ttyname(tty);
if(t_name == NULL)
t_name = "?";
2. I suppose while i'm asking stuff I might aswell ask for ideas on implementing
"ps -A" which basically prints all the current processes, not those just
belonging to the current terminal.
*/
#include <stdio.h>
#include <sys/types.h>
#include <fcntl.h>
#include <dirent.h>
#include <string.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <regex.h>
#include <unistd.h>
#define SIZE 256
/*prototypes*/
int matchDetails(char* filename,char* path);
void printDetails(char* filename,char* path,char* termid);
char* getTime(int clockticks);
int intcompare(const void *a,const void *b);
char *get_regerror(int errcode,regex_t *compiled);
int main(int argc,char **argv){
int result,count,index; /*Set Conditions*/
char path[] = "/proc"; /*Path to the proc directory*/
struct dirent **direntp; /*Directory entry pointer*/
struct stat sbuf; /*Holds information about files*/
char temp[FILENAME_MAX];
char* termid;
if(argv[1] != '\0'){
if(strcmp(argv[1], "-A") == 0){
if (stat(path,&sbuf) != -1){
if(S_ISDIR(sbuf.st_mode)){
count = scandir(path,&direntp,NULL,intcompare);
if(count){
printf("PID TTY TIME CMD\n");
for(index=0; index<count; ++index){
strcpy(temp,path);
result = matchDetails(direntp[index]->d_name,temp);
if(result > 0) /*If directory name was matched*/
printDetails(direntp[index]->d_name,temp,NULL);
free(direntp[index]);
}
}else{
fprintf(stderr,"Can't open %s\n",path);
exit(EXIT_FAILURE);
}
}else
return;
}else{
fprintf(stderr,"Can't stat %s\n",path);
return;
}
}else
printf("INVALID OPTION\n");
}else{
if (stat(path,&sbuf) != -1){
if(S_ISDIR(sbuf.st_mode)){
termid = ctermid(NULL);
count = scandir(path,&direntp,NULL,intcompare);
if(count){
printf("PID TTY TIME CMD\n");
for(index=0; index<count; ++index){
strcpy(temp,path);
result = matchDetails(direntp[index]->d_name,temp);
if(result > 0) /*If directory name was matched*/
printDetails(direntp[index]->d_name,temp,termid);
free(direntp[index]);
}
}else{
fprintf(stderr,"Can't open %s\n",path);
exit(EXIT_FAILURE);
}
}else
return;
}else{
fprintf(stderr,"Can't stat %s\n",path);
return;
}
}
return EXIT_SUCCESS;
}
/*Used to find process directories*/
int matchDetails(char* filename,char* path){
int status,regstat;
char *pattern = "[0-9]+"; /*Match digits only*/
char *result;
struct stat sbuf;
/*Get the full pathname*/
strcat(path,"/");
strcat(path,filename);
/*Stat the full path name*/
if(stat(path,&sbuf) != -1){
if(S_ISDIR(sbuf.st_mode)){ /*If a directory*/
regex_t re;
if((regstat = regcomp(&re,pattern,REG_EXTENDED | REG_NOSUB)) != 0){
result = get_regerror(regstat,&re);
fprintf(stderr,"%s\n",result);
return(0);
}
if((status = regexec(&re,filename,(size_t) 0,NULL,0)) != 0)
return(0);
regfree(&re);
}else
return(0);
}else{
fprintf(stderr,"Can't stat %s\n",filename);
return(0);
}
return(1);
}
/*Print the process information*/
void printDetails(char* filename,char* path,char* termid){
FILE *f_name;
int pid,tty,stime;
char pname[FILENAME_MAX];
char* t_name;
char* time;
/*Format the path*/
strcat(path,"/");
strcat(path,"stat");
if((f_name = fopen(path,"r")) != NULL){
fscanf(f_name,"%*d %s %*c %*d %*d %*d %d %*d "
"%*u %*u %*u %*u %*u %*d %d",&pname,&tty,&stime);
t_name = ttyname(tty);
time = getTime(stime);
if(t_name == NULL)
t_name = "?";
if(termid == NULL){
printf("%-9s%-12s%-6s %s\n",filename,t_name,time,pname);
}else{
if(t_name == termid)
printf("%-9s%-12s%-6s %s\n",filename,t_name,time,pname);
}
fclose(f_name);
}else
fprintf(stderr,"Can't open %s\n",path);
}
/*Format jiffies into hours,minutes,seconds*/
char* getTime(int clockticks){
float jiffies,result;
int min,hr,seconds;
char* time = (char*)malloc(SIZE);
jiffies = 0.01f;
result = jiffies * clockticks;
seconds = result;
min = seconds/60;
hr = min/60;
seconds %= 60; /*MOD it into 0-59*/
min %= 60; /*MOD it into 0-59*/
if(hr < 10 && min < 10 && seconds < 10)
sprintf(time,"0%d:0%d:0%d",hr,min,seconds);
else if(hr < 10 && min < 10)
sprintf(time,"0%d:0%d:%d",hr,min,seconds);
else if(hr < 10 && seconds < 10)
sprintf(time,"0%d:%d:0%d",hr,min,seconds);
else if(min < 10 && seconds < 10)
sprintf(time,"%d:0%d:0%d",hr,min,seconds);
else if(hr < 10)
sprintf(time,"0%d:%d:%d",hr,min,seconds);
else if(min < 10)
sprintf(time,"%d:0%d:%d",hr,min,seconds);
else if(seconds < 10)
sprintf(time,"%d:%d:0%d",hr,min,seconds);
else
sprintf(time,"%d:%d:%d",hr,min,seconds);
return time;
}
/*Used for sorting processes*/
int intcompare(const void *a,const void *b){
struct dirent * const *x=a, * const *y=b;
return atoi((*x)->d_name) - atoi((*y)->d_name);
}
void dirStuff(char* path){
}
/*Used to store regex errors*/
char *get_regerror(int errcode,regex_t *compiled){
size_t length = regerror(errcode,compiled,NULL,0);
char *buffer = malloc(length);
(void) regerror(errcode,compiled,buffer,length);
return buffer;
}