The HyperNews Linux KHG Discussion Pages

Idea: try this code

Forum: Filesystems
Re: Question Documentation on /proc/pid#/ dirs?
Date: Sun, 21 Jun 1998 16:58:18 GMT
From: <marty@twsu.campus.mci.net>

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <ctype.h>

#include <pwd.h>
#include <sys/types.h>
#include <dirent.h>

#include <sys/stat.h>
#include <unistd.h>
#include <time.h>

extern int errno;

typedef signed char bool_t;

#if !defined ( FALSE )
#define FALSE 0
#endif

#if !defined ( TRUE )
#define TRUE 1
#endif

#define GU_LINE_BUFFER_LEN 1024
#define GU_FILE_NAME_LEN   81

#define START_TIME_STR_LEN     16
#define DIFF_TIME_STR_LEN      12
#define RUN_TIME_STR_LEN       12

#define GU_DEBUG

#if defined GU_DEBUG
#define GU_ASSERT(A) \
     if (A) { \
     } else { \
         GU_logAssertion( __FILE__, __LINE__ ); \
     }
#else
#define GU_ASSERT(A)
#endif

static FILE *SpfLog = (FILE *) NULL; static char *SszLog = "message.log";

typedef struct UserStatTag {
    int pid;
    char szName[GU_FILE_NAME_LEN];
    char state;
    int ppid;
    int pgrp;
    int sid;
    int terminal;
    int pgid;
    unsigned long flags;
    unsigned long min_flt;
    unsigned long cmin_flt;
    unsigned long maj_flt;
    unsigned long cmaj_flt;
    long utime;
    long stime;
    long cutime;
    long cstime;
    long counter;
    long priority;
    unsigned long timeout;
    unsigned long it_real_value;
    long start_time;
    unsigned size;
    unsigned rss;
    unsigned rlim;
    unsigned long start_code;
    unsigned long end_code;
    unsigned long start_stack;
    unsigned long st_ptr;
    unsigned long ip_ptr;
    unsigned long signal;
    unsigned long blocked;
    unsigned long sv_ignored;
    unsigned long sv_handle;
    unsigned long addr_kernel;
} UserStatStruct;

void
GU_exit(int nLevel)
{
  exit(nLevel);
}

static void
openLogFile(void)
{
  SpfLog = fopen(SszLog, "w");
  if (!SpfLog) {
    fprintf(stderr, "%s(%d): Could not open %s for message logging!\n",
            __FILE__, __LINE__, SszLog);
    GU_exit(-1);
  }
  setvbuf(SpfLog, NULL, 0, _IONBF);
}

static void
closeLogFile(void)
{
  fclose(SpfLog);
  SpfLog = (FILE *) NULL;
}

int
GU_logError(FILE * pf, char *szFmt,...)
{
  va_list vargPtr;

  va_start(vargPtr, szFmt);

  if (!SpfLog) {
    openLogFile();
  }
  if (pf) {
    vfprintf(pf, szFmt, vargPtr);
  }
  vfprintf(SpfLog, szFmt, vargPtr);

  va_end(vargPtr);

return (0); }

void
GU_logAssertion(char *szFile, int nLine)
{
  fprintf(stderr, "%s(%d): Assertion failed!\n", szFile, nLine);
  exit(-99);
}

static int parseTimeLong ( char *timeStr, time_t timeVal, char *timeFormat ) { int returnCode = 0; /* Return code from strftime */ struct tm *tm = (struct tm *)NULL; /* Time struct, used as temp space */

    memset( timeStr, '\0', DIFF_TIME_STR_LEN );

    tm = localtime( &timeVal );
    returnCode = strftime( timeStr,
                           START_TIME_STR_LEN - 4,
                           timeFormat,
                           tm );

return( returnCode ); }

static char * getRunTime ( time_t timeVal ) { static char timeStr[ RUN_TIME_STR_LEN ];

time_t seconds = (time_t)0; time_t minutes = (time_t)0; time_t hours = (time_t)0; time_t days = (time_t)0;

    memset( timeStr, '\0', RUN_TIME_STR_LEN );

    /* If to be reported as ... */
    if ( timeVal < (time_t)60 ) {
        sprintf( timeStr, "%ld s", timeVal );
    } else if ( timeVal < (time_t)3600 ) {
        minutes = timeVal / (time_t)60;
        seconds = timeVal % (time_t)60;
        sprintf( timeStr, "%ld:%ld m", minutes, seconds );
    } else if ( timeVal < (time_t)86400 ) {
        hours   = timeVal / (time_t)3600;
        minutes = ( timeVal % (time_t)3600 ) / (time_t)60;
        seconds = ( timeVal % (time_t)3600 ) % (time_t)60;
        sprintf( timeStr, "%ld:%ld h", hours, minutes );
    } else {                                    
        days    = timeVal / (time_t)86400;
        hours   = ( timeVal % (time_t)86400 ) / (time_t)3600;
        sprintf( timeStr, "%ld:%ld d", days, hours );                  
    }

return( timeStr ); }

/* **************** Start of stuff **************************** */

int main ( int argc, char *argv[] ) { FILE *pf = (FILE *)NULL;

struct passwd *pwdUser = (struct passwd *)NULL;
struct passwd *pwdCurr = (struct passwd *)NULL;

char *pszProc = (char *)NULL;
char *pszUser = (char *)NULL;

DIR *pDir = (DIR *)NULL; struct dirent *pEnt = (struct dirent *)NULL;

char szFileName[GU_FILE_NAME_LEN];

int iRC = 0;

uid_t uidUser;

struct stat ss;

UserStatStruct sus;

time_t ttStart = 0; time_t ttCur = 0; time_t ttMidNight = 0; time_t ttElapsed = 0; time_t ttBoot = 0;

char szLine[GU_LINE_BUFFER_LEN]; char szBuf[GU_LINE_BUFFER_LEN];

int iReadIn;

char *psz = (char *)NULL;

char szStartTime[ START_TIME_STR_LEN ]; char szRunTime[ DIFF_TIME_STR_LEN ];

char *pszStartFormat = (char *)NULL;
char *pszRunFormat = (char *)NULL;

char *pszCurrUser = (char *)NULL;

int i; int j; int k;

struct tm *ptm = (struct tm *)NULL; struct tm tm;

   ttCur = time( (time_t *)NULL );
   ptm = localtime( &ttCur );
   tm = *ptm;
   tm.tm_sec = 0;
   tm.tm_min = 0;
   tm.tm_hour = 0;
   ttMidNight = mktime( &tm );

   /* printf( "%ld %ld\n", ttCur, ttMidNight ); */

   if ( argc == 2 || argc == 3 ) {
           pszProc = argv[1];
       if ( argc == 3 ) {
           pszUser = argv[2];
           pwdUser = getpwnam( pszUser );
           if ( pwdUser ) {
               GU_logError( NULL, "%s has uid %d\n",
                            pwdUser->pw_name, pwdUser->pw_uid );
               uidUser = pwdUser->pw_uid;
           } else {
               GU_logError( stderr, "%s has no account\n", pszUser );
               GU_exit( -1 );
           }
       }
   } else {
       GU_logError( stderr, "%s <base name> [<user>]\n", argv[0] );
       GU_exit( -1 );
   }

   /*
    * Get the boot time!
    */
   sprintf( szFileName, "%s/stat", pszProc );
   pf = fopen( szFileName, "r" );
   if ( !pf ) {
       GU_logError( stderr, "%s(%d): Could not open %s for reading.\n",
                __FILE__, __LINE__, szFileName );
       exit( -1 );
   }

   iReadIn = 0;
   while (fgets(szLine, GU_LINE_BUFFER_LEN, pf)) {                                      
       if ( feof( pf ) ) {                                                         
           break;                                                      
       }

       strcpy( szBuf, szLine );
       iReadIn++;

       psz = strtok(szLine, " ");
       if ( !psz ) {
           continue;
       }

       if ( !strcmp( psz, "btime" ) ) {
           psz = strtok(NULL, "\n");
           if ( !psz ) {
               continue;
           }

           ttBoot = atol( psz );
           break;
       }
   }

   GU_logError( NULL, "Current time is %ld\nBoot Time is %ld\n",
                ttCur, ttBoot );

   fclose( pf );
   pf = (FILE *)NULL;

   pDir = opendir( pszProc );
   if ( !pDir ) {
       GU_logError( stderr, "%s does not exist!\n", pszProc );
       GU_exit( -1 );
   }

   GU_logError( stdout, "%8s %5s %5s %5s %s %3s %12s %12s %5s %s %s\n",
                "User", "pid", "uid", "pgrp", "F", "pri", "start", "elapsed",
                "ppid", "pwd", "command line" );
   while ( 1 ) {
       pEnt = readdir( pDir );
       if ( !pEnt ) {
           break;
       }

       if ( !isdigit( pEnt->d_name[0] ) ) {
           continue;
       }

       GU_logError( NULL, "%s current entry\n", pEnt->d_name );
       sprintf( szFileName, "%s/%s/stat", pszProc, pEnt->d_name );

       iRC = stat( szFileName, &ss );
       if ( iRC ) {
           GU_logError( stderr, "Could not access %s -- %s\n",
                        szFileName, strerror( errno ) );
           continue;
       }

       if ( pszUser && ss.st_uid != uidUser ) {
           continue;
       } else if ( pszUser ) {
           pszCurrUser = pszUser;
       } else {
           pwdCurr = getpwuid( ss.st_uid );
           if ( pwdCurr ) {
                pszCurrUser = pwdCurr->pw_name;
           } else {
               GU_logError( stderr, "%s has no account\n", pszUser );
               continue;
           }
       }

       GU_logError( NULL, "UID = %d\n", ss.st_uid );

       pf = fopen( szFileName, "r" );
       if ( !pf ) {
           GU_logError( stderr, "PID has expired: %s\n", szFileName );
           continue;
       }

       fscanf( pf, "%d %s %c %d %d %d %d %d %lu %lu %lu %lu %lu"
                   "%ld %ld %ld %ld %ld %ld %lu %lu %ld %u %u %u"
                   "%lu %lu %lu %lu %lu %lu %lu %lu %lu %lu",
               &sus.pid, sus.szName, &sus.state, &sus.ppid, &sus.pgrp,
               &sus.sid, &sus.terminal, &sus.pgid, &sus.flags,
               &sus.min_flt, &sus.cmin_flt, &sus.maj_flt, &sus.cmaj_flt,
               &sus.utime, &sus.stime, &sus.cutime, &sus.cstime,
               &sus.counter, &sus.priority, &sus.timeout,
               &sus.it_real_value, &sus.start_time, &sus.size,
               &sus.rss, &sus.rlim, &sus.start_code, &sus.end_code,
               &sus.start_stack, &sus.st_ptr, &sus.ip_ptr, &sus.signal,
               &sus.blocked, &sus.sv_ignored, &sus.sv_handle,
               &sus.addr_kernel );

       GU_logError( NULL, "%d %s %c %d %d %d %d %d %lu %lu %lu %lu %lu"
                   "%ld %ld %ld %ld %ld %ld %lu %lu %ld %u %u %u"
                   "%lu %lu %lu %lu %lu %lu %lu %lu %lu %lu\n",
               sus.pid, sus.szName, sus.state, sus.ppid, sus.pgrp,
               sus.sid, sus.terminal, sus.pgid, sus.flags,
               sus.min_flt, sus.cmin_flt, sus.maj_flt, sus.cmaj_flt,
               sus.utime, sus.stime, sus.cutime, sus.cstime,
               sus.counter, sus.priority, sus.timeout,
               sus.it_real_value, sus.start_time, sus.size,
               sus.rss, sus.rlim, sus.start_code, sus.end_code,
               sus.start_stack, sus.st_ptr, sus.ip_ptr, sus.signal,
               sus.blocked, sus.sv_ignored, sus.sv_handle,
               sus.addr_kernel );

       fclose( pf );
       pf = (FILE *)NULL;

       ttStart = ttBoot + sus.start_time / 100;
       ttElapsed = ttCur - ttStart;

        if ( ttStart < ttMidNight ) {
            pszRunFormat = "%b %d";
            pszStartFormat = "%b %d";
        } else {
            if ( ttElapsed < ( 60 * 60 ) ) {
                pszRunFormat = "%M:%S";
                pszStartFormat = "%r";
            } else if ( ttElapsed < ( 24 * 60 * 60 ) ) {
                pszRunFormat = "%H:%M:%S";
                pszStartFormat = "%r";
            } else {
                pszRunFormat = "%b %d";
                pszStartFormat = "%b %d";
            }
        }

        /* Get the time the process was kicked off */
        parseTimeLong( szStartTime, ttStart, pszStartFormat );

        /* Get the time the proc ran */
#if defined ( NOT_NOW )
        parseTimeLong( szRunTime, ttElapsed, pszRunFormat );
#else
        strcpy( szRunTime, getRunTime( ttElapsed ) );
#endif

	/* username pid uid gid state nice start time elasped time parent pid
	   fullpath command line args */

        GU_logError( stdout,
                     "%8s %5d %5d %5d %c %3d %12s %12s %5d",
                     pszCurrUser, sus.pid, uidUser,
                     sus.pgrp, sus.state, sus.priority, szStartTime, szRunTime,
                     sus.ppid );

       sprintf( szFileName, "%s/%s/environ", pszProc, pEnt->d_name );
       pf = fopen( szFileName, "r" );
       if ( !pf ) {
           GU_logError( stdout, "\n" );
           continue;
       }

       memset( szLine, '\0', GU_LINE_BUFFER_LEN );
       psz = fgets(szLine, GU_LINE_BUFFER_LEN, pf);
       if ( !psz ) {
           GU_logError( NULL,
                        "Could not get data from %s -- %d -- %d\n",
                        szFileName,
                        ferror( pf ), feof( pf ) );
       }

       for ( i = 0; i < GU_LINE_BUFFER_LEN; i = k ) {
           for ( k = i + 1; k < GU_LINE_BUFFER_LEN; k++ ) {
               if ( szLine[k] == '=' ) {
                   szLine[k] = '\0';
                   j = k + 1;
               } else if ( szLine[k] == '\0' ) {
                   k++;
                   break;
               }
           }

           if ( !strcmp( &szLine[i], "PWD" ) ) {
               GU_logError( stdout, " %s", &szLine[j] );
               break;
           }
       }

       fclose( pf );
       pf = (FILE *)NULL;

       sprintf( szFileName, "%s/%s/cmdline", pszProc, pEnt->d_name );
       pf = fopen( szFileName, "r" );
       if ( !pf ) {
           GU_logError( stdout, "\n" );
           continue;
       }

       memset( szLine, '\0', GU_LINE_BUFFER_LEN );
       psz = fgets(szLine, GU_LINE_BUFFER_LEN, pf);
       if ( !psz ) {
           GU_logError( NULL,
                        "Could not get data from %s -- %d -- %d\n",
                        szFileName,
                        ferror( pf ), feof( pf ) );
       }

       for ( i = 0; i < GU_LINE_BUFFER_LEN; i++ ) {
           if ( szLine[i] == '\0' ) {
               szLine[i] = ' ';
           }
       }

       for ( i--; i > 0; i-- ) {
           if ( szLine[i] != ' ' ) {
               break;
           } else {
               szLine[i] = '\0';
           }
       } 

       GU_logError( stdout, " %s", szLine );

       fclose( pf );
       pf = (FILE *)NULL;

       GU_logError( stdout, "\n" );
   }

   closedir( pDir );

   closeLogFile();
   return ( 0 );
}