home *** CD-ROM | disk | FTP | other *** search
/ Black Box 4 / BlackBox.cdr / os2 / procs.arj / PROCS.C < prev    next >
Encoding:
C/C++ Source or Header  |  1992-05-31  |  23.8 KB  |  554 lines

  1. /**********************************************************************
  2.  * MODULE NAME :  procs.c                AUTHOR:  Rick Fishman        *
  3.  * DATE WRITTEN:  05-30-92                                            *
  4.  *                                                                    *
  5.  * DESCRIPTION:                                                       *
  6.  *                                                                    *
  7.  *  This program lists all running processes under OS/2 2.0. It uses  *
  8.  *  the undocumented API DosQProcStatus to get a buffer filled with   *
  9.  *  information related to the current state of the system. It then   *
  10.  *  performs the following using the buffer:                          *
  11.  *                                                                    *
  12.  *  1. Get the relevant process information for all active pids into  *
  13.  *     an array.                                                      *
  14.  *  2. Go thru the module information table. For each module found,   *
  15.  *     compare its module reference number against all module         *
  16.  *     reference numbers associated with the active pids. If any      *
  17.  *     match, add the module name to the active pid array.            *
  18.  *  3. Print the process names that were found.                       *
  19.  *                                                                    *
  20.  * UPDATES:                                                           *
  21.  *                                                                    *
  22.  **********************************************************************/
  23.  
  24.  
  25. /*********************************************************************/
  26. /*------- Include relevant sections of the OS/2 header files --------*/
  27. /*********************************************************************/
  28.  
  29. #define INCL_DOSERRORS
  30. #define INCL_DOSPROCESS
  31. #define INCL_VIO
  32.  
  33. /**********************************************************************/
  34. /*----------------------------- INCLUDES -----------------------------*/
  35. /**********************************************************************/
  36.  
  37. #include <os2.h>
  38. #include <conio.h>
  39. #include <ctype.h>
  40. #include <process.h>
  41. #include <stdarg.h>
  42. #include <stdio.h>
  43. #include <string.h>
  44. #include <stdlib.h>
  45. #include "procstat.h"
  46.  
  47. /*********************************************************************/
  48. /*------------------- APPLICATION DEFINITIONS -----------------------*/
  49. /*********************************************************************/
  50.  
  51. #define BUFFER_SIZE         0x8000
  52.  
  53. #define SCREEN_LINE_OVERHD  3
  54. #define DEF_SCREEN_LINES    25
  55.  
  56.                                 // COMMAND-LINE OPTIONS
  57. #define SUPPRESSMORE        'S' // Suppress More[Y,N] messages
  58.  
  59. #define OUT_OF_MEMORY_MSG   "\nOut of memory!\n"
  60.  
  61. #define COPYRIGHT_INFO      "Procs.exe, 32-bit, Version 2.0\n"                 \
  62.                             "Copyright (c) Code Blazers, Inc. 1991-1992. "     \
  63.                             "All rights reserved.\n"
  64.  
  65. #define USAGE_INFO          "\nusage: procs StartingPoint [ /s ]\n "           \
  66.                             "\n    StartingPoint is a string that indicates "  \
  67.                             "\n    a ProcessName or partial ProcessName after" \
  68.                             "\n    which to start listing running processes"   \
  69.                             "\n"                                               \
  70.                             "\n    /s - Suppress More[y,n] displays"           \
  71.                             "\n\n"
  72.  
  73. /**********************************************************************/
  74. /*---------------------------- STRUCTURES ----------------------------*/
  75. /**********************************************************************/
  76.  
  77. typedef struct _ACTIVEPID           // INFO ON AN ACTIVE PROCESS
  78. {
  79.     USHORT  hModRef;                // It's module reference handle
  80.     PID     pid;                    // It's Process Id
  81.     PSZ     szProcess;              // It's name
  82.  
  83. } ACTIVEPID, *PACTIVEPID;
  84.  
  85. /**********************************************************************/
  86. /*----------------------- FUNCTION PROTOTYPES ------------------------*/
  87. /**********************************************************************/
  88.  
  89. INT   main               ( INT argc, PSZ szArg[] );
  90. BOOL  Init               ( INT argc, PSZ szArg[] );
  91. BOOL  BuildActivePidTbl  ( PPROCESSINFO ppi );
  92. INT   CompareActivePids  ( const void *pActivePid1, const void *pActivePid2 );
  93. VOID  Procs              ( PSZ szStartingPoint );
  94. VOID  StoreProcessName   ( PMODINFO pmi );
  95. INT   CompareProcessNames( const void *pActivePid1, const void *pActivePid2 );
  96. VOID  PrintReport        ( PSZ szStartingPoint );
  97. VOID  Term               ( VOID );
  98.  
  99. /**********************************************************************/
  100. /*------------------------ GLOBAL VARIABLES --------------------------*/
  101. /**********************************************************************/
  102.  
  103. BOOL        fSuppressMore;
  104.  
  105. INT         iStartingPoint;
  106.  
  107. USHORT      usActiveProcesses,      // Number of active processes
  108.             usScreenLines;
  109.  
  110. ACTIVEPID   *aActivePid;            // Array of active processes
  111.  
  112. PBUFFHEADER pbh;                    // Pointer to buffer header structure
  113.  
  114. /**********************************************************************/
  115. /*------------------------------ MAIN --------------------------------*/
  116. /*                                                                    */
  117. /*  MAIN DRIVER FOR PROGRAM.                                          */
  118. /*                                                                    */
  119. /*  INPUT: number of command-line arguments,                          */
  120. /*         command-line argument array                                */
  121. /*                                                                    */
  122. /*  1. Perform program initialization which will issue the            */
  123. /*     DosQProcStatus call and obtain the buffer of information.      */
  124. /*  2. If a starting point was given on the commandline, pass that    */
  125. /*     to the Procs function that will list running processes. If not,*/
  126. /*     pass a NULL address to the Procs function.                     */
  127. /*  3. Perform program termination.                                   */
  128. /*                                                                    */
  129. /*  OUTPUT: nothing                                                   */
  130. /*--------------------------------------------------------------------*/
  131. /**********************************************************************/
  132. INT main( INT argc, PSZ szArg[] )
  133. {
  134.     if( Init( argc, szArg ) )
  135.         if( iStartingPoint )
  136.             Procs( szArg[ iStartingPoint ] );
  137.         else
  138.             Procs( NULL );
  139.  
  140.     Term();
  141.  
  142.     return 0;
  143. }
  144.  
  145. /**********************************************************************/
  146. /*------------------------------ Init --------------------------------*/
  147. /*                                                                    */
  148. /*  PERFORM PROGRAM INITIALIZATION.                                   */
  149. /*                                                                    */
  150. /*  INPUT: number of command-line arguments,                          */
  151. /*         command-line argument array                                */
  152. /*                                                                    */
  153. /*  1. Print copyright notice.                                        */
  154. /*  2. If too many commandline parms, exit with usage info.           */
  155. /*  3. Process commandline options:                                   */
  156. /*     A. If SUPPRESSMORE option is found, set the appropriate flag.  */
  157. /*     B. If an invalid option, exit with usage info.                 */
  158. /*     C. If a starting point was specified, store the index into     */
  159. /*        the argv array for later use.                               */
  160. /*  4. Alocate memory for the output from DosQProcStatus.             */
  161. /*  5. Make the DosQProcStatus call.                                  */
  162. /*  6. Build an array of information related to active processes.     */
  163. /*  7. Get the number of screen lines supported by the window we are  */
  164. /*     running under.                                                 */
  165. /*                                                                    */
  166. /*  OUTPUT: TRUE or FALSE if successful or not                        */
  167. /*                                                                    */
  168. /*--------------------------------------------------------------------*/
  169. /**********************************************************************/
  170. BOOL Init( INT argc, PSZ szArg[] )
  171. {
  172.     SHORT   sIndex;
  173.     USHORT  usRetCode;
  174.     BOOL    fSuccess = TRUE;
  175.  
  176.     printf( COPYRIGHT_INFO );
  177.  
  178.     if( argc > 3 )
  179.     {
  180.         (void) printf( USAGE_INFO );
  181.  
  182.         fSuccess = FALSE;
  183.     }
  184.  
  185.     for( sIndex = 1; fSuccess && sIndex < argc; sIndex++ )
  186.     {
  187.         if( szArg[ sIndex ][ 0 ] == '/' || szArg[ sIndex ][ 0 ] == '-' )
  188.         {
  189.             switch( toupper( szArg[ sIndex ][ 1 ] ) )
  190.             {
  191.                 case SUPPRESSMORE:
  192.                     fSuppressMore = TRUE;
  193.  
  194.                     break;
  195.  
  196.                 default:
  197.                     (void) printf( USAGE_INFO );
  198.  
  199.                     fSuccess = FALSE;
  200.             }
  201.         }
  202.         else if( !iStartingPoint )
  203.             iStartingPoint = sIndex;
  204.         else
  205.         {
  206.             (void) printf( USAGE_INFO );
  207.  
  208.             fSuccess = FALSE;
  209.         }
  210.     }
  211.  
  212.     if( fSuccess && !(pbh = malloc( BUFFER_SIZE )) )
  213.     {
  214.         printf( OUT_OF_MEMORY_MSG );
  215.  
  216.         fSuccess = FALSE;
  217.     }
  218.  
  219.     if( fSuccess )
  220.     {
  221.         usRetCode = DosQProcStatus( pbh, BUFFER_SIZE );
  222.  
  223.         if( usRetCode )
  224.         {
  225.             printf( "\nDosQProcStatus failed. RC: %u.", usRetCode );
  226.  
  227.             fSuccess = FALSE;
  228.         }
  229.         else
  230.             fSuccess = BuildActivePidTbl( pbh->ppi );
  231.     }
  232.  
  233.     if( fSuccess )
  234.     {
  235.         VIOMODEINFO vmi;
  236.  
  237.         vmi.cb = sizeof( VIOMODEINFO );
  238.  
  239.         usRetCode = VioGetMode( &vmi, 0 );
  240.  
  241.         if( usRetCode )
  242.             usScreenLines = DEF_SCREEN_LINES - SCREEN_LINE_OVERHD;
  243.         else
  244.             usScreenLines = vmi.row - SCREEN_LINE_OVERHD;
  245.     }
  246.  
  247.     return fSuccess;
  248. }
  249.  
  250. /**********************************************************************/
  251. /*------------------------ BuildActivePidTbl -------------------------*/
  252. /*                                                                    */
  253. /*  BUILD AN ARRAY OF ACTIVE PROCESSES USING THE PROCESS INFO SECTION */
  254. /*  OF THE DosQProcStatus BUFFER.                                     */
  255. /*                                                                    */
  256. /*  INPUT: pointer to ProcessInfo section of buffer                   */
  257. /*                                                                    */
  258. /*  1. Get a count of active processes.                               */
  259. /*  2. Allocate memory for the ActiveProcess table.                   */
  260. /*  3. Store information about each active process in the table.      */
  261. /*  4. Sort the table in ascending module number order.               */
  262. /*                                                                    */
  263. /*  OUTPUT: exit code                                                 */
  264. /*                                                                    */
  265. /*--------------------------------------------------------------------*/
  266. /**********************************************************************/
  267. BOOL BuildActivePidTbl( PPROCESSINFO ppi )
  268. {
  269.     PPROCESSINFO ppiLocal = ppi;
  270.     BOOL         fSuccess = TRUE;
  271.  
  272.     // Count the number of processes in the process info section. The process
  273.     // count in the summary record is not reliable (2/17/92 - version 6.177)
  274.  
  275.     usActiveProcesses = 0;
  276.  
  277.     while( ppiLocal->ulEndIndicator != PROCESS_END_INDICATOR )
  278.     {
  279.         usActiveProcesses++;
  280.  
  281.         // Next PROCESSINFO struct found by taking the address of the first
  282.         // thread control block of the current PROCESSINFO structure and
  283.         // adding the size of a THREADINFO structure times the number of
  284.         // threads
  285.  
  286.         ppiLocal = (PPROCESSINFO) (ppiLocal->ptiFirst+ppiLocal->usThreadCount );
  287.     }
  288.  
  289.     if( !(aActivePid = malloc( usActiveProcesses * sizeof( ACTIVEPID ) )) )
  290.     {
  291.         printf( OUT_OF_MEMORY_MSG );
  292.  
  293.         fSuccess = FALSE;
  294.     }
  295.     else
  296.     {
  297.         INT i;
  298.  
  299.         memset( aActivePid, 0, usActiveProcesses * sizeof( ACTIVEPID ) );
  300.  
  301.         for( i = 0; i < usActiveProcesses; i++ )
  302.         {
  303.             aActivePid[ i ].hModRef = ppi->hModRef;
  304.  
  305.             aActivePid[ i ].pid = (PID) ppi->pid;
  306.  
  307.             ppi = (PPROCESSINFO) (ppi->ptiFirst + ppi->usThreadCount);
  308.         }
  309.  
  310.         qsort( aActivePid, usActiveProcesses, sizeof( ACTIVEPID ),
  311.                CompareActivePids );
  312.     }
  313.  
  314.     return fSuccess;
  315. }
  316.  
  317. /**********************************************************************/
  318. /*------------------------ CompareActivePids -------------------------*/
  319. /*                                                                    */
  320. /*  COMPARE FUNCTION FOR THE QSORT OF THE ACTIVE PID ARRAY. SORTS     */
  321. /*  THE ARRAY IN MODULE HANDLE ORDER.                                 */
  322. /*                                                                    */
  323. /*  INPUT: pointer to first element for compare,                      */
  324. /*         pointer to second element of compare                       */
  325. /*                                                                    */
  326. /*  1. Do the compare.                                                */
  327. /*                                                                    */
  328. /*  OUTPUT: < 0 means first < second                                  */
  329. /*          = 0 means first = second                                  */
  330. /*          > 0 means first > second                                  */
  331. /*                                                                    */
  332. /*--------------------------------------------------------------------*/
  333. /**********************************************************************/
  334. INT CompareActivePids( const void *pActivePid1, const void *pActivePid2 )
  335. {
  336.     if( ((PACTIVEPID)pActivePid1)->hModRef < ((PACTIVEPID)pActivePid2)->hModRef )
  337.         return -1;
  338.     else
  339.     if( ((PACTIVEPID)pActivePid1)->hModRef > ((PACTIVEPID)pActivePid2)->hModRef )
  340.         return +1;
  341.     else
  342.         return 0;
  343. }
  344.  
  345. /**********************************************************************/
  346. /*------------------------------ Procs -------------------------------*/
  347. /*                                                                    */
  348. /*  LIST ALL RUNNING PROCESSES.                                       */
  349. /*                                                                    */
  350. /*  INPUT: starting point of report                                   */
  351. /*                                                                    */
  352. /*  1. Print the titles for the report.                               */
  353. /*  2. Store the process names in the ActivePid array.                */
  354. /*  3. Sort the ActivePid array by process name.                      */
  355. /*  4. Print the report.                                              */
  356. /*                                                                    */
  357. /*  OUTPUT: nothing                                                   */
  358. /*                                                                    */
  359. /*--------------------------------------------------------------------*/
  360. /**********************************************************************/
  361. VOID Procs( PSZ szStartingPoint )
  362. {
  363.     PMODINFO pmi = pbh->pmi;
  364.  
  365.     printf( "\n%-25.25s %-5.5s %-9.9s",
  366.             "Process Name", "PID", "PID(hex)" );
  367.  
  368.     printf( "\n%-25.25s %-5.5s %-9.9s",
  369.             "──────────────────────", "───", "────────" );
  370.  
  371.     while( pmi )
  372.     {
  373.         StoreProcessName( pmi );
  374.  
  375.         pmi = pmi->pNext;
  376.     }
  377.  
  378.     qsort( aActivePid, usActiveProcesses, sizeof( ACTIVEPID ),
  379.            CompareProcessNames );
  380.  
  381.     PrintReport( szStartingPoint );
  382. }
  383.  
  384. /**********************************************************************/
  385. /*------------------------- StoreProcessName -------------------------*/
  386. /*                                                                    */
  387. /*  STORE THE PROCESS NAME FOR LATER PRINTING.                        */
  388. /*                                                                    */
  389. /*  INPUT: pointer to MODINFO structure                               */
  390. /*                                                                    */
  391. /*  1. Go thru each entry in the ActivePid array:                     */
  392. /*     A. If the module reference handle in the array is greater      */
  393. /*        than the one passed here, we could not find a match         */
  394. /*        because at this point the ActivePid array is sorted in      */
  395. /*        module reference handle order.                              */
  396. /*     B. If we find a match:                                         */
  397. /*        1. Set a pointer to the beginning of the process name,      */
  398. /*           since the name in the buffer is fully qualified.         */
  399. /*        2. Allocate memory for the process name in the ActivePid    */
  400. /*           array element.                                           */
  401. /*        3. Copy the process name into the allocated memory.         */
  402. /*                                                                    */
  403. /*  OUTPUT: nothing                                                   */
  404. /*--------------------------------------------------------------------*/
  405. /**********************************************************************/
  406. VOID StoreProcessName( PMODINFO pmi )
  407. {
  408.     INT i;
  409.     PSZ szProcess;
  410.  
  411.     for( i = 0; i < usActiveProcesses; i++ )
  412.     {
  413.         if( aActivePid[ i ].hModRef > pmi->hMod )
  414.             break;
  415.  
  416.         if( aActivePid[ i ].hModRef == pmi->hMod )
  417.         {
  418.             szProcess = strrchr( pmi->szModName, '\\' );
  419.  
  420.             if( szProcess )
  421.                 szProcess++;
  422.             else
  423.                 szProcess = pmi->szModName;
  424.  
  425.             aActivePid[ i ].szProcess = malloc( strlen( szProcess ) + 1 );
  426.  
  427.             if( aActivePid[ i ].szProcess )
  428.                 (void) strcpy( aActivePid[ i ].szProcess, szProcess );
  429.             else
  430.                 (void) printf( OUT_OF_MEMORY_MSG );
  431.         }
  432.     }
  433. }
  434.  
  435. /**********************************************************************/
  436. /*----------------------- CompareProcessNames ------------------------*/
  437. /*                                                                    */
  438. /*  COMPARE FUNCTION FOR THE QSORT OF THE ACTIVE PID ARRAY. SORTS     */
  439. /*  THE ARRAY IN PROCESS NAME ORDER.                                  */
  440. /*                                                                    */
  441. /*  INPUT: pointer to first element for compare,                      */
  442. /*         pointer to second element of compare                       */
  443. /*                                                                    */
  444. /*  1. Do the compare.                                                */
  445. /*                                                                    */
  446. /*  OUTPUT: return from stricmp                                       */
  447. /*                                                                    */
  448. /*--------------------------------------------------------------------*/
  449. /**********************************************************************/
  450. INT CompareProcessNames( const void *pActivePid1, const void *pActivePid2 )
  451. {
  452.     return stricmp( ((PACTIVEPID) pActivePid1)->szProcess,
  453.                     ((PACTIVEPID) pActivePid2)->szProcess );
  454. }
  455.  
  456. /**********************************************************************/
  457. /*--------------------------- PrintReport ----------------------------*/
  458. /*                                                                    */
  459. /*  PRINT INFO ABOUT EACH PROCESS.                                    */
  460. /*                                                                    */
  461. /*  INPUT: starting point to begin report                             */
  462. /*                                                                    */
  463. /*  1. For each element in the ActivePid array:                       */
  464. /*     A. If there is a process name for this element:                */
  465. /*        1. If we are not passed the starting point specified on     */
  466. /*           the commandline, get the next element.                   */
  467. /*        2. If we have exceeeded the screen lines for the window     */
  468. /*           that we are running under and the user has not specified */
  469. /*           to suppress the More[Y,N] messages, display that message */
  470. /*           and wait on a key. If the user wants more displayed,     */
  471. /*           continue, else exit.                                     */
  472. /*        3. Print information about the process.                     */
  473. /*                                                                    */
  474. /*  OUTPUT: nothing                                                   */
  475. /*--------------------------------------------------------------------*/
  476. /**********************************************************************/
  477. VOID PrintReport( PSZ szStartingPoint )
  478. {
  479.     INT     i;
  480.     USHORT  usLines = 0;
  481.  
  482.     for( i = 0; i < usActiveProcesses; i++ )
  483.         if( aActivePid[ i ].szProcess )
  484.         {
  485.             if( szStartingPoint &&
  486.                 stricmp( szStartingPoint, aActivePid[ i ].szProcess ) > 0 )
  487.                 continue;
  488.  
  489.             if( !fSuppressMore && ++usLines > usScreenLines )
  490.             {
  491.                 int KbdChar;
  492.  
  493.                 printf( "\nMore [Y,N]?" );
  494.  
  495.                 fflush( stdout );
  496.  
  497.                 KbdChar = getch();
  498.  
  499.                 printf( "\r           \r" );
  500.  
  501.                 fflush( stdout );
  502.  
  503.                 if( toupper( KbdChar ) == 'N' )
  504.                     return;
  505.  
  506.                 usLines = 0;
  507.             }
  508.             else
  509.                 printf( "\n" );
  510.  
  511.             printf( "%-25.25s %-5u %-9x", aActivePid[ i ].szProcess,
  512.                     aActivePid[ i ].pid, aActivePid[ i ].pid );
  513.         }
  514. }
  515.  
  516. /**********************************************************************/
  517. /*------------------------------ Term --------------------------------*/
  518. /*                                                                    */
  519. /*  PERFORM PROGRAM TERMINATION                                       */
  520. /*                                                                    */
  521. /*  INPUT: nothing                                                    */
  522. /*                                                                    */
  523. /*  1. Free the ActiveProcess array. First free the memory for the    */
  524. /*     process name associated with each element of the array.        */
  525. /*  2. Free the buffer allocated for the DosQProcStatus output.       */
  526. /*  3. Return to the operating system.                                */
  527. /*                                                                    */
  528. /*  OUTPUT: nothing                                                   */
  529. /*                                                                    */
  530. /*--------------------------------------------------------------------*/
  531. /**********************************************************************/
  532. VOID Term()
  533. {
  534.     if( aActivePid )
  535.     {
  536.         INT i;
  537.  
  538.         for( i = 0; i < usActiveProcesses; i++ )
  539.             if( aActivePid[ i ].szProcess )
  540.                 free( aActivePid[ i ].szProcess );
  541.  
  542.         free( aActivePid );
  543.     }
  544.  
  545.     if( pbh )
  546.         free( pbh );
  547.  
  548.     DosExit( EXIT_PROCESS, 0 );
  549. }
  550.  
  551. /**********************************************************************
  552.  *                       END OF SOURCE CODE                           *
  553.  **********************************************************************/
  554.