[comp.unix.questions] killing processes thru' C programs

grx0736@uoft02.utoledo.edu (04/24/91)

greetings,

does anyone know how to kill processes through C programs
if only the name of the running process is known, and not
its pid. The call  to this function could be something like

	kill_process("process_name");

I would not like to do this by using ps, or by executing a 
shell script from within the C program. 

sunil kulkarni

mike@bria.UUCP (Michael Stefanik) (04/28/91)

Is there an entry in the FAQ for this yet?

In an article, grx0736@uoft02.utoledo.edu writes:
|does anyone know how to kill processes through C programs
|if only the name of the running process is known, and not
|its pid. The call  to this function could be something like
|
|	kill_process("process_name");
|
|I would not like to do this by using ps, or by executing a 
|shell script from within the C program. 

The politically correct answer in this case is "no".  In reality, of
course, there are ways to get process information, but it is implementation
dependant, and highly unportable.

Sepaking in the broadest of terms:

	1. read the kernel's namelist, searching for _proc
	2. seek to the offset in /dev/kmem, and read in the proc table entry
	3. determine if the process is in core or swapped
	4. if in core, read the u area from /dev/mem
	   if swapped, read the u area from the swap device

You may or may not have functions that will provided a nicer way to glean
this information (rather than rummaging around with nlist() and lseek())

-- 
Michael Stefanik, MGI Inc, Los Angeles | Opinions stated are never realistic
Title of the week: Systems Engineer    | UUCP: ...!uunet!bria!mike
-------------------------------------------------------------------------------
If MS-DOS didn't exist, who would UNIX programmers have to make fun of?

torek@elf.ee.lbl.gov (Chris Torek) (04/28/91)

In article <1991Apr24.144240.3322@uoft02.utoledo.edu>
grx0736@uoft02.utoledo.edu writes:
>does anyone know how to kill processes through C programs if only
>the name of the running process is known, and not its pid.

The `name' of a process *is* its pid.  The `command' text ps prints
is purely for your convenience in case you have forgotten what the
process named `12345' might be doing.

>The call  to this function could be something like
>
>	kill_process("process_name");
>
>I would not like to do this by using ps, or by executing a 
>shell script from within the C program. 

Consider something like:

	$ foo & foo &
	7179
	7180
	$ your_program

One process is named 7179, the other 7180.  Both of them were started
with the command `foo'.  Which one do you want to kill?

Now, if you start each process yourself, or if you are willing to run
`ps' or something equivalent, you can of course associate your own
arbitrary strings with each PID.  Since you control this, you can make
the mapping invertible and do whatever you like.
-- 
In-Real-Life: Chris Torek, Lawrence Berkeley Lab CSE/EE (+1 415 486 5427)
Berkeley, CA		Domain:	torek@ee.lbl.gov

jik@athena.mit.edu (Jonathan I. Kamens) (04/29/91)

I just sent this to Steve Hayman and suggested he include something like it in
the comp.unix.questions FAQ.  It's pretty BSD-oriented (since that's what I
work on); if you can expand on it to make it more generally applicable, please
post corrections here or send them to me and I'll forward them to Steve.

  It seems to me that, considering how many times people have asked
this month about finding the pid of a process given its name, it's
about time to add it to the FAQ.  There should be two questions in the
FAQ, one of them talking about shell scripts and one of them talking
about C programs.  Something like this:

*) How do I find out the process ID of a program with a particular
   name from inside a shell script?

There is no utility specifically designed to map between program names
and process IDs.  Furthermore, such mappings are often unreliable,
since it's possible for more than one process to have the same name,
and since it's possible for a process to change its name once it
starts running.  However, a pipeline like this can often be used to
get a list of processes (owned by you) with a particular name:

	ps ux | awk '/name/ && !/awk/ {print $2}'

You replace "name" with the name of the process for which you are
searching.

The general idea is to parse the output of ps, using awk or grep or
other utilities, to search for the lines with the specified name on
them, and print the PID's for those lines.  Note that the "!/awk/"
above prevents the awk process for being listed.

You may have to change the arguments to ps, depending on what kind of
Unix you are using.

*) How do I find out the process ID of a program with a particular name
   from inside a C program?

Just as there is no utility specifically designed to map between
program names and process IDs, there are no (portable) C library
functions to do it either.

However, some vendors provide functions for reading Kernel memory; for
example, Sun provides the "kvm_" functions, and Data General provides
the "dg_" functions.  It may be possible for any user to use these, or
they may only be useable by the super-user (or a user in group "kmem")
if read-access to kernel memory on your system is restricted.
Furthermore, these functions are often not documented or documented
badly, and might change from release to release.

Some vendors provide a "/proc" filesystem, which appears as a
directory with a bunch of filenames in it.  Each filename is a number,
corresponding to a process ID, and you can open the file and read it
to get information about the process.  Once again, access to this may
be restricted, and the interface to it may change from system to
system.

If you can't use vendor-specific library functions, and you don't have
/proc, and you still want to do this completely in C, you are going to
have to do the grovelling through kernel memory yourself.  For a good
example of how to do this on many systems, see the sources to
"ofiles", available in the comp.sources.unix archives.

If all else fails, you can call popen() on "ps" and parse its output.

-- 
Jonathan Kamens			              USnail:
MIT Project Athena				11 Ashford Terrace
jik@Athena.MIT.EDU				Allston, MA  02134
Office: 617-253-8085			      Home: 617-782-0710

dan@systech.bjorn.COM (Dan Gill) (04/30/91)

> 	ps ux | awk '/name/ && !/awk/ {print $2}'
> 
> You replace "name" with the name of the process for which you are
> searching.
> 
> them, and print the PID's for those lines.  Note that the "!/awk/"
> above prevents the awk process for being listed.

if you use ps uxc | grep name | awk '{print $2}' the only thing displayed
is the pid of the processes name.  You should be careful for if you used
vi as the name, there could be some unhappy campers in your KOA.

Dg
-- 
-------------------------------------------------------------------------------
"On second thought, let us not go to Camelot.  It is a silly place"
Dan Gill                              [uunet ucsd.edu]!systech!dan
-------------------------------------------------------------------------------

gwyn@smoke.brl.mil (Doug Gwyn) (04/30/91)

In article <12582@dog.ee.lbl.gov> torek@elf.ee.lbl.gov (Chris Torek) writes:
>In article <1991Apr24.144240.3322@uoft02.utoledo.edu>
>grx0736@uoft02.utoledo.edu writes:
>>does anyone know how to kill processes through C programs if only
>>the name of the running process is known, and not its pid.
>The `name' of a process *is* its pid.

While I was tempted to respond in much the same way, actually it is
possible to interpret the original request in a way that might make
enough sense to have an adequate solution.

#!/bin/sh
#	zap -- kill all processes matching pattern
#	adapted from Kernighan & Pike
HEAD=head	# see below
PICK=pick	# see below
IFS='
'
sig=
case $1 in
"")	echo 'Usage: zap [-2] pattern' 1>&2; exit 1;;
-*)	sig=$1; shift;;
esac
# BSD flavor of "ps" assumed:
ps -ag | $HEAD 1
exec kill $sig `$PICK \`ps -ag | egrep "$*" | egrep -v 'zap|egrep'\` | awk '{print $1}'`

#!/bin/sh
#	head -- print first few lines of file
if [ $# -eq 0 ]
then	n=10
else	case $1 in
	[0-9]*)	n=$1;	shift;;
	*)	n=10;;
	esac
fi
exec sed -e ${n}q $*

#!/bin/sh
#	pick -- select arguments
#	adapted from Kernighan & Pike
for i
do	echo -n "$i? " > /dev/tty	# BSD or Research UNIX "echo" assumed
	read response
	case $response in
	[yY]*)	echo $i;;
	[qQ]*)	break;;
	esac
done < /dev/tty

jik@athena.mit.edu (Jonathan I. Kamens) (05/01/91)

In article <878@systech.bjorn.COM>, dan@systech.bjorn.COM (Dan Gill) writes:
|> if you use ps uxc | grep name | awk '{print $2}' the only thing displayed
|> is the pid of the processes name.  You should be careful for if you used
|> vi as the name, there could be some unhappy campers in your KOA.

  There are two problems with what you have suggested.

  First of all, there's no reason to use two processes, when awk has regular
expression capabilities.  Change what you said to:

	ps uxc | awk '/name/ {print $2}'

  Second, as someone else has pointed out in another message, if you use 'ps
uxc', then shell scripts are listed as "sh" instead of as the name of the
script, which means you can't kill scripts using this method.  Given that I
need to do that at times, it makes more sense to use what I suggested (i.e.
"ps ux" and search with awk '/name/ && !/awk/ {print $2}') than it does to use
"ps uxc".

-- 
Jonathan Kamens			              USnail:
MIT Project Athena				11 Ashford Terrace
jik@Athena.MIT.EDU				Allston, MA  02134
Office: 617-253-8085			      Home: 617-782-0710