/* * Mini killproc implementation for busybox. * * Copyright (C) 2005 by David Seikel won_fang@yahoo.com.au * * * Clean room implementation of LSB init.d specs. * A tiny bit was stolen from procps/kill.c in busybox. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 USA * */ #include #include #include #include #include "busybox.h" #include "lib_init_d.h" int killproc(char *pidfile, char *pathname, int my_signal) { char *pids = NULL; int status = pidofproc(pidfile, pathname, &pids); if (status == INIT_D_STATUS_OK) { int i; char *pid; char *strtok_temp; pid = strtok_r(pids, " ", &strtok_temp); for (i = 0; pid != NULL; i++) { int pid_num; if (!isdigit(*pid)) bb_error_msg("Bad PID '%s'", pid); pid_num = strtol(pid, NULL, 0); if (my_signal != 0) { if (kill(pid_num, my_signal) != 0) bb_perror_msg("Could not kill pid '%d'", pid_num); } else { if (kill(pid_num, SIGTERM) != 0) bb_perror_msg("Could not kill pid '%d'", pid_num); sleep(1); status = pidofproc(pidfile, pathname, &pids); if (status == INIT_D_STATUS_OK) { sleep(5); status = pidofproc(pidfile, pathname, &pids); if (status == INIT_D_STATUS_OK) { if (kill(pid_num, SIGKILL) != 0) bb_perror_msg("Could not kill pid '%d'", pid_num); } } } pid = strtok_r(NULL, " ", &strtok_temp); } status = pidofproc(pidfile, pathname, &pids); if (status == INIT_D_STATUS_DEAD_PID) { if (pidfile != NULL) remove_file(pidfile, FILEUTILS_FORCE); status = INIT_D_STATUS_NOT_RUNNING; } if ((my_signal == 0) && (status == INIT_D_STATUS_NOT_RUNNING)) status = INIT_D_STATUS_OK; } return status; } /* killproc [-p pidfile] pathname [signal] This stops the specified program. The program is found using the algorithm given above. If a signal is specified, using the -signal_name or -signal_number syntaxes as specified by the kill command, the program is sent that signal. Otherwise, a SIGTERM followed by a SIGKILL after some number of seconds shall be sent. If a program has been terminated, the pidfile should be removed if the terminated process has not already done so. Compliant applications may use the basename instead of the pathname. killproc should return the LSB defined exit status codes. If called without a signal, it shall return 0 if the program has been stopped or is not running and not 0 otherwise. If a signal is given, it shall return 0 only if the program is running. */ /* getopt not used, because I don't think it can handle [signal] */ int killproc_main(int argc, char **argv) { int i; int my_signal = 0; char *pidfile = NULL; char *pathname = NULL; char *signame = NULL; for (i = 1; i < argc; i++) { char *p = argv[i]; if (*p == '-') { p++; if (*p == 'p') { if ((i + 1) < argc) pidfile = argv[++i]; else bb_show_usage(); } else signame = &argv[i][1]; } else if (pathname == NULL) pathname = p; else if (signame == NULL) signame = p; else bb_show_usage(); } if (pathname == NULL) bb_show_usage(); if (signame != NULL) { u_signal_names(signame, &my_signal, 1); if (my_signal == 0) { log_failure_msg("unknown signal."); bb_show_usage(); } } //bb_printf("ARGS - %s %s %d = %s\n", pidfile, pathname, my_signal, u_signal_names(NULL, &signal, 1)); return killproc(pidfile, pathname, my_signal); }