diff options
Diffstat (limited to 'init/msvc.c')
-rw-r--r-- | init/msvc.c | 300 |
1 files changed, 300 insertions, 0 deletions
diff --git a/init/msvc.c b/init/msvc.c new file mode 100644 index 000000000..d72ddce1e --- /dev/null +++ b/init/msvc.c | |||
@@ -0,0 +1,300 @@ | |||
1 | /* | ||
2 | * minit version 0.9.1 by Felix von Leitner | ||
3 | * ported to busybox by Glenn McGrath <bug1@optushome.com.au> | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License as published by | ||
7 | * the Free Software Foundation; either version 2 of the License, or | ||
8 | * (at your option) any later version. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
18 | */ | ||
19 | |||
20 | #include <sys/fcntl.h> | ||
21 | #include <sys/file.h> | ||
22 | #include <signal.h> | ||
23 | #include <stdio.h> | ||
24 | #include <stdlib.h> | ||
25 | #include <string.h> | ||
26 | #include <unistd.h> | ||
27 | |||
28 | #include "busybox.h" | ||
29 | |||
30 | static int infd, outfd; | ||
31 | |||
32 | static char buf[1500]; | ||
33 | |||
34 | static unsigned int fmt_ulong(char *dest, unsigned long i) | ||
35 | { | ||
36 | register unsigned long len, tmp, len2; | ||
37 | |||
38 | /* first count the number of bytes needed */ | ||
39 | for (len = 1, tmp = i; tmp > 9; ++len) | ||
40 | tmp /= 10; | ||
41 | if (dest) | ||
42 | for (tmp = i, dest += len, len2 = len + 1; --len2; tmp /= 10) | ||
43 | *--dest = (tmp % 10) + '0'; | ||
44 | return len; | ||
45 | } | ||
46 | |||
47 | static void addservice(char *service) | ||
48 | { | ||
49 | char *service_ptr; | ||
50 | |||
51 | if (strncmp(service, "/etc/minit/", 11) == 0) { | ||
52 | service += 11; | ||
53 | } | ||
54 | |||
55 | while ((service_ptr = last_char_is(service, '/')) != NULL) { | ||
56 | *service_ptr = 0; | ||
57 | } | ||
58 | strncpy(buf + 1, service, 1400); | ||
59 | buf[1400] = 0; | ||
60 | } | ||
61 | |||
62 | static int addreadwrite(char *service) | ||
63 | { | ||
64 | addservice(service); | ||
65 | write(infd, buf, strlen(buf)); | ||
66 | return read(outfd, buf, 1500); | ||
67 | } | ||
68 | |||
69 | /* return PID, 0 if error */ | ||
70 | static pid_t __readpid(char *service) | ||
71 | { | ||
72 | int len; | ||
73 | |||
74 | buf[0] = 'p'; | ||
75 | len = addreadwrite(service); | ||
76 | if (len < 0) | ||
77 | return 0; | ||
78 | buf[len] = 0; | ||
79 | return atoi(buf); | ||
80 | } | ||
81 | |||
82 | /* return nonzero if error */ | ||
83 | static int respawn(char *service, int yesno) | ||
84 | { | ||
85 | int len; | ||
86 | |||
87 | buf[0] = yesno ? 'R' : 'r'; | ||
88 | len = addreadwrite(service); | ||
89 | return (len != 1 || buf[0] == '0'); | ||
90 | } | ||
91 | |||
92 | /* return nonzero if error */ | ||
93 | static int startservice(char *service) | ||
94 | { | ||
95 | int len; | ||
96 | |||
97 | buf[0] = 's'; | ||
98 | len = addreadwrite(service); | ||
99 | return (len != 1 || buf[0] == '0'); | ||
100 | } | ||
101 | |||
102 | extern int msvc_main(int argc, char **argv) | ||
103 | { | ||
104 | if (argc < 2) { | ||
105 | bb_show_usage(); | ||
106 | } | ||
107 | infd = bb_xopen("/etc/minit/in", O_WRONLY); | ||
108 | outfd = bb_xopen("/etc/minit/out", O_RDONLY); | ||
109 | |||
110 | while (lockf(infd, F_LOCK, 1)) { | ||
111 | bb_perror_msg("could not aquire lock!\n"); | ||
112 | sleep(1); | ||
113 | } | ||
114 | |||
115 | if (argc == 2) { | ||
116 | pid_t pid = __readpid(argv[1]); | ||
117 | |||
118 | if (buf[0] != '0') { | ||
119 | int len; | ||
120 | int up_time; | ||
121 | |||
122 | printf("%s: ", argv[1]); | ||
123 | if (pid == 0) | ||
124 | printf("down "); | ||
125 | else if (pid == 1) | ||
126 | printf("finished "); | ||
127 | else { | ||
128 | printf("up (pid %d) ", pid); | ||
129 | } | ||
130 | |||
131 | buf[0] = 'u'; | ||
132 | len = addreadwrite(argv[1]); | ||
133 | if (len < 0) { | ||
134 | up_time = 0; | ||
135 | } else { | ||
136 | buf[len] = 0; | ||
137 | up_time = atoi(buf); | ||
138 | } | ||
139 | printf("%d seconds\n", up_time); | ||
140 | |||
141 | if (pid == 0) | ||
142 | return 2; | ||
143 | else if (pid == 1) | ||
144 | return 3; | ||
145 | else | ||
146 | return 0; | ||
147 | } else { | ||
148 | bb_error_msg_and_die("no such service"); | ||
149 | } | ||
150 | } else { | ||
151 | int i; | ||
152 | int ret = 0; | ||
153 | int sig = 0; | ||
154 | pid_t pid; | ||
155 | |||
156 | if (argv[1][0] == '-') { | ||
157 | switch (argv[1][1]) { | ||
158 | case 'g': | ||
159 | for (i = 2; i < argc; ++i) { | ||
160 | pid = __readpid(argv[i]); | ||
161 | if (pid < 2) { | ||
162 | if (pid == 1) { | ||
163 | bb_error_msg("%s, service termination", argv[i]); | ||
164 | } else { | ||
165 | bb_error_msg("%s, no such service", argv[i]); | ||
166 | } | ||
167 | ret = 1; | ||
168 | } | ||
169 | printf("%d\n", pid); | ||
170 | } | ||
171 | break; | ||
172 | case 'p': | ||
173 | sig = SIGSTOP; | ||
174 | goto dokill; | ||
175 | break; | ||
176 | case 'c': | ||
177 | sig = SIGCONT; | ||
178 | goto dokill; | ||
179 | break; | ||
180 | case 'h': | ||
181 | sig = SIGHUP; | ||
182 | goto dokill; | ||
183 | break; | ||
184 | case 'a': | ||
185 | sig = SIGALRM; | ||
186 | goto dokill; | ||
187 | break; | ||
188 | case 'i': | ||
189 | sig = SIGINT; | ||
190 | goto dokill; | ||
191 | break; | ||
192 | case 't': | ||
193 | sig = SIGTERM; | ||
194 | goto dokill; | ||
195 | break; | ||
196 | case 'k': | ||
197 | sig = SIGKILL; | ||
198 | goto dokill; | ||
199 | break; | ||
200 | case 'o': | ||
201 | for (i = 2; i < argc; ++i) | ||
202 | if (startservice(argv[i]) || respawn(argv[i], 0)) { | ||
203 | bb_error_msg("Couldnt not start %s\n", argv[i]); | ||
204 | ret = 1; | ||
205 | } | ||
206 | break; | ||
207 | case 'd': | ||
208 | for (i = 2; i < argc; ++i) { | ||
209 | pid = __readpid(argv[i]); | ||
210 | if (pid == 0) { | ||
211 | bb_error_msg("%s, no such service\n", argv[i]); | ||
212 | ret = 1; | ||
213 | } else if (pid == 1) | ||
214 | continue; | ||
215 | if (respawn(argv[i], 0) || kill(pid, SIGTERM) | ||
216 | || kill(pid, SIGCONT)); | ||
217 | } | ||
218 | break; | ||
219 | case 'u': | ||
220 | for (i = 2; i < argc; ++i) { | ||
221 | if (startservice(argv[i]) || respawn(argv[i], 1)) { | ||
222 | bb_error_msg("Couldnt not start %s\n", argv[i]); | ||
223 | ret = 1; | ||
224 | } | ||
225 | break; | ||
226 | } | ||
227 | case 'C': | ||
228 | for (i = 2; i < argc; ++i) { | ||
229 | int len; | ||
230 | |||
231 | buf[0] = 'C'; | ||
232 | len = addreadwrite(argv[i]); | ||
233 | if (len != 1 || buf[0] == '0') { | ||
234 | bb_error_msg("%s has terminated or was killed\n", | ||
235 | argv[i]); | ||
236 | ret = 1; | ||
237 | } | ||
238 | } | ||
239 | break; | ||
240 | case 'P': | ||
241 | pid = atoi(argv[1] + 2); | ||
242 | if (pid > 1) { | ||
243 | char *tmp; | ||
244 | int len; | ||
245 | |||
246 | buf[0] = 'P'; | ||
247 | addservice(argv[2]); | ||
248 | tmp = buf + strlen(buf) + 1; | ||
249 | tmp[fmt_ulong(tmp, pid)] = 0; | ||
250 | write(infd, buf, strlen(buf) + strlen(tmp) + 2); | ||
251 | len = read(outfd, buf, 1500); | ||
252 | if (len != 1 || buf[0] == '0') { | ||
253 | bb_error_msg_and_die("Couldnt not set pid of service %s\n", argv[2]); | ||
254 | } | ||
255 | } | ||
256 | break; | ||
257 | default: | ||
258 | bb_show_usage(); | ||
259 | } | ||
260 | } else { | ||
261 | bb_show_usage(); | ||
262 | } | ||
263 | return ret; | ||
264 | dokill: | ||
265 | for (i = 2; i < argc; i++) { | ||
266 | pid = __readpid(argv[i]); | ||
267 | if (!pid) { | ||
268 | bb_error_msg("%s no such service\n", argv[i]); | ||
269 | ret = 1; | ||
270 | } | ||
271 | if (kill(pid, sig)) { | ||
272 | bb_error_msg("%s, could not send signal %d to PID %d\n", | ||
273 | argv[i], sig, pid); | ||
274 | ret = 1; | ||
275 | } | ||
276 | } | ||
277 | return ret; | ||
278 | } | ||
279 | } | ||
280 | |||
281 | /* | ||
282 | -u Up. If the service is not running, start it. If the service stops, | ||
283 | restart it. | ||
284 | -d Down. If the service is running, send it a TERM signal and then a CONT | ||
285 | signal. After it stops, do not restart it. | ||
286 | -o Once. If the service is not running, start it. Do not restart it if it | ||
287 | stops. | ||
288 | -r Tell supervise that the service is normally running; this affects status | ||
289 | messages. | ||
290 | -s Tell supervise that the service is normally stopped; this affects status | ||
291 | messages. | ||
292 | -p Pause. Send the service a STOP signal. | ||
293 | -c Continue. Send the service a CONT signal. | ||
294 | -h Hangup. Send the service a HUP signal. | ||
295 | -a Alarm. Send the service an ALRM signal. | ||
296 | -i Interrupt. Send the service an INT signal. | ||
297 | -t Terminate. Send the service a TERM signal. | ||
298 | -k Kill. Send the service a KILL signal. | ||
299 | -x Exit. supervise will quit as soon as the service is down. | ||
300 | */ | ||