📄 start-stop-daemon.c
字号:
/* ==================================================================== * The Kannel Software License, Version 1.0 * * Copyright (c) 2001-2004 Kannel Group * Copyright (c) 1998-2001 WapIT Ltd. * 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. The end-user documentation included with the redistribution, * if any, must include the following acknowledgment: * "This product includes software developed by the * Kannel Group (http://www.kannel.org/)." * Alternately, this acknowledgment may appear in the software itself, * if and wherever such third-party acknowledgments normally appear. * * 4. The names "Kannel" and "Kannel Group" must not be used to * endorse or promote products derived from this software without * prior written permission. For written permission, please * contact org@kannel.org. * * 5. Products derived from this software may not be called "Kannel", * nor may "Kannel" appear in their name, without prior written * permission of the Kannel Group. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED 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 KANNEL GROUP OR ITS 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. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Kannel Group. For more information on * the Kannel Group, please see <http://www.kannel.org/>. * * Portions of this software are based upon software originally written at * WapIT Ltd., Helsinki, Finland for the Kannel project. */ /* This utility was added to the Kannel source tree for the benefit of * those distributions that aren't Debian. It is used by kannel-init.d * to start and stop the run_kannel_box daemon. * It was copied from the dpkg 1.6.11 source tree on 21 March 2000. * If that was very long ago, refreshing the copy would be a good idea, * in case bugs were fixed. * Richard Braakman *//* * A rewrite of the original Debian's start-stop-daemon Perl script * in C (faster - it is executed many times during system startup). * * Written by Marek Michalkiewicz <marekm@i17linuxb.ists.pwr.wroc.pl>, * public domain. Based conceptually on start-stop-daemon.pl, by Ian * Jackson <ijackson@gnu.ai.mit.edu>. May be used and distributed * freely for any purpose. Changes by Christian Schwarz * <schwarz@monet.m.isar.de>, to make output conform to the Debian * Console Message Standard, also placed in public domain. Minor * changes by Klee Dienes <klee@debian.org>, also placed in the Public * Domain. * * Changes by Ben Collins <bcollins@debian.org>, added --chuid, --background * and --make-pidfile options, placed in public domain aswell. */#include "gw-config.h"#if defined(linux)#define OSLinux#elif defined(__GNU__)#define OSHURD#elif defined(SunOS)#elif defined(__FreeBSD__) || defined(__APPLE__)#define FreeBSD#else#error Unknown architecture - cannot build start-stop-daemon#endif#ifdef HAVE_HURH_H#include <hurd.h>#endif#ifdef HAVE_PS_H#include <ps.h>#endif#include <errno.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <stdarg.h>#include <signal.h>#include <sys/stat.h>#include <dirent.h>#include <unistd.h>#if HAVE_GETOPT_H#include <getopt.h>#endif#include <unistd.h>#include <pwd.h>#include <grp.h>#include <sys/ioctl.h>#include <sys/types.h>#include <sys/termios.h>#include <fcntl.h>/*Solaris needs to be told howto talk to it's proc filesystem*/#define _STRUCTURED_PROC 1#ifdef SunOS#include <sys/procfs.h>#endif#ifdef HAVE_ERROR_H#include <error.h>#endif#ifdef HURD_IHASH_H#include <hurd/ihash.h>#endifstatic int testmode = 0;static int quietmode = 0;static int exitnodo = 1;static int start = 0;static int stop = 0;static int background = 0;static int mpidfile = 0;static int signal_nr = 15;static const char *signal_str = NULL;static int user_id = -1;static int runas_uid = -1;static int runas_gid = -1;static const char *userspec = NULL;static char *changeuser = NULL;static char *changegroup = NULL;static char *changeroot = NULL;static const char *cmdname = NULL;static char *execname = NULL;static char *startas = NULL;static const char *pidfile = NULL;static const char *progname = "";static struct stat exec_stat;#if defined(OSHURD)static struct ps_context *context;static struct proc_stat_list *procset;#endifstruct pid_list { struct pid_list *next; int pid;};static struct pid_list *found = NULL;static struct pid_list *killed = NULL;static void *xmalloc(int size);static void push(struct pid_list **list, int pid);static void do_help(void);static void parse_options(int argc, char * const *argv);#if defined(OSLinux) || defined(OSHURD) || defined(SunOS) || defined(FreeBSD)static int pid_is_user(int pid, int uid);static int pid_is_cmd(int pid, const char *name);#endifstatic void check(int pid);static void do_pidfile(const char *name);static int do_stop(void);#if defined(OSLinux)static int pid_is_exec(int pid, const struct stat *esb);#endif#if defined(OSHURD)static void do_psinit(void);#endif#ifdef __GNUC__static void fatal(const char *format, ...) __attribute__((noreturn, format(printf, 1, 2)));static void badusage(const char *msg) __attribute__((noreturn));#elsestatic void fatal(const char *format, ...);static void badusage(const char *msg);#endifstatic voidfatal(const char *format, ...){ va_list arglist; fprintf(stderr, "%s: ", progname); va_start(arglist, format); vfprintf(stderr, format, arglist); va_end(arglist); putc('\n', stderr); exit(2);}static void *xmalloc(int size){ void *ptr; ptr = malloc(size); if (ptr) return ptr; fatal("malloc(%d) failed", size);}static voidpush(struct pid_list **list, int pid){ struct pid_list *p; p = xmalloc(sizeof(*p)); p->next = *list; p->pid = pid; *list = p;}static voiddo_help(void){/*Print the help for systems that have getopt long*/#ifndef SunOS /*Solaris doesn't*/ printf("\start-stop-daemon for Debian GNU/Linux - small and fast C version written by\n\Marek Michalkiewicz <marekm@i17linuxb.ists.pwr.wroc.pl>, public domain.\n"GW_VERSION "\n\\n\Usage:\n\ start-stop-daemon -S|--start options ... -- arguments ...\n\ start-stop-daemon -K|--stop options ...\n\ start-stop-daemon -H|--help\n\ start-stop-daemon -V|--version\n\\n\Options (at least one of --exec|--pidfile|--user is required):\n\ -x|--exec <executable> program to start/check if it is running\n\ -p|--pidfile <pid-file> pid file to check\n\ -c|--chuid <name|uid[:group|gid]>\n\ change to this user/group before starting process\n\ -u|--user <username>|<uid> stop processes owned by this user\n\ -n|--name <process-name> stop processes with this name\n\ -s|--signal <signal> signal to send (default TERM)\n\ -a|--startas <pathname> program to start (default is <executable>)\n\ -b|--background force the process to detach\n\ -m|--make-pidfile create the pidfile before starting\n\ -t|--test test mode, don't do anything\n\ -o|--oknodo exit status 0 (not 1) if nothing done\n\ -q|--quiet be more quiet\n\ -v|--verbose be more verbose\n\\n\Exit status: 0 = done 1 = nothing done (=> 0 if --oknodo) 2 = trouble\n");#else /* Deal with systems that don't have getopt long, like Solaris*/ printf("\start-stop-daemon for Debian GNU/Linux - small and fast C version written by\n\Marek Michalkiewicz <marekm@i17linuxb.ists.pwr.wroc.pl>, public domain.\n"GW_VERSION "\n\\n\Usage:\n\ start-stop-daemon -S options ... -- arguments ...\n\ start-stop-daemon -K options ...\n\ start-stop-daemon -H\n\ start-stop-daemon -V\n\\n\Options (at least one of --exec|--pidfile|--user is required):\n\ -x <executable> program to start/check if it is running\n\ -p <pid-file> pid file to check\n\ -c <name|uid[:group|gid]> change to this user/group before starting process\n\ -u <username>|<uid> stop processes owned by this user\n\ -n <process-name> stop processes with this name\n\ -s <signal> signal to send (default TERM)\n\ -a <pathname> program to start (default is <executable>)\n\ -b force the process to detach\n\ -m create the pidfile before starting\n\ -t test mode, don't do anything\n\ -o exit status 0 (not 1) if nothing done\n\ -q be more quiet\n\ -v be more verbose\n\\n\Exit status: 0 = done 1 = nothing done (=> 0 if -o) 2 = trouble\n");#endif /*No more OS ( getopt ) specific stuff this function... */}static voidbadusage(const char *msg){ if (msg) fprintf(stderr, "%s: %s\n", progname, msg); #ifndef SunOS fprintf(stderr, "Try `%s --help' for more information.\n", progname); #else fprintf(stderr, "Try `%s -H' for more information.\n", progname); #endif exit(2);}struct sigpair { const char *name; int signal;};static const struct sigpair siglist[] = { { "ABRT", SIGABRT }, { "ALRM", SIGALRM }, { "FPE", SIGFPE }, { "HUP", SIGHUP }, { "ILL", SIGILL }, { "INT", SIGINT }, { "KILL", SIGKILL }, { "PIPE", SIGPIPE }, { "QUIT", SIGQUIT }, { "SEGV", SIGSEGV }, { "TERM", SIGTERM }, { "USR1", SIGUSR1 }, { "USR2", SIGUSR2 }, { "CHLD", SIGCHLD }, { "CONT", SIGCONT }, { "STOP", SIGSTOP }, { "TSTP", SIGTSTP }, { "TTIN", SIGTTIN }, { "TTOU", SIGTTOU }};static int sigcount = sizeof (siglist) / sizeof (siglist[0]);static int parse_signal (const char *signal_str, int *signal_nr){ int i; for (i = 0; i < sigcount; i++) { if (strcmp (signal_str, siglist[i].name) == 0) { *signal_nr = siglist[i].signal; return 0; } } return -1;}static voidparse_options(int argc, char * const *argv){#if HAVE_GETOPT_LONG static struct option longopts[] = { { "help", 0, NULL, 'H'}, { "stop", 0, NULL, 'K'}, { "start", 0, NULL, 'S'}, { "version", 0, NULL, 'V'}, { "startas", 1, NULL, 'a'}, { "name", 1, NULL, 'n'}, { "oknodo", 0, NULL, 'o'}, { "pidfile", 1, NULL, 'p'}, { "quiet", 0, NULL, 'q'}, { "signal", 1, NULL, 's'}, { "test", 0, NULL, 't'}, { "user", 1, NULL, 'u'}, { "chroot", 1, NULL, 'r'}, { "verbose", 0, NULL, 'v'}, { "exec", 1, NULL, 'x'}, { "chuid", 1, NULL, 'c'}, { "background", 0, NULL, 'b'}, { "make-pidfile", 0, NULL, 'm'}, { NULL, 0, NULL, 0} };#endif int c; for (;;) {#if HAVE_GETOPT_LONG c = getopt_long(argc, argv, "HKSVa:n:op:qr:s:tu:vx:c:bm", longopts, (int *) 0);#else c = getopt(argc, argv, "HKSVa:n:op:qr:s:tu:vx:c:bm");#endif if (c == -1) break; switch (c) { case 'H': /* --help */ do_help(); exit(0); case 'K': /* --stop */ stop = 1; break; case 'S': /* --start */ start = 1; break; case 'V': /* --version */ printf("start-stop-daemon " GW_VERSION "\n"); exit(0); case 'a': /* --startas <pathname> */ startas = optarg; break; case 'n': /* --name <process-name> */ cmdname = optarg; break; case 'o': /* --oknodo */ exitnodo = 0; break; case 'p': /* --pidfile <pid-file> */ pidfile = optarg; break; case 'q': /* --quiet */ quietmode = 1; break; case 's': /* --signal <signal> */ signal_str = optarg; break; case 't': /* --test */ testmode = 1; break; case 'u': /* --user <username>|<uid> */ userspec = optarg; break; case 'v': /* --verbose */ quietmode = -1; break; case 'x': /* --exec <executable> */ execname = optarg; break; case 'c': /* --chuid <username>|<uid> */ /* we copy the string just in case we need the * argument later. */ changeuser = strdup(optarg); changeuser = strtok(changeuser, ":"); changegroup = strtok(NULL, ":"); break; case 'r': /* --chroot /new/root */ changeroot = optarg; break; case 'b': /* --background */ background = 1; break; case 'm': /* --make-pidfile */ mpidfile = 1; break; default: badusage(NULL); /* message printed by getopt */ } } if (signal_str != NULL) { if (sscanf (signal_str, "%d", &signal_nr) != 1) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -