Imported Upstream version 3.3.3
[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  * Copyright (c) 2007-2012 Zmanda, Inc.  All Rights Reserved.
5  * All Rights Reserved.
6  *
7  * Permission to use, copy, modify, distribute, and sell this software and its
8  * documentation for any purpose is hereby granted without fee, provided that
9  * the above copyright notice appear in all copies and that both that
10  * copyright notice and this permission notice appear in supporting
11  * documentation, and that the name of U.M. not be used in advertising or
12  * publicity pertaining to distribution of the software without specific,
13  * written prior permission.  U.M. makes no representations about the
14  * suitability of this software for any purpose.  It is provided "as is"
15  * without express or implied warranty.
16  *
17  * U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M.
19  * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
20  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
21  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
22  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23  *
24  * Authors: the Amanda Development Team.  Its members are listed in a
25  * file named AUTHORS, in the root directory of this distribution.
26  */
27 /*
28  * $Id: killpgrp.c,v 1.17 2006/07/25 18:27:56 martinea Exp $
29  *
30  * if it is the process group leader, it kills all processes in its
31  * process group when it is killed itself.
32  *
33  * argv[0] is the killpgrp program name
34  * argv[1] is the config name or NOCONFIG
35  *
36  */
37 #include "amanda.h"
38 #include "util.h"
39 #include "conffile.h"
40
41 #ifdef HAVE_GETPGRP
42 #ifdef GETPGRP_VOID
43 #define AM_GETPGRP() getpgrp()
44 #else
45 #define AM_GETPGRP() getpgrp(getpid())
46 #endif
47 #else
48 /* we cannot check it, so let us assume it is ok */
49 #define AM_GETPGRP() getpid()
50 #endif
51  
52 int main(int argc, char **argv);
53 static void term_kill_soft(int sig);
54 static void term_kill_hard(int sig);
55
56 int
57 main(
58     int         argc,
59     char **     argv)
60 {
61     int ch;
62     char *exitstr;
63     amwait_t status;
64
65     if (argc > 1 && argv && argv[1] && g_str_equal(argv[1], "--version")) {
66         printf("killpgrp-%s\n", VERSION);
67         return (0);
68     }
69
70     /*
71      * Configure program for internationalization:
72      *   1) Only set the message locale for now.
73      *   2) Set textdomain for all amanda related programs to "amanda"
74      *      We don't want to be forced to support dozens of message catalogs.
75      */  
76     setlocale(LC_MESSAGES, "C");
77     textdomain("amanda"); 
78
79     safe_fd(-1, 0);
80     safe_cd();
81
82     set_pname("killpgrp");
83
84     dbopen(DBG_SUBDIR_CLIENT);
85     config_init(CONFIG_INIT_CLIENT, NULL);
86
87     if (argc < 2) {
88         error("Need at least 2 arguments\n");
89         /*NOTREACHED*/
90     }
91     dbprintf(_("version %s\n"), VERSION);
92     dbprintf(_("config: %s\n"), argv[1]);
93     if (strcmp(argv[1], "NOCONFIG") != 0)
94         dbrename(argv[1], DBG_SUBDIR_CLIENT);
95
96 #ifdef WANT_SETUID_CLIENT
97     check_running_as(RUNNING_AS_CLIENT_LOGIN | RUNNING_AS_UID_ONLY);
98     if (!become_root()) {
99         error(_("error [%s could not become root (is the setuid bit set?)]\n"), get_pname());
100         /*NOTREACHED*/
101     }
102 #else
103     check_running_as(RUNNING_AS_CLIENT_LOGIN);
104 #endif
105
106     if (AM_GETPGRP() != getpid()) {
107         error(_("error [must be the process group leader]"));
108         /*NOTREACHED*/
109     }
110
111     signal(SIGTERM, term_kill_soft);
112
113     /* Consume any extranious input */
114     do {
115         ch = getchar();
116         /* wait until EOF */
117     } while (ch != EOF);
118
119     term_kill_soft(0);
120
121     for(;;) {
122         if (wait(&status) != -1)
123             break;
124         if (errno != EINTR) {
125             error(_("error [wait() failed: %s]"), strerror(errno));
126             /*NOTREACHED*/
127         }
128     }
129     exitstr = str_exit_status("child", status);
130     dbprintf("%s\n", exitstr);
131     amfree(exitstr);
132
133     /*@ignore@*/
134     return WIFEXITED(status)?WEXITSTATUS(status):1;
135     /*@end@*/
136 }
137
138 static void term_kill_soft(
139     int sig)
140 {
141     pid_t dumppid = getpid();
142     int killerr;
143
144     (void)sig;  /* Quiet unused parameter warning */
145
146     signal(SIGTERM, SIG_IGN);
147     signal(SIGALRM, term_kill_hard);
148     alarm(3);
149     /*
150      * First, try to kill the dump process nicely.  If it ignores us
151      * for three seconds, hit it harder.
152      */
153     dbprintf(_("sending SIGTERM to process group %ld\n"), (long) dumppid);
154     killerr = kill(-dumppid, SIGTERM);
155     if (killerr == -1) {
156         dbprintf(_("kill failed: %s\n"), strerror(errno));
157     }
158 }
159
160 static void term_kill_hard(
161     int sig)
162 {
163     pid_t dumppid = getpid();
164     int killerr;
165
166     (void)sig;  /* Quiet unused parameter warning */
167
168     dbprintf(_("It won\'t die with SIGTERM, but SIGKILL should do.\n"));
169     dbprintf(_("Don't expect any further output, this will be suicide.\n"));
170     killerr = kill(-dumppid, SIGKILL);
171     /* should never reach this point, but so what? */
172     if (killerr == -1) {
173         dbprintf(_("kill failed: %s\n"), strerror(errno));
174         dbprintf(_("waiting until child terminates\n"));
175     }
176 }