diff options
Diffstat (limited to 'urunlevel/runlevel/rc.c')
-rw-r--r-- | urunlevel/runlevel/rc.c | 2013 |
1 files changed, 1073 insertions, 940 deletions
diff --git a/urunlevel/runlevel/rc.c b/urunlevel/runlevel/rc.c index 9efe84d..8a69e77 100644 --- a/urunlevel/runlevel/rc.c +++ b/urunlevel/runlevel/rc.c | |||
@@ -1,8 +1,11 @@ | |||
1 | /* | 1 | /* |
2 | * Mini rc implementation for busybox. | 2 | * init.d runlevel implementation for busybox. |
3 | * | 3 | * |
4 | * Copyright (C) 2005 by David Seikel won_fang@yahoo.com.au | 4 | * Copyright (C) 2005 by David Seikel won_fang@yahoo.com.au |
5 | * | 5 | * |
6 | * Clean room implementation of LSB init.d specs. | ||
7 | * I didn't steal any of this, honest B-). | ||
8 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | 9 | * This program is free software; you can redistribute it and/or modify |
7 | * it under the terms of the GNU General Public License as published by | 10 | * it under the terms of the GNU General Public License as published by |
8 | * the Free Software Foundation; either version 2 of the License, or | 11 | * the Free Software Foundation; either version 2 of the License, or |
@@ -33,1209 +36,1299 @@ | |||
33 | #include "lib_init_d.h" | 36 | #include "lib_init_d.h" |
34 | 37 | ||
35 | 38 | ||
36 | const static char *commands[] = | 39 | const static char *commands[] = { |
37 | { | 40 | "start", |
38 | "start", | 41 | "stop", |
39 | "stop", | 42 | "restart", |
40 | "restart", | 43 | "try-restart", |
41 | "try-restart", | 44 | "reload", |
42 | "reload", | 45 | "force-reload", |
43 | "force-reload", | 46 | "status", |
44 | "status", | 47 | "info", |
45 | "info", | 48 | NULL |
46 | NULL | ||
47 | }; | 49 | }; |
48 | 50 | ||
49 | 51 | ||
50 | const static char *INFOS[] = | 52 | const static char *INFOS[] = { |
51 | { | 53 | INIT_D_BEGIN, |
52 | INIT_D_BEGIN, | 54 | INIT_D_PROV, |
53 | INIT_D_PROV, | 55 | INIT_D_RSTART, |
54 | INIT_D_RSTART, | 56 | INIT_D_RSTOP, |
55 | INIT_D_RSTOP, | 57 | INIT_D_SSTART, |
56 | INIT_D_SSTART, | 58 | INIT_D_SSTOP, |
57 | INIT_D_SSTOP, | 59 | INIT_D_DSTART, |
58 | INIT_D_DSTART, | 60 | INIT_D_DSTOP, |
59 | INIT_D_DSTOP, | 61 | INIT_D_SDESC, |
60 | INIT_D_SDESC, | 62 | INIT_D_DESC, |
61 | INIT_D_DESC, | 63 | INIT_D_COMMENT, |
62 | INIT_D_COMMENT, | 64 | INIT_D_CONT, |
63 | INIT_D_CONT, | 65 | INIT_D_CONT2, |
64 | INIT_D_CONT2, | 66 | INIT_D_END, |
65 | INIT_D_END, | 67 | NULL |
66 | NULL | ||
67 | }; | 68 | }; |
68 | 69 | ||
69 | 70 | ||
70 | int default_start(struct init_d_handle_s *init_d, int just_checking) | 71 | int default_start(struct init_d_handle_s *init_d, int just_checking) |
71 | { | 72 | { |
72 | int status = (init_d->status)(init_d, 0); | 73 | int status = (init_d->status) (init_d, 0); |
73 | 74 | ||
74 | switch (status) | 75 | switch (status) { |
75 | { | 76 | case INIT_D_STATUS_OK: |
76 | case INIT_D_STATUS_OK : | ||
77 | { | 77 | { |
78 | status = INIT_D_OK; | 78 | status = INIT_D_OK; |
79 | break; | 79 | break; |
80 | } | 80 | } |
81 | 81 | ||
82 | case INIT_D_STATUS_DEAD_PID : | 82 | case INIT_D_STATUS_DEAD_PID: |
83 | { | 83 | { |
84 | log_warning_msg("Stale pid file exists!"); | 84 | log_warning_msg("Stale pid file exists!"); |
85 | status = INIT_D_ERROR_GENERIC; // LSB is not clear on what to return, but this is an error condition. | 85 | status = INIT_D_ERROR_GENERIC; // LSB is not clear on what to return, but this is an error condition. |
86 | break; | 86 | break; |
87 | } | 87 | } |
88 | 88 | ||
89 | case INIT_D_STATUS_DEAD_LOCK : | 89 | case INIT_D_STATUS_DEAD_LOCK: |
90 | { | 90 | { |
91 | log_warning_msg("Stale lock file exists!"); | 91 | log_warning_msg("Stale lock file exists!"); |
92 | status = INIT_D_ERROR_GENERIC; // LSB is not clear on what to return, but this is an error condition. | 92 | status = INIT_D_ERROR_GENERIC; // LSB is not clear on what to return, but this is an error condition. |
93 | break; | 93 | break; |
94 | } | 94 | } |
95 | 95 | ||
96 | case INIT_D_STATUS_NOT_RUNNING : | 96 | case INIT_D_STATUS_NOT_RUNNING: |
97 | { | 97 | { |
98 | struct stat script_stat; | 98 | struct stat script_stat; |
99 | 99 | ||
100 | if (stat(init_d->pathname, &script_stat) == 0) | 100 | if (stat(init_d->pathname, &script_stat) == 0) { |
101 | { | 101 | if (just_checking) |
102 | if (just_checking) | 102 | status = INIT_D_ERROR_JUST_NOT_RUNNING; |
103 | status = INIT_D_ERROR_JUST_NOT_RUNNING; | 103 | else |
104 | else | 104 | status = |
105 | status = start_daemon(0, 0, init_d->pidfile, init_d->pathname, init_d->args); | 105 | start_daemon(0, 0, init_d->pidfile, init_d->pathname, |
106 | } | 106 | init_d->args); |
107 | else | 107 | } else |
108 | status = INIT_D_ERROR_NOT_INSTALLED; | 108 | status = INIT_D_ERROR_NOT_INSTALLED; |
109 | break; | 109 | break; |
110 | } | 110 | } |
111 | 111 | ||
112 | default : | 112 | default: |
113 | { | 113 | { |
114 | status = INIT_D_ERROR_GENERIC; | 114 | status = INIT_D_ERROR_GENERIC; |
115 | break; | 115 | break; |
116 | } | ||
116 | } | 117 | } |
117 | } | ||
118 | 118 | ||
119 | return status; | 119 | return status; |
120 | } | 120 | } |
121 | 121 | ||
122 | 122 | ||
123 | int default_stop(struct init_d_handle_s *init_d, int just_checking) | 123 | int default_stop(struct init_d_handle_s *init_d, int just_checking) |
124 | { | 124 | { |
125 | int status = (init_d->status)(init_d, 0); | 125 | int status = (init_d->status) (init_d, 0); |
126 | 126 | ||
127 | switch (status) | 127 | switch (status) { |
128 | { | 128 | case INIT_D_STATUS_OK: |
129 | case INIT_D_STATUS_OK : | ||
130 | { | 129 | { |
131 | if (just_checking) | 130 | if (just_checking) |
132 | status = INIT_D_ERROR_JUST_RUNNING; | 131 | status = INIT_D_ERROR_JUST_RUNNING; |
133 | else | 132 | else |
134 | status = killproc(init_d->pidfile, init_d->pathname, 0); | 133 | status = killproc(init_d->pidfile, init_d->pathname, 0); |
135 | break; | 134 | break; |
136 | } | 135 | } |
137 | 136 | ||
138 | case INIT_D_STATUS_DEAD_PID : | 137 | case INIT_D_STATUS_DEAD_PID: |
139 | { | 138 | { |
140 | log_warning_msg("Stale pid file exists!"); | 139 | log_warning_msg("Stale pid file exists!"); |
141 | status = INIT_D_ERROR_GENERIC; // LSB is not clear on what to return, but this is an error condition. | 140 | status = INIT_D_ERROR_GENERIC; // LSB is not clear on what to return, but this is an error condition. |
142 | break; | 141 | break; |
143 | } | 142 | } |
144 | 143 | ||
145 | case INIT_D_STATUS_DEAD_LOCK : | 144 | case INIT_D_STATUS_DEAD_LOCK: |
146 | { | 145 | { |
147 | log_warning_msg("Stale lock file exists!"); | 146 | log_warning_msg("Stale lock file exists!"); |
148 | status = INIT_D_ERROR_GENERIC; // LSB is not clear on what to return, but this is an error condition. | 147 | status = INIT_D_ERROR_GENERIC; // LSB is not clear on what to return, but this is an error condition. |
149 | break; | 148 | break; |
150 | } | 149 | } |
151 | 150 | ||
152 | case INIT_D_STATUS_NOT_RUNNING : | 151 | case INIT_D_STATUS_NOT_RUNNING: |
153 | { | 152 | { |
154 | status = INIT_D_OK; | 153 | status = INIT_D_OK; |
155 | break; | 154 | break; |
156 | } | 155 | } |
157 | 156 | ||
158 | default : | 157 | default: |
159 | { | 158 | { |
160 | status = INIT_D_ERROR_GENERIC; | 159 | status = INIT_D_ERROR_GENERIC; |
161 | break; | 160 | break; |
161 | } | ||
162 | } | 162 | } |
163 | } | ||
164 | 163 | ||
165 | return status; | 164 | return status; |
166 | } | 165 | } |
167 | 166 | ||
168 | 167 | ||
169 | int default_restart(struct init_d_handle_s *init_d, int just_checking) | 168 | int default_restart(struct init_d_handle_s *init_d, int just_checking) |
170 | { | 169 | { |
171 | int status = (init_d->status)(init_d, 0); | 170 | int status = (init_d->status) (init_d, 0); |
172 | 171 | ||
173 | switch (status) | 172 | switch (status) { |
174 | { | 173 | case INIT_D_STATUS_OK: |
175 | case INIT_D_STATUS_OK : | ||
176 | { | 174 | { |
177 | status = (init_d->stop)(init_d, just_checking); | 175 | status = (init_d->stop) (init_d, just_checking); |
178 | if ((status == INIT_D_OK) || (status == INIT_D_ERROR_NOT_RUNNING)) | 176 | if ((status == INIT_D_OK) || (status == INIT_D_ERROR_NOT_RUNNING)) |
179 | status = INIT_D_STATUS_NOT_RUNNING; | 177 | status = INIT_D_STATUS_NOT_RUNNING; |
180 | else | 178 | else |
181 | status = INIT_D_STATUS_UNKNOWN; | 179 | status = INIT_D_STATUS_UNKNOWN; |
182 | break; | 180 | break; |
183 | } | 181 | } |
184 | 182 | ||
185 | case INIT_D_STATUS_DEAD_PID : | 183 | case INIT_D_STATUS_DEAD_PID: |
186 | { | 184 | { |
187 | log_warning_msg("Stale pid file exists!"); | 185 | log_warning_msg("Stale pid file exists!"); |
188 | break; | 186 | break; |
189 | } | 187 | } |
190 | 188 | ||
191 | case INIT_D_STATUS_DEAD_LOCK : | 189 | case INIT_D_STATUS_DEAD_LOCK: |
192 | { | 190 | { |
193 | log_warning_msg("Stale lock file exists!"); | 191 | log_warning_msg("Stale lock file exists!"); |
194 | break; | 192 | break; |
195 | } | 193 | } |
196 | } | 194 | } |
197 | if (status == INIT_D_STATUS_NOT_RUNNING) | 195 | if (status == INIT_D_STATUS_NOT_RUNNING) |
198 | status = (init_d->start)(init_d, just_checking); | 196 | status = (init_d->start) (init_d, just_checking); |
199 | else | 197 | else |
200 | status = INIT_D_ERROR_GENERIC; | 198 | status = INIT_D_ERROR_GENERIC; |
201 | 199 | ||
202 | return status; | 200 | return status; |
203 | } | 201 | } |
204 | 202 | ||
205 | 203 | ||
206 | int default_try_restart(struct init_d_handle_s *init_d, int just_checking) | 204 | int default_try_restart(struct init_d_handle_s *init_d, int just_checking) |
207 | { | 205 | { |
208 | int status = (init_d->status)(init_d, 0); | 206 | int status = (init_d->status) (init_d, 0); |
209 | 207 | ||
210 | switch (status) | 208 | switch (status) { |
211 | { | 209 | case INIT_D_STATUS_OK: |
212 | case INIT_D_STATUS_OK : | ||
213 | { | 210 | { |
214 | status = (init_d->stop)(init_d, just_checking); | 211 | status = (init_d->stop) (init_d, just_checking); |
215 | if (status == INIT_D_OK) | 212 | if (status == INIT_D_OK) |
216 | status = (init_d->start)(init_d, just_checking); | 213 | status = (init_d->start) (init_d, just_checking); |
217 | else if (status == INIT_D_ERROR_NOT_RUNNING) /* I think this is what LSB 8.2.61 means. LSB 8.2.59 means that this should never happen though. */ | 214 | else if (status == INIT_D_ERROR_NOT_RUNNING) /* I think this is what LSB 8.2.61 means. LSB 8.2.59 means that this should never happen though. */ |
218 | status = INIT_D_OK; | 215 | status = INIT_D_OK; |
219 | break; | 216 | break; |
220 | } | 217 | } |
221 | 218 | ||
222 | case INIT_D_STATUS_NOT_RUNNING : /* I think this is what LSB 8.2.61 means. */ | 219 | case INIT_D_STATUS_NOT_RUNNING: /* I think this is what LSB 8.2.61 means. */ |
223 | { /* If try-restart was meant to start a stopped service, then it would be no different from restart. | 220 | { /* If try-restart was meant to start a stopped service, then it would be no different from restart. |
224 | * LSB 8.2.42-44 may have some bearing on this, but the english is broken, rendering it unintelligable. | 221 | * LSB 8.2.42-44 may have some bearing on this, but the english is broken, rendering it unintelligable. |
225 | * OTH, try-restart is optional, so a broken implentation is no problem B-). | 222 | * OTH, try-restart is optional, so a broken implentation is no problem B-). |
226 | * OTGH, our force-reload uses this as it's fallback position. | 223 | * OTGH, our force-reload uses this as it's fallback position. |
227 | */ | 224 | */ |
228 | status = INIT_D_OK; | 225 | status = INIT_D_OK; |
229 | break; | 226 | break; |
230 | } | 227 | } |
231 | 228 | ||
232 | default : | 229 | default: |
233 | { | 230 | { |
234 | status = INIT_D_ERROR_GENERIC; | 231 | status = INIT_D_ERROR_GENERIC; |
232 | } | ||
235 | } | 233 | } |
236 | } | ||
237 | 234 | ||
238 | return status; | 235 | return status; |
239 | } | 236 | } |
240 | 237 | ||
241 | 238 | ||
242 | int default_reload(struct init_d_handle_s *init_d, int just_checking) | 239 | int default_reload(struct init_d_handle_s *init_d, int just_checking) |
243 | { | 240 | { |
244 | return INIT_D_ERROR_NOT_IMPLEMENTED; | 241 | return INIT_D_ERROR_NOT_IMPLEMENTED; |
245 | } | 242 | } |
246 | 243 | ||
247 | 244 | ||
248 | int sighup_reload(struct init_d_handle_s *init_d, int just_checking) | 245 | int sighup_reload(struct init_d_handle_s *init_d, int just_checking) |
249 | { | 246 | { |
250 | int status = (init_d->status)(init_d, 0); | 247 | int status = (init_d->status) (init_d, 0); |
251 | 248 | ||
252 | switch (status) | 249 | switch (status) { |
253 | { | 250 | case INIT_D_STATUS_OK: |
254 | case INIT_D_STATUS_OK : | ||
255 | { | 251 | { |
256 | if (just_checking) | 252 | if (just_checking) |
257 | status = INIT_D_ERROR_JUST_RUNNING; | 253 | status = INIT_D_ERROR_JUST_RUNNING; |
258 | else | 254 | else |
259 | status = killproc(init_d->pidfile, init_d->pathname, SIGHUP); | 255 | status = killproc(init_d->pidfile, init_d->pathname, SIGHUP); |
260 | break; | 256 | break; |
261 | } | 257 | } |
262 | 258 | ||
263 | case INIT_D_STATUS_NOT_RUNNING : | 259 | case INIT_D_STATUS_NOT_RUNNING: |
264 | { | 260 | { |
265 | status = INIT_D_ERROR_NOT_RUNNING; | 261 | status = INIT_D_ERROR_NOT_RUNNING; |
266 | break; | 262 | break; |
267 | } | 263 | } |
268 | 264 | ||
269 | default : | 265 | default: |
270 | { | 266 | { |
271 | status = INIT_D_ERROR_GENERIC; | 267 | status = INIT_D_ERROR_GENERIC; |
272 | break; | 268 | break; |
269 | } | ||
273 | } | 270 | } |
274 | } | ||
275 | 271 | ||
276 | return status; | 272 | return status; |
277 | } | 273 | } |
278 | 274 | ||
279 | 275 | ||
280 | int default_force_reload(struct init_d_handle_s *init_d, int just_checking) | 276 | int default_force_reload(struct init_d_handle_s *init_d, int just_checking) |
281 | { | 277 | { |
282 | int status = (init_d->reload)(init_d, just_checking); | 278 | int status = (init_d->reload) (init_d, just_checking); |
283 | 279 | ||
284 | if (status == INIT_D_ERROR_NOT_IMPLEMENTED) | 280 | if (status == INIT_D_ERROR_NOT_IMPLEMENTED) |
285 | status = (init_d->try_restart)(init_d, just_checking); | 281 | status = (init_d->try_restart) (init_d, just_checking); |
286 | 282 | ||
287 | return status; | 283 | return status; |
288 | } | 284 | } |
289 | 285 | ||
290 | 286 | ||
291 | int print_status(struct init_d_handle_s *init_d, int quiet, int status) | 287 | int print_status(struct init_d_handle_s *init_d, int quiet, int status) |
292 | { | 288 | { |
293 | if (quiet) | 289 | if (quiet) |
294 | switch (status) | 290 | switch (status) { |
295 | { | 291 | case INIT_D_STATUS_OK: |
296 | case INIT_D_STATUS_OK : | 292 | { |
297 | { | 293 | bb_printf("%s is running.\n", init_d->basename); |
298 | bb_printf("%s is running.\n", init_d->basename); | 294 | break; |
299 | break; | 295 | } |
300 | } | ||
301 | 296 | ||
302 | case INIT_D_STATUS_DEAD_PID : | 297 | case INIT_D_STATUS_DEAD_PID: |
303 | { | 298 | { |
304 | bb_printf("%s is not running, but there is a stale %s.\n", init_d->basename, init_d->pidfile); | 299 | bb_printf("%s is not running, but there is a stale %s.\n", |
305 | break; | 300 | init_d->basename, init_d->pidfile); |
306 | } | 301 | break; |
302 | } | ||
307 | 303 | ||
308 | case INIT_D_STATUS_DEAD_LOCK : | 304 | case INIT_D_STATUS_DEAD_LOCK: |
309 | { | 305 | { |
310 | bb_printf("%s is not running, but there is a stale lock file.\n", init_d->basename); | 306 | bb_printf("%s is not running, but there is a stale lock file.\n", |
311 | break; | 307 | init_d->basename); |
312 | } | 308 | break; |
309 | } | ||
313 | 310 | ||
314 | case INIT_D_STATUS_NOT_RUNNING : | 311 | case INIT_D_STATUS_NOT_RUNNING: |
315 | { | 312 | { |
316 | bb_printf("%s is not running.\n", init_d->basename); | 313 | bb_printf("%s is not running.\n", init_d->basename); |
317 | break; | 314 | break; |
318 | } | 315 | } |
319 | |||
320 | default : | ||
321 | { | ||
322 | bb_printf("The status of %s is not known.\n", init_d->basename); | ||
323 | break; | ||
324 | } | ||
325 | } | ||
326 | 316 | ||
327 | return status; | 317 | default: |
318 | { | ||
319 | bb_printf("The status of %s is not known.\n", init_d->basename); | ||
320 | break; | ||
321 | } | ||
322 | } | ||
323 | |||
324 | return status; | ||
328 | } | 325 | } |
329 | 326 | ||
330 | 327 | ||
331 | int default_status(struct init_d_handle_s *init_d, int quiet) | 328 | int default_status(struct init_d_handle_s *init_d, int quiet) |
332 | { | 329 | { |
333 | return print_status(init_d, quiet, pidofproc(init_d->pidfile, init_d->pathname, NULL)); | 330 | return print_status(init_d, quiet, |
331 | pidofproc(init_d->pidfile, init_d->pathname, NULL)); | ||
334 | } | 332 | } |
335 | 333 | ||
336 | 334 | ||
337 | int default_show_info(struct init_d_handle_s *init_d, int just_checking) | 335 | int default_show_info(struct init_d_handle_s *init_d, int just_checking) |
338 | { | 336 | { |
339 | bb_printf("%s", init_d->info); | 337 | bb_printf("%s", init_d->info); |
340 | return INIT_D_OK; | 338 | return INIT_D_OK; |
341 | } | 339 | } |
342 | 340 | ||
343 | 341 | ||
344 | int no_stop(struct init_d_handle_s *init_d, int just_checking) | 342 | int no_stop(struct init_d_handle_s *init_d, int just_checking) |
345 | { | 343 | { |
346 | return INIT_D_ERROR_NOT_IMPLEMENTED; | 344 | return INIT_D_ERROR_NOT_IMPLEMENTED; |
347 | } | 345 | } |
348 | 346 | ||
349 | 347 | ||
350 | int no_reload(struct init_d_handle_s *init_d, int just_checking) | 348 | int no_reload(struct init_d_handle_s *init_d, int just_checking) |
351 | { | 349 | { |
352 | return INIT_D_ERROR_NOT_IMPLEMENTED; | 350 | return INIT_D_ERROR_NOT_IMPLEMENTED; |
353 | } | 351 | } |
354 | 352 | ||
355 | 353 | ||
356 | int no_status(struct init_d_handle_s *init_d, int quiet) | 354 | int no_status(struct init_d_handle_s *init_d, int quiet) |
357 | { | 355 | { |
358 | return INIT_D_ERROR_NOT_IMPLEMENTED; | 356 | return INIT_D_ERROR_NOT_IMPLEMENTED; |
359 | } | 357 | } |
360 | 358 | ||
361 | 359 | ||
362 | int do_init_from_main(int argc, char **argv, struct init_d_handle_s *init_d) | 360 | int do_init_from_main(int argc, char **argv, struct init_d_handle_s *init_d) |
363 | { | 361 | { |
364 | return do_init(init_d, (argc > 1) ? argv[1] : NULL); | 362 | read_sysconfig("/etc/runlevels.conf"); |
363 | return do_init(init_d, (argc > 1) ? argv[1] : NULL); | ||
365 | } | 364 | } |
366 | 365 | ||
367 | 366 | ||
368 | int do_init(struct init_d_handle_s *init_d, const char *command) | 367 | int do_init(struct init_d_handle_s *init_d, const char *command) |
369 | { | 368 | { |
370 | int i; | 369 | int i; |
371 | int status = INIT_D_ERROR_NOT_IMPLEMENTED; | 370 | int status = INIT_D_ERROR_NOT_IMPLEMENTED; |
372 | char *original_pidfile = init_d->pidfile; | 371 | char *original_pidfile = init_d->pidfile; |
373 | 372 | char *sysconfig; | |
374 | if (init_d->start == NULL) init_d->start = &default_start; | 373 | |
375 | if (init_d->stop == NULL) init_d->stop = &default_stop; | 374 | if (init_d->start == NULL) |
376 | if (init_d->restart == NULL) init_d->restart = &default_restart; | 375 | init_d->start = &default_start; |
377 | if (init_d->try_restart == NULL) init_d->try_restart = &default_try_restart; | 376 | if (init_d->stop == NULL) |
378 | if (init_d->reload == NULL) init_d->reload = &default_reload; | 377 | init_d->stop = &default_stop; |
379 | if (init_d->force_reload == NULL) init_d->force_reload = &default_force_reload; | 378 | if (init_d->restart == NULL) |
380 | if (init_d->status == NULL) init_d->status = &default_status; | 379 | init_d->restart = &default_restart; |
381 | if (init_d->show_info == NULL) init_d->show_info = &default_show_info; | 380 | if (init_d->try_restart == NULL) |
382 | if (init_d->basename == NULL) init_d->basename = bb_get_last_path_component(init_d->pathname); | 381 | init_d->try_restart = &default_try_restart; |
383 | if (init_d->pathname == NULL) init_d->pathname = init_d->basename; | 382 | if (init_d->reload == NULL) |
384 | if (init_d->args == NULL) init_d->args = ""; | 383 | init_d->reload = &default_reload; |
385 | if (init_d->pidfile == NULL) bb_xasprintf(&(init_d->pidfile), "/var/run/%s.pid", init_d->basename); | 384 | if (init_d->force_reload == NULL) |
386 | if (init_d->info == NULL) init_d->info = ""; | 385 | init_d->force_reload = &default_force_reload; |
387 | 386 | if (init_d->status == NULL) | |
388 | if (command == NULL) | 387 | init_d->status = &default_status; |
389 | command = commands[2]; // Default to restart. | 388 | if (init_d->show_info == NULL) |
390 | 389 | init_d->show_info = &default_show_info; | |
391 | for (i = 0; commands[i] != 0; i++) | 390 | if (init_d->basename == NULL) |
392 | { | 391 | init_d->basename = bb_get_last_path_component(init_d->pathname); |
393 | if (strcmp(commands[i], command ) == 0) | 392 | if (init_d->pathname == NULL) |
394 | { | 393 | init_d->pathname = init_d->basename; |
395 | switch (i) | 394 | if (init_d->args == NULL) |
396 | { | 395 | init_d->args = ""; |
397 | case 0 : status = (init_d->start)(init_d, 0); break; | 396 | if (init_d->pidfile == NULL) |
398 | case 1 : status = (init_d->stop)(init_d, 0); break; | 397 | bb_xasprintf(&(init_d->pidfile), "/var/run/%s.pid", init_d->basename); |
399 | case 2 : status = (init_d->restart)(init_d, 0); break; | 398 | if (init_d->info == NULL) |
400 | case 3 : status = (init_d->try_restart)(init_d, 0); break; | 399 | init_d->info = ""; |
401 | case 4 : status = (init_d->reload)(init_d, 0); break; | 400 | |
402 | case 5 : status = (init_d->force_reload)(init_d, 0); break; | 401 | bb_xasprintf(&sysconfig, "/etc/sysconfig/%s", init_d->basename); |
403 | case 6 : status = (init_d->status)(init_d, 1); break; | 402 | read_sysconfig(sysconfig); |
404 | case 7 : status = (init_d->show_info)(init_d, 0); break; | 403 | |
405 | } | 404 | if (command == NULL) |
406 | break; | 405 | command = commands[2]; // Default to restart. |
406 | |||
407 | for (i = 0; commands[i] != 0; i++) { | ||
408 | if (strcmp(commands[i], command) == 0) { | ||
409 | switch (i) { | ||
410 | case 0: | ||
411 | status = (init_d->start) (init_d, 0); | ||
412 | break; | ||
413 | case 1: | ||
414 | status = (init_d->stop) (init_d, 0); | ||
415 | break; | ||
416 | case 2: | ||
417 | status = (init_d->restart) (init_d, 0); | ||
418 | break; | ||
419 | case 3: | ||
420 | status = (init_d->try_restart) (init_d, 0); | ||
421 | break; | ||
422 | case 4: | ||
423 | status = (init_d->reload) (init_d, 0); | ||
424 | break; | ||
425 | case 5: | ||
426 | status = (init_d->force_reload) (init_d, 0); | ||
427 | break; | ||
428 | case 6: | ||
429 | status = (init_d->status) (init_d, 1); | ||
430 | break; | ||
431 | case 7: | ||
432 | status = (init_d->show_info) (init_d, 0); | ||
433 | break; | ||
434 | } | ||
435 | break; | ||
436 | } | ||
407 | } | 437 | } |
408 | } | ||
409 | 438 | ||
410 | if (original_pidfile == NULL) | 439 | free(sysconfig); |
411 | free(init_d->pidfile); | 440 | if (original_pidfile == NULL) |
412 | return status; | 441 | free(init_d->pidfile); |
442 | return status; | ||
413 | } | 443 | } |
414 | 444 | ||
415 | 445 | ||
416 | static int init_script(char *script, char *command) | 446 | static int init_script(char *script, char *command) |
417 | { | 447 | { |
418 | int status = INIT_D_ERROR_NOT_IMPLEMENTED; | 448 | int status = INIT_D_ERROR_NOT_IMPLEMENTED; |
419 | 449 | ||
420 | bb_printf("%c%s %s ... ", toupper(command[0]), &command[1], script); | 450 | bb_printf("%c%s %s ... ", toupper(command[0]), &command[1], script); |
421 | fflush(stdout); | 451 | fflush(stdout); |
422 | doit(0, "/etc/init.d/%s %s", script, command); | 452 | doit(0, "/etc/init.d/%s %s", script, command); |
423 | status = errno; | 453 | status = errno; |
424 | if (strcmp("status", command) != 0) | 454 | if (strcmp("status", command) != 0) { |
425 | { | 455 | bb_printf("\t\t"); |
426 | bb_printf("\t\t"); | 456 | switch (status) { |
427 | switch (status) | 457 | case INIT_D_OK: |
428 | { | 458 | bb_printf("OK"); |
429 | case INIT_D_OK : bb_printf("OK"); break; | 459 | break; |
430 | case INIT_D_ERROR_NOT_IMPLEMENTED : bb_printf("not implemented"); break; | 460 | case INIT_D_ERROR_NOT_IMPLEMENTED: |
431 | case INIT_D_ERROR_NOT_INSTALLED : bb_printf("not installed"); break; | 461 | bb_printf("not implemented"); |
432 | case INIT_D_ERROR_NOT_CONFIGURED : bb_printf("not configured"); break; | 462 | break; |
433 | case INIT_D_ERROR_NOT_RUNNING : bb_printf("not running"); break; | 463 | case INIT_D_ERROR_NOT_INSTALLED: |
434 | case INIT_D_ERROR_GENERIC : bb_printf("failed"); break; | 464 | bb_printf("not installed"); |
435 | case INIT_D_ERROR_ARGS : bb_printf("invalid arguments"); break; | 465 | break; |
436 | case INIT_D_ERROR_SECURITY : bb_printf("security failure"); break; | 466 | case INIT_D_ERROR_NOT_CONFIGURED: |
437 | default : bb_printf("Failed!"); break; | 467 | bb_printf("not configured"); |
468 | break; | ||
469 | case INIT_D_ERROR_NOT_RUNNING: | ||
470 | bb_printf("not running"); | ||
471 | break; | ||
472 | case INIT_D_ERROR_GENERIC: | ||
473 | bb_printf("failed"); | ||
474 | break; | ||
475 | case INIT_D_ERROR_ARGS: | ||
476 | bb_printf("invalid arguments"); | ||
477 | break; | ||
478 | case INIT_D_ERROR_SECURITY: | ||
479 | bb_printf("security failure"); | ||
480 | break; | ||
481 | default: | ||
482 | bb_printf("Failed!"); | ||
483 | break; | ||
484 | } | ||
485 | bb_printf("\n"); | ||
438 | } | 486 | } |
439 | bb_printf("\n"); | 487 | return status; |
440 | } | ||
441 | return status; | ||
442 | } | 488 | } |
443 | 489 | ||
444 | 490 | ||
445 | init_d_info_t *parse_init_info(char *info_text, char *name) | 491 | init_d_info_t *parse_init_info(char *info_text, char *name) |
446 | { | 492 | { |
447 | init_d_info_t *info = NULL; | 493 | init_d_info_t *info = NULL; |
448 | 494 | ||
449 | // if init info found | 495 | // if init info found |
450 | if ((info_text != NULL) && (strncmp(info_text, INIT_D_BEGIN, strlen(INIT_D_BEGIN) - 1) == 0)) | 496 | if ((info_text != NULL) |
451 | { | 497 | && (strncmp(info_text, INIT_D_BEGIN, strlen(INIT_D_BEGIN) - 1) == |
452 | if (strncmp(info_text, INIT_D_BEGIN, strlen(INIT_D_BEGIN) - 1) == 0) | 498 | 0)) { |
453 | { | 499 | if (strncmp(info_text, INIT_D_BEGIN, strlen(INIT_D_BEGIN) - 1) == 0) { |
454 | int lastfound = -1; | 500 | int lastfound = -1; |
455 | char *strtok_line; | 501 | char *strtok_line; |
456 | char *line; | 502 | char *line; |
457 | char *linecopy; | 503 | char *linecopy; |
458 | 504 | ||
459 | info = (init_d_info_t *) xcalloc(1, sizeof(init_d_info_t)); | 505 | info = (init_d_info_t *) xcalloc(1, sizeof(init_d_info_t)); |
460 | bb_xasprintf(&info->path, "%s", name); | 506 | bb_xasprintf(&info->path, "%s", name); |
461 | 507 | ||
462 | //bb_printf("%s is an init script -%s", name, info_text); | 508 | //bb_printf("%s is an init script -%s", name, info_text); |
463 | //bb_printf("%s is an init script\n", name); | 509 | //bb_printf("%s is an init script\n", name); |
464 | // parse info into structure | 510 | // parse info into structure |
465 | for (line = strtok_r(info_text, "\n\r", &strtok_line); line != NULL; line = strtok_r(NULL, "\n\r", &strtok_line)) | 511 | for (line = strtok_r(info_text, "\n\r", &strtok_line); |
466 | { | 512 | line != NULL; line = strtok_r(NULL, "\n\r", &strtok_line)) { |
467 | int count = 0; | 513 | int count = 0; |
468 | int found = -1; | 514 | int found = -1; |
469 | char *strtok_token; | 515 | char *strtok_token; |
470 | char *token; | 516 | char *token; |
471 | 517 | ||
472 | bb_xasprintf(&linecopy, "%s", line); | 518 | bb_xasprintf(&linecopy, "%s", line); |
473 | for (token = strtok_r(line, " \t", &strtok_token); token != NULL; token = strtok_r(NULL, " \t", &strtok_token)) | 519 | for (token = strtok_r(line, " \t", &strtok_token); |
474 | { | 520 | token != NULL; |
475 | switch (count++) | 521 | token = strtok_r(NULL, " \t", &strtok_token)) { |
476 | { | 522 | switch (count++) { |
477 | case 0 : break; /* Ignore the "#". */ | 523 | case 0: |
524 | break; /* Ignore the "#". */ | ||
525 | |||
526 | case 1: | ||
527 | { | ||
528 | int j; | ||
478 | 529 | ||
479 | case 1 : | 530 | for (j = 1; INFOS[j] != NULL; j++) { |
480 | { | ||
481 | int j; | ||
482 | for (j = 1; INFOS[j] != NULL; j++) | ||
483 | { | ||
484 | //bb_printf("%s = %s %s\n", linecopy, &(INFOS[j][1]), token); | 531 | //bb_printf("%s = %s %s\n", linecopy, &(INFOS[j][1]), token); |
485 | if (strncmp(&(INFOS[j][1]), linecopy, strlen(&(INFOS[j][1])) - 1) == 0) | 532 | if (strncmp |
486 | { | 533 | (&(INFOS[j][1]), linecopy, |
487 | found = j - 1; | 534 | strlen(&(INFOS[j][1])) - 1) == 0) { |
488 | break; | 535 | found = j - 1; |
489 | } | 536 | break; |
490 | } | 537 | } |
491 | break; | 538 | } |
492 | } | 539 | break; |
493 | 540 | } | |
494 | default : | ||
495 | { | ||
496 | int multi = 1; | ||
497 | int string = 1; | ||
498 | void **kludge = (void **)info; | ||
499 | |||
500 | switch (found) | ||
501 | { | ||
502 | case 5 : /* INIT_D_DSTART */ string = 0; break; | ||
503 | case 6 : /* INIT_D_DSTOP */ string = 0; break; | ||
504 | case 7 : /* INIT_D_SDESC */ multi = 0; break; | ||
505 | case 8 : /* INIT_D_DESC */ multi = 0; break; | ||
506 | case 10 : /* INIT_D_CONT */ | ||
507 | case 11 : /* INIT_D_CONT2 */ multi = 0; found = lastfound; break; | ||
508 | case 12 : /* INIT_D_END */ found = -1; break; | ||
509 | } | ||
510 | |||
511 | if (found != -1) | ||
512 | { | ||
513 | void *temp = kludge[found]; | ||
514 | |||
515 | if (multi == 1) | ||
516 | { | ||
517 | int size = info->sizes[found]; | ||
518 | 541 | ||
519 | info->sizes[found]++; | 542 | default: |
543 | { | ||
544 | int multi = 1; | ||
545 | int string = 1; | ||
546 | void **kludge = (void **) info; | ||
547 | |||
548 | switch (found) { | ||
549 | case 5: /* INIT_D_DSTART */ | ||
550 | string = 0; | ||
551 | break; | ||
552 | case 6: /* INIT_D_DSTOP */ | ||
553 | string = 0; | ||
554 | break; | ||
555 | case 7: /* INIT_D_SDESC */ | ||
556 | multi = 0; | ||
557 | break; | ||
558 | case 8: /* INIT_D_DESC */ | ||
559 | multi = 0; | ||
560 | break; | ||
561 | case 10: /* INIT_D_CONT */ | ||
562 | case 11: /* INIT_D_CONT2 */ | ||
563 | multi = 0; | ||
564 | found = lastfound; | ||
565 | break; | ||
566 | case 12: /* INIT_D_END */ | ||
567 | found = -1; | ||
568 | break; | ||
569 | } | ||
570 | |||
571 | if (found != -1) { | ||
572 | void *temp = kludge[found]; | ||
573 | |||
574 | if (multi == 1) { | ||
575 | int size = info->sizes[found]; | ||
576 | |||
577 | info->sizes[found]++; | ||
520 | // not LSB, but SuSE does it | 578 | // not LSB, but SuSE does it |
521 | if (token[0] == '$') | 579 | if (token[0] == '$') |
522 | token = &token[1]; | 580 | token = &token[1]; |
523 | // not LSB, but SuSE does it | 581 | // not LSB, but SuSE does it |
524 | if (strncmp(token, "boot.", 5) == 0) | 582 | if (strncmp(token, "boot.", 5) == 0) |
525 | token = &token[5]; | 583 | token = &token[5]; |
526 | if (temp != NULL) | 584 | if (temp != NULL) |
527 | kludge[found] = xrealloc(kludge[found], sizeof (char **) * (size + 1)); | 585 | kludge[found] = |
528 | else | 586 | xrealloc(kludge[found], |
529 | kludge[found] = xcalloc(1, sizeof (char **)); | 587 | sizeof(char **) * (size + |
530 | if (string == 1) | 588 | 1)); |
531 | bb_xasprintf(&((char **) kludge[found])[size], "%s", token); | 589 | else |
532 | else | 590 | kludge[found] = |
533 | { | 591 | xcalloc(1, sizeof(char **)); |
592 | if (string == 1) | ||
593 | bb_xasprintf(&((char **) kludge[found]) | ||
594 | [size], "%s", token); | ||
595 | else { | ||
534 | // not LSB, but SuSE does it | 596 | // not LSB, but SuSE does it |
535 | if (token[0] == 'B') | 597 | if (token[0] == 'B') { |
536 | { | 598 | token[0] = '5'; |
537 | token[0] = '5'; | 599 | kludge[found] = |
538 | kludge[found] = xrealloc(kludge[found], sizeof (char **) * (10 + 1)); | 600 | xrealloc(kludge[found], |
539 | ((int *) kludge[found])[0] = 1; | 601 | sizeof(char **) * (10 + |
540 | ((int *) kludge[found])[1] = 2; | 602 | 1)); |
541 | ((int *) kludge[found])[2] = 3; | 603 | ((int *) kludge[found])[0] = 1; |
542 | ((int *) kludge[found])[3] = 4; | 604 | ((int *) kludge[found])[1] = 2; |
543 | size = 4; | 605 | ((int *) kludge[found])[2] = 3; |
544 | info->sizes[found] = 5; | 606 | ((int *) kludge[found])[3] = 4; |
545 | } | 607 | size = 4; |
608 | info->sizes[found] = 5; | ||
609 | } | ||
546 | // not LSB, but SuSE does it | 610 | // not LSB, but SuSE does it |
547 | if (token[0] == 'S') | 611 | if (token[0] == 'S') |
548 | token[0] = '1'; | 612 | token[0] = '1'; |
549 | ((int *) kludge[found])[size] = atoi(token); | 613 | ((int *) kludge[found])[size] = |
550 | } | 614 | atoi(token); |
551 | temp = NULL; | 615 | } |
552 | } | 616 | temp = NULL; |
553 | else | 617 | } else { |
554 | { | 618 | if (string == 1) { |
555 | if (string == 1) | 619 | if (kludge[found] == NULL) |
556 | { | 620 | bb_xasprintf((char **) &kludge[found], |
557 | if (kludge[found] == NULL) | 621 | "%s", token); |
558 | bb_xasprintf((char **) &kludge[found], "%s", token); | 622 | else |
559 | else | 623 | bb_xasprintf((char **) &kludge[found], |
560 | bb_xasprintf((char **) &kludge[found], "%s %s", (char *) kludge[found], token); | 624 | "%s %s", |
561 | } | 625 | (char *) kludge[found], |
562 | else | 626 | token); |
563 | { | 627 | } else { |
564 | // Should never happen. int value = atoi(token); | 628 | // Should never happen. int value = atoi(token); |
565 | temp = NULL; | 629 | temp = NULL; |
566 | } | 630 | } |
631 | } | ||
632 | |||
633 | if (temp != NULL) | ||
634 | free(temp); | ||
635 | } | ||
636 | lastfound = found; | ||
637 | |||
638 | break; | ||
639 | } | ||
640 | } | ||
567 | } | 641 | } |
568 | |||
569 | if (temp != NULL) | ||
570 | free(temp); | ||
571 | } | ||
572 | lastfound = found; | ||
573 | |||
574 | break; | ||
575 | } | 642 | } |
576 | } | ||
577 | } | ||
578 | } | ||
579 | 643 | ||
580 | 644 | ||
581 | #if 0 | 645 | #if 0 |
582 | { | 646 | { |
583 | int k; | 647 | int k; |
584 | 648 | ||
585 | bb_printf("SCRIPT %s path %s\n", name, info->path); | 649 | bb_printf("SCRIPT %s path %s\n", name, info->path); |
586 | // bb_printf("%s sizes ", name); | 650 | // bb_printf("%s sizes ", name); |
587 | // for(k = 0; k < 10; k++) | 651 | // for(k = 0; k < 10; k++) |
588 | // bb_printf("%d ", info->sizes[k]); | 652 | // bb_printf("%d ", info->sizes[k]); |
589 | // bb_printf("\n"); | 653 | // bb_printf("\n"); |
590 | if (info->provides != NULL) | 654 | if (info->provides != NULL) { |
591 | { | 655 | bb_printf("%s provides ", name); |
592 | bb_printf("%s provides ", name); | 656 | for (k = 0; k < info->sizes[0]; k++) |
593 | for(k = 0; k < info->sizes[0]; k++) | 657 | bb_printf("%s ", info->provides[k]); |
594 | bb_printf("%s ", info->provides[k]); | 658 | bb_printf("\n"); |
595 | bb_printf("\n"); | 659 | } |
596 | } | 660 | if (info->reqstart != NULL) { |
597 | if (info->reqstart != NULL) | 661 | bb_printf("%s reqstart ", name); |
598 | { | 662 | for (k = 0; k < info->sizes[1]; k++) |
599 | bb_printf("%s reqstart ", name); | 663 | bb_printf("%s ", info->reqstart[k]); |
600 | for(k = 0; k < info->sizes[1]; k++) | 664 | bb_printf("\n"); |
601 | bb_printf("%s ", info->reqstart[k]); | 665 | } |
602 | bb_printf("\n"); | 666 | if (info->reqstop != NULL) { |
603 | } | 667 | bb_printf("%s reqstop ", name); |
604 | if (info->reqstop != NULL) | 668 | for (k = 0; k < info->sizes[2]; k++) |
605 | { | 669 | bb_printf("%s ", info->reqstop[k]); |
606 | bb_printf("%s reqstop ", name); | 670 | bb_printf("\n"); |
607 | for(k = 0; k < info->sizes[2]; k++) | 671 | } |
608 | bb_printf("%s ", info->reqstop[k]); | ||
609 | bb_printf("\n"); | ||
610 | } | ||
611 | 672 | ||
612 | if (info->shouldstart != NULL) | 673 | if (info->shouldstart != NULL) { |
613 | { | 674 | bb_printf("%s shouldstart ", name); |
614 | bb_printf("%s shouldstart ", name); | 675 | for (k = 0; k < info->sizes[3]; k++) |
615 | for(k = 0; k < info->sizes[3]; k++) | 676 | bb_printf("%s ", info->shouldstart[k]); |
616 | bb_printf("%s ", info->shouldstart[k]); | 677 | bb_printf("\n"); |
617 | bb_printf("\n"); | 678 | } |
618 | } | 679 | if (info->shouldstop != NULL) { |
619 | if (info->shouldstop != NULL) | 680 | bb_printf("%s shouldstop ", name); |
620 | { | 681 | for (k = 0; k < info->sizes[4]; k++) |
621 | bb_printf("%s shouldstop ", name); | 682 | bb_printf("%s ", info->shouldstop[k]); |
622 | for(k = 0; k < info->sizes[4]; k++) | 683 | bb_printf("\n"); |
623 | bb_printf("%s ", info->shouldstop[k]); | 684 | } |
624 | bb_printf("\n"); | ||
625 | } | ||
626 | 685 | ||
627 | if (info->defstart != NULL) | 686 | if (info->defstart != NULL) { |
628 | { | 687 | bb_printf("%s defstart ", name); |
629 | bb_printf("%s defstart ", name); | 688 | for (k = 0; k < info->sizes[5]; k++) |
630 | for(k = 0; k < info->sizes[5]; k++) | 689 | bb_printf("%d ", info->defstart[k]); |
631 | bb_printf("%d ", info->defstart[k]); | 690 | bb_printf("\n"); |
632 | bb_printf("\n"); | 691 | } |
633 | } | 692 | if (info->defstop != NULL) { |
634 | if (info->defstop != NULL) | 693 | bb_printf("%s defstop ", name); |
635 | { | 694 | for (k = 0; k < info->sizes[6]; k++) |
636 | bb_printf("%s defstop ", name); | 695 | bb_printf("%d ", info->defstop[k]); |
637 | for(k = 0; k < info->sizes[6]; k++) | 696 | bb_printf("\n"); |
638 | bb_printf("%d ", info->defstop[k]); | 697 | } |
639 | bb_printf("\n"); | 698 | if (info->shortdesc != NULL) |
640 | } | 699 | bb_printf("%s shortdes %s\n", name, info->shortdesc); |
641 | if (info->shortdesc != NULL) | 700 | if (info->desc != NULL) |
642 | bb_printf("%s shortdes %s\n", name, info->shortdesc); | 701 | bb_printf("%s descript %s\n", name, info->desc); |
643 | if (info->desc != NULL) | 702 | bb_printf("\n"); |
644 | bb_printf("%s descript %s\n", name, info->desc); | 703 | } |
645 | bb_printf("\n"); | ||
646 | } | ||
647 | #endif | 704 | #endif |
648 | 705 | ||
649 | // if database of runlevels per script includes overrides | 706 | // if database of runlevels per script includes overrides |
650 | // change info structure accordingly | 707 | // change info structure accordingly |
708 | } | ||
651 | } | 709 | } |
652 | } | ||
653 | 710 | ||
654 | return info; | 711 | return info; |
655 | } | 712 | } |
656 | 713 | ||
657 | 714 | ||
658 | char *get_init_info(char *pathname) | 715 | char *get_init_info(char *pathname) |
659 | { | 716 | { |
660 | struct stat script_stat; | 717 | struct stat script_stat; |
661 | char *info_text = NULL; | 718 | char *info_text = NULL; |
662 | char *base_name = bb_get_last_path_component(pathname); | 719 | char *base_name = bb_get_last_path_component(pathname); |
663 | 720 | ||
664 | 721 | ||
665 | //bb_printf("CHECKING %s, ", pathname); | 722 | //bb_printf("CHECKING %s, ", pathname); |
666 | // ignore rc, rcS, directories, non executables | 723 | // ignore rc, rcS, directories, non executables |
667 | if ((strcmp(base_name, "rc") != 0) && | 724 | if ((strcmp(base_name, "rc") != 0) && |
668 | (strcmp(base_name, "rcS") != 0) && | 725 | (strcmp(base_name, "rcS") != 0) && |
669 | (stat(pathname, &script_stat) == 0)) | 726 | (stat(pathname, &script_stat) == 0)) { |
670 | { | 727 | if ((!S_ISDIR(script_stat.st_mode)) && |
671 | if ((!S_ISDIR(script_stat.st_mode)) && | 728 | S_ISREG(script_stat.st_mode) && |
672 | S_ISREG(script_stat.st_mode) && | 729 | ((script_stat.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH)) != 0)) { |
673 | ((script_stat.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH)) != 0 )) | ||
674 | { | ||
675 | //bb_printf("maybe init script, "); | 730 | //bb_printf("maybe init script, "); |
676 | // script info | 731 | // script info |
677 | if ((info_text == NULL) || (strncmp(info_text, INIT_D_BEGIN, strlen(INIT_D_BEGIN) - 1) != 0)) | 732 | if ((info_text == NULL) |
678 | bb_xasprintf(&info_text, "%s", doit(REDIR | QUIET, "%s info", pathname)); | 733 | || (strncmp(info_text, INIT_D_BEGIN, strlen(INIT_D_BEGIN) - 1) |
734 | != 0)) | ||
735 | bb_xasprintf(&info_text, "%s", | ||
736 | doit(REDIR | QUIET, "%s info", pathname)); | ||
679 | //bb_printf("INFO = %s\n", info_text); | 737 | //bb_printf("INFO = %s\n", info_text); |
680 | 738 | ||
681 | // if not proper response | 739 | // if not proper response |
682 | if ((info_text == NULL) || (strncmp(info_text, INIT_D_BEGIN, strlen(INIT_D_BEGIN) - 1) != 0)) | 740 | if ((info_text == NULL) |
683 | { | 741 | || (strncmp(info_text, INIT_D_BEGIN, strlen(INIT_D_BEGIN) - 1) |
684 | int count = 1; | 742 | != 0)) { |
685 | int found = -1; | 743 | int count = 1; |
686 | char *line; | 744 | int found = -1; |
687 | FILE *contents; | 745 | char *line; |
746 | FILE *contents; | ||
688 | 747 | ||
689 | //bb_printf("search for INFO, "); | 748 | //bb_printf("search for INFO, "); |
690 | // search script for init info | 749 | // search script for init info |
691 | info_text = (char *) xmalloc(sizeof (char) * 256 * 64); | 750 | info_text = (char *) xmalloc(sizeof(char) * 256 * 64); |
692 | info_text[0] = '\n'; | 751 | info_text[0] = '\n'; |
693 | info_text[1] = '\0'; | 752 | info_text[1] = '\0'; |
694 | contents = fopen(pathname, "r"); | 753 | contents = fopen(pathname, "r"); |
695 | if (contents != NULL) | 754 | if (contents != NULL) { |
696 | { | 755 | do { |
697 | do | 756 | line = fgets(&info_text[count], 255, contents); |
698 | { | 757 | if (line != NULL) { |
699 | line = fgets(&info_text[count], 255, contents); | 758 | line--; |
700 | if (line != NULL) | 759 | if ((found == -1) |
701 | { | 760 | && |
702 | line--; | 761 | (strncmp |
703 | if ((found == -1) && (strncmp(line, INIT_D_BEGIN, strlen(INIT_D_BEGIN) - 1) == 0)) | 762 | (line, INIT_D_BEGIN, |
704 | found = 0; | 763 | strlen(INIT_D_BEGIN) - 1) == 0)) |
705 | 764 | found = 0; | |
706 | if (found != -1) | 765 | |
707 | { | 766 | if (found != -1) { |
708 | 767 | ||
709 | if (strncmp(line, INIT_D_CUSTOM, strlen(INIT_D_CUSTOM)) != 0) | 768 | if (strncmp |
710 | { | 769 | (line, INIT_D_CUSTOM, |
711 | if (strncmp(line, INIT_D_END, strlen(INIT_D_END) - 1) == 0) | 770 | strlen(INIT_D_CUSTOM)) != 0) { |
712 | { | 771 | if (strncmp |
772 | (line, INIT_D_END, | ||
773 | strlen(INIT_D_END) - 1) == 0) { | ||
713 | //bb_printf("INFO found, "); | 774 | //bb_printf("INFO found, "); |
714 | line = NULL; | 775 | line = NULL; |
715 | found = 64 + 1; | 776 | found = 64 + 1; |
716 | } | 777 | } else { |
717 | else | 778 | int cont = 0; |
718 | { | 779 | |
719 | int cont = 0; | 780 | if (strncmp |
720 | 781 | (line, INIT_D_CONT, | |
721 | if (strncmp(line, INIT_D_CONT, strlen(INIT_D_CONT)) == 0) | 782 | strlen(INIT_D_CONT)) == 0) |
722 | cont = 1; | 783 | cont = 1; |
723 | if (strncmp(line, INIT_D_CONT2, strlen(INIT_D_CONT2)) == 0) | 784 | if (strncmp |
724 | cont = 1; | 785 | (line, INIT_D_CONT2, |
725 | if (cont == 1) | 786 | strlen(INIT_D_CONT2)) == 0) |
726 | { | 787 | cont = 1; |
788 | if (cont == 1) { | ||
727 | //bb_printf("\n\n\nCONT found%s\n\n\n, ", line); | 789 | //bb_printf("\n\n\nCONT found%s\n\n\n, ", line); |
728 | info_text[count - 1] = ' '; | 790 | info_text[count - 1] = ' '; |
729 | info_text[count] = ' '; | 791 | info_text[count] = ' '; |
730 | } | 792 | } |
731 | 793 | ||
732 | found++; | 794 | found++; |
733 | count += strlen(line) - 1; | 795 | count += strlen(line) - 1; |
734 | if (info_text[count - 1] != '\n') | 796 | if (info_text[count - 1] != '\n') { |
735 | { | 797 | info_text[count++] = '\n'; |
736 | info_text[count++] = '\n'; | ||
737 | // Should seek until the next \n, | 798 | // Should seek until the next \n, |
738 | } | 799 | } |
739 | } | 800 | } |
740 | info_text[count] = '\0'; | 801 | info_text[count] = '\0'; |
802 | } | ||
803 | } | ||
804 | } | ||
805 | } while ((line != NULL) && (found < 64)); | ||
806 | |||
807 | fclose(contents); | ||
741 | } | 808 | } |
742 | } | ||
743 | } | 809 | } |
744 | } while ((line != NULL) && (found < 64)); | ||
745 | |||
746 | fclose(contents); | ||
747 | } | 810 | } |
748 | } | ||
749 | } | 811 | } |
750 | } | ||
751 | //bb_printf("\n"); | 812 | //bb_printf("\n"); |
752 | 813 | ||
753 | return info_text; | 814 | return info_text; |
754 | } | 815 | } |
755 | 816 | ||
756 | 817 | ||
757 | llist_t *get_scripts(void) | 818 | llist_t *get_scripts(void) |
758 | { | 819 | { |
759 | llist_t *result = NULL; | 820 | llist_t *result = NULL; |
760 | DIR *initd = opendir("/etc/init.d"); | 821 | DIR *initd = opendir("/etc/init.d"); |
761 | 822 | ||
762 | if (initd != NULL) | 823 | if (initd != NULL) { |
763 | { | 824 | struct dirent *script; |
764 | struct dirent *script; | 825 | |
765 | 826 | // foreach ls /etc/init.d | |
766 | // foreach ls /etc/init.d | 827 | while ((script = readdir(initd)) != NULL) { |
767 | while ((script = readdir(initd)) != NULL) | 828 | char *info_text = NULL; |
768 | { | 829 | char *pathname = NULL; |
769 | char *info_text = NULL; | 830 | init_d_info_t *info = NULL; |
770 | char *pathname = NULL; | 831 | |
771 | init_d_info_t *info = NULL; | 832 | bb_xasprintf(&pathname, "/etc/init.d/%s", script->d_name); |
772 | 833 | info_text = get_init_info(pathname); | |
773 | bb_xasprintf(&pathname, "/etc/init.d/%s", script->d_name); | 834 | info = parse_init_info(info_text, script->d_name); |
774 | info_text = get_init_info(pathname); | 835 | if (info) |
775 | info = parse_init_info(info_text, script->d_name); | 836 | result = llist_add_to(result, (char *) info); |
776 | if (info) | 837 | |
777 | result = llist_add_to(result, (char *) info); | 838 | free(info_text); |
778 | 839 | } | |
779 | free(info_text); | 840 | closedir(initd); |
780 | } | ||
781 | closedir(initd); | ||
782 | } | 841 | } |
783 | 842 | ||
784 | return result; | 843 | return result; |
785 | } | 844 | } |
786 | 845 | ||
787 | 846 | ||
788 | llist_t *sort_scripts(llist_t *unsorted) | 847 | llist_t *sort_scripts(llist_t * unsorted, init_d_info_t *for_script) |
789 | { | 848 | { |
790 | // Should do something with info->shouldstart's | 849 | // Should do something with info->shouldstart's |
791 | int count_moves = 0; | 850 | int count_moves = 0; |
792 | // all scripts start in unsorted list | ||
793 | llist_t *sorted = NULL; | ||
794 | llist_t *current = unsorted; | ||
795 | llist_t *previous = NULL; | ||
796 | |||
797 | // pull out those with no deps and create a sorted list for each | ||
798 | while (current) | ||
799 | { | ||
800 | init_d_info_t *info = (init_d_info_t *) current->data; | ||
801 | |||
802 | if (info->reqstart == NULL) | ||
803 | { | ||
804 | llist_t *new_list = NULL; | ||
805 | new_list = llist_add_to_end(new_list, (char *) info); | ||
806 | sorted = llist_add_to_end(sorted, (char *) new_list); | ||
807 | current = llist_delete(&unsorted, previous, current); | ||
808 | } | ||
809 | else | ||
810 | { | ||
811 | previous = current; | ||
812 | current = current->link; | ||
813 | } | ||
814 | } | ||
815 | 851 | ||
816 | do | 852 | // all scripts start in unsorted list |
817 | { | 853 | llist_t *sorted = NULL; |
818 | count_moves = 0; | 854 | llist_t *current = unsorted; |
819 | current = unsorted; | 855 | llist_t *previous = NULL; |
820 | previous = NULL; | ||
821 | // foreach in unsorted list | ||
822 | while (current) | ||
823 | { | ||
824 | int moved = 0; | ||
825 | init_d_info_t *info = (init_d_info_t *) current->data; | ||
826 | 856 | ||
827 | if (info->reqstart != NULL) | 857 | // pull out those with no deps and create a sorted list for each |
828 | { | 858 | while (current) { |
829 | int k; | 859 | init_d_info_t *info = (init_d_info_t *) current->data; |
830 | llist_t *current_sort = sorted; | ||
831 | short done[info->sizes[1]]; | ||
832 | 860 | ||
833 | // foreach sorted list | 861 | if (info->reqstart == NULL) { |
834 | while (current_sort) | 862 | llist_t *new_list = NULL; |
835 | { | ||
836 | llist_t *current_list = (llist_t *) current_sort->data; | ||
837 | 863 | ||
838 | // if ALL deps are in sorted list move script to end of sorted list | 864 | new_list = llist_add_to_end(new_list, (char *) info); |
839 | for(k = 0; k < info->sizes[1]; k++) | 865 | sorted = llist_add_to_end(sorted, (char *) new_list); |
840 | done[k] = 0; | 866 | current = llist_delete(&unsorted, previous, current); |
841 | while (current_list) | 867 | } else { |
842 | { | 868 | previous = current; |
843 | init_d_info_t *this_info = (init_d_info_t *) current_list->data; | 869 | current = current->link; |
844 | 870 | } | |
845 | for(k = 0; k < info->sizes[1]; k++) | 871 | } |
846 | { | ||
847 | int i; | ||
848 | char *needs = info->reqstart[k]; | ||
849 | 872 | ||
850 | if (done[k] == 0) | 873 | do { |
851 | { | 874 | count_moves = 0; |
875 | current = unsorted; | ||
876 | previous = NULL; | ||
877 | // foreach in unsorted list | ||
878 | while (current) { | ||
879 | int moved = 0; | ||
880 | init_d_info_t *info = (init_d_info_t *) current->data; | ||
881 | |||
882 | if (info->reqstart != NULL) { | ||
883 | int k; | ||
884 | llist_t *current_sort = sorted; | ||
885 | short done[info->sizes[1]]; | ||
886 | |||
887 | // foreach sorted list | ||
888 | while (current_sort) { | ||
889 | llist_t *current_list = (llist_t *) current_sort->data; | ||
890 | |||
891 | // if ALL deps are in sorted list move script to end of sorted list | ||
892 | for (k = 0; k < info->sizes[1]; k++) | ||
893 | done[k] = 0; | ||
894 | while (current_list) { | ||
895 | init_d_info_t *this_info = | ||
896 | (init_d_info_t *) current_list->data; | ||
897 | |||
898 | for (k = 0; k < info->sizes[1]; k++) { | ||
899 | int i; | ||
900 | char *needs = info->reqstart[k]; | ||
901 | |||
902 | if (done[k] == 0) { | ||
852 | //bb_printf("%s NEEDS %s - ", info->path, needs); | 903 | //bb_printf("%s NEEDS %s - ", info->path, needs); |
853 | for(i = 0; i < this_info->sizes[0]; i++) | 904 | for (i = 0; i < this_info->sizes[0]; i++) { |
854 | { | ||
855 | //bb_printf("%s ", this_info->provides[i]); | 905 | //bb_printf("%s ", this_info->provides[i]); |
856 | if (strcmp(this_info->provides[i], needs) == 0) | 906 | if (strcmp(this_info->provides[i], needs) |
857 | { | 907 | == 0) { |
858 | done[k] = 1; | 908 | done[k] = 1; |
859 | break; | 909 | break; |
860 | } | 910 | } |
861 | } | 911 | } |
862 | //bb_printf("\n"); | 912 | //bb_printf("\n"); |
863 | } | 913 | } |
914 | } | ||
915 | current_list = current_list->link; | ||
916 | } | ||
917 | |||
918 | moved = 1; | ||
919 | for (k = 0; k < info->sizes[1]; k++) { | ||
920 | if (done[k] == 0) { | ||
921 | moved = 0; | ||
922 | break; | ||
923 | } | ||
924 | } | ||
925 | if (moved == 1) { | ||
926 | llist_t *list = (llist_t *) current_sort->data; | ||
927 | |||
928 | llist_add_to_end(list, (char *) info); | ||
929 | current = llist_delete(&unsorted, previous, current); | ||
930 | moved = 1; | ||
931 | count_moves++; | ||
932 | current_sort = NULL; | ||
933 | } else | ||
934 | current_sort = current_sort->link; | ||
935 | } | ||
864 | } | 936 | } |
865 | current_list = current_list->link; | ||
866 | } | ||
867 | 937 | ||
868 | moved = 1; | 938 | if (moved == 0) { |
869 | for(k = 0; k < info->sizes[1]; k++) | 939 | previous = current; |
870 | { | 940 | current = current->link; |
871 | if (done[k] == 0) | ||
872 | { | ||
873 | moved = 0; | ||
874 | break; | ||
875 | } | 941 | } |
876 | } | ||
877 | if (moved == 1) | ||
878 | { | ||
879 | llist_t *list = (llist_t *) current_sort->data; | ||
880 | llist_add_to_end(list, (char *) info); | ||
881 | current = llist_delete(&unsorted, previous, current); | ||
882 | moved = 1; | ||
883 | count_moves++; | ||
884 | current_sort = NULL; | ||
885 | } | ||
886 | else | ||
887 | current_sort = current_sort->link; | ||
888 | } | 942 | } |
889 | } | 943 | } while (count_moves != 0); |
890 | 944 | // until no more moves happen | |
891 | if (moved == 0) | 945 | |
892 | { | 946 | |
893 | previous = current; | 947 | do { |
894 | current = current->link; | 948 | count_moves = 0; |
895 | } | 949 | current = unsorted; |
896 | } | 950 | previous = NULL; |
897 | } while (count_moves != 0); | 951 | // foreach in unsorted list |
898 | // until no more moves happen | 952 | while (current) { |
899 | 953 | int moved = 1; | |
900 | 954 | init_d_info_t *info = (init_d_info_t *) current->data; | |
901 | do | 955 | short done[info->sizes[1]]; |
902 | { | 956 | |
903 | count_moves = 0; | 957 | if (info->reqstart != NULL) { |
904 | current = unsorted; | 958 | int k; |
905 | previous = NULL; | 959 | llist_t *current_sortof = sorted; |
906 | // foreach in unsorted list | 960 | |
907 | while (current) | 961 | // if ALL deps are in sorted lists |
908 | { | 962 | for (k = 0; k < info->sizes[1]; k++) |
909 | int moved = 1; | 963 | done[k] = 0; |
910 | init_d_info_t *info = (init_d_info_t *) current->data; | 964 | while ((moved == 1) && (current_sortof != NULL)) { |
911 | short done[info->sizes[1]]; | 965 | llist_t *current_listof = |
912 | 966 | (llist_t *) current_sortof->data; | |
913 | if (info->reqstart != NULL) | 967 | |
914 | { | 968 | while (current_listof) { |
915 | int k; | 969 | init_d_info_t *this_info = |
916 | llist_t *current_sortof = sorted; | 970 | (init_d_info_t *) current_listof->data; |
917 | 971 | ||
918 | // if ALL deps are in sorted lists | 972 | for (k = 0; k < info->sizes[1]; k++) { |
919 | for(k = 0; k < info->sizes[1]; k++) | 973 | int i; |
920 | done[k] = 0; | 974 | char *needs = info->reqstart[k]; |
921 | while ((moved == 1) && (current_sortof != NULL)) | 975 | |
922 | { | 976 | if (done[k] == 0) { |
923 | llist_t *current_listof = (llist_t *) current_sortof->data; | ||
924 | |||
925 | while (current_listof) | ||
926 | { | ||
927 | init_d_info_t *this_info = (init_d_info_t *) current_listof->data; | ||
928 | |||
929 | for(k = 0; k < info->sizes[1]; k++) | ||
930 | { | ||
931 | int i; | ||
932 | char *needs = info->reqstart[k]; | ||
933 | |||
934 | if (done[k] == 0) | ||
935 | { | ||
936 | //bb_printf("%s NEEDS %s - ", info->path, needs); | 977 | //bb_printf("%s NEEDS %s - ", info->path, needs); |
937 | for(i = 0; i < this_info->sizes[0]; i++) | 978 | for (i = 0; i < this_info->sizes[0]; i++) { |
938 | { | ||
939 | //bb_printf("%s ", this_info->provides[i]); | 979 | //bb_printf("%s ", this_info->provides[i]); |
940 | if (strcmp(this_info->provides[i], needs) == 0) | 980 | if (strcmp(this_info->provides[i], needs) |
941 | { | 981 | == 0) { |
942 | done[k] = 1; | 982 | done[k] = 1; |
943 | break; | 983 | break; |
944 | } | 984 | } |
945 | } | 985 | } |
946 | //bb_printf("\n"); | 986 | //bb_printf("\n"); |
947 | } | 987 | } |
948 | } | 988 | } |
949 | current_listof = current_listof->link; | 989 | current_listof = current_listof->link; |
950 | } | 990 | } |
951 | current_sortof = current_sortof->link; | 991 | current_sortof = current_sortof->link; |
952 | } | 992 | } |
953 | |||
954 | moved = 1; | ||
955 | for(k = 0; k < info->sizes[1]; k++) | ||
956 | { | ||
957 | if (done[k] == 0) | ||
958 | { | ||
959 | moved = 0; | ||
960 | break; | ||
961 | } | ||
962 | } | ||
963 | 993 | ||
964 | if (moved == 1) | 994 | moved = 1; |
965 | { | 995 | for (k = 0; k < info->sizes[1]; k++) { |
966 | // create a merged list for script | 996 | if (done[k] == 0) { |
967 | llist_t *current_sort = sorted; | 997 | moved = 0; |
968 | llist_t *new_list = NULL; | 998 | break; |
969 | new_list = llist_add_to_end(new_list, (char *) info); | 999 | } |
970 | count_moves++; | 1000 | } |
971 | |||
972 | // foreach sorted | merged list | ||
973 | while (current_sort) | ||
974 | { | ||
975 | int found = 0; | ||
976 | llist_t *current_list = (llist_t *) current_sort->data; | ||
977 | |||
978 | // if A dep is in s|m add s|m to end of new merged list & continue with next s|m | ||
979 | while (current_list) | ||
980 | { | ||
981 | init_d_info_t *this_info = (init_d_info_t *) current_list->data; | ||
982 | 1001 | ||
983 | for(k = 0; k < info->sizes[1]; k++) | 1002 | if (moved == 1) { |
984 | { | 1003 | // create a merged list for script |
985 | int i; | 1004 | llist_t *current_sort = sorted; |
986 | char *needs = info->reqstart[k]; | 1005 | llist_t *new_list = NULL; |
1006 | |||
1007 | new_list = llist_add_to_end(new_list, (char *) info); | ||
1008 | count_moves++; | ||
1009 | |||
1010 | // foreach sorted | merged list | ||
1011 | while (current_sort) { | ||
1012 | int found = 0; | ||
1013 | llist_t *current_list = | ||
1014 | (llist_t *) current_sort->data; | ||
1015 | |||
1016 | // if A dep is in s|m add s|m to end of new merged list & continue with next s|m | ||
1017 | while (current_list) { | ||
1018 | init_d_info_t *this_info = | ||
1019 | (init_d_info_t *) current_list->data; | ||
1020 | |||
1021 | for (k = 0; k < info->sizes[1]; k++) { | ||
1022 | int i; | ||
1023 | char *needs = info->reqstart[k]; | ||
1024 | |||
1025 | for (i = 0; i < this_info->sizes[0]; i++) { | ||
1026 | if (strcmp(this_info->provides[i], needs) | ||
1027 | == 0) { | ||
1028 | found = 1; | ||
1029 | break; | ||
1030 | } | ||
1031 | } | ||
1032 | if (found == 1) | ||
1033 | break; | ||
1034 | } | ||
1035 | if (found == 1) { | ||
1036 | init_d_info_t *new_info = | ||
1037 | (init_d_info_t *) xcalloc(1, | ||
1038 | sizeof | ||
1039 | (init_d_info_t)); | ||
1040 | new_info->start = current_sort; | ||
1041 | new_list = | ||
1042 | llist_add_to_end(new_list, | ||
1043 | (char *) new_info); | ||
1044 | current_list = NULL; | ||
1045 | } else | ||
1046 | current_list = current_list->link; | ||
1047 | } | ||
1048 | |||
1049 | current_sort = current_sort->link; | ||
1050 | } | ||
987 | 1051 | ||
988 | for(i = 0; i < this_info->sizes[0]; i++) | 1052 | sorted = llist_add_to_end(sorted, (char *) new_list); |
989 | { | 1053 | current = llist_delete(&unsorted, previous, current); |
990 | if (strcmp(this_info->provides[i], needs) == 0) | ||
991 | { | ||
992 | found = 1; | ||
993 | break; | ||
994 | } | ||
995 | } | 1054 | } |
996 | if (found == 1) | ||
997 | break; | ||
998 | } | ||
999 | if (found == 1) | ||
1000 | { | ||
1001 | init_d_info_t *new_info = (init_d_info_t *) xcalloc(1, sizeof(init_d_info_t)); | ||
1002 | new_info->start = current_sort; | ||
1003 | new_list = llist_add_to_end(new_list, (char *) new_info); | ||
1004 | current_list = NULL; | ||
1005 | } | ||
1006 | else | ||
1007 | current_list = current_list->link; | ||
1008 | } | 1055 | } |
1009 | 1056 | ||
1010 | current_sort = current_sort->link; | 1057 | if (moved == 0) { |
1011 | } | 1058 | previous = current; |
1012 | 1059 | current = current->link; | |
1013 | sorted = llist_add_to_end(sorted, (char *) new_list); | 1060 | } |
1014 | current = llist_delete(&unsorted, previous, current); | ||
1015 | } | 1061 | } |
1016 | } | 1062 | } while (count_moves != 0); |
1017 | 1063 | // until no more creates happen | |
1018 | if (moved == 0) | ||
1019 | { | ||
1020 | previous = current; | ||
1021 | current = current->link; | ||
1022 | } | ||
1023 | } | ||
1024 | } while (count_moves != 0); | ||
1025 | // until no more creates happen | ||
1026 | 1064 | ||
1027 | 1065 | ||
1028 | // unsorted list now contains unsatisfied and circular dependencies | 1066 | // unsorted list now contains unsatisfied and circular dependencies |
1029 | // complain if not empty. | 1067 | // complain if not empty. |
1030 | if (unsorted != NULL) | 1068 | if (unsorted != NULL) { |
1031 | { | 1069 | bb_printf |
1032 | bb_printf("\nWARNING, the following init scripts have unresolved or circular dependencies -\n"); | 1070 | ("\nWARNING, the following init scripts have unresolved or circular dependencies -\n"); |
1033 | current = unsorted; | 1071 | current = unsorted; |
1034 | 1072 | ||
1035 | while (current) | 1073 | while (current) { |
1036 | { | 1074 | init_d_info_t *info = (init_d_info_t *) current->data; |
1037 | init_d_info_t *info = (init_d_info_t *) current->data; | ||
1038 | 1075 | ||
1039 | bb_printf("%s\n", info->path); | 1076 | bb_printf("%s\n", info->path); |
1040 | current = current->link; | 1077 | current = current->link; |
1041 | #if 0 | 1078 | #if 0 |
1042 | { | 1079 | { |
1043 | int k; | 1080 | int k; |
1044 | 1081 | ||
1045 | bb_printf("SCRIPT %s - ", info->path); | 1082 | bb_printf("SCRIPT %s - ", info->path); |
1046 | if (info->defstart != NULL) | 1083 | if (info->defstart != NULL) { |
1047 | { | 1084 | bb_printf("\t\t "); |
1048 | bb_printf("\t\t "); | 1085 | for (k = 0; k < info->sizes[5]; k++) |
1049 | for(k = 0; k < info->sizes[5]; k++) | 1086 | bb_printf("%d ", info->defstart[k]); |
1050 | bb_printf("%d ", info->defstart[k]); | 1087 | // bb_printf("\n"); |
1051 | // bb_printf("\n"); | 1088 | } |
1052 | } | 1089 | if (info->provides != NULL) { |
1053 | if (info->provides != NULL) | 1090 | bb_printf("\t\t "); |
1054 | { | 1091 | for (k = 0; k < info->sizes[0]; k++) |
1055 | bb_printf("\t\t "); | 1092 | bb_printf("%s ", info->provides[k]); |
1056 | for(k = 0; k < info->sizes[0]; k++) | 1093 | // bb_printf("\n"); |
1057 | bb_printf("%s ", info->provides[k]); | 1094 | } |
1058 | // bb_printf("\n"); | 1095 | if (info->reqstart != NULL) { |
1059 | } | 1096 | bb_printf("\n\t "); |
1060 | if (info->reqstart != NULL) | 1097 | for (k = 0; k < info->sizes[1]; k++) |
1061 | { | 1098 | bb_printf("%s ", info->reqstart[k]); |
1062 | bb_printf("\n\t "); | 1099 | // bb_printf("\n"); |
1063 | for(k = 0; k < info->sizes[1]; k++) | 1100 | } |
1064 | bb_printf("%s ", info->reqstart[k]); | 1101 | bb_printf("\n"); |
1065 | // bb_printf("\n"); | 1102 | } |
1066 | } | ||
1067 | bb_printf("\n"); | ||
1068 | } | ||
1069 | #endif | 1103 | #endif |
1104 | } | ||
1105 | bb_printf("\n"); | ||
1070 | } | 1106 | } |
1071 | bb_printf("\n"); | ||
1072 | } | ||
1073 | 1107 | ||
1074 | return sorted; | 1108 | return sorted; |
1075 | } | 1109 | } |
1076 | 1110 | ||
1077 | 1111 | ||
1078 | static void call_scripts(llist_t *sorted, char *command, int oldlevel, int level) | 1112 | static void call_scripts(llist_t * sorted, char *command, int oldlevel, |
1113 | int level) | ||
1079 | { | 1114 | { |
1080 | // call init_script(script, command) for each script in each list in created order | 1115 | // call init_script(script, command) for each script in each list in created order |
1081 | llist_t *current_sort = sorted; | 1116 | llist_t *current_sort = sorted; |
1082 | 1117 | ||
1083 | while (current_sort) | 1118 | while (current_sort) { |
1084 | { | 1119 | llist_t *current_list = (llist_t *) current_sort->data; |
1085 | llist_t *current_list = (llist_t *) current_sort->data; | ||
1086 | 1120 | ||
1087 | //bb_printf("\nLIST\n"); | 1121 | //bb_printf("\nLIST\n"); |
1088 | while (current_list) | 1122 | while (current_list) { |
1089 | { | 1123 | init_d_info_t *info = (init_d_info_t *) current_list->data; |
1090 | init_d_info_t *info = (init_d_info_t *) current_list->data; | 1124 | |
1091 | 1125 | if (info->path != NULL) { | |
1092 | if (info->path != NULL) | 1126 | if (info->defstart != NULL) { |
1093 | { | 1127 | int k; |
1094 | if (info->defstart != NULL) | 1128 | int found = 0; |
1095 | { | 1129 | |
1096 | int k; | 1130 | // if info->DefaultStart includes level |
1097 | int found = 0; | 1131 | for (k = 0; k < info->sizes[5]; k++) { |
1098 | 1132 | if (info->defstart[k] == level) { | |
1099 | // if info->DefaultStart includes level | 1133 | found = 1; |
1100 | for(k = 0; k < info->sizes[5]; k++) | 1134 | break; |
1101 | { | 1135 | } |
1102 | if (info->defstart[k] == level) | 1136 | } |
1103 | { | 1137 | // if info->DefaultStart does not include previous level |
1104 | found = 1; | 1138 | for (k = 0; k < info->sizes[5]; k++) { |
1105 | break; | 1139 | if (info->defstart[k] == oldlevel) { |
1106 | } | 1140 | found = 0; |
1107 | } | 1141 | break; |
1108 | // if info->DefaultStart does not include previous level | 1142 | } |
1109 | for(k = 0; k < info->sizes[5]; k++) | 1143 | } |
1110 | { | 1144 | // add info structure to list |
1111 | if (info->defstart[k] == oldlevel) | 1145 | if (found == 1) |
1112 | { | 1146 | init_script(info->path, command); |
1113 | found = 0; | 1147 | } |
1114 | break; | ||
1115 | } | ||
1116 | } | ||
1117 | // add info structure to list | ||
1118 | if (found == 1) | ||
1119 | init_script(info->path, command); | ||
1120 | } | ||
1121 | |||
1122 | #if 0 | 1148 | #if 0 |
1123 | { | 1149 | { |
1124 | int k; | 1150 | int k; |
1125 | 1151 | ||
1126 | bb_printf("SCRIPT %s - ", info->path); | 1152 | bb_printf("SCRIPT %s - ", info->path); |
1127 | if (info->defstart != NULL) | 1153 | if (info->defstart != NULL) { |
1128 | { | 1154 | bb_printf("\t\t "); |
1129 | bb_printf("\t\t "); | 1155 | for (k = 0; k < info->sizes[5]; k++) |
1130 | for(k = 0; k < info->sizes[5]; k++) | 1156 | bb_printf("%d ", info->defstart[k]); |
1131 | bb_printf("%d ", info->defstart[k]); | 1157 | // bb_printf("\n"); |
1132 | // bb_printf("\n"); | 1158 | } |
1133 | } | 1159 | if (info->provides != NULL) { |
1134 | if (info->provides != NULL) | 1160 | bb_printf("\t\t "); |
1135 | { | 1161 | for (k = 0; k < info->sizes[0]; k++) |
1136 | bb_printf("\t\t "); | 1162 | bb_printf("%s ", info->provides[k]); |
1137 | for(k = 0; k < info->sizes[0]; k++) | 1163 | // bb_printf("\n"); |
1138 | bb_printf("%s ", info->provides[k]); | 1164 | } |
1139 | // bb_printf("\n"); | 1165 | if (info->reqstart != NULL) { |
1140 | } | 1166 | bb_printf("\n\t "); |
1141 | if (info->reqstart != NULL) | 1167 | for (k = 0; k < info->sizes[1]; k++) |
1142 | { | 1168 | bb_printf("%s ", info->reqstart[k]); |
1143 | bb_printf("\n\t "); | 1169 | // bb_printf("\n"); |
1144 | for(k = 0; k < info->sizes[1]; k++) | 1170 | } |
1145 | bb_printf("%s ", info->reqstart[k]); | 1171 | bb_printf("\n"); |
1146 | // bb_printf("\n"); | 1172 | } |
1147 | } | ||
1148 | bb_printf("\n"); | ||
1149 | } | ||
1150 | #endif | 1173 | #endif |
1151 | } | 1174 | } |
1152 | current_list = current_list->link; | 1175 | current_list = current_list->link; |
1176 | } | ||
1177 | current_sort = current_sort->link; | ||
1153 | } | 1178 | } |
1154 | current_sort = current_sort->link; | ||
1155 | } | ||
1156 | } | 1179 | } |
1157 | 1180 | ||
1158 | 1181 | ||
1159 | int run_level(char *level) | 1182 | static int run_level(char *level) |
1160 | { | 1183 | { |
1161 | int oldlevel = 0; | 1184 | int oldlevel = 0; |
1162 | int newlevel = atoi(level); | 1185 | int newlevel = atoi(level); |
1163 | char *temp; | 1186 | char *temp; |
1164 | llist_t *sorted = NULL; | 1187 | llist_t *sorted = NULL; |
1165 | llist_t *reversed = NULL; | 1188 | llist_t *reversed = NULL; |
1166 | llist_t *current_sort = NULL; | 1189 | llist_t *current_sort = NULL; |
1167 | 1190 | ||
1168 | bb_printf("\n\nSwitching to run level %d", newlevel); | 1191 | bb_printf("\n\nSwitching to run level %d", newlevel); |
1169 | 1192 | ||
1170 | // get previous run level | 1193 | // get previous run level |
1171 | temp = quick_read("/var/lib/misc/runlevel"); | 1194 | temp = quick_read("/var/lib/misc/runlevel"); |
1172 | if (temp != NULL) | 1195 | if (temp != NULL) { |
1173 | { | 1196 | oldlevel = atoi(temp); |
1174 | oldlevel = atoi(temp); | 1197 | if (oldlevel < 1) |
1175 | if (oldlevel < 0) | 1198 | oldlevel = 1; |
1176 | oldlevel = 1; | 1199 | if ((oldlevel == 6) || (oldlevel > 9)) |
1177 | if (oldlevel > 6) | 1200 | oldlevel = 5; |
1178 | oldlevel = 5; | 1201 | bb_printf(" from run level %d", oldlevel); |
1179 | bb_printf(" from run level %d", oldlevel); | 1202 | free(temp); |
1180 | free(temp); | 1203 | } |
1181 | } | 1204 | bb_printf(".\n\n"); |
1182 | bb_printf(".\n\n"); | ||
1183 | 1205 | ||
1184 | // get scripts and sort dependencies, careful with circular dependencies | 1206 | // get scripts and sort dependencies, careful with circular dependencies |
1185 | sorted = sort_scripts(get_scripts()); | 1207 | sorted = sort_scripts(get_scripts(), NULL); |
1186 | 1208 | ||
1187 | // reverse | 1209 | // reverse |
1188 | current_sort = sorted; | 1210 | current_sort = sorted; |
1189 | while (current_sort) | 1211 | while (current_sort) { |
1190 | { | 1212 | llist_t *current_list = (llist_t *) current_sort->data; |
1191 | llist_t *current_list = (llist_t *) current_sort->data; | 1213 | llist_t *new_list = NULL; |
1192 | llist_t *new_list = NULL; | ||
1193 | 1214 | ||
1194 | while (current_list) | 1215 | while (current_list) { |
1195 | { | 1216 | new_list = llist_add_to(new_list, current_list->data); |
1196 | new_list = llist_add_to(new_list, current_list->data); | 1217 | current_list = current_list->link; |
1197 | current_list = current_list->link; | 1218 | } |
1219 | reversed = llist_add_to(reversed, (char *) new_list); | ||
1220 | current_sort = current_sort->link; | ||
1198 | } | 1221 | } |
1199 | reversed = llist_add_to(reversed, (char *) new_list); | ||
1200 | current_sort = current_sort->link; | ||
1201 | } | ||
1202 | 1222 | ||
1203 | // call "stop" for each script | 1223 | // call "stop" for each script |
1204 | bb_printf("\n"); | 1224 | bb_printf("\n"); |
1205 | call_scripts(reversed, "stop", newlevel, oldlevel); | 1225 | call_scripts(reversed, "stop", newlevel, oldlevel); |
1206 | 1226 | ||
1207 | // call "start" for each script | 1227 | // call "start" for each script |
1208 | bb_printf("\n"); | 1228 | bb_printf("\n"); |
1209 | call_scripts(sorted, "start", oldlevel, newlevel); | 1229 | call_scripts(sorted, "start", oldlevel, newlevel); |
1210 | // free all infos | 1230 | // free all infos |
1211 | 1231 | ||
1212 | // set previous run level to new run level | 1232 | // set previous run level to new run level |
1213 | quick_write("/var/lib/misc/runlevel", "%d", newlevel); | 1233 | quick_write("/var/lib/misc/runlevel", "%d", newlevel); |
1214 | 1234 | ||
1215 | 1235 | ||
1216 | // Later, optionally call them in parallel when possible. | 1236 | // Later, optionally call them in parallel when possible. |
1217 | 1237 | ||
1218 | 1238 | ||
1219 | // Later, add a database of runlevels per script and allow editing them - | 1239 | // Later, add a database of runlevels per script and allow editing them - |
1220 | // rc network --runlevels 3 4 5 | 1240 | // rc network -l 3 4 5 |
1221 | // cat /etc/runlevels.conf | 1241 | // cat /etc/runlevels.conf |
1222 | // runlevel="3" | 1242 | // runlevel="3" |
1223 | // runlevel3="multi user with network." | 1243 | // runlevel_3="multi user with network." |
1224 | // runlevel4="multi user with network and twin." | 1244 | // runlevel_4="multi user with network and twin." |
1225 | // runlevel5="multi user with network and X." | 1245 | // runlevel_5="multi user with network and X." |
1226 | // local_fs="1 2 3 4 5" | 1246 | // runlevel_local_fs="1 2 3 4 5" |
1227 | // network="3 4 5" | 1247 | // runlevel_network="3 4 5" |
1228 | // script1="2 3 5" | 1248 | // runlevel_script1="2 3 5" |
1229 | // script1="3 5" | 1249 | // runlevel_script1="3 5" |
1230 | // rc network --runlevels | 1250 | // rc network -l |
1231 | // 3 4 5 | 1251 | // 3 4 5 |
1232 | // rc network --runlevels -v | 1252 | // rc network -lv |
1233 | // The "network" service will be active during these run levels : | 1253 | // The "network" service will be active during these run levels : |
1234 | // 3 - multi user with network. | 1254 | // 3 - multi user with network. |
1235 | // 4 - multi user with network and twin. | 1255 | // 4 - multi user with network and twin. |
1236 | // 5 - multi user with network and X. | 1256 | // 5 - multi user with network and X. |
1237 | 1257 | ||
1238 | return EXIT_SUCCESS; | 1258 | return EXIT_SUCCESS; |
1259 | } | ||
1260 | |||
1261 | |||
1262 | static void print_levels(char *script, char *levels, int verbose) | ||
1263 | { | ||
1264 | if (verbose) { | ||
1265 | char *token; | ||
1266 | char *strtok_temp; | ||
1267 | |||
1268 | bb_printf("The \"%s\" service will be active during these run levels :\n", script); | ||
1269 | |||
1270 | for (token = strtok_r(levels, " \t\n\r", &strtok_temp); token != NULL; token = strtok_r(NULL, " \t\n\r", &strtok_temp)) { | ||
1271 | char *env; | ||
1272 | |||
1273 | bb_xasprintf(&env, "runlevel_%s", token); | ||
1274 | bb_printf("%s - %s\n", token, getenv(env)); | ||
1275 | } | ||
1276 | } else { | ||
1277 | bb_printf("%s\n", levels); | ||
1278 | } | ||
1279 | } | ||
1280 | |||
1281 | |||
1282 | static int show_run_levels(char *script, int verbose) | ||
1283 | { | ||
1284 | int result = EXIT_FAILURE; | ||
1285 | |||
1286 | char *info_text = NULL; | ||
1287 | char *pathname = NULL; | ||
1288 | init_d_info_t *info = NULL; | ||
1289 | //bb_printf("SHOW levels for %s\n", script); | ||
1290 | |||
1291 | bb_xasprintf(&pathname, "/etc/init.d/%s", script); | ||
1292 | info_text = get_init_info(pathname); | ||
1293 | info = parse_init_info(info_text, script); | ||
1294 | if (info) { | ||
1295 | char *env; | ||
1296 | char *levels; | ||
1297 | |||
1298 | result = EXIT_SUCCESS; | ||
1299 | bb_xasprintf(&env, "runlevel_%s", script); | ||
1300 | levels = getenv(env); | ||
1301 | if (levels) | ||
1302 | print_levels(script, levels, verbose); | ||
1303 | else { | ||
1304 | int k; | ||
1305 | RESERVE_CONFIG_BUFFER(temp, PATH_MAX); | ||
1306 | |||
1307 | temp[0] = '\0'; | ||
1308 | if (info->defstart != NULL) { | ||
1309 | for (k = 0; k < info->sizes[5]; k++) | ||
1310 | snprintf(temp, PATH_MAX, "%s%d ", temp, info->defstart[k]); | ||
1311 | } | ||
1312 | |||
1313 | print_levels(script, temp, verbose); | ||
1314 | |||
1315 | RELEASE_CONFIG_BUFFER(temp); | ||
1316 | } | ||
1317 | } | ||
1318 | |||
1319 | free(info); | ||
1320 | free(info_text); | ||
1321 | free(pathname); | ||
1322 | |||
1323 | return result; | ||
1324 | } | ||
1325 | |||
1326 | |||
1327 | static int edit_run_levels(char *script, char *levels, int verbose) | ||
1328 | { | ||
1329 | int result = 0; | ||
1330 | bb_printf("CHANGE levels for %s to %s\n", script, levels); | ||
1331 | return result; | ||
1239 | } | 1332 | } |
1240 | 1333 | ||
1241 | 1334 | ||
@@ -1243,29 +1336,69 @@ int run_level(char *level) | |||
1243 | * rc | 1336 | * rc |
1244 | * rc 1 | 1337 | * rc 1 |
1245 | * rc network start | 1338 | * rc network start |
1246 | * rc network --runlevels | 1339 | * rc network -l |
1247 | * rc network --runlevels -v | 1340 | * rc network -lv |
1248 | * rc network --runlevels 3 4 5 | 1341 | * rc network -l 3 4 5 |
1249 | */ | 1342 | */ |
1250 | 1343 | ||
1251 | int rc_main(int argc, char **argv) | 1344 | int rc_main(int argc, char **argv) |
1252 | { | 1345 | { |
1253 | switch (argc) | 1346 | int opt; |
1254 | { | 1347 | int levels = 0, verbose = 0; |
1255 | case 0 : | 1348 | |
1256 | case 1 : | 1349 | while ((opt = getopt(argc, argv, "lv")) > 0) { |
1257 | { | 1350 | switch (opt) { |
1258 | return run_level(quick_read("/etc/runlevel")); | 1351 | case 'l': |
1352 | levels = 1; | ||
1353 | break; | ||
1354 | |||
1355 | case 'v': | ||
1356 | verbose = 1; | ||
1357 | break; | ||
1358 | |||
1359 | default: | ||
1360 | bb_show_usage(); | ||
1361 | } | ||
1259 | } | 1362 | } |
1260 | case 2 : return run_level(argv[1]); | 1363 | |
1261 | case 3 : | 1364 | read_sysconfig("/etc/runlevels.conf"); |
1262 | { | 1365 | argc -= optind - 1; |
1366 | argv += optind - 1; | ||
1367 | |||
1368 | if (levels) { | ||
1369 | switch (argc) { | ||
1370 | case 0: | ||
1371 | case 1: | ||
1372 | { | ||
1373 | return INIT_D_ERROR_NOT_IMPLEMENTED; | ||
1374 | } | ||
1375 | case 2: | ||
1376 | { | ||
1377 | return show_run_levels(argv[1], verbose); | ||
1378 | } | ||
1379 | default: | ||
1380 | { | ||
1381 | return edit_run_levels(argv[1], argv_cat(argc - 1, &argv[1]), verbose); | ||
1382 | } | ||
1383 | } | ||
1384 | } else { | ||
1385 | switch (argc) { | ||
1386 | case 0: | ||
1387 | case 1: | ||
1388 | { | ||
1389 | return run_level(quick_read("/etc/runlevel")); | ||
1390 | } | ||
1391 | case 2: | ||
1392 | return run_level(argv[1]); | ||
1393 | case 3: | ||
1394 | { | ||
1263 | // Should take care of dependencies for argv[1] script. | 1395 | // Should take care of dependencies for argv[1] script. |
1264 | return init_script(argv[1], argv[2]); | 1396 | return init_script(argv[1], argv[2]); |
1265 | } | 1397 | } |
1266 | default : | 1398 | default: |
1267 | { | 1399 | { |
1268 | return INIT_D_ERROR_NOT_IMPLEMENTED; | 1400 | return INIT_D_ERROR_NOT_IMPLEMENTED; |
1401 | } | ||
1402 | } | ||
1269 | } | 1403 | } |
1270 | } | ||
1271 | } | 1404 | } |