jc@minya.UUCP (John Chambers) (12/10/87)
> > On SV, non-root users may kill(2) processes having the same uid and > > their children. > > > > On BSD, non-root users may only kill(2) processes having the same uid > > (modulo the setpgrp bug recently mentioned in this group.). This makes > > it awkward to kill setuid subprocesses. This reminds me of a question I'd like to pose to all the wizards out there. Is there a universal way that will work on any Unix to write a function isprocess(n) which returns TRUE if process n is alive, and FALSE if it isn't alive? Note that I have said nothing about the relationship of process n (if it exists) to the process that is asking. They might or might not be related. They might or might not have the same uid and gid. I don't want to kill the process (or even upset it in any way). I just want to know if it is alive. On this SysV, this can be done (with some difficulty) by doing a kill(0,n), which doesn't actually do anything to the process (as far as I can tell), but it does return different values in errno for no-such-process and for wrong-uid. I.e., you can examine the return value (0 or -1) and errno, and from them you can determine whether the process exists or not. So far, I haven't tried to solve the problem on BSD, but the above remark implies that my SysV code won't work. It'd be useful to have a portable subroutine (presumably with an #ifdef or three) to answer this question. -- John Chambers <{adelie,ima,maynard,mit-eddie}!minya!{jc,root}> (617/484-6393)
dave@spool.wisc.edu (Dave Cohrs) (12/10/87)
In article <429@minya.UUCP> jc@minya.UUCP (John Chambers) writes: >Is there a universal way that will work on any Unix to write a function > isprocess(n) >which returns TRUE if process n is alive, and FALSE if it isn't alive? Any Unix? Well, if the Unix acts like either 4.3BSD or SysV, the following should work: int isprocess(n) int n; { extern int errno; return (kill(n,0) == 0 || errno != ESRCH); } If you read the 4.3BSD kill(2) man page, you see that kill still does permission checks, so you have to check errno upon return to make sure that the error isn't EPERM, meaning the process is alive, but you can't send it signals. This works on SysV as well. I tested it. Dave Cohrs +1 608 262-6617 UW-Madison Computer Sciences Department dave@cs.wisc.edu ...!{harvard,ihnp4,rutgers,ucbvax}!uwvax!dave
andrew@frip.gwd.tek.com (Andrew Klossner) (12/11/87)
"On this SysV, this can be done (with some difficulty) by doing a kill(0,n), which doesn't actually do anything to the process (as far as I can tell), but it does return different values in errno for no-such-process and for wrong-uid ... So far, I haven't tried to solve the problem on BSD, but the above remark implies that my SysV code won't work." Your code will work. BSD kill(2) guarantees that validity checking happens in this order: first that the signal number is valid (and 0 is); next that the target process exists; next that you're allowed to send the signal; next (other irrelevancies). Thus, kill(pid,0) will always return errno==ESRCH if pid doesn't exist. -=- Andrew Klossner (decvax!tektronix!tekecs!andrew) [UUCP] (andrew%tekecs.tek.com@relay.cs.net) [ARPA]
bak@csd_v.UUCP (Bruce) (12/11/87)
In article <429@minya.UUCP>, jc@minya.UUCP (John Chambers) writes: > Is there a universal way that will work on any Unix to write a function > isprocess(n) > which returns TRUE if process n is alive, and FALSE if it isn't alive? > > Note that I have said nothing about the relationship of process n (if it > exists) to the process that is asking. They might or might not be related. > They might or might not have the same uid and gid. I don't want to kill > the process (or even upset it in any way). I just want to know if it is > alive. > This solution is a little awkward but will definitely work. Open a read-only pipe to the "ps -ef" command ( "-al" on BSD I believe, anyway there are your #ifdefs ) and read the output searching the PID field for the process of interest to you. I have a routine (from Kernighan and Pike) called zap which matches any string in the line and then does a kill -9 to the pid, thereby allowing me to kill processes mneumonically rather than PID. Thus $ tail -f abc & 9803 . . many screenfulls of junk later . $ zap abc bak 1632 1354 0 19:51:13 cons2 0:58 tail -f ggg ? n bak 1648 1354 0 19:51:13 cons2 0:58 tail -f abc ? y $ ksh: 1648 Killed The same idea is applicable to just looking at the PID field for your case. Of course ps is not the quickest command to execute and if there are a lot of processes running quite a bit of winnowing has to be done. But if no better solutions come along, this will do the job and is highly portable. One other thing it will absolutely be transparent ot the running process on all flavors of unix. -- Bruce Kern | uunet!swlabs!csd_v!bak Computer Systems Design | 1-203-270-0399 29 High Rock Rd., Sandy Hook, Ct. 06482 | This space for rent.
ado@elsie.UUCP (Arthur David Olson) (12/11/87)
# Is there a universal way that will work on any Unix to write a function # isprocess(n) # which returns TRUE if process n is alive, and FALSE if it isn't alive? echo Here's source for a command we've found useful here at elsie. : To unbundle, sh this file echo 'adopt.1' 1>&2 cat >'adopt.1' <<'End of adopt.1' .LC @(#)adopt.1 1.1 .TH ADOPT 1E \*(eH .SH NAME adopt \- wait for process .SH SYNOPSIS .B adopt [ .B \-v ] [ processid ... ] .= adopt .SH DESCRIPTION .I Adopt waits for completion of the process(es) identified by the ID number(s) given on the command line. It differs from .IR wait (1), which can only be used to wait for completion of a shell's own child processes. .PP This option is available: .TP .B \-v Warn about processes that are not running when .I adopt begins execution. End of adopt.1 echo 'adopt.c' 1>&2 cat >'adopt.c' <<'End of adopt.c' # #include "stdio.h" #if !defined lint && !defined NOID static char sccsid[] = "@(#)adopt.c 1.2"; #endif /* !defined lint && !defined NOID */ #include "errno.h" #include "ctype.h" #ifndef SLEEPTIME #define SLEEPTIME 5 #endif /* !SLEEPTIME */ extern int errno; extern int optind; static exists(s) char * s; { char * cp; int pid; if (s == NULL || *s == '\0') return -1; for (cp = s; *cp != '\0'; ++cp) if (!isascii(*cp) || !isdigit(*cp)) return -1; if (sscanf(s, "%d", &pid) != 1 || pid < 0) return -1; return kill(pid, 0) == 0 || errno != ESRCH; } main(argc, argv) int argc; char * argv[]; { int vflag; int i; int c; int result; int ok; vflag = 0; while ((c = getopt(argc, argv, "v")) == 'v') vflag = 1; if (c != EOF || optind == (argc - 1) && strcmp(argv[optind], "=") == 0) { (void) fprintf(stderr, "%s: usage is %s [-v] processid ...\n", argv[0], argv[0]); return 1; } /* ** Initial checks. */ ok = 1; for (i = optind; c != EOF || i < argc; ++i) { result = exists(argv[i]); if (result < 0) { (void) fprintf(stderr, "%s: wild argument '%s'\n", argv[0], argv[i]); return 1; } if (vflag && result != 1) { (void) fprintf(stderr, "%s: process %s does not exist\n", argv[0], argv[i]); ok = 0; } } /* ** Wait loop. */ for (i = optind; i < argc; ++i) while (exists(argv[i]) == 1) (void) sleep(SLEEPTIME); return ok ? 0 : 1; } End of adopt.c exit -- ado@vax2.nlm.nih.gov ADO, VAX, and NIH are Ampex and DEC trademarks
rjd@occrsh.ATT.COM (12/12/87)
> Is there a universal way that will work on any Unix to write a function > isprocess(n) > which returns TRUE if process n is alive, and FALSE if it isn't alive? > > Note that I have said nothing about the relationship of process n (if it > exists) to the process that is asking. They might or might not be related. > They might or might not have the same uid and gid. I don't want to kill > the process (or even upset it in any way). I just want to know if it is > alive. I don't have the base note for this, just the above. If you have the process number (such as saving it when it went into background) either (in shell) a ps -p <process number> will give you a status code, or (in C) kill(0,<processnumber>) will also give you a status code. If you don't have a process number, it gets a little more difficult. Randy
pdg@ihdev.ATT.COM (Joe Isuzu) (12/17/87)
All of these answers about kill(0,procid) to probe are almost correct. Various flavours of UNIX will return success for a probe of a zombie (sys Vr0, BSD, amdahl UTS to name a few), while others (SysVrX (X>=2)) will return ESRCH. I'm not sure how important this is, but someone is sure to get caught by this sometime. -- Paul Guthrie Zippy the Pinhead - Zen for the American masses ihnp4!ihdev!pdg -- me.
rml@hpfcdc.HP.COM (Bob Lenk) (12/18/87)
> int > isprocess(n) > int n; > { > extern int errno; > > return (kill(n,0) == 0 || errno != ESRCH); > } As several people have pointed out, this approach works on System V and recent BSD systems. One important note is that the semantics are not identical on those systems. If the process in question is a zombie, System V will tell you it exists while BSD will tell you it doesn't. A couple of other points: Older systems (eg. V7) don't support signal 0. Systems meeting certain levels of security won't permit this sort of thing in any form. Bob Lenk {ihnp4, hplabs}!hpfcla!rml