summaryrefslogtreecommitdiffstats
path: root/urunlevel/runlevel/rc.c
diff options
context:
space:
mode:
Diffstat (limited to 'urunlevel/runlevel/rc.c')
-rw-r--r--urunlevel/runlevel/rc.c2013
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
36const static char *commands[] = 39const 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
50const static char *INFOS[] = 52const 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
70int default_start(struct init_d_handle_s *init_d, int just_checking) 71int 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
123int default_stop(struct init_d_handle_s *init_d, int just_checking) 123int 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
169int default_restart(struct init_d_handle_s *init_d, int just_checking) 168int 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
206int default_try_restart(struct init_d_handle_s *init_d, int just_checking) 204int 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
242int default_reload(struct init_d_handle_s *init_d, int just_checking) 239int 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
248int sighup_reload(struct init_d_handle_s *init_d, int just_checking) 245int 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
280int default_force_reload(struct init_d_handle_s *init_d, int just_checking) 276int 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
291int print_status(struct init_d_handle_s *init_d, int quiet, int status) 287int 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
331int default_status(struct init_d_handle_s *init_d, int quiet) 328int 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
337int default_show_info(struct init_d_handle_s *init_d, int just_checking) 335int 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
344int no_stop(struct init_d_handle_s *init_d, int just_checking) 342int 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
350int no_reload(struct init_d_handle_s *init_d, int just_checking) 348int 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
356int no_status(struct init_d_handle_s *init_d, int quiet) 354int 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
362int do_init_from_main(int argc, char **argv, struct init_d_handle_s *init_d) 360int 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
368int do_init(struct init_d_handle_s *init_d, const char *command) 367int 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
416static int init_script(char *script, char *command) 446static 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
445init_d_info_t *parse_init_info(char *info_text, char *name) 491init_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
521if (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
524if (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
535if (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
547if (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
658char *get_init_info(char *pathname) 715char *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
757llist_t *get_scripts(void) 818llist_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
788llist_t *sort_scripts(llist_t *unsorted) 847llist_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
1078static void call_scripts(llist_t *sorted, char *command, int oldlevel, int level) 1112static 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
1159int run_level(char *level) 1182static 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
1262static 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
1282static 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
1327static int edit_run_levels(char *script, char *levels, int verbose)
1328{
1329 int result = 0;
1330bb_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
1251int rc_main(int argc, char **argv) 1344int 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}