diff options
Diffstat (limited to 'misc-utils/kill.c')
-rw-r--r-- | misc-utils/kill.c | 272 |
1 files changed, 272 insertions, 0 deletions
diff --git a/misc-utils/kill.c b/misc-utils/kill.c new file mode 100644 index 000000000..f89ff67c1 --- /dev/null +++ b/misc-utils/kill.c @@ -0,0 +1,272 @@ +/* + * Copyright (c) 1988, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +/* + * oct 5 1994 -- almost entirely re-written to allow for process names. + * modifications (c) salvatore valente <svalente@mit.edu> + * may be used / modified / distributed under the same terms as the original. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include <unistd.h> +#include <signal.h> + +#ifdef __linux__ +/* + * sys_signame -- an ordered list of signals. + * lifted from /usr/include/linux/signal.h + * this particular order is only correct for linux. + * this is _not_ portable. + */ +char *sys_signame[NSIG] = { + "zero", "HUP", "INT", "QUIT", "ILL", "TRAP", "IOT", "UNUSED", + "FPE", "KILL", "USR1", "SEGV", "USR2", "PIPE", "ALRM", "TERM", + "STKFLT","CHLD", "CONT", "STOP", "TSTP", "TTIN", "TTOU", "IO", + "XCPU", "XFSZ", "VTALRM","PROF", "WINCH", NULL +}; +#endif + +int main (int argc, char *argv[]); +char *mybasename(char *pathname); +int signame_to_signum (char *sig); +int arg_to_signum (char *arg); +void nosig (char *name); +void printsig (int sig); +void printsignals (FILE *fp); +int usage (int status); +int kill_verbose (char *procname, int pid, int sig); + +extern int *get_pids (char *, int); + +char version_string[] = "kill v2.0\n"; +char *whoami; + +int main (int argc, char *argv[]) +{ + int errors, numsig, pid; + char *ep, *arg; + int do_pid, do_kill, check_all; + int *pids, *ip; + + whoami = mybasename (*argv); + numsig = SIGTERM; + do_pid = (! strcmp (whoami, "pid")); + do_kill = 0; + check_all = 0; + + /* loop through the arguments. + actually, -a is the only option can be used with other options. + `kill' is basically a one-option-at-most program. */ + for (argc--, argv++; argc > 0; argc--, argv++) { + arg = *argv; + if (*arg != '-') { + break; + } + if (! strcmp (arg, "-u")) { + return usage (0); + } + if (! strcmp (arg, "-v")) { + fputs (version_string, stdout); + return 0; + } + if (! strcmp (arg, "-a")) { + check_all++; + continue; + } + if (! strcmp (arg, "-l")) { + if (argc < 2) { + printsignals (stdout); + return 0; + } + if (argc > 2) { + return usage (1); + } + /* argc == 2 */ + arg = argv[1]; + if ((numsig = arg_to_signum (arg)) < 0) { + fprintf (stderr, "%s: unknown signal %s\n", whoami, arg); + return 1; + } + printsig (numsig); + return 0; + } + if (! strcmp (arg, "-p")) { + do_pid++; + if (do_kill) + return usage (1); + continue; + } + if (! strcmp (arg, "-s")) { + if (argc < 2) { + return usage (1); + } + do_kill++; + if (do_pid) + return usage (1); + argc--, argv++; + arg = *argv; + if ((numsig = arg_to_signum (arg)) < 0) { + nosig (arg); + return 1; + } + continue; + } + /* `arg' begins with a dash but is not a known option. + so it's probably something like -HUP. + try to deal with it. */ + arg++; + if ((numsig = arg_to_signum (arg)) < 0) { + return usage (1); + } + do_kill++; + if (do_pid) + return usage (1); + continue; + } + + if (! *argv) { + return usage (1); + } + if (do_pid) { + numsig = -1; + } + + /* we're done with the options. + the rest of the arguments should be process ids and names. + kill them. */ + for (errors = 0; (arg = *argv) != NULL; argv++) { + pid = strtol (arg, &ep, 10); + if (! *ep) + errors += kill_verbose (arg, pid, numsig); + else { + pids = get_pids (arg, check_all); + if (! pids) { + errors++; + fprintf (stderr, "%s: can't find process \"%s\"\n", + whoami, arg); + continue; + } + for (ip = pids; *ip >= 0; ip++) + errors += kill_verbose (arg, *ip, numsig); + free (pids); + } + } + return (errors); +} + +char *mybasename (char *path) +{ + char *cp; + + cp = strrchr (path, '/'); + return (cp ? cp + 1 : path); +} + +int signame_to_signum (char *sig) +{ + int n; + + if (! strncasecmp (sig, "sig", 3)) + sig += 3; + for (n = 1; (n < NSIG) && (sys_signame[n] != NULL); n++) { + if (! strcasecmp (sys_signame[n], sig)) + return n; + } + return (-1); +} + +int arg_to_signum (char *arg) +{ + int numsig; + char *ep; + + if (isdigit (*arg)) { + numsig = strtol (arg, &ep, 10); + if (*ep != 0 || numsig < 0 || numsig >= NSIG) + return (-1); + return (numsig); + } + return (signame_to_signum (arg)); +} + +void nosig (char *name) +{ + fprintf (stderr, "%s: unknown signal %s; valid signals:\n", whoami, name); + printsignals (stderr); +} + +void printsig (int sig) +{ + printf ("%s\n", sys_signame[sig]); +} + +void printsignals (FILE *fp) +{ + int n; + + for (n = 1; (n < NSIG) && (sys_signame[n] != NULL); n++) { + fputs (sys_signame[n], fp); + if (n == (NSIG / 2) || n == (NSIG - 1)) + fputc ('\n', fp); + else + fputc (' ', fp); + } + if (n < (NSIG - 1)) + fputc ('\n', fp); +} + +int usage (int status) +{ + FILE *fp; + + fp = (status == 0 ? stdout : stderr); + fprintf (fp, "usage: %s [ -s signal | -p ] [ -a ] pid ...\n", whoami); + fprintf (fp, " %s -l [ signal ]\n", whoami); + return status; +} + +int kill_verbose (char *procname, int pid, int sig) +{ + if (sig < 0) { + printf ("%d\n", pid); + return 0; + } + if (kill (pid, sig) < 0) { + fprintf (stderr, "%s ", whoami); + perror (procname); + return 1; + } + return 0; +} |