1/***********************************************************************
2*                                                                      *
3*               This software is part of the ast package               *
4*          Copyright (c) 1990-2011 AT&T Intellectual Property          *
5*                      and is licensed under the                       *
6*                 Eclipse Public License, Version 1.0                  *
7*                    by AT&T Intellectual Property                     *
8*                                                                      *
9*                A copy of the License is available at                 *
10*          http://www.eclipse.org/org/documents/epl-v10.html           *
11*         (with md5 checksum b35adb5213ca9657e911e9befb180842)         *
12*                                                                      *
13*              Information and Software Systems Research               *
14*                            AT&T Research                             *
15*                           Florham Park NJ                            *
16*                                                                      *
17*                 Glenn Fowler <gsf@research.att.com>                  *
18*                                                                      *
19***********************************************************************/
20#pragma prototyped
21/*
22 * Glenn Fowler
23 * AT&T Research
24 *
25 * if co==0 then kill all coshell jobs with sig
26 * elif cj==0 then kill co jobs with sig
27 * else kill cj with sig
28 *
29 * if sig==0 then cause all CO_SERVICE jobs to fail
30 */
31
32#include "colib.h"
33
34/*
35 * kill job cj in shell co with signal sig
36 */
37
38static int
39cokilljob(register Coshell_t* co, register Cojob_t* cj, int sig)
40{
41	int	n;
42
43	if (co->flags & CO_DEBUG)
44		errormsg(state.lib, 2, "coshell %d kill co=%d cj=%d sig=%d", co->index, co->pid, cj->pid, sig);
45	if (cj->pid < 0)
46		return 0;
47	if (cj->pid == 0)
48	{
49		if (cj->service)
50			co->svc_running--;
51		else
52			co->running--;
53		cj->pid = CO_PID_ZOMBIE;
54		cj->status = EXIT_TERM(sig);
55		return 0;
56	}
57	if (sig == SIGKILL)
58	{
59		co->running--;
60		cj->pid = CO_PID_ZOMBIE;
61		cj->status = EXIT_TERM(sig);
62	}
63	n = kill(cj->pid, sig);
64	killpg(cj->pid, sig);
65	return n;
66}
67
68/*
69 * kill cj (or all jobs if cj==0) in shell co with sig
70 */
71
72static int
73cokillshell(register Coshell_t* co, register Cojob_t* cj, int sig)
74{
75	int	n;
76
77	if (sig && (co->flags & CO_SERVER))
78	{
79		char	buf[CO_BUFSIZ];
80
81		n = sfsprintf(buf, sizeof(buf), "#%05d\nk %d %d\n", 0, cj ? cj->id : 0, sig);
82		sfsprintf(buf, 7, "#%05d\n", n - 7);
83		return write(co->cmdfd, buf, n) == n ? 0 : -1;
84	}
85	if (cj)
86		return cokilljob(co, cj, sig);
87	n = 0;
88	for (cj = co->jobs; cj; cj = cj->next)
89		if (cj->pid > 0)
90			n |= cokilljob(co, cj, sig);
91	return n;
92}
93
94int
95cokill(register Coshell_t* co, register Cojob_t* cj, int sig)
96{
97	int	any;
98	int	n;
99
100	if (cj)
101	{
102		if (!co)
103			co = cj->coshell;
104		else if (co != cj->coshell)
105			return -1;
106		any = 0;
107	}
108	else if (co)
109		any = 0;
110	else if (!(co = state.coshells))
111		return -1;
112	else
113		any = 1;
114	if (co->flags & CO_DEBUG)
115		errormsg(state.lib, 2, "coshell %d kill co=%d cj=%d sig=%d", co->index, co ? co->pid : 0, cj ? cj->pid : 0, sig);
116	switch (sig)
117	{
118	case SIGINT:
119		sig = SIGTERM;
120		break;
121#if defined(SIGSTOP) && defined(SIGTSTP)
122	case SIGTSTP:
123		sig = SIGSTOP;
124		break;
125#endif
126	}
127	n = 0;
128	do
129	{
130		cowait(co, (Cojob_t*)co, 0);
131		n |= cokillshell(co, cj, sig);
132	} while (any && (co = co->next));
133	return n;
134}
135