Imported Upstream version 3.3.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 "util.h"
38 #include "conffile.h"
39
40 #ifdef HAVE_GETPGRP
41 #ifdef GETPGRP_VOID
42 #define AM_GETPGRP() getpgrp()
43 #else
44 #define AM_GETPGRP() getpgrp(getpid())
45 #endif
46 #else
47 /* we cannot check it, so let us assume it is ok */
48 #define AM_GETPGRP() getpid()
49 #endif
50  
51 int main(int argc, char **argv);
52 static void term_kill_soft(int sig);
53 static void term_kill_hard(int sig);
54
55 int
56 main(
57     int         argc,
58     char **     argv)
59 {
60     int ch;
61     char *exitstr;
62     amwait_t status;
63
64     if (argc > 1 && argv && argv[1] && g_str_equal(argv[1], "--version")) {
65         printf("killpgrp-%s\n", VERSION);
66         return (0);
67     }
68
69     /*
70      * Configure program for internationalization:
71      *   1) Only set the message locale for now.
72      *   2) Set textdomain for all amanda related programs to "amanda"
73      *      We don't want to be forced to support dozens of message catalogs.
74      */  
75     setlocale(LC_MESSAGES, "C");
76     textdomain("amanda"); 
77
78     safe_fd(-1, 0);
79     safe_cd();
80
81     set_pname("killpgrp");
82
83     dbopen(DBG_SUBDIR_CLIENT);
84     config_init(CONFIG_INIT_CLIENT, NULL);
85
86     if (argc < 2) {
87         error("Need at least 2 arguments\n");
88         /*NOTREACHED*/
89     }
90     dbprintf(_("version %s\n"), VERSION);
91     dbprintf(_("config: %s\n"), argv[1]);
92     if (strcmp(argv[1], "NOCONFIG") != 0)
93         dbrename(argv[1], DBG_SUBDIR_CLIENT);
94
95 #ifdef WANT_SETUID_CLIENT
96     check_running_as(RUNNING_AS_CLIENT_LOGIN | RUNNING_AS_UID_ONLY);
97     if (!become_root()) {
98         error(_("error [%s could not become root (is the setuid bit set?)]\n"), get_pname());
99         /*NOTREACHED*/
100     }
101 #else
102     check_running_as(RUNNING_AS_CLIENT_LOGIN);
103 #endif
104
105     if (AM_GETPGRP() != getpid()) {
106         error(_("error [must be the process group leader]"));
107         /*NOTREACHED*/
108     }
109
110     signal(SIGTERM, term_kill_soft);
111
112     /* Consume any extranious input */
113     do {
114         ch = getchar();
115         /* wait until EOF */
116     } while (ch != EOF);
117
118     term_kill_soft(0);
119
120     for(;;) {
121         if (wait(&status) != -1)
122             break;
123         if (errno != EINTR) {
124             error(_("error [wait() failed: %s]"), strerror(errno));
125             /*NOTREACHED*/
126         }
127     }
128     exitstr = str_exit_status("child", status);
129     dbprintf("%s\n", exitstr);
130     amfree(exitstr);
131
132     /*@ignore@*/
133     return WIFEXITED(status)?WEXITSTATUS(status):1;
134     /*@end@*/
135 }
136
137 static void term_kill_soft(
138     int sig)
139 {
140     pid_t dumppid = getpid();
141     int killerr;
142
143     (void)sig;  /* Quiet unused parameter warning */
144
145     signal(SIGTERM, SIG_IGN);
146     signal(SIGALRM, term_kill_hard);
147     alarm(3);
148     /*
149      * First, try to kill the dump process nicely.  If it ignores us
150      * for three seconds, hit it harder.
151      */
152     dbprintf(_("sending SIGTERM to process group %ld\n"), (long) dumppid);
153     killerr = kill(-dumppid, SIGTERM);
154     if (killerr == -1) {
155         dbprintf(_("kill failed: %s\n"), strerror(errno));
156     }
157 }
158
159 static void term_kill_hard(
160     int sig)
161 {
162     pid_t dumppid = getpid();
163     int killerr;
164
165     (void)sig;  /* Quiet unused parameter warning */
166
167     dbprintf(_("It won\'t die with SIGTERM, but SIGKILL should do.\n"));
168     dbprintf(_("Don't expect any further output, this will be suicide.\n"));
169     killerr = kill(-dumppid, SIGKILL);
170     /* should never reach this point, but so what? */
171     if (killerr == -1) {
172         dbprintf(_("kill failed: %s\n"), strerror(errno));
173         dbprintf(_("waiting until child terminates\n"));
174     }
175 }