home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 11 Util
/
11-Util.zip
/
KILLEM.ZIP
/
KILLEM.C
< prev
next >
Wrap
Text File
|
1992-07-06
|
31KB
|
677 lines
/**********************************************************************
* MODULE NAME : killem.c AUTHOR: Rick Fishman *
* DATE WRITTEN: 10-24-91 *
* *
* DESCRIPTION: *
* *
* This program kills the specified process(s). It uses the *
* undocumented function DosQProcStatus to get a buffer filled with *
* information related to the current state of the system. It then *
* performs the following using the buffer: *
* *
* 1. Get the relevant process information for all active pids into *
* an array. *
* 2. Go thru the module information table. For each module found, *
* see if the module name matches those given on the command *
* line. If so, compare its module reference number against all *
* module reference numbers associated with the active pids. If *
* any match, issue a DosKillProcess against the matching pids. *
* *
* UPDATES: *
* *
* 5/21/92 - increased buffer to 32k from 16k because of Trap D *
* on LAN. *
* 5/21/92 - changed compare of process name to buffer so that if *
* 'e' is specified on command line, processes that end *
* in 'e' will not be killed. *
* 6/08/92 - added commandline support for process ids. Now Ver 2.1.*
* *
**********************************************************************/
/*********************************************************************/
/*------- Include relevant sections of the OS/2 header files --------*/
/*********************************************************************/
#define INCL_DOSERRORS
#define INCL_DOSPROCESS
/**********************************************************************/
/*----------------------------- INCLUDES -----------------------------*/
/**********************************************************************/
#include <os2.h>
#include <ctype.h>
#include <process.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "procstat.h"
/*********************************************************************/
/*------------------- APPLICATION DEFINITIONS -----------------------*/
/*********************************************************************/
#define COPYRIGHT_INFO "KillEm.exe, 32-bit, Version 2.1\n" \
"Copyright (c) Code Blazers, Inc 1991. All " \
"rights reserved.\n"
#define USAGE_INFO "\nUsage: KillEm processname-or-PID " \
"processname-or-PID ...\n" \
"\n*** PID must be in decimal ***\n"
#define OUT_OF_MEMORY_MSG "\nOut of memory!\n"
#define BUFFER_SIZE 0x8000 //** 5/21/92 changed to 32k
/**********************************************************************/
/*---------------------------- STRUCTURES ----------------------------*/
/**********************************************************************/
typedef struct _ACTIVEPID // INFO ON AN ACTIVE PROCESS
{
USHORT hModRef; // It's module reference handle
PID pid; // It's Process Id
} ACTIVEPID, *PACTIVEPID;
/**********************************************************************/
/*----------------------- FUNCTION PROTOTYPES ------------------------*/
/**********************************************************************/
INT main ( INT argc, PSZ szArg[] );
VOID KillEm ( INT iProcessesToKill );
INT CompareActivePids( const void *pActivePid1, const void *pActivePid2 );
BOOL ShouldBeKilled ( PSZ szProcessName, INT iProcessesToKill );
VOID FindAndKill ( PMODINFO pmi );
ULONG KillProcess ( PID pid, PSZ szProcessName );
ULONG Init ( INT argc, PSZ szArg[], PINT piProcessesToKill );
INT StoreCmdLinePids ( INT argc, PSZ szArg[] );
BOOL IsStringNumeric ( PSZ szString );
ULONG CopyProcessName ( PSZ szProcessName, INT iArrayIndex );
VOID UpCaseNames ( PMODINFO pmi );
ULONG BuildActivePidTbl( PPROCESSINFO ppi );
VOID Term ( ULONG ulExitCode, INT iProcNameEntries );
/**********************************************************************/
/*------------------------ GLOBAL VARIABLES --------------------------*/
/**********************************************************************/
USHORT usActiveProcesses; // Number of active processes
INT iPidCount; // Number of commandline process ids
ACTIVEPID *aActivePid; // Array of active processes
PSZ *pszProcess; // Array of command-line process names
PID apid[ 50 ]; // Array of cmdline process ids
PBUFFHEADER pbh; // Pointer to buffer header structure
/**********************************************************************/
/*------------------------------ MAIN --------------------------------*/
/* */
/* MAIN DRIVER FOR PROGRAM. */
/* */
/* INPUT: number of command-line arguments, */
/* command-line argument array */
/* */
/* 1. Perform program initialization which will issue the */
/* DosQProcStatus call and obtain the buffer of information. */
/* 2. Use the buffer to kill processes that match the names given */
/* on the command-line. */
/* 3. Perform program termination. */
/* */
/* OUTPUT: nothing */
/* */
/*--------------------------------------------------------------------*/
/**********************************************************************/
INT main( INT argc, PSZ szArg[] )
{
INT iProcessesToKill;
ULONG ulExitCode = Init( argc, szArg, &iProcessesToKill );
if( ulExitCode == NO_ERROR )
KillEm( iProcessesToKill );
Term( ulExitCode, iProcessesToKill );
return 0;
}
/**********************************************************************/
/*------------------------------ KillEm ------------------------------*/
/* */
/* FIND PROCESSES NAMED ON COMMAND-LINE AND KILL THEM */
/* */
/* INPUT: number of processes to attempt to kill */
/* */
/* 1. Kill all process ids that were specified on the commandline. */
/* 2. If there were process names on the commandline: */
/* A. Get the address of the beginning of the module info section.*/
/* B. For each module information block, check if this is one's */
/* module name matches any process names given on the command */
/* line. If it does, kill all active pids whose module handle */
/* matches its module handle. */
/* */
/* OUTPUT: nothing */
/* */
/*--------------------------------------------------------------------*/
/**********************************************************************/
VOID KillEm( INT iProcessesToKill )
{
PMODINFO pmi;
INT i;
ULONG ulRetCode;
for( i = 0; i < iPidCount; i++ )
{
ulRetCode = DosKillProcess( DKP_PROCESS, apid[ i ] );
if( ulRetCode )
if( ulRetCode == ERROR_INVALID_PROCID )
printf( "\nPid %u not found", apid[ i ] );
else
printf( "\nFound Pid %u but DosKillProcess failed (RC=%u)",
apid[ i ], ulRetCode );
else
printf( "\nFound pid %u and Killed it", apid[ i ] );
fflush( stdout );
}
if( pbh )
{
pmi = pbh->pmi;
while( pmi )
{
if( ShouldBeKilled( pmi->szModName, iProcessesToKill ) )
FindAndKill( pmi );
pmi = pmi->pNext;
}
}
}
/**********************************************************************/
/*------------------------- ShouldBeKilled ---------------------------*/
/* */
/* DETERMINE WHETHER OR NOT WE SHOULD KILL THIS PROCESS. */
/* */
/* INPUT: process name, */
/* number of processes we are attempting to kill */
/* */
/* 1. For each process name given on the command line, see if it */
/* is a substring of the process name passed as a parameter. */
/* The passed module name could be a fully qualified file name. */
/* */
/* OUTPUT: TRUE if we should kill it, FALSE if not */
/* */
/*--------------------------------------------------------------------*/
/**********************************************************************/
BOOL ShouldBeKilled( PSZ szProcessName, INT iProcessesToKill )
{
BOOL fProcessFound = FALSE;
PSZ szFound;
INT i;
for( i = 0; i < iProcessesToKill; i++ )
{
//** 5/21/92 bug fix
if( (szFound = strstr( szProcessName, pszProcess[ i ] )) &&
( szFound == szProcessName || *(szFound - 1) == '\\' ) )
{
fProcessFound = TRUE;
break;
}
}
return fProcessFound;
}
/**********************************************************************/
/*--------------------------- FindAndKill ----------------------------*/
/* */
/* FIND ALL PROCESSES FOR A MODULE HANDLE AND KILL THEM */
/* */
/* INPUT: pointer to module info block */
/* */
/* 1. For each active pid, match it's module handle against the */
/* module handle of the passed module information block. If it */
/* matches, kill that process. */
/* */
/* NOTE: The active array table is sorted in ascending module handle */
/* order. */
/* */
/* OUTPUT: nothing */
/* */
/*--------------------------------------------------------------------*/
/**********************************************************************/
VOID FindAndKill( PMODINFO pmi )
{
USHORT usKilled = 0;
register INT i;
for( i = 0; i < usActiveProcesses; i++ )
{
if( aActivePid[ i ].hModRef > pmi->hMod )
break;
if( aActivePid[ i ].hModRef == pmi->hMod )
if( KillProcess( aActivePid[ i ].pid, pmi->szModName ) == NO_ERROR )
usKilled++;
}
if( !usKilled )
printf( "\nCould not find PID for %s!\n", pmi->szModName );
}
/**********************************************************************/
/*--------------------------- KillProcess ----------------------------*/
/* */
/* KILL A PROCESS BY PID */
/* */
/* INPUT: process id, */
/* process name */
/* */
/* 1. Issue a DosKillProcess for the passed process id. */
/* */
/* OUTPUT: return code from DosKillProcess */
/* */
/*--------------------------------------------------------------------*/
/**********************************************************************/
ULONG KillProcess( PID pid, PSZ szProcessName )
{
ULONG ulRetCode = DosKillProcess( DKP_PROCESS, pid );
if( ulRetCode )
{
if( ulRetCode != ERROR_INVALID_PROCID )
printf( "\nFound %s (pid %u) but DosKillProcess failed (RC=%u)",
szProcessName, pid, ulRetCode );
}
else
printf( "\nFound %s (pid %u) and Killed it", szProcessName, pid );
fflush( stdout );
return ulRetCode;
}
/**********************************************************************/
/*------------------------------ Init --------------------------------*/
/* */
/* PERFORM PROGRAM INITIALIZATION */
/* */
/* INPUT: number of command-line arguments, */
/* command-line argument array, */
/* address of int storing count of process names to kill */
/* */
/* 1. Print copyright notice. */
/* 2. If no process names were specified on the command line, exit. */
/* 3. Allocate memory for an array of pointers to process name */
/* strings. We will use this array during the main program loop */
/* to identify process names to kill. */
/* 4. Allocate memory for each string in the array. */
/* 5. Copy the process names from the command line into the memory */
/* we just allocated. */
/* 6. Alocate memory for the output from DosQProcStatus. */
/* 7. Make the DosQProcStatus call. */
/* 8. Uppercase the names in the module information section to make */
/* string compares easier during main program logic. */
/* 9. Build an array of information related to active processes. */
/* */
/* OUTPUT: exit code */
/* */
/*--------------------------------------------------------------------*/
/**********************************************************************/
ULONG Init( INT argc, PSZ szArg[], PINT piProcessNamesToKill )
{
ULONG ulExitCode = NO_ERROR;
INT iPszCount = StoreCmdLinePids( argc, szArg );
INT iPszArraySize = iPszCount * sizeof( PSZ );
*piProcessNamesToKill = iPszCount;
(void) printf( COPYRIGHT_INFO );
if( iPszCount )
{
// Allocate memory for the array of ASCIIZ process names passed on the
// command line. We can't just use the commandline because we may need
// to add .EXE to the end of the process name. So we allocate our own
// array of strings so we have enough room for that extension if
// necessary.
pszProcess = (PSZ *) malloc( iPszArraySize );
if( pszProcess )
{
INT i, iNext = 0;
(void) memset( pszProcess, 0, iPszArraySize );
for( i = 1; i < argc && ulExitCode == NO_ERROR; i++ )
if( !IsStringNumeric( szArg[ i ] ) )
{
ulExitCode = CopyProcessName( szArg[ i ], iNext );
iNext++;
}
}
if( ulExitCode == NO_ERROR )
if( !(pbh = malloc( BUFFER_SIZE )) )
{
printf( OUT_OF_MEMORY_MSG );
ulExitCode = ERROR_NOT_ENOUGH_MEMORY;
}
if( ulExitCode == NO_ERROR )
{
USHORT usRetCode = DosQProcStatus( pbh, BUFFER_SIZE );
if( usRetCode )
{
printf( "\nDosQProcStatus failed. RC: %u.", usRetCode );
ulExitCode = (ULONG) usRetCode;
}
}
if( ulExitCode == NO_ERROR )
{
UpCaseNames( pbh->pmi );
ulExitCode = BuildActivePidTbl( pbh->ppi );
}
}
else if( argc <= 1 )
{
printf( USAGE_INFO );
ulExitCode = ERROR_INVALID_PARAMETER;
}
return ulExitCode;
}
/**********************************************************************/
/*----------------------- StoreCmdLinePids ---------------------------*/
/* */
/* STORE THE PIDS FOUND ON THE COMMANDLINE. */
/* */
/* INPUT: number of command-line arguments, */
/* command-line argument array */
/* */
/* 1. If the argument is numeric, store it in an array that */
/* contains pids to kill. Otherwise increment the count of */
/* process names found on the command line. */
/* */
/* OUTPUT: number of process names found on the command-line */
/* */
/*--------------------------------------------------------------------*/
/**********************************************************************/
INT StoreCmdLinePids( INT argc, PSZ szArg[] )
{
INT i, iProcessNames = 0;
if( argc > 1 )
for( i = 1; i < argc; i++ )
if( IsStringNumeric( szArg[ i ] ) )
apid[ iPidCount++ ] = atoi( szArg[ i ] );
else
iProcessNames++;
return iProcessNames;
}
/**********************************************************************/
/*----------------------- IsStringNumeric ---------------------------*/
/* */
/* CHECK IF A STRING IS NUMERIC. */
/* */
/* INPUT: string */
/* */
/* 1. Check if the string contains all digits. */
/* */
/* OUTPUT: TRUE or FALSE if numeric or not */
/* */
/*--------------------------------------------------------------------*/
/**********************************************************************/
BOOL IsStringNumeric( PSZ szString )
{
BOOL fNumeric = TRUE;
while( *szString && fNumeric )
{
if( !isdigit( *szString ) )
fNumeric = FALSE;
szString++;
}
return fNumeric;
}
/**********************************************************************/
/*-------------------------- CopyProcessName -------------------------*/
/* */
/* COPY A COMMANDLINE PROCESS NAME TO OUR ARRAY OF PROCESS NAMES. */
/* */
/* INPUT: pointer to commandline process name, */
/* index into process-name array */
/* */
/* 1. Allocate memory for the process-name string. */
/* 2. Copy the process name from the command line into the memory */
/* we just allocated. If the process name has no .EXE extension, */
/* force it on. */
/* */
/* OUTPUT: exit code */
/* */
/*--------------------------------------------------------------------*/
/**********************************************************************/
ULONG CopyProcessName( PSZ szProcessName, INT iArrayIndex )
{
ULONG ulExitCode = NO_ERROR;
USHORT usStringLen;
PCH pchExtension;
// Calculate memory needed for the process name. Make sure the
// memory size is large enough to include an EXE extension,
// especially if we need to add one.
usStringLen = strlen( szProcessName ) + 1;
if( !(pchExtension = strchr( szProcessName, '.' )) )
usStringLen += 4;
pszProcess[ iArrayIndex ] = malloc( usStringLen );
if( pszProcess[ iArrayIndex ] )
{
(void) strcpy( pszProcess[ iArrayIndex ], szProcessName );
(void) strupr( pszProcess[ iArrayIndex ] );
if( !pchExtension )
(void) strcat( pszProcess[ iArrayIndex ], ".EXE" );
}
else
{
printf( OUT_OF_MEMORY_MSG );
ulExitCode = ERROR_NOT_ENOUGH_MEMORY;
}
return ulExitCode;
}
/**********************************************************************/
/*---------------------------- UpCaseNames ---------------------------*/
/* */
/* MAKE PROCESS NAMES IN MODULE TABLE UPPERCASE. */
/* */
/* INPUT: pointer to module table */
/* */
/* 1. Upcase all names in the module information section to make it */
/* easy on the module name string compare. */
/* */
/* OUTPUT: nothing */
/* */
/*--------------------------------------------------------------------*/
/**********************************************************************/
VOID UpCaseNames( PMODINFO pmi )
{
while( pmi )
{
(void) strupr( pmi->szModName );
pmi = pmi->pNext;
}
}
/**********************************************************************/
/*------------------------ BuildActivePidTbl -------------------------*/
/* */
/* BUILD AN ARRAY OF ACTIVE PROCESSES USING THE PROCESS INFO SECTION */
/* OF THE DosQProcStatus BUFFER. */
/* */
/* INPUT: pointer to ProcessInfo section of buffer */
/* */
/* 1. Get a count of active processes. */
/* 2. Allocate memory for the ActiveProcess table. */
/* 3. Store information about each active process in the table. */
/* 4. Sort the table in ascending module number order. */
/* */
/* OUTPUT: exit code */
/* */
/*--------------------------------------------------------------------*/
/**********************************************************************/
ULONG BuildActivePidTbl( PPROCESSINFO ppi )
{
PPROCESSINFO ppiLocal = ppi;
ULONG ulExitCode = NO_ERROR;
// Count the number of processes in the process info section. The process
// count in the summary record is not reliable (2/17/92 - version 6.177)
usActiveProcesses = 0;
while( ppiLocal->ulEndIndicator != PROCESS_END_INDICATOR )
{
usActiveProcesses++;
// Next PROCESSINFO struct found by taking the address of the first
// thread control block of the current PROCESSINFO structure and
// adding the size of a THREADINFO structure times the number of
// threads
ppiLocal = (PPROCESSINFO) (ppiLocal->ptiFirst+ppiLocal->usThreadCount );
}
if( !(aActivePid = malloc( usActiveProcesses * sizeof( ACTIVEPID ) )) )
{
printf( OUT_OF_MEMORY_MSG );
ulExitCode = ERROR_NOT_ENOUGH_MEMORY;
}
else
{
register INT i;
for( i = 0; i < usActiveProcesses; i++ )
{
aActivePid[ i ].hModRef = ppi->hModRef;
aActivePid[ i ].pid = (PID) ppi->pid;
ppi = (PPROCESSINFO) (ppi->ptiFirst + ppi->usThreadCount);
}
qsort( aActivePid, usActiveProcesses, sizeof( ACTIVEPID ),
CompareActivePids );
}
return ulExitCode;
}
/**********************************************************************/
/*------------------------ CompareActivePids -------------------------*/
/* */
/* COMPARE FUNCTION FOR THE QSORT OF THE ACTIVE PID ARRAY. SORTS */
/* THE ARRAY IN MODULE HANDLE ORDER. */
/* */
/* INPUT: pointer to first element for compare, */
/* pointer to second element of compare */
/* */
/* 1. Do the compare. */
/* */
/* OUTPUT: < 0 means first < second */
/* = 0 means first = second */
/* > 0 means first > second */
/* */
/*--------------------------------------------------------------------*/
/**********************************************************************/
INT CompareActivePids( const void *pActivePid1, const void *pActivePid2 )
{
if( ((PACTIVEPID)pActivePid1)->hModRef < ((PACTIVEPID)pActivePid2)->hModRef )
return -1;
else
if( ((PACTIVEPID)pActivePid1)->hModRef > ((PACTIVEPID)pActivePid2)->hModRef )
return +1;
else
return 0;
}
/**********************************************************************/
/*------------------------------ Term --------------------------------*/
/* */
/* PERFORM PROGRAM TERMINATION */
/* */
/* INPUT: exit code, */
/* number of process names entered on the command line */
/* */
/* 1. Free the array of process name strings that we allocated */
/* during program initialization. */
/* 2. Free the ActiveProcess array. */
/* 3. Free the buffer allocated for the DosQProcStatus output. */
/* 4. Return the exit code to the operating system. */
/* */
/* OUTPUT: nothing */
/* */
/*--------------------------------------------------------------------*/
/**********************************************************************/
VOID Term( ULONG ulExitCode, INT iProcessNameEntries )
{
if( pszProcess )
{
register INT i;
for( i = 0; i < iProcessNameEntries; i++ )
if( pszProcess[ i ] )
free( pszProcess[ i ] );
free( pszProcess );
}
if( aActivePid )
free( aActivePid );
if( pbh )
free( pbh );
DosExit( EXIT_PROCESS, ulExitCode );
}
/**********************************************************************
* END OF SOURCE CODE *
**********************************************************************/