Imported Upstream version 2.5.1
[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.17 2006/07/25 18:27:56 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  * argv[0] is the killpgrp program name
33  * argv[1] is the config name or NOCONFIG
34  *
35  */
36 #include "amanda.h"
37 #include "version.h"
38
39 #ifdef HAVE_GETPGRP
40 #ifdef GETPGRP_VOID
41 #define AM_GETPGRP() getpgrp()
42 #else
43 #define AM_GETPGRP() getpgrp(getpid())
44 #endif
45 #else
46 /* we cannot check it, so let us assume it is ok */
47 #define AM_GETPGRP() getpid()
48 #endif
49  
50 int main(int argc, char **argv);
51 static void term_kill_soft(int sig);
52 static void term_kill_hard(int sig);
53
54 int main(
55     int argc,
56     char **argv)
57 {
58     int ch;
59     amwait_t status;
60
61     safe_fd(-1, 0);
62     safe_cd();
63
64     set_pname("killpgrp");
65
66     dbopen(DBG_SUBDIR_CLIENT);
67     if (argc < 2) {
68         error("%s: Need at least 2 arguments\n", debug_prefix(NULL));
69         /*NOTREACHED*/
70     }
71     dbprintf(("%s: version %s\n", debug_prefix(NULL), version()));
72     dbprintf(("config: %s\n", argv[1]));
73     if (strcmp(argv[1], "NOCONFIG") != 0)
74         dbrename(argv[1], DBG_SUBDIR_CLIENT);
75
76     if(client_uid == (uid_t) -1) {
77         error("error [cannot find user %s in passwd file]", CLIENT_LOGIN);
78         /*NOTREACHED*/
79     }
80
81 #ifdef FORCE_USERID
82     if (getuid() != client_uid) {
83         error("error [must be invoked by %s]", CLIENT_LOGIN);
84         /*NOTREACHED*/
85     }
86     if (geteuid() != 0) {
87         error("error [must be setuid root]");
88         /*NOTREACHED*/
89     }
90 #endif  /* FORCE_USERID */
91
92 #if !defined (DONT_SUID_ROOT)
93     setuid(0);
94 #endif
95
96     if (AM_GETPGRP() != getpid()) {
97         error("error [must be the process group leader]");
98         /*NOTREACHED*/
99     }
100
101     /* Consume any extranious input */
102     signal(SIGTERM, term_kill_soft);
103
104     do {
105         ch = getchar();
106         /* wait until EOF */
107     } while (ch != EOF);
108
109     term_kill_soft(0);
110
111     for(;;) {
112         if (wait(&status) != -1)
113             break;
114         if (errno != EINTR) {
115             error("error [wait() failed: %s]", strerror(errno));
116             /*NOTREACHED*/
117         }
118     }
119
120     /*@ignore@*/
121     dbprintf(("child process exited with status %d\n", WEXITSTATUS(status)));
122
123     return WEXITSTATUS(status);
124     /*@end@*/
125 }
126
127 static void term_kill_soft(
128     int sig)
129 {
130     pid_t dumppid = getpid();
131     int killerr;
132
133     (void)sig;  /* Quiet unused parameter warning */
134
135     signal(SIGTERM, SIG_IGN);
136     signal(SIGALRM, term_kill_hard);
137     alarm(3);
138     /*
139      * First, try to kill the dump process nicely.  If it ignores us
140      * for three seconds, hit it harder.
141      */
142     dbprintf(("sending SIGTERM to process group %ld\n", (long) dumppid));
143     killerr = kill(-dumppid, SIGTERM);
144     if (killerr == -1) {
145         dbprintf(("kill failed: %s\n", strerror(errno)));
146     }
147 }
148
149 static void term_kill_hard(
150     int sig)
151 {
152     pid_t dumppid = getpid();
153     int killerr;
154
155     (void)sig;  /* Quiet unused parameter warning */
156
157     dbprintf(("it won\'t die with SIGTERM, but SIGKILL should do\n"));
158     dbprintf(("do\'t expect any further output, this will be suicide\n"));
159     killerr = kill(-dumppid, SIGKILL);
160     /* should never reach this point, but so what? */
161     if (killerr == -1) {
162         dbprintf(("kill failed: %s\n", strerror(errno)));
163         dbprintf(("waiting until child terminates\n"));
164     }
165 }