Gentoo Websites Logo
Go to: Gentoo Home Documentation Forums Lists Bugs Planet Store Wiki Get Gentoo!
View | Details | Raw Unified | Return to bug 426948
Collapse All | Expand All

(-)openrc-0.11.8.orig/src/librc/librc.c (-6 / +33 lines)
Lines 433-438 Link Here
433
}
433
}
434
librc_hidden_def(rc_runlevel_stacks)
434
librc_hidden_def(rc_runlevel_stacks)
435
435
436
/* Returns a list of all the chained runlevels used by the
437
 * specified runlevel in dependency order, including the
438
 * specified runlevel. */
439
void
440
rc_get_runlevel_chain(const char *runlevel, RC_STRINGLIST *level_list)
441
{
442
	// If we haven't been passed a runlevel or a level list, or
443
	// if the passed runlevel doesn't exist then we're done already!
444
	if (!runlevel || !level_list || !rc_runlevel_exists(runlevel))
445
		return;
446
447
	// We want to add this runlevel to the list but if
448
	// it is already in the list it needs to go at the
449
	// end again.
450
	if (rc_stringlist_find(level_list, runlevel))
451
		rc_stringlist_delete(level_list, runlevel);
452
	rc_stringlist_add(level_list, runlevel);
453
454
	// We can now do exactly the above procedure for our chained
455
	// runlevels.
456
	char path[PATH_MAX];
457
	RC_STRINGLIST *dirs;
458
	RC_STRING *d, *dn;
459
	snprintf(path, sizeof(path), "%s/%s", RC_RUNLEVELDIR, runlevel);
460
	dirs = ls_dir(path, LS_DIR);
461
	TAILQ_FOREACH_SAFE(d, dirs, entries, dn)
462
		rc_get_runlevel_chain(d->value, level_list);
463
}
464
librc_hidden_def(rc_get_runlevel_chain)
465
436
/* Resolve a service name to its full path */
466
/* Resolve a service name to its full path */
437
char *
467
char *
438
rc_service_resolve(const char *service)
468
rc_service_resolve(const char *service)
Lines 892-903 Link Here
892
	list = rc_services_in_runlevel(runlevel);
922
	list = rc_services_in_runlevel(runlevel);
893
	stacks = rc_runlevel_stacks(runlevel);
923
	stacks = rc_runlevel_stacks(runlevel);
894
	TAILQ_FOREACH(stack, stacks, entries) {
924
	TAILQ_FOREACH(stack, stacks, entries) {
895
		sl = rc_services_in_runlevel(stack->value);
925
		sl = rc_services_in_runlevel_stacked(stack->value);
896
		if (list != NULL) {
926
		TAILQ_CONCAT(list, sl, entries);
897
			TAILQ_CONCAT(list, sl, entries);
927
		free(sl);
898
			free(sl);
899
		} else
900
			list = sl;
901
	}
928
	}
902
	return list;
929
	return list;
903
}
930
}
(-)openrc-0.11.8.orig/src/librc/librc.h (+1 lines)
Lines 95-100 Link Here
95
librc_hidden_proto(rc_runlevel_set)
95
librc_hidden_proto(rc_runlevel_set)
96
librc_hidden_proto(rc_runlevel_stack)
96
librc_hidden_proto(rc_runlevel_stack)
97
librc_hidden_proto(rc_runlevel_stacks)
97
librc_hidden_proto(rc_runlevel_stacks)
98
librc_hidden_proto(rc_get_runlevel_chain)
98
librc_hidden_proto(rc_runlevel_starting)
99
librc_hidden_proto(rc_runlevel_starting)
99
librc_hidden_proto(rc_runlevel_stopping)
100
librc_hidden_proto(rc_runlevel_stopping)
100
librc_hidden_proto(rc_runlevel_unstack)
101
librc_hidden_proto(rc_runlevel_unstack)
(-)openrc-0.11.8.orig/src/librc/rc.h.in (+4 lines)
Lines 111-116 Link Here
111
 * @return a NULL terminated list of runlevels */
111
 * @return a NULL terminated list of runlevels */
112
RC_STRINGLIST *rc_runlevel_stacks(const char *);
112
RC_STRINGLIST *rc_runlevel_stacks(const char *);
113
113
114
/*! Return a NULL terminated list of runlevels in the runlevel chain
115
 * @return a NULL terminated list of runlevels */
116
void rc_get_runlevel_chain(const char *, RC_STRINGLIST *);
117
114
/*! Return a NULL terminated list of runlevels
118
/*! Return a NULL terminated list of runlevels
115
 * @return a NULL terminated list of runlevels */
119
 * @return a NULL terminated list of runlevels */
116
RC_STRINGLIST *rc_runlevel_list(void);
120
RC_STRINGLIST *rc_runlevel_list(void);
(-)openrc-0.11.8.orig/src/librc/rc.map (+1 lines)
Lines 25-30 Link Here
25
	rc_runlevel_set;
25
	rc_runlevel_set;
26
	rc_runlevel_stack;
26
	rc_runlevel_stack;
27
	rc_runlevel_stacks;
27
	rc_runlevel_stacks;
28
	rc_get_runlevel_chain;
28
	rc_runlevel_starting;
29
	rc_runlevel_starting;
29
	rc_runlevel_stopping;
30
	rc_runlevel_stopping;
30
	rc_runlevel_unstack;
31
	rc_runlevel_unstack;
(-)openrc-0.11.8.orig/src/rc/rc.c (-52 / +70 lines)
Lines 79-94 Link Here
79
79
80
const char *applet = NULL;
80
const char *applet = NULL;
81
static char *runlevel;
81
static char *runlevel;
82
static RC_STRINGLIST *hotplugged_services;
83
static RC_STRINGLIST *stop_services;
84
static RC_STRINGLIST *start_services;
85
static RC_STRINGLIST *types_n;
86
static RC_STRINGLIST *types_nua;
87
static RC_DEPTREE *deptree;
88
static RC_HOOK hook_out;
82
static RC_HOOK hook_out;
89
90
struct termios *termios_orig = NULL;
83
struct termios *termios_orig = NULL;
91
92
RC_PIDLIST service_pids;
84
RC_PIDLIST service_pids;
93
85
94
static void
86
static void
Lines 113-120 Link Here
113
			snprintf(path, l, RC_SVCDIR "/failed/%s", d->d_name);
105
			snprintf(path, l, RC_SVCDIR "/failed/%s", d->d_name);
114
			if (path) {
106
			if (path) {
115
				if (unlink(path))
107
				if (unlink(path))
116
					eerror("%s: unlink `%s': %s",
108
					eerror("%s: unlink `%s': %s", applet, path, strerror(errno));
117
					    applet, path, strerror(errno));
118
				free(path);
109
				free(path);
119
			}
110
			}
120
		}
111
		}
Lines 524-530 Link Here
524
}
515
}
525
516
526
static void
517
static void
527
do_stop_services(const char *newlevel, bool parallel, bool going_down)
518
do_stop_services(const RC_STRINGLIST *types_n, const RC_STRINGLIST *start_services,
519
				 const RC_STRINGLIST *stop_services, const RC_DEPTREE *deptree,
520
				 const char *newlevel, bool parallel, bool going_down)
528
{
521
{
529
	pid_t pid;
522
	pid_t pid;
530
	RC_STRING *service, *svc1, *svc2;
523
	RC_STRING *service, *svc1, *svc2;
Lines 581-588 Link Here
581
				 * be stopped if we have a runlevel
574
				 * be stopped if we have a runlevel
582
				 * configuration file for either the current
575
				 * configuration file for either the current
583
				 * or next so we use the correct one. */
576
				 * or next so we use the correct one. */
584
				if (!runlevel_config(service->value,runlevel) &&
577
				if (!runlevel_config(service->value, runlevel) &&
585
				    !runlevel_config(service->value,newlevel))
578
				    !runlevel_config(service->value, newlevel))
586
					continue;
579
					continue;
587
			}
580
			}
588
			else
581
			else
Lines 627-633 Link Here
627
}
620
}
628
621
629
static void
622
static void
630
do_start_services(bool parallel)
623
do_start_services(const RC_STRINGLIST *start_services, bool parallel)
631
{
624
{
632
	RC_STRING *service;
625
	RC_STRING *service;
633
	pid_t pid;
626
	pid_t pid;
Lines 750-755 Link Here
750
{
743
{
751
	const char *bootlevel = NULL;
744
	const char *bootlevel = NULL;
752
	char *newlevel = NULL;
745
	char *newlevel = NULL;
746
	static RC_STRINGLIST *hotplugged_services;
747
	static RC_STRINGLIST *stop_services;
748
	static RC_STRINGLIST *start_services;
749
	static RC_STRINGLIST *types_n;
750
	static RC_STRINGLIST *types_nua;
751
	static RC_DEPTREE *deptree;
752
753
	RC_STRINGLIST *deporder = NULL;
753
	RC_STRINGLIST *deporder = NULL;
754
	RC_STRINGLIST *tmplist;
754
	RC_STRINGLIST *tmplist;
755
	RC_STRING *service;
755
	RC_STRING *service;
Lines 885-890 Link Here
885
	/* Now we start handling our children */
885
	/* Now we start handling our children */
886
	signal_setup(SIGCHLD, handle_signal);
886
	signal_setup(SIGCHLD, handle_signal);
887
887
888
	/* Are we heading for a shutdown or a transition to single user mode? */
888
	if (newlevel &&
889
	if (newlevel &&
889
	    (strcmp(newlevel, RC_LEVEL_SHUTDOWN) == 0 ||
890
	    (strcmp(newlevel, RC_LEVEL_SHUTDOWN) == 0 ||
890
		strcmp(newlevel, RC_LEVEL_SINGLE) == 0))
891
		strcmp(newlevel, RC_LEVEL_SINGLE) == 0))
Lines 964-971 Link Here
964
		    applet, RC_STOPPING, strerror(errno));
965
		    applet, RC_STOPPING, strerror(errno));
965
	}
966
	}
966
967
967
	/* Build a list of all services to stop and then work out the
968
	/* Create a list of all services which we could stop (assuming
968
	 * correct order for stopping them */
969
	 * they won't be active in the new or current runlevel) including
970
	 * all those services which have been started, are inactive or
971
	 * are currently starting.  Clearly, some of these will be listed
972
	 * in the new or current runlevel so we won't actually be stopping
973
	 * them all.
974
	 */
969
	stop_services = rc_services_in_state(RC_SERVICE_STARTED);
975
	stop_services = rc_services_in_state(RC_SERVICE_STARTED);
970
	tmplist = rc_services_in_state(RC_SERVICE_INACTIVE);
976
	tmplist = rc_services_in_state(RC_SERVICE_INACTIVE);
971
	TAILQ_CONCAT(stop_services, tmplist, entries);
977
	TAILQ_CONCAT(stop_services, tmplist, entries);
Lines 982-1018 Link Here
982
	rc_stringlist_add(types_nua, "iafter");
988
	rc_stringlist_add(types_nua, "iafter");
983
989
984
	if (stop_services) {
990
	if (stop_services) {
985
		tmplist = rc_deptree_depends(deptree, types_nua, stop_services,
991
		tmplist = rc_deptree_depends(deptree, types_nua, stop_services, runlevel, depoptions | RC_DEP_STOP);
986
		    runlevel, depoptions | RC_DEP_STOP);
987
		rc_stringlist_free(stop_services);
992
		rc_stringlist_free(stop_services);
988
		stop_services = tmplist;
993
		stop_services = tmplist;
989
	}
994
	}
990
995
991
	/* Load our list of start services */
996
	/* Create a list of all services which should be started for the new or
997
	 * current runlevel including those in boot, sysinit and hotplugged
998
	 * runlevels.  Clearly, some of these will already be started so we
999
	 * won't actually be starting them all.
1000
	 */
992
	hotplugged_services = rc_services_in_state(RC_SERVICE_HOTPLUGGED);
1001
	hotplugged_services = rc_services_in_state(RC_SERVICE_HOTPLUGGED);
993
	start_services = rc_services_in_runlevel_stacked(newlevel ?
1002
	start_services = rc_services_in_runlevel_stacked(newlevel ? newlevel : runlevel);
994
	    newlevel : runlevel);
995
	if (strcmp(newlevel ? newlevel : runlevel, RC_LEVEL_SHUTDOWN) != 0 &&
1003
	if (strcmp(newlevel ? newlevel : runlevel, RC_LEVEL_SHUTDOWN) != 0 &&
996
	    strcmp(newlevel ? newlevel : runlevel, RC_LEVEL_SYSINIT) != 0)
1004
	    strcmp(newlevel ? newlevel : runlevel, RC_LEVEL_SYSINIT) != 0)
997
	{
1005
	{
998
		tmplist = rc_services_in_runlevel(RC_LEVEL_SYSINIT);
1006
		tmplist = rc_services_in_runlevel(RC_LEVEL_SYSINIT);
999
		TAILQ_CONCAT(start_services, tmplist, entries);
1007
		TAILQ_CONCAT(start_services, tmplist, entries);
1000
		free(tmplist);
1008
		free(tmplist);
1001
		if (strcmp(newlevel ? newlevel : runlevel,
1009
		// If we are NOT headed for the single-user runlevel...
1002
			RC_LEVEL_SINGLE) != 0)
1010
		if (strcmp(newlevel ? newlevel : runlevel, RC_LEVEL_SINGLE) != 0)
1003
		{
1011
		{
1004
			if (strcmp(newlevel ? newlevel : runlevel,
1012
			// If we are NOT headed for the boot runlevel...
1005
				bootlevel) != 0)
1013
			if (strcmp(newlevel ? newlevel : runlevel, bootlevel) != 0)
1006
			{
1014
			{
1007
				tmplist = rc_services_in_runlevel(bootlevel);
1015
				tmplist = rc_services_in_runlevel(bootlevel);
1008
				TAILQ_CONCAT(start_services, tmplist, entries);
1016
				TAILQ_CONCAT(start_services, tmplist, entries);
1009
				free(tmplist);
1017
				free(tmplist);
1010
			}
1018
			}
1011
			if (hotplugged_services) {
1019
			if (hotplugged_services) {
1012
				TAILQ_FOREACH(service, hotplugged_services,
1020
				TAILQ_FOREACH(service, hotplugged_services, entries)
1013
				    entries)
1021
				    rc_stringlist_addu(start_services, service->value);
1014
				    rc_stringlist_addu(start_services,
1015
					service->value);
1016
			}
1022
			}
1017
		}
1023
		}
1018
	}
1024
	}
Lines 1021-1034 Link Here
1021
1027
1022
	/* Now stop the services that shouldn't be running */
1028
	/* Now stop the services that shouldn't be running */
1023
	if (stop_services)
1029
	if (stop_services)
1024
		do_stop_services(newlevel, parallel, going_down);
1030
		do_stop_services(types_n, start_services, stop_services, deptree, newlevel, parallel, going_down);
1025
1031
1026
	/* Wait for our services to finish */
1032
	/* Wait for our services to finish */
1027
	wait_for_services();
1033
	wait_for_services();
1028
1034
1029
	/* Notify the plugins we have finished */
1035
	/* Notify the plugins we have finished */
1030
	rc_plugin_run(RC_HOOK_RUNLEVEL_STOP_OUT,
1036
	rc_plugin_run(RC_HOOK_RUNLEVEL_STOP_OUT, going_down ? newlevel : runlevel);
1031
	    going_down ? newlevel : runlevel);
1032
	hook_out = 0;
1037
	hook_out = 0;
1033
1038
1034
	rmdir(RC_STOPPING);
1039
	rmdir(RC_STOPPING);
Lines 1057-1074 Link Here
1057
		TAILQ_FOREACH(service, hotplugged_services, entries)
1062
		TAILQ_FOREACH(service, hotplugged_services, entries)
1058
		    rc_service_mark(service->value, RC_SERVICE_HOTPLUGGED);
1063
		    rc_service_mark(service->value, RC_SERVICE_HOTPLUGGED);
1059
1064
1060
	/* Order the services to start */
1061
	if (start_services) {
1062
		rc_stringlist_sort(&start_services);
1063
		deporder = rc_deptree_depends(deptree, types_nua,
1064
		    start_services, runlevel,
1065
		    depoptions | RC_DEP_START);
1066
		rc_stringlist_free(start_services);
1067
		start_services = deporder;
1068
	}
1069
1070
#ifdef __linux__
1065
#ifdef __linux__
1071
	/* mark any services skipped as started */
1066
	/* If the "noinit" parameter was passed on the kernel command line then
1067
	 * mark the specified services as started so they will not be started
1068
	 * by us. */
1072
	proc = p = rc_proc_getent("noinit");
1069
	proc = p = rc_proc_getent("noinit");
1073
	if (proc) {
1070
	if (proc) {
1074
		while ((token = strsep(&p, ",")))
1071
		while ((token = strsep(&p, ",")))
Lines 1077-1095 Link Here
1077
	}
1074
	}
1078
#endif
1075
#endif
1079
1076
1080
	if (start_services) {
1077
	// If we have a list of services to start then...
1081
		do_start_services(parallel);
1078
	if (start_services)
1082
		/* FIXME: If we skip the boot runlevel and go straight
1079
	{
1083
		 * to default from sysinit, we should now re-evaluate our
1080
		// Get a list of the chained runlevels which compose the target runlevel
1084
		 * start services + hotplugged services and call
1081
		RC_STRINGLIST *runlevel_chain = rc_stringlist_new();
1085
		 * do_start_services a second time. */
1082
		rc_get_runlevel_chain(runlevel, runlevel_chain);
1083
1084
		// Loop through them in reverse order.
1085
		RC_STRING *rlevel;
1086
		TAILQ_FOREACH_REVERSE(rlevel, runlevel_chain, rc_stringlist, entries)
1087
		{
1088
			// Get a list of all the services in that runlevel
1089
			RC_STRINGLIST *run_services = rc_services_in_runlevel(rlevel->value);
1090
1091
			// Start those services.
1092
			rc_stringlist_sort(&run_services);
1093
			deporder = rc_deptree_depends(deptree, types_nua, run_services, rlevel->value, depoptions | RC_DEP_START);
1094
			rc_stringlist_free(run_services);
1095
			run_services = deporder;
1096
			do_start_services(run_services, parallel);
1086
1097
1087
		/* Wait for our services to finish */
1098
			/* Wait for our services to finish */
1088
		wait_for_services();
1099
			wait_for_services();
1100
1101
			// Free the list of services, we're done with it.
1102
			rc_stringlist_free(run_services);
1103
		}
1104
		rc_stringlist_free(runlevel_chain);
1089
	}
1105
	}
1090
1106
1091
#ifdef __linux__
1107
#ifdef __linux__
1092
	/* mark any services skipped as stopped */
1108
	/* If the "noinit" parameter was passed on the kernel command line then
1109
	 * mark the specified services as stopped so that our records reflect
1110
	 * reality.	 */
1093
	proc = p = rc_proc_getent("noinit");
1111
	proc = p = rc_proc_getent("noinit");
1094
	if (proc) {
1112
	if (proc) {
1095
		while ((token = strsep(&p, ",")))
1113
		while ((token = strsep(&p, ",")))
(-)openrc-0.11.8.orig/src/rc/rc-status.c (-30 / +37 lines)
Lines 171-176 Link Here
171
	rc_stringlist_free(l);
171
	rc_stringlist_free(l);
172
}
172
}
173
173
174
static void
175
print_stacked_services(const char *runlevel)
176
{
177
	RC_STRINGLIST *stackedlevels, *servicelist;
178
	RC_STRING *stackedlevel;
179
180
	stackedlevels = rc_runlevel_stacks(runlevel);
181
	TAILQ_FOREACH(stackedlevel, stackedlevels, entries) {
182
		if (rc_stringlist_find(levels, stackedlevel->value) != NULL)
183
			continue;
184
		print_level("Stacked", stackedlevel->value);
185
		servicelist = rc_services_in_runlevel(stackedlevel->value);
186
		print_services(stackedlevel->value, servicelist);
187
		rc_stringlist_free(servicelist);
188
		print_stacked_services(stackedlevel->value);
189
	}
190
	rc_stringlist_free(stackedlevels);
191
	stackedlevels = NULL;
192
}
193
174
#include "_usage.h"
194
#include "_usage.h"
175
#define extraopts "[runlevel1] [runlevel2] ..."
195
#define extraopts "[runlevel1] [runlevel2] ..."
176
#define getoptstring "aclrsu" getoptstring_COMMON
196
#define getoptstring "aclrsu" getoptstring_COMMON
Lines 197-203 Link Here
197
int
217
int
198
rc_status(int argc, char **argv)
218
rc_status(int argc, char **argv)
199
{
219
{
200
	RC_STRING *s, *l, *t;
220
	RC_STRING *s, *l, *t, *level;
201
	char *p, *runlevel = NULL;
221
	char *p, *runlevel = NULL;
202
	int opt, aflag = 0, retval = 0;
222
	int opt, aflag = 0, retval = 0;
203
223
Lines 278-295 Link Here
278
		print_level(NULL, l->value);
298
		print_level(NULL, l->value);
279
		services = rc_services_in_runlevel(l->value);
299
		services = rc_services_in_runlevel(l->value);
280
		print_services(l->value, services);
300
		print_services(l->value, services);
281
		nservices = rc_runlevel_stacks(l->value);
301
		print_stacked_services(l->value);
282
		TAILQ_FOREACH(s, nservices, entries) {
283
			if (rc_stringlist_find(levels, s->value) != NULL)
284
				continue;
285
			print_level("Stacked", s->value);
286
			sservices = rc_services_in_runlevel(s->value);
287
			print_services(s->value, sservices);
288
			rc_stringlist_free(sservices);
289
		}
290
		sservices = NULL;
291
		rc_stringlist_free(nservices);
292
		nservices = NULL;
293
		rc_stringlist_free(services);
302
		rc_stringlist_free(services);
294
		services = NULL;
303
		services = NULL;
295
	}
304
	}
Lines 315-330 Link Here
315
		services = rc_services_in_runlevel(NULL);
324
		services = rc_services_in_runlevel(NULL);
316
		sservices = rc_stringlist_new();
325
		sservices = rc_stringlist_new();
317
		TAILQ_FOREACH(l, levels, entries) {
326
		TAILQ_FOREACH(l, levels, entries) {
318
			nservices = rc_services_in_runlevel(l->value);
327
			nservices = rc_services_in_runlevel_stacked(l->value);
319
			TAILQ_CONCAT(sservices, nservices, entries);
328
			TAILQ_CONCAT(sservices, nservices, entries);
320
			free(nservices);
329
			free(nservices);
321
		}
330
		}
322
		TAILQ_FOREACH_SAFE(s, services, entries, t) {
331
		TAILQ_FOREACH_SAFE(s, services, entries, t) {
323
			if (rc_stringlist_find(sservices, s->value) ||
332
			if ((rc_stringlist_find(sservices, s->value) ||
324
			    rc_service_state(s->value) &
333
			    (rc_service_state(s->value) & (RC_SERVICE_STOPPED | RC_SERVICE_HOTPLUGGED)))) {
325
			    (RC_SERVICE_STOPPED | RC_SERVICE_HOTPLUGGED))
334
				TAILQ_REMOVE(services, s, entries);
326
		{
327
			TAILQ_REMOVE(services, s, entries);
328
				free(s->value);
335
				free(s->value);
329
				free(s);
336
				free(s);
330
			}
337
			}
Lines 335-354 Link Here
335
		alist = rc_stringlist_new();
342
		alist = rc_stringlist_new();
336
		l = rc_stringlist_add(alist, "");
343
		l = rc_stringlist_add(alist, "");
337
		p = l->value;
344
		p = l->value;
338
		if (!runlevel)
345
		TAILQ_FOREACH(level, levels, entries) {
339
			runlevel = rc_runlevel_get();
346
			TAILQ_FOREACH_SAFE(s, services, entries, t) {
340
		TAILQ_FOREACH_SAFE(s, services, entries, t) {
347
				l->value = s->value;
341
			l->value = s->value;
348
				setenv("RC_SVCNAME", l->value, 1);
342
			unsetenv("RC_SVCNAME");
349
				tmp = rc_deptree_depends(deptree, needsme, alist, level->value, RC_DEP_TRACE);
343
			setenv("RC_SVCNAME", l->value, 1);
350
				if (TAILQ_FIRST(tmp)) {
344
			tmp = rc_deptree_depends(deptree, needsme, alist, runlevel, RC_DEP_TRACE);
351
					TAILQ_REMOVE(services, s, entries);
345
			if (TAILQ_FIRST(tmp)) {
352
					TAILQ_INSERT_TAIL(nservices, s, entries);
346
				TAILQ_REMOVE(services, s, entries);
353
				}
347
				TAILQ_INSERT_TAIL(nservices, s, entries);
354
				rc_stringlist_free(tmp);
348
			}
355
			}
349
			rc_stringlist_free(tmp);
350
		}
356
		}
351
		l->value = p;
357
		l->value = p;
358
		unsetenv("RC_SVCNAME");
352
		print_level("Dynamic", "needed");
359
		print_level("Dynamic", "needed");
353
		print_services(NULL, nservices);
360
		print_services(NULL, nservices);
354
		print_level("Dynamic", "manual");
361
		print_level("Dynamic", "manual");

Return to bug 426948