/* vi: set sw=4 ts=4: */ /* * Mini kill/killall implementation for busybox * * Copyright (C) 1995, 1996 by Bruce Perens . * Copyright (C) 1999-2004 by Erik Andersen * * Licensed under the GPL v2 or later, see the file LICENSE in this tarball. */ #include "busybox.h" int kill_main(int argc, char **argv) { char *arg; pid_t pid; int signo = SIGTERM, errors = 0, quiet = 0; const int killall = (ENABLE_KILLALL && bb_applet_name[4]=='a' && (!ENABLE_KILLALL5 || bb_applet_name[7]!='5')); const int killall5 = (ENABLE_KILLALL5 && bb_applet_name[4]=='a' && (!ENABLE_KILLALL || bb_applet_name[7]=='5')); /* Parse any options */ argc--; arg = *++argv; if (argc<1 || arg[0]!='-') { goto do_it_now; } /* The -l option, which prints out signal names. */ if (arg[1]=='l' && arg[2]=='\0') { const char *name; if (argc==1) { /* Print the whole signal list */ int col = 0; for (signo = 1; signo<32; signo++) { name = get_signame(signo); if (isdigit(name[0])) continue; if (col > 66) { puts(""); col = 0; } col += printf("%2d) %-6s", signo, name); } puts(""); } else { /* -l */ while ((arg = *++argv)!=NULL) { if (isdigit(arg[0])) { signo = atoi(arg); name = get_signame(signo); } else { signo = get_signum(arg); if (signo<0) bb_error_msg_and_die("unknown signal '%s'", arg); name = get_signame(signo); } printf("%2d) %s\n", signo, name); } } /* If they specified -l, we are all done */ return EXIT_SUCCESS; } /* The -q quiet option */ if (killall && arg[1]=='q' && arg[2]=='\0') { quiet = 1; arg = *++argv; argc--; if (argc<1) bb_show_usage(); if (arg[0]!='-') goto do_it_now; } /* -SIG */ signo = get_signum(&arg[1]); if (signo<0) bb_error_msg_and_die("bad signal name '%s'", &arg[1]); arg = *++argv; argc--; do_it_now: if (killall5) { pid_t sid; procps_status_t* p; /* kill(-1, sig) on Linux (at least 2.1.x) * might send signal to the calling process too */ signal(SIGTERM, SIG_IGN); /* Now stop all processes */ kill(-1, SIGSTOP); /* Find out our own session id */ pid = getpid(); sid = getsid(pid); /* Now kill all processes except our session */ while ((p = procps_scan(0))!=0) { if (getsid(p->pid)!=sid && p->pid!=pid && p->pid!=1) kill(p->pid, signo); } /* And let them continue */ kill(-1, SIGCONT); return 0; } /* Pid or name required for kill/killall */ if (argc<1) bb_show_usage(); if (killall) { /* Looks like they want to do a killall. Do that */ pid = getpid(); while (arg) { long* pidList; pidList = find_pid_by_name(arg); if (!pidList || *pidList<=0) { errors++; if (!quiet) bb_error_msg("%s: no process killed", arg); } else { long *pl; for (pl = pidList; *pl!=0; pl++) { if (*pl==pid) continue; if (kill(*pl, signo)!=0) { errors++; if (!quiet) bb_perror_msg("cannot kill pid %ld", *pl); } } } free(pidList); arg = *++argv; } return errors; } /* Looks like they want to do a kill. Do that */ while (arg) { if (!isdigit(arg[0]) && arg[0]!='-') bb_error_msg_and_die("bad pid '%s'", arg); pid = strtol(arg, NULL, 0); /* FIXME: better overflow check? */ if (kill(pid, signo)!=0) { bb_perror_msg("cannot kill pid %ld", (long)pid); errors++; } arg = *++argv; } return errors; }