Advertisement

Some loose ends

Started by March 31, 2002 05:42 AM
-1 comments, last by pdstatha 22 years, 10 months ago
Please read the following long commented piece of 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. 

 Fortunately there are only a few things to iron out now
 here goes. 
 1. When the processes and their details get printed out
    they are not in order. I can''t say i really understand
    why this doesn''t happen as this line in main should 
    perform this task

    count = scandir(path,&direntp,NULL,alphasort);

 2. 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 = "?";

 3. Getting the run time of the process is not always succesful,
    for example it sometimes gives the correct output such as
    00:00:05 (Hours,Minutes,Seconds). But some of the time it prints
    garble instead eg.

    h-@h-@

    This seems to suggest to me that the variable time hasn''t been assigned
    any value and is just printing non-sense, where as it can be clearly
    seen that this is not the case.

    time = getTime(stime);

 4. 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 user. Would this involve use of the getuid method??   

    */

#include <stdio.h>
#include <sys/types.h>
#include <fcntl.h>
#include <dirent.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* getTime(int clockticks);
char *get_regerror(int errcode,regex_t *compiled);

int main(void){
  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*/

  if (stat(path,&sbuf) != -1){
    if(S_ISDIR(sbuf.st_mode)){
       count = scandir(path,&direntp,NULL,alphasort);
       if(count){
         char temp[FILENAME_MAX];
         printf("PID      TTY         TIME      CMD\n");
         for(index=0; indexd_name,temp);
           if(result > 0)   /*If directory name was matched*/
             printDetails(direntp[index]->d_name,temp);
           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){
  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",&pid,&pname,&tty,&stime);
    t_name = ttyname(tty);
    time = getTime(stime); 
    if(t_name == NULL)
      t_name = "?";           
    printf("%-9d%-12s%-6s  %s\n",pid,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);
  free(time); 

  return time;
}

/*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;
} 

This topic is closed to new replies.

Advertisement