9c12141a03ff4a5542e92104d64b3ec449890a32
[debian/amanda] / client-src / killpgrp.c
1 /*
2  * Amanda, The Advanced Maryland Automatic Network Disk Archiver
3  * Copyright (c) 1991-1998 University of Maryland at College Park
4  * All Rights Reserved.
5  *
6  * Permission to use, copy, modify, distribute, and sell this software and its
7  * documentation for any purpose is hereby granted without fee, provided that
8  * the above copyright notice appear in all copies and that both that
9  * copyright notice and this permission notice appear in supporting
10  * documentation, and that the name of U.M. not be used in advertising or
11  * publicity pertaining to distribution of the software without specific,
12  * written prior permission.  U.M. makes no representations about the
13  * suitability of this software for any purpose.  It is provided "as is"
14  * without express or implied warranty.
15  *
16  * U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M.
18  * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
20  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
21  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22  *
23  * Authors: the Amanda Development Team.  Its members are listed in a
24  * file named AUTHORS, in the root directory of this distribution.
25  */
26 /*
27  * $Id: killpgrp.c,v 1.8.4.2.4.1 2002/10/27 14:31:18 martinea Exp $
28  *
29  * if it is the process group leader, it kills all processes in its
30  * process group when it is killed itself.
31  */
32 #include "amanda.h"
33 #include "version.h"
34
35 #ifdef HAVE_GETPGRP
36 #ifdef GETPGRP_VOID
37 #define AM_GETPGRP() getpgrp()
38 #else
39 #define AM_GETPGRP() getpgrp(getpid())
40 #endif
41 #else
42 /* we cannot check it, so let us assume it is ok */
43 #define AM_GETPGRP() getpid()
44 #endif
45  
46 int main P((int argc, char **argv));
47 static void term_kill_soft P((int sig));
48 static void term_kill_hard P((int sig));
49
50 int main(argc, argv)
51 int argc;
52 char **argv;
53 {
54     amwait_t status;
55     int fd;
56
57     for(fd = 3; fd < FD_SETSIZE; fd++) {
58         /*
59          * Make sure nobody spoofs us with a lot of extra open files
60          * that would cause an open we do to get a very high file
61          * descriptor, which in turn might be used as an index into
62          * an array (e.g. an fd_set).
63          */
64         close(fd);
65     }
66
67     safe_cd();
68
69     set_pname("killpgrp");
70
71     dbopen();
72     dbprintf(("%s: version %s\n", argv[0], version()));
73
74     if(client_uid == (uid_t) -1) {
75         error("error [cannot find user %s in passwd file]", CLIENT_LOGIN);
76     }
77
78 #ifdef FORCE_USERID
79     if (getuid() != client_uid) {
80         error("error [must be invoked by %s]", CLIENT_LOGIN);
81     }
82
83     if (geteuid() != 0) {
84         error("error [must be setuid root]");
85     }
86 #endif  /* FORCE_USERID */
87
88 #if !defined (DONT_SUID_ROOT)
89     setuid(0);
90 #endif
91
92     if (AM_GETPGRP() != getpid()) {
93         error("error [must be the process group leader]");
94     }
95
96     signal(SIGTERM, term_kill_soft);
97
98     while (getchar() != EOF) {
99         /* wait until EOF */
100     }
101
102     term_kill_soft(0);
103
104     for(;;) {
105         if (wait(&status) != -1)
106             break;
107         if (errno != EINTR) {
108             error("error [wait() failed: %s]", strerror(errno));
109             return -1;
110         }
111     }
112
113     dbprintf(("child process exited with status %d\n", WEXITSTATUS(status)));
114
115     return WEXITSTATUS(status);
116 }
117
118 static void term_kill_soft(sig)
119 int sig;
120 {
121     pid_t dumppid = getpid();
122     int killerr;
123
124     signal(SIGTERM, SIG_IGN);
125     signal(SIGALRM, term_kill_hard);
126     alarm(3);
127     /*
128      * First, try to kill the dump process nicely.  If it ignores us
129      * for three seconds, hit it harder.
130      */
131     dbprintf(("sending SIGTERM to process group %ld\n", (long) dumppid));
132     killerr = kill(-dumppid, SIGTERM);
133     if (killerr == -1) {
134         dbprintf(("kill failed: %s\n", strerror(errno)));
135     }
136 }
137
138 static void term_kill_hard(sig)
139 int sig;
140 {
141     pid_t dumppid = getpid();
142     int killerr;
143
144     dbprintf(("it won\'t die with SIGTERM, but SIGKILL should do\n"));
145     dbprintf(("do\'t expect any further output, this will be suicide\n"));
146     killerr = kill(-dumppid, SIGKILL);
147     /* should never reach this point, but so what? */
148     if (killerr == -1) {
149         dbprintf(("kill failed: %s\n", strerror(errno)));
150         dbprintf(("waiting until child terminates\n"));
151     }
152 }