/[baselayout]/trunk/src/rc.c
Gentoo

Diff of /trunk/src/rc.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

Revision 2572 Revision 2577
44#define INTERACTIVE RC_SVCDIR "interactive" 44#define INTERACTIVE RC_SVCDIR "interactive"
45 45
46#define DEVBOOT "/dev/.rcboot" 46#define DEVBOOT "/dev/.rcboot"
47 47
48/* Cleanup anything in main */ 48/* Cleanup anything in main */
49#define CHAR_FREE(_item) \ 49#define CHAR_FREE(_item) if (_item) { \
50 if (_item) \
51{ \
52 free (_item); \ 50 free (_item); \
53 _item = NULL; \ 51 _item = NULL; \
54} 52}
55 53
56extern char **environ; 54extern char **environ;
57 55
58static char *applet = NULL; 56static char *applet = NULL;
69 67
70struct termios *termios_orig; 68struct termios *termios_orig;
71 69
72static void cleanup (void) 70static void cleanup (void)
73{ 71{
74 rc_plugin_unload (); 72 rc_plugin_unload ();
75 73
76 if (termios_orig) 74 if (termios_orig) {
77 {
78 tcsetattr (STDIN_FILENO, TCSANOW, termios_orig); 75 tcsetattr (STDIN_FILENO, TCSANOW, termios_orig);
79 free (termios_orig); 76 free (termios_orig);
80 } 77 }
81 78
82 if (env) 79 if (env)
83 rc_strlist_free (env); 80 rc_strlist_free (env);
84 if (newenv) 81 if (newenv)
85 rc_strlist_free (newenv); 82 rc_strlist_free (newenv);
86 if (coldplugged_services) 83 if (coldplugged_services)
87 rc_strlist_free (coldplugged_services); 84 rc_strlist_free (coldplugged_services);
88 if (stop_services) 85 if (stop_services)
89 rc_strlist_free (stop_services); 86 rc_strlist_free (stop_services);
90 if (start_services) 87 if (start_services)
91 rc_strlist_free (start_services); 88 rc_strlist_free (start_services);
92 if (deptree) 89 if (deptree)
93 rc_free_deptree (deptree); 90 rc_free_deptree (deptree);
94 if (types) 91 if (types)
95 rc_strlist_free (types); 92 rc_strlist_free (types);
96 if (mycmd) 93 if (mycmd)
97 free (mycmd); 94 free (mycmd);
98 if (myarg) 95 if (myarg)
99 free (myarg); 96 free (myarg);
100 97
101 /* Clean runlevel start, stop markers */ 98 /* Clean runlevel start, stop markers */
102 if (rc_is_dir (RC_SVCDIR "softscripts.new")) 99 if (rc_is_dir (RC_SVCDIR "softscripts.new"))
103 rc_rm_dir (RC_SVCDIR "softscripts.new", true); 100 rc_rm_dir (RC_SVCDIR "softscripts.new", true);
104 if (rc_is_dir (RC_SVCDIR "softscripts.old")) 101 if (rc_is_dir (RC_SVCDIR "softscripts.old"))
105 rc_rm_dir (RC_SVCDIR "softscripts.old", true); 102 rc_rm_dir (RC_SVCDIR "softscripts.old", true);
106 103
107 if (applet) 104 if (applet)
108 free (applet); 105 free (applet);
109} 106}
110 107
111static int do_e (int argc, char **argv) 108static int do_e (int argc, char **argv)
112{ 109{
113 int retval = EXIT_SUCCESS; 110 int retval = EXIT_SUCCESS;
114 int i; 111 int i;
115 int l = 0; 112 int l = 0;
116 char *message = NULL; 113 char *message = NULL;
117 char *p; 114 char *p;
118 char *fmt = NULL; 115 char *fmt = NULL;
119 116
120 if (strcmp (applet, "eend") == 0 || 117 if (strcmp (applet, "eend") == 0 ||
121 strcmp (applet, "ewend") == 0 || 118 strcmp (applet, "ewend") == 0 ||
122 strcmp (applet, "veend") == 0 || 119 strcmp (applet, "veend") == 0 ||
123 strcmp (applet, "vweend") == 0) 120 strcmp (applet, "vweend") == 0)
124 { 121 {
125 if (argc > 0) 122 if (argc > 0) {
126 { 123 errno = 0;
127 errno = 0;
128 retval = strtol (argv[0], NULL, 0); 124 retval = strtol (argv[0], NULL, 0);
129 if (errno != 0) 125 if (errno != 0)
130 retval = EXIT_FAILURE; 126 retval = EXIT_FAILURE;
131 else 127 else {
132 { 128 argc--;
133 argc--; 129 argv++;
134 argv++; 130 }
135 } 131 }
136 } 132 else
137 else
138 retval = EXIT_FAILURE; 133 retval = EXIT_FAILURE;
139 } 134 }
140 135
141 if (argc > 0) 136 if (argc > 0) {
142 {
143 for (i = 0; i < argc; i++) 137 for (i = 0; i < argc; i++)
144 l += strlen (argv[i]) + 1; 138 l += strlen (argv[i]) + 1;
145 139
146 message = rc_xmalloc (l); 140 message = rc_xmalloc (l);
147 p = message; 141 p = message;
148 142
149 for (i = 0; i < argc; i++) 143 for (i = 0; i < argc; i++) {
150 { 144 if (i > 0)
151 if (i > 0) 145 *p++ = ' ';
152 *p++ = ' ';
153 memcpy (p, argv[i], strlen (argv[i])); 146 memcpy (p, argv[i], strlen (argv[i]));
154 p += strlen (argv[i]); 147 p += strlen (argv[i]);
155 } 148 }
156 *p = 0; 149 *p = 0;
157 } 150 }
158 151
159 if (message) 152 if (message)
160 fmt = strdup ("%s"); 153 fmt = strdup ("%s");
161 154
162 if (strcmp (applet, "einfo") == 0) 155 if (strcmp (applet, "einfo") == 0)
163 einfo (fmt, message); 156 einfo (fmt, message);
164 else if (strcmp (applet, "einfon") == 0) 157 else if (strcmp (applet, "einfon") == 0)
165 einfon (fmt, message); 158 einfon (fmt, message);
166 else if (strcmp (applet, "ewarn") == 0) 159 else if (strcmp (applet, "ewarn") == 0)
167 ewarn (fmt, message); 160 ewarn (fmt, message);
168 else if (strcmp (applet, "ewarnn") == 0) 161 else if (strcmp (applet, "ewarnn") == 0)
169 ewarnn (fmt, message); 162 ewarnn (fmt, message);
170 else if (strcmp (applet, "eerror") == 0) 163 else if (strcmp (applet, "eerror") == 0) {
171 {
172 eerror (fmt, message); 164 eerror (fmt, message);
173 retval = 1; 165 retval = 1;
174 }
175 else if (strcmp (applet, "eerrorn") == 0) 166 } else if (strcmp (applet, "eerrorn") == 0) {
176 {
177 eerrorn (fmt, message); 167 eerrorn (fmt, message);
178 retval = 1; 168 retval = 1;
179 }
180 else if (strcmp (applet, "ebegin") == 0) 169 } else if (strcmp (applet, "ebegin") == 0)
181 ebegin (fmt, message); 170 ebegin (fmt, message);
182 else if (strcmp (applet, "eend") == 0) 171 else if (strcmp (applet, "eend") == 0)
183 eend (retval, fmt, message); 172 eend (retval, fmt, message);
184 else if (strcmp (applet, "ewend") == 0) 173 else if (strcmp (applet, "ewend") == 0)
185 ewend (retval, fmt, message); 174 ewend (retval, fmt, message);
186 else if (strcmp (applet, "veinfo") == 0) 175 else if (strcmp (applet, "veinfo") == 0)
187 einfov (fmt, message); 176 einfov (fmt, message);
188 else if (strcmp (applet, "veinfon") == 0) 177 else if (strcmp (applet, "veinfon") == 0)
189 einfovn (fmt, message); 178 einfovn (fmt, message);
190 else if (strcmp (applet, "vewarn") == 0) 179 else if (strcmp (applet, "vewarn") == 0)
191 ewarnv (fmt, message); 180 ewarnv (fmt, message);
192 else if (strcmp (applet, "vewarnn") == 0) 181 else if (strcmp (applet, "vewarnn") == 0)
193 ewarnvn (fmt, message); 182 ewarnvn (fmt, message);
194 else if (strcmp (applet, "vebegin") == 0) 183 else if (strcmp (applet, "vebegin") == 0)
195 ebeginv (fmt, message); 184 ebeginv (fmt, message);
196 else if (strcmp (applet, "veend") == 0) 185 else if (strcmp (applet, "veend") == 0)
197 eendv (retval, fmt, message); 186 eendv (retval, fmt, message);
198 else if (strcmp (applet, "vewend") == 0) 187 else if (strcmp (applet, "vewend") == 0)
199 ewendv (retval, fmt, message); 188 ewendv (retval, fmt, message);
200 else if (strcmp (applet, "eindent") == 0) 189 else if (strcmp (applet, "eindent") == 0)
201 eindent (); 190 eindent ();
202 else if (strcmp (applet, "eoutdent") == 0) 191 else if (strcmp (applet, "eoutdent") == 0)
203 eoutdent (); 192 eoutdent ();
204 else if (strcmp (applet, "veindent") == 0) 193 else if (strcmp (applet, "veindent") == 0)
205 eindentv (); 194 eindentv ();
206 else if (strcmp (applet, "veoutdent") == 0) 195 else if (strcmp (applet, "veoutdent") == 0)
207 eoutdentv (); 196 eoutdentv ();
208 else if (strcmp (applet, "eflush") == 0) 197 else if (strcmp (applet, "eflush") == 0)
209 eflush (); 198 eflush ();
210 else 199 else {
211 {
212 eerror ("%s: unknown applet", applet); 200 eerror ("%s: unknown applet", applet);
213 retval = EXIT_FAILURE; 201 retval = EXIT_FAILURE;
214 } 202 }
215 203
216 if (fmt) 204 if (fmt)
217 free (fmt); 205 free (fmt);
218 if (message) 206 if (message)
219 free (message); 207 free (message);
220 return (retval); 208 return (retval);
221} 209}
222 210
223static int do_service (int argc, char **argv) 211static int do_service (int argc, char **argv)
224{ 212{
225 bool ok = false; 213 bool ok = false;
226 214
227 if (argc < 1 || ! argv[0] || strlen (argv[0]) == 0) 215 if (argc < 1 || ! argv[0] || strlen (argv[0]) == 0)
228 eerrorx ("%s: no service specified", applet); 216 eerrorx ("%s: no service specified", applet);
229 217
230 if (strcmp (applet, "service_started") == 0) 218 if (strcmp (applet, "service_started") == 0)
231 ok = rc_service_state (argv[0], rc_service_started); 219 ok = rc_service_state (argv[0], rc_service_started);
232 else if (strcmp (applet, "service_stopped") == 0) 220 else if (strcmp (applet, "service_stopped") == 0)
233 ok = rc_service_state (argv[0], rc_service_stopped); 221 ok = rc_service_state (argv[0], rc_service_stopped);
234 else if (strcmp (applet, "service_inactive") == 0) 222 else if (strcmp (applet, "service_inactive") == 0)
235 ok = rc_service_state (argv[0], rc_service_inactive); 223 ok = rc_service_state (argv[0], rc_service_inactive);
236 else if (strcmp (applet, "service_starting") == 0) 224 else if (strcmp (applet, "service_starting") == 0)
237 ok = rc_service_state (argv[0], rc_service_starting); 225 ok = rc_service_state (argv[0], rc_service_starting);
238 else if (strcmp (applet, "service_stopping") == 0) 226 else if (strcmp (applet, "service_stopping") == 0)
239 ok = rc_service_state (argv[0], rc_service_stopping); 227 ok = rc_service_state (argv[0], rc_service_stopping);
240 else if (strcmp (applet, "service_coldplugged") == 0) 228 else if (strcmp (applet, "service_coldplugged") == 0)
241 ok = rc_service_state (argv[0], rc_service_coldplugged); 229 ok = rc_service_state (argv[0], rc_service_coldplugged);
242 else if (strcmp (applet, "service_wasinactive") == 0) 230 else if (strcmp (applet, "service_wasinactive") == 0)
243 ok = rc_service_state (argv[0], rc_service_wasinactive); 231 ok = rc_service_state (argv[0], rc_service_wasinactive);
244 else if (strcmp (applet, "service_started_daemon") == 0) 232 else if (strcmp (applet, "service_started_daemon") == 0) {
245 {
246 int idx = 0; 233 int idx = 0;
247 if (argc > 2) 234 if (argc > 2)
248 sscanf (argv[2], "%d", &idx); 235 sscanf (argv[2], "%d", &idx);
249 exit (rc_service_started_daemon (argv[0], argv[1], idx) 236 exit (rc_service_started_daemon (argv[0], argv[1], idx)
250 ? 0 : 1); 237 ? 0 : 1);
251 }
252 else 238 } else
253 eerrorx ("%s: unknown applet", applet); 239 eerrorx ("%s: unknown applet", applet);
254 240
255 return (ok ? EXIT_SUCCESS : EXIT_FAILURE); 241 return (ok ? EXIT_SUCCESS : EXIT_FAILURE);
256} 242}
257 243
258static int do_mark_service (int argc, char **argv) 244static int do_mark_service (int argc, char **argv)
259{ 245{
260 bool ok = false; 246 bool ok = false;
261 char *svcname = getenv ("SVCNAME"); 247 char *svcname = getenv ("SVCNAME");
262 248
263 if (argc < 1 || ! argv[0] || strlen (argv[0]) == 0) 249 if (argc < 1 || ! argv[0] || strlen (argv[0]) == 0)
264 eerrorx ("%s: no service specified", applet); 250 eerrorx ("%s: no service specified", applet);
265 251
266 if (strcmp (applet, "mark_service_started") == 0) 252 if (strcmp (applet, "mark_service_started") == 0)
267 ok = rc_mark_service (argv[0], rc_service_started); 253 ok = rc_mark_service (argv[0], rc_service_started);
268 else if (strcmp (applet, "mark_service_stopped") == 0) 254 else if (strcmp (applet, "mark_service_stopped") == 0)
269 ok = rc_mark_service (argv[0], rc_service_stopped); 255 ok = rc_mark_service (argv[0], rc_service_stopped);
270 else if (strcmp (applet, "mark_service_inactive") == 0) 256 else if (strcmp (applet, "mark_service_inactive") == 0)
271 ok = rc_mark_service (argv[0], rc_service_inactive); 257 ok = rc_mark_service (argv[0], rc_service_inactive);
272 else if (strcmp (applet, "mark_service_starting") == 0) 258 else if (strcmp (applet, "mark_service_starting") == 0)
273 ok = rc_mark_service (argv[0], rc_service_starting); 259 ok = rc_mark_service (argv[0], rc_service_starting);
274 else if (strcmp (applet, "mark_service_stopping") == 0) 260 else if (strcmp (applet, "mark_service_stopping") == 0)
275 ok = rc_mark_service (argv[0], rc_service_stopping); 261 ok = rc_mark_service (argv[0], rc_service_stopping);
276 else if (strcmp (applet, "mark_service_coldplugged") == 0) 262 else if (strcmp (applet, "mark_service_coldplugged") == 0)
277 ok = rc_mark_service (argv[0], rc_service_coldplugged); 263 ok = rc_mark_service (argv[0], rc_service_coldplugged);
278 else 264 else
279 eerrorx ("%s: unknown applet", applet); 265 eerrorx ("%s: unknown applet", applet);
280 266
281 /* If we're marking ourselves then we need to inform our parent runscript 267 /* If we're marking ourselves then we need to inform our parent runscript
282 process so they do not mark us based on our exit code */ 268 process so they do not mark us based on our exit code */
283 if (ok && svcname && strcmp (svcname, argv[0]) == 0) 269 if (ok && svcname && strcmp (svcname, argv[0]) == 0) {
284 {
285 char *runscript_pid = getenv ("RC_RUNSCRIPT_PID"); 270 char *runscript_pid = getenv ("RC_RUNSCRIPT_PID");
286 char *mtime; 271 char *mtime;
287 pid_t pid = 0; 272 pid_t pid = 0;
288 int l; 273 int l;
289 274
290 if (runscript_pid && sscanf (runscript_pid, "%d", &pid) == 1) 275 if (runscript_pid && sscanf (runscript_pid, "%d", &pid) == 1)
291 if (kill (pid, SIGHUP) != 0) 276 if (kill (pid, SIGHUP) != 0)
292 eerror ("%s: failed to signal parent %d: %s", 277 eerror ("%s: failed to signal parent %d: %s",
293 applet, pid, strerror (errno)); 278 applet, pid, strerror (errno));
294 279
295 /* Remove the exclsive time test. This ensures that it's not 280 /* Remove the exclsive time test. This ensures that it's not
296 in control as well */ 281 in control as well */
297 l = strlen (RC_SVCDIR "exclusive") + 282 l = strlen (RC_SVCDIR "exclusive") +
298 strlen (svcname) + 283 strlen (svcname) +
299 strlen (runscript_pid) + 284 strlen (runscript_pid) +
300 4; 285 4;
301 mtime = rc_xmalloc (l); 286 mtime = rc_xmalloc (l);
302 snprintf (mtime, l, RC_SVCDIR "exclusive/%s.%s", 287 snprintf (mtime, l, RC_SVCDIR "exclusive/%s.%s",
303 svcname, runscript_pid); 288 svcname, runscript_pid);
304 if (rc_exists (mtime) && unlink (mtime) != 0) 289 if (rc_exists (mtime) && unlink (mtime) != 0)
305 eerror ("%s: unlink: %s", applet, strerror (errno)); 290 eerror ("%s: unlink: %s", applet, strerror (errno));
306 free (mtime); 291 free (mtime);
307 } 292 }
308 293
309 return (ok ? EXIT_SUCCESS : EXIT_FAILURE); 294 return (ok ? EXIT_SUCCESS : EXIT_FAILURE);
310} 295}
311 296
312static int do_options (int argc, char **argv) 297static int do_options (int argc, char **argv)
313{ 298{
314 bool ok = false; 299 bool ok = false;
315 char *service = getenv ("SVCNAME"); 300 char *service = getenv ("SVCNAME");
316 301
317 if (! service) 302 if (! service)
318 eerrorx ("%s: no service specified", applet); 303 eerrorx ("%s: no service specified", applet);
319 304
320 if (argc < 1 || ! argv[0] || strlen (argv[0]) == 0) 305 if (argc < 1 || ! argv[0] || strlen (argv[0]) == 0)
321 eerrorx ("%s: no option specified", applet); 306 eerrorx ("%s: no option specified", applet);
322 307
323 if (strcmp (applet, "get_options") == 0) 308 if (strcmp (applet, "get_options") == 0) {
324 {
325 char buffer[1024]; 309 char buffer[1024];
326 memset (buffer, 0, 1024); 310 memset (buffer, 0, 1024);
327 ok = rc_get_service_option (service, argv[0], buffer); 311 ok = rc_get_service_option (service, argv[0], buffer);
328 if (ok) 312 if (ok)
329 printf ("%s", buffer); 313 printf ("%s", buffer);
330 }
331 else if (strcmp (applet, "save_options") == 0) 314 } else if (strcmp (applet, "save_options") == 0)
332 ok = rc_set_service_option (service, argv[0], argv[1]); 315 ok = rc_set_service_option (service, argv[0], argv[1]);
333 else 316 else
334 eerrorx ("%s: unknown applet", applet); 317 eerrorx ("%s: unknown applet", applet);
335 318
336 return (ok ? EXIT_SUCCESS : EXIT_FAILURE); 319 return (ok ? EXIT_SUCCESS : EXIT_FAILURE);
337} 320}
338 321
339static char read_key (bool block) 322static char read_key (bool block)
340{ 323{
341 struct termios termios; 324 struct termios termios;
342 char c = 0; 325 char c = 0;
343 326
344 if (! isatty (STDIN_FILENO)) 327 if (! isatty (STDIN_FILENO))
345 return (false); 328 return (false);
346 329
347 /* Now save our terminal settings. We need to restore them at exit as we 330 /* Now save our terminal settings. We need to restore them at exit as we
348 will be changing it for non-blocking reads for Interactive */ 331 will be changing it for non-blocking reads for Interactive */
349 if (! termios_orig) 332 if (! termios_orig) {
350 {
351 termios_orig = rc_xmalloc (sizeof (struct termios)); 333 termios_orig = rc_xmalloc (sizeof (struct termios));
352 tcgetattr (STDIN_FILENO, termios_orig); 334 tcgetattr (STDIN_FILENO, termios_orig);
353 } 335 }
354 336
355 tcgetattr (STDIN_FILENO, &termios); 337 tcgetattr (STDIN_FILENO, &termios);
356 termios.c_lflag &= ~(ICANON | ECHO); 338 termios.c_lflag &= ~(ICANON | ECHO);
357 if (block) 339 if (block)
358 termios.c_cc[VMIN] = 1; 340 termios.c_cc[VMIN] = 1;
359 else 341 else {
360 {
361 termios.c_cc[VMIN] = 0; 342 termios.c_cc[VMIN] = 0;
362 termios.c_cc[VTIME] = 0; 343 termios.c_cc[VTIME] = 0;
363 } 344 }
364 tcsetattr (STDIN_FILENO, TCSANOW, &termios); 345 tcsetattr (STDIN_FILENO, TCSANOW, &termios);
365 346
366 read (STDIN_FILENO, &c, 1); 347 read (STDIN_FILENO, &c, 1);
367 348
368 tcsetattr (STDIN_FILENO, TCSANOW, termios_orig); 349 tcsetattr (STDIN_FILENO, TCSANOW, termios_orig);
369 350
370 return (c); 351 return (c);
371} 352}
372 353
373static bool want_interactive (void) 354static bool want_interactive (void)
374{ 355{
375 char c = read_key (false); 356 char c = read_key (false);
376 return ((c == 'I' || c == 'i') ? true : false); 357 return ((c == 'I' || c == 'i') ? true : false);
377} 358}
378 359
379static void mark_interactive (void) 360static void mark_interactive (void)
380{ 361{
381 FILE *fp = fopen (INTERACTIVE, "w"); 362 FILE *fp = fopen (INTERACTIVE, "w");
382 if (fp) 363 if (fp)
383 fclose (fp); 364 fclose (fp);
384} 365}
385 366
386static void sulogin (bool cont) 367static void sulogin (bool cont)
387{ 368{
388#ifdef __linux__ 369#ifdef __linux__
389 if (cont) 370 if (cont) {
390 {
391 int status = 0; 371 int status = 0;
392 pid_t pid = fork(); 372 pid_t pid = fork();
393 373
394 if (pid == -1) 374 if (pid == -1)
395 eerrorx ("%s: fork: %s", applet, strerror (errno)); 375 eerrorx ("%s: fork: %s", applet, strerror (errno));
396 if (pid == 0) 376 if (pid == 0) {
397 {
398 newenv = rc_filter_env (); 377 newenv = rc_filter_env ();
399 mycmd = rc_xstrdup ("/sbin/sulogin"); 378 mycmd = rc_xstrdup ("/sbin/sulogin");
400 myarg = rc_xstrdup (getenv ("CONSOLE")); 379 myarg = rc_xstrdup (getenv ("CONSOLE"));
401 execle (mycmd, mycmd, myarg, (char *) NULL, newenv); 380 execle (mycmd, mycmd, myarg, (char *) NULL, newenv);
402 eerrorx ("%s: unable to exec `/sbin/sulogin': %s", applet, strerror (errno)); 381 eerrorx ("%s: unable to exec `/sbin/sulogin': %s", applet, strerror (errno));
403 } 382 }
404 waitpid (pid, &status, 0); 383 waitpid (pid, &status, 0);
405 } 384 } else {
406 else
407 {
408
409 newenv = rc_filter_env (); 385 newenv = rc_filter_env ();
410 mycmd = rc_xstrdup ("/sbin/sulogin"); 386 mycmd = rc_xstrdup ("/sbin/sulogin");
411 myarg = rc_xstrdup (getenv ("CONSOLE")); 387 myarg = rc_xstrdup (getenv ("CONSOLE"));
412 execle (mycmd, mycmd, myarg, (char *) NULL, newenv); 388 execle (mycmd, mycmd, myarg, (char *) NULL, newenv);
413 eerrorx ("%s: unable to exec `/sbin/sulogin': %s", applet, strerror (errno)); 389 eerrorx ("%s: unable to exec `/sbin/sulogin': %s", applet, strerror (errno));
414 } 390 }
415#else 391#else
416 /* Appease gcc */ 392 /* Appease gcc */
417 cont = cont; 393 exit (cont ? EXIT_FAILURE : EXIT_SUCCESS);
418 exit (EXIT_SUCCESS);
419#endif 394#endif
420} 395}
421 396
422static void set_ksoftlevel (const char *runlevel) 397static void set_ksoftlevel (const char *runlevel)
423{ 398{
424 FILE *fp; 399 FILE *fp;
425 400
426 if (! runlevel || 401 if (! runlevel ||
427 strcmp (runlevel, RC_LEVEL_BOOT) == 0 || 402 strcmp (runlevel, RC_LEVEL_BOOT) == 0 ||
428 strcmp (runlevel, RC_LEVEL_SINGLE) == 0 || 403 strcmp (runlevel, RC_LEVEL_SINGLE) == 0 ||
429 strcmp (runlevel, RC_LEVEL_SYSINIT) == 0) 404 strcmp (runlevel, RC_LEVEL_SYSINIT) == 0)
430 { 405 {
431 if (rc_exists (RC_SVCDIR "ksoftlevel") && 406 if (rc_exists (RC_SVCDIR "ksoftlevel") &&
432 unlink (RC_SVCDIR "ksoftlevel") != 0) 407 unlink (RC_SVCDIR "ksoftlevel") != 0)
433 eerror ("unlink `%s': %s", RC_SVCDIR "ksoftlevel", strerror (errno)); 408 eerror ("unlink `%s': %s", RC_SVCDIR "ksoftlevel", strerror (errno));
434 return; 409 return;
435 } 410 }
436 411
437 if (! (fp = fopen (RC_SVCDIR "ksoftlevel", "w"))) 412 if (! (fp = fopen (RC_SVCDIR "ksoftlevel", "w"))) {
438 {
439 eerror ("fopen `%s': %s", RC_SVCDIR "ksoftlevel", strerror (errno)); 413 eerror ("fopen `%s': %s", RC_SVCDIR "ksoftlevel", strerror (errno));
440 return; 414 return;
441 } 415 }
442 416
443 fprintf (fp, "%s", runlevel); 417 fprintf (fp, "%s", runlevel);
444 fclose (fp); 418 fclose (fp);
445} 419}
446 420
447static void wait_for_services () 421static void wait_for_services ()
448{ 422{
449 int status = 0; 423 int status = 0;
450 struct timeval tv; 424 struct timeval tv;
451 while (wait (&status) != -1); 425 while (wait (&status) != -1);
452 426
453 /* Wait for a little bit to flush our ebuffer */ 427 /* Wait for a little bit to flush our ebuffer */
454 tv.tv_usec = 50000; 428 tv.tv_usec = 50000;
455 tv.tv_sec = 0; 429 tv.tv_sec = 0;
456 select (0, NULL, NULL, NULL, &tv); 430 select (0, NULL, NULL, NULL, &tv);
457} 431}
458 432
459static void handle_signal (int sig) 433static void handle_signal (int sig)
460{ 434{
461 int serrno = errno; 435 int serrno = errno;
462 char signame[10] = { '\0' }; 436 char signame[10] = { '\0' };
463 437
464 switch (sig) 438 switch (sig) {
465 {
466 case SIGINT: 439 case SIGINT:
467 if (! signame[0]) 440 if (! signame[0])
468 snprintf (signame, sizeof (signame), "SIGINT"); 441 snprintf (signame, sizeof (signame), "SIGINT");
469 case SIGTERM: 442 case SIGTERM:
470 if (! signame[0]) 443 if (! signame[0])
471 snprintf (signame, sizeof (signame), "SIGTERM"); 444 snprintf (signame, sizeof (signame), "SIGTERM");
472 case SIGQUIT: 445 case SIGQUIT:
473 if (! signame[0]) 446 if (! signame[0])
474 snprintf (signame, sizeof (signame), "SIGQUIT"); 447 snprintf (signame, sizeof (signame), "SIGQUIT");
475 eerrorx ("%s: caught %s, aborting", applet, signame); 448 eerrorx ("%s: caught %s, aborting", applet, signame);
476 449
477 default: 450 default:
478 eerror ("%s: caught unknown signal %d", applet, sig); 451 eerror ("%s: caught unknown signal %d", applet, sig);
479 } 452 }
480 453
481 /* Restore errno */ 454 /* Restore errno */
482 errno = serrno; 455 errno = serrno;
483} 456}
484 457
485int main (int argc, char **argv) 458int main (int argc, char **argv)
486{ 459{
487 char *RUNLEVEL = NULL; 460 char *RUNLEVEL = NULL;
488 char *PREVLEVEL = NULL; 461 char *PREVLEVEL = NULL;
489 char *runlevel = NULL; 462 char *runlevel = NULL;
490 char *newlevel = NULL; 463 char *newlevel = NULL;
491 char *service = NULL; 464 char *service = NULL;
492 char **deporder = NULL; 465 char **deporder = NULL;
493 int i = 0; 466 int i = 0;
494 int j = 0; 467 int j = 0;
495 bool going_down = false; 468 bool going_down = false;
496 bool interactive = false; 469 bool interactive = false;
497 int depoptions = RC_DEP_STRICT | RC_DEP_TRACE; 470 int depoptions = RC_DEP_STRICT | RC_DEP_TRACE;
498 char ksoftbuffer [PATH_MAX]; 471 char ksoftbuffer [PATH_MAX];
499 472
500 if (argv[0]) 473 if (argv[0])
501 applet = strdup (basename (argv[0])); 474 applet = strdup (basename (argv[0]));
502 475
503 if (! applet) 476 if (! applet)
504 eerrorx ("arguments required"); 477 eerrorx ("arguments required");
505 478
506 argc--; 479 argc--;
507 argv++; 480 argv++;
508 481
509 /* Handle multicall stuff */ 482 /* Handle multicall stuff */
510 if (applet[0] == 'e' || (applet[0] == 'v' && applet[1] == 'e')) 483 if (applet[0] == 'e' || (applet[0] == 'v' && applet[1] == 'e'))
511 exit (do_e (argc, argv)); 484 exit (do_e (argc, argv));
512 485
513 if (strncmp (applet, "service_", strlen ("service_")) == 0) 486 if (strncmp (applet, "service_", strlen ("service_")) == 0)
514 exit (do_service (argc, argv)); 487 exit (do_service (argc, argv));
515 488
516 if (strcmp (applet, "get_options") == 0 || 489 if (strcmp (applet, "get_options") == 0 ||
517 strcmp (applet, "save_options") == 0) 490 strcmp (applet, "save_options") == 0)
518 exit (do_options (argc, argv)); 491 exit (do_options (argc, argv));
519 492
520 if (strncmp (applet, "mark_service_", strlen ("mark_service_")) == 0) 493 if (strncmp (applet, "mark_service_", strlen ("mark_service_")) == 0)
521 exit (do_mark_service (argc, argv)); 494 exit (do_mark_service (argc, argv));
522 495
523 if (strcmp (applet, "is_runlevel_start") == 0) 496 if (strcmp (applet, "is_runlevel_start") == 0)
524 exit (rc_runlevel_starting () ? 0 : 1); 497 exit (rc_runlevel_starting () ? 0 : 1);
525 else if (strcmp (applet, "is_runlevel_stop") == 0) 498 else if (strcmp (applet, "is_runlevel_stop") == 0)
526 exit (rc_runlevel_stopping () ? 0 : 1); 499 exit (rc_runlevel_stopping () ? 0 : 1);
527 else if (strcmp (applet, "color_terminal") == 0) 500 else if (strcmp (applet, "color_terminal") == 0)
528 exit (colour_terminal () ? 0 : 1); 501 exit (colour_terminal () ? 0 : 1);
529 502
530 if (strcmp (applet, "rc" ) != 0) 503 if (strcmp (applet, "rc" ) != 0)
531 eerrorx ("%s: unknown applet", applet); 504 eerrorx ("%s: unknown applet", applet);
532 505
533 /* OK, so we really are the main RC process 506 /* OK, so we really are the main RC process
534 Only root should be able to run us */ 507 Only root should be able to run us */
535 if (geteuid () != 0) 508 if (geteuid () != 0)
536 eerrorx ("%s: root access required", applet); 509 eerrorx ("%s: root access required", applet);
537 510
538 atexit (cleanup); 511 atexit (cleanup);
539 newlevel = argv[0]; 512 newlevel = argv[0];
540 513
541 /* Setup a signal handler */ 514 /* Setup a signal handler */
542 signal (SIGINT, handle_signal); 515 signal (SIGINT, handle_signal);
543 signal (SIGQUIT, handle_signal); 516 signal (SIGQUIT, handle_signal);
544 signal (SIGTERM, handle_signal); 517 signal (SIGTERM, handle_signal);
545 518
546 /* Ensure our environment is pure 519 /* Ensure our environment is pure
547 Also, add our configuration to it */ 520 Also, add our configuration to it */
548 env = rc_filter_env (); 521 env = rc_filter_env ();
549 env = rc_config_env (env); 522 env = rc_config_env (env);
550 523
551 if (env) 524 if (env) {
552 { 525 char *p;
553 char *p;
554 526
555#ifdef __linux__ 527#ifdef __linux__
556 /* clearenv isn't portable, but there's no harm in using it 528 /* clearenv isn't portable, but there's no harm in using it
557 if we have it */ 529 if we have it */
558 clearenv (); 530 clearenv ();
559#else 531#else
560 char *var; 532 char *var;
561 /* No clearenv present here then. 533 /* No clearenv present here then.
562 We could manipulate environ directly ourselves, but it seems that 534 We could manipulate environ directly ourselves, but it seems that
563 some kernels bitch about this according to the environ man pages 535 some kernels bitch about this according to the environ man pages
564 so we walk though environ and call unsetenv for each value. */ 536 so we walk though environ and call unsetenv for each value. */
565 while (environ[0]) 537 while (environ[0]) {
566 {
567 tmp = rc_xstrdup (environ[0]); 538 tmp = rc_xstrdup (environ[0]);
568 p = tmp; 539 p = tmp;
569 var = strsep (&p, "="); 540 var = strsep (&p, "=");
570 unsetenv (var); 541 unsetenv (var);
571 free (tmp); 542 free (tmp);
572 } 543 }
573 tmp = NULL; 544 tmp = NULL;
574#endif 545#endif
575 546
576 STRLIST_FOREACH (env, p, i) 547 STRLIST_FOREACH (env, p, i)
577 if (strcmp (p, "RC_SOFTLEVEL") != 0 && strcmp (p, "SOFTLEVEL") != 0) 548 if (strcmp (p, "RC_SOFTLEVEL") != 0 && strcmp (p, "SOFTLEVEL") != 0)
578 putenv (p); 549 putenv (p);
579 550
580 /* We don't free our list as that would be null in environ */ 551 /* We don't free our list as that would be null in environ */
581 } 552 }
582 553
583 /* Enable logging */ 554 /* Enable logging */
584 setenv ("RC_ELOG", "rc", 1); 555 setenv ("RC_ELOG", "rc", 1);
585 556
586 interactive = rc_exists (INTERACTIVE); 557 interactive = rc_exists (INTERACTIVE);
587 rc_plugin_load (); 558 rc_plugin_load ();
588 559
589 /* RUNLEVEL is set by sysvinit as is a magic number 560 /* RUNLEVEL is set by sysvinit as is a magic number
590 RC_SOFTLEVEL is set by us and is the name for this magic number 561 RC_SOFTLEVEL is set by us and is the name for this magic number
591 even though all our userland documentation refers to runlevel */ 562 even though all our userland documentation refers to runlevel */
592 RUNLEVEL = getenv ("RUNLEVEL"); 563 RUNLEVEL = getenv ("RUNLEVEL");
593 PREVLEVEL = getenv ("PREVLEVEL"); 564 PREVLEVEL = getenv ("PREVLEVEL");
594 565
595 if (RUNLEVEL && newlevel) 566 if (RUNLEVEL && newlevel) {
596 {
597 if (strcmp (RUNLEVEL, "S") == 0 || strcmp (RUNLEVEL, "1") == 0) 567 if (strcmp (RUNLEVEL, "S") == 0 || strcmp (RUNLEVEL, "1") == 0) {
598 {
599 /* OK, we're either in runlevel 1 or single user mode */ 568 /* OK, we're either in runlevel 1 or single user mode */
600 if (strcmp (newlevel, RC_LEVEL_SYSINIT) == 0) 569 if (strcmp (newlevel, RC_LEVEL_SYSINIT) == 0) {
601 { 570 struct utsname uts;
602 struct utsname uts; 571 pid_t pid;
603 pid_t pid; 572 pid_t wpid;
604 pid_t wpid; 573 int status = 0;
605 int status = 0;
606#ifdef __linux__ 574#ifdef __linux__
607 FILE *fp; 575 FILE *fp;
608#endif 576#endif
609 577
610 uname (&uts); 578 uname (&uts);
611 579
612 printf ("\n"); 580 printf ("\n");
613 PEINFO_GOOD; 581 PEINFO_GOOD;
614 printf (" Gentoo/%s; ", uts.sysname); 582 printf (" Gentoo/%s; ", uts.sysname);
615 PEINFO_BRACKET; 583 PEINFO_BRACKET;
616 printf ("http://www.gentoo.org/"); 584 printf ("http://www.gentoo.org/");
617 PEINFO_NORMAL; 585 PEINFO_NORMAL;
618 printf ("\n Copyright 1999-2007 Gentoo Foundation; " 586 printf ("\n Copyright 1999-2007 Gentoo Foundation; "
619 "Distributed under the GPLv2\n\n"); 587 "Distributed under the GPLv2\n\n");
620 588
621 printf ("Press "); 589 printf ("Press ");
622 PEINFO_GOOD; 590 PEINFO_GOOD;
623 printf ("I"); 591 printf ("I");
624 PEINFO_NORMAL; 592 PEINFO_NORMAL;
625 printf (" to enter interactive boot mode\n\n"); 593 printf (" to enter interactive boot mode\n\n");
626 594
627 setenv ("RC_SOFTLEVEL", newlevel, 1); 595 setenv ("RC_SOFTLEVEL", newlevel, 1);
628 rc_plugin_run (rc_hook_runlevel_start_in, newlevel); 596 rc_plugin_run (rc_hook_runlevel_start_in, newlevel);
629 597
630 if ((pid = fork ()) == -1) 598 if ((pid = fork ()) == -1)
631 eerrorx ("%s: fork: %s", applet, strerror (errno)); 599 eerrorx ("%s: fork: %s", applet, strerror (errno));
632 600
633 if (pid == 0) 601 if (pid == 0) {
634 { 602 mycmd = rc_xstrdup (INITSH);
635 mycmd = rc_xstrdup (INITSH);
636 execl (mycmd, mycmd, (char *) NULL); 603 execl (mycmd, mycmd, (char *) NULL);
637 eerrorx ("%s: unable to exec `" INITSH "': %s", 604 eerrorx ("%s: unable to exec `" INITSH "': %s",
638 applet, strerror (errno)); 605 applet, strerror (errno));
639 } 606 }
640 607
641 do 608 do {
642 { 609 wpid = waitpid (pid, &status, 0);
643 wpid = waitpid (pid, &status, 0); 610 if (wpid < 1)
644 if (wpid < 1)
645 eerror ("waitpid: %s", strerror (errno)); 611 eerror ("waitpid: %s", strerror (errno));
646 } while (! WIFEXITED (status) && ! WIFSIGNALED (status)); 612 } while (! WIFEXITED (status) && ! WIFSIGNALED (status));
647 613
648 if (! WIFEXITED (status) || ! WEXITSTATUS (status) == 0) 614 if (! WIFEXITED (status) || ! WEXITSTATUS (status) == 0)
649 exit (EXIT_FAILURE); 615 exit (EXIT_FAILURE);
650 616
651 /* If we requested a softlevel, save it now */ 617 /* If we requested a softlevel, save it now */
652#ifdef __linux__ 618#ifdef __linux__
653 set_ksoftlevel (NULL); 619 set_ksoftlevel (NULL);
654 620
655 if ((fp = fopen ("/proc/cmdline", "r"))) 621 if ((fp = fopen ("/proc/cmdline", "r"))) {
656 { 622 char buffer[RC_LINEBUFFER];
657 char buffer[RC_LINEBUFFER]; 623 char *soft;
658 char *soft;
659 624
660 memset (buffer, 0, sizeof (buffer)); 625 memset (buffer, 0, sizeof (buffer));
661 if (fgets (buffer, RC_LINEBUFFER, fp) && 626 if (fgets (buffer, RC_LINEBUFFER, fp) &&
662 (soft = strstr (buffer, "softlevel="))) 627 (soft = strstr (buffer, "softlevel=")))
663 { 628 {
664 i = soft - buffer; 629 i = soft - buffer;
665 if (i == 0 || buffer[i - 1] == ' ') 630 if (i == 0 || buffer[i - 1] == ' ') {
666 { 631 char *level;
667 char *level;
668 632
669 /* Trim the trailing carriage return if present */ 633 /* Trim the trailing carriage return if present */
670 i = strlen (buffer) - 1; 634 i = strlen (buffer) - 1;
671 if (buffer[i] == '\n') 635 if (buffer[i] == '\n')
672 buffer[i] = 0; 636 buffer[i] = 0;
673 637
674 soft += strlen ("softlevel="); 638 soft += strlen ("softlevel=");
675 level = strsep (&soft, " "); 639 level = strsep (&soft, " ");
676 set_ksoftlevel (level); 640 set_ksoftlevel (level);
677 } 641 }
678 } 642 }
679 fclose (fp); 643 fclose (fp);
680 } 644 }
681#endif 645#endif
682 rc_plugin_run (rc_hook_runlevel_start_out, newlevel); 646 rc_plugin_run (rc_hook_runlevel_start_out, newlevel);
683 647
684 if (want_interactive ()) 648 if (want_interactive ())
685 mark_interactive (); 649 mark_interactive ();
686 650
687 exit (EXIT_SUCCESS); 651 exit (EXIT_SUCCESS);
688 } 652 }
689 653
690#ifdef __linux__ 654#ifdef __linux__
691 /* Parse the inittab file so we can work out the level to telinit */ 655 /* Parse the inittab file so we can work out the level to telinit */
692 if (strcmp (newlevel, RC_LEVEL_BOOT) != 0 && 656 if (strcmp (newlevel, RC_LEVEL_BOOT) != 0 &&
693 strcmp (newlevel, RC_LEVEL_SINGLE) != 0) 657 strcmp (newlevel, RC_LEVEL_SINGLE) != 0)
694 { 658 {
695 char **inittab = rc_get_list (NULL, "/etc/inittab"); 659 char **inittab = rc_get_list (NULL, "/etc/inittab");
696 char *line; 660 char *line;
697 char *p; 661 char *p;
698 char *token; 662 char *token;
699 char lvl[2] = {0, 0}; 663 char lvl[2] = {0, 0};
700 664
701 STRLIST_FOREACH (inittab, line, i) 665 STRLIST_FOREACH (inittab, line, i) {
702 { 666 p = line;
703 p = line; 667 token = strsep (&p, ":");
704 token = strsep (&p, ":"); 668 if (! token || token[0] != 'l')
705 if (! token || token[0] != 'l') 669 continue;
706 continue;
707 670
708 if ((token = strsep (&p, ":")) == NULL) 671 if ((token = strsep (&p, ":")) == NULL)
709 continue; 672 continue;
710 673
711 /* Snag the level */ 674 /* Snag the level */
712 lvl[0] = token[0]; 675 lvl[0] = token[0];
713 676
714 /* The name is spaced after this */ 677 /* The name is spaced after this */
715 if ((token = strsep (&p, " ")) == NULL) 678 if ((token = strsep (&p, " ")) == NULL)
716 continue; 679 continue;
717 680
718 if ((token = strsep (&p, " ")) == NULL) 681 if ((token = strsep (&p, " ")) == NULL)
719 continue; 682 continue;
720 683
721 if (strcmp (token, newlevel) == 0) 684 if (strcmp (token, newlevel) == 0)
722 break; 685 break;
723 } 686 }
724 rc_strlist_free (inittab); 687 rc_strlist_free (inittab);
725 688
726 /* We have a level, so telinit into it */ 689 /* We have a level, so telinit into it */
727 if (lvl[0] == 0) 690 if (lvl[0] == 0) {
728 {
729 eerrorx ("%s: couldn't find a runlevel called `%s'", 691 eerrorx ("%s: couldn't find a runlevel called `%s'",
730 applet, newlevel); 692 applet, newlevel);
731 } 693 } else {
732 else
733 {
734 mycmd = rc_xstrdup ("/sbin/telinit"); 694 mycmd = rc_xstrdup ("/sbin/telinit");
735 myarg = rc_xstrdup (lvl); 695 myarg = rc_xstrdup (lvl);
736 execl (mycmd, mycmd, myarg, (char *) NULL); 696 execl (mycmd, mycmd, myarg, (char *) NULL);
737 eerrorx ("%s: unable to exec `/sbin/telinit': %s", 697 eerrorx ("%s: unable to exec `/sbin/telinit': %s",
738 applet, strerror (errno)); 698 applet, strerror (errno));
739 } 699 }
740 } 700 }
741#endif 701#endif
742 } 702 }
743 } 703 }
744 704
745 /* Check we're in the runlevel requested, ie from 705 /* Check we're in the runlevel requested, ie from
746 rc single 706 rc single
747 rc shutdown 707 rc shutdown
748 rc reboot 708 rc reboot
749 */ 709 */
750 if (newlevel) 710 if (newlevel) {
751 { 711 if (myarg) {
752 if (myarg) 712 free (myarg);
753 { 713 myarg = NULL;
754 free (myarg); 714 }
755 myarg = NULL;
756 }
757 715
758 if (strcmp (newlevel, RC_LEVEL_SINGLE) == 0) 716 if (strcmp (newlevel, RC_LEVEL_SINGLE) == 0) {
759 { 717 if (! RUNLEVEL ||
760 if (! RUNLEVEL ||
761 (strcmp (RUNLEVEL, "S") != 0 && 718 (strcmp (RUNLEVEL, "S") != 0 &&
762 strcmp (RUNLEVEL, "1") != 0)) 719 strcmp (RUNLEVEL, "1") != 0))
763 { 720 {
764 /* Remember the current runlevel for when we come back */ 721 /* Remember the current runlevel for when we come back */
765 set_ksoftlevel (runlevel); 722 set_ksoftlevel (runlevel);
766#ifdef __linux__ 723#ifdef __linux__
767 mycmd = rc_xstrdup ("/sbin/telinit"); 724 mycmd = rc_xstrdup ("/sbin/telinit");
768 myarg = rc_xstrdup ("S"); 725 myarg = rc_xstrdup ("S");
769 execl (mycmd, mycmd, myarg, (char *) NULL); 726 execl (mycmd, mycmd, myarg, (char *) NULL);
770 eerrorx ("%s: unable to exec `/%s': %s", 727 eerrorx ("%s: unable to exec `/%s': %s",
771 mycmd, applet, strerror (errno)); 728 mycmd, applet, strerror (errno));
772#else 729#else
773 if (kill (1, SIGTERM) != 0) 730 if (kill (1, SIGTERM) != 0)
774 eerrorx ("%s: unable to send SIGTERM to init (pid 1): %s", 731 eerrorx ("%s: unable to send SIGTERM to init (pid 1): %s",
775 applet, strerror (errno)); 732 applet, strerror (errno));
776 exit (EXIT_SUCCESS); 733 exit (EXIT_SUCCESS);
777#endif 734#endif
778 } 735 }
779 }
780 else if (strcmp (newlevel, RC_LEVEL_REBOOT) == 0) 736 } else if (strcmp (newlevel, RC_LEVEL_REBOOT) == 0) {
781 { 737 if (! RUNLEVEL ||
782 if (! RUNLEVEL ||
783 strcmp (RUNLEVEL, "6") != 0) 738 strcmp (RUNLEVEL, "6") != 0)
784 { 739 {
785 mycmd = rc_xstrdup ("/sbin/shutdown"); 740 mycmd = rc_xstrdup ("/sbin/shutdown");
786 myarg = rc_xstrdup ("-r"); 741 myarg = rc_xstrdup ("-r");
787 tmp = rc_xstrdup ("now"); 742 tmp = rc_xstrdup ("now");
788 execl (mycmd, mycmd, myarg, tmp, (char *) NULL); 743 execl (mycmd, mycmd, myarg, tmp, (char *) NULL);
789 eerrorx ("%s: unable to exec `%s': %s", 744 eerrorx ("%s: unable to exec `%s': %s",
790 mycmd, applet, strerror (errno)); 745 mycmd, applet, strerror (errno));
791 } 746 }
792 }
793 else if (strcmp (newlevel, RC_LEVEL_SHUTDOWN) == 0) 747 } else if (strcmp (newlevel, RC_LEVEL_SHUTDOWN) == 0) {
794 { 748 if (! RUNLEVEL ||
795 if (! RUNLEVEL ||
796 strcmp (RUNLEVEL, "0") != 0) 749 strcmp (RUNLEVEL, "0") != 0)
797 { 750 {
798 mycmd = rc_xstrdup ("/sbin/shutdown"); 751 mycmd = rc_xstrdup ("/sbin/shutdown");
799#ifdef __linux__ 752#ifdef __linux__
800 myarg = rc_xstrdup ("-h"); 753 myarg = rc_xstrdup ("-h");
801#else 754#else
802 myarg = rc_xstrdup ("-p"); 755 myarg = rc_xstrdup ("-p");
803#endif 756#endif
804 tmp = rc_xstrdup ("now"); 757 tmp = rc_xstrdup ("now");
805 execl (mycmd, mycmd, myarg, tmp, (char *) NULL); 758 execl (mycmd, mycmd, myarg, tmp, (char *) NULL);
806 eerrorx ("%s: unable to exec `%s': %s", 759 eerrorx ("%s: unable to exec `%s': %s",
807 mycmd, applet, strerror (errno)); 760 mycmd, applet, strerror (errno));
808 } 761 }
809 } 762 }
810 } 763 }
811 764
812 /* Export our current softlevel */ 765 /* Export our current softlevel */
813 runlevel = rc_get_runlevel (); 766 runlevel = rc_get_runlevel ();
814 767
815 /* If we're in the default runlevel and ksoftlevel exists, we should use 768 /* If we're in the default runlevel and ksoftlevel exists, we should use
816 that instead */ 769 that instead */
817 if (newlevel && 770 if (newlevel &&
818 rc_exists (RC_SVCDIR "ksoftlevel") && 771 rc_exists (RC_SVCDIR "ksoftlevel") &&
819 strcmp (newlevel, RC_LEVEL_DEFAULT) == 0) 772 strcmp (newlevel, RC_LEVEL_DEFAULT) == 0)
820 { 773 {
821 /* We should only use ksoftlevel if we were in single user mode 774 /* We should only use ksoftlevel if we were in single user mode
822 If not, we need to erase ksoftlevel now. */ 775 If not, we need to erase ksoftlevel now. */
823 if (PREVLEVEL && 776 if (PREVLEVEL &&
824 (strcmp (PREVLEVEL, "1") == 0 || 777 (strcmp (PREVLEVEL, "1") == 0 ||
825 strcmp (PREVLEVEL, "S") == 0 || 778 strcmp (PREVLEVEL, "S") == 0 ||
826 strcmp (PREVLEVEL, "N") == 0)) 779 strcmp (PREVLEVEL, "N") == 0))
827 { 780 {
828 FILE *fp; 781 FILE *fp;
829 782
830 if (! (fp = fopen (RC_SVCDIR "ksoftlevel", "r"))) 783 if (! (fp = fopen (RC_SVCDIR "ksoftlevel", "r")))
831 eerror ("fopen `%s': %s", RC_SVCDIR "ksoftlevel", 784 eerror ("fopen `%s': %s", RC_SVCDIR "ksoftlevel",
832 strerror (errno)); 785 strerror (errno));
833 else 786 else {
834 {
835 if (fgets (ksoftbuffer, sizeof (ksoftbuffer), fp)) 787 if (fgets (ksoftbuffer, sizeof (ksoftbuffer), fp)) {
836 { 788 i = strlen (ksoftbuffer) - 1;
837 i = strlen (ksoftbuffer) - 1; 789 if (ksoftbuffer[i] == '\n')
838 if (ksoftbuffer[i] == '\n') 790 ksoftbuffer[i] = 0;
839 ksoftbuffer[i] = 0; 791 newlevel = ksoftbuffer;
840 newlevel = ksoftbuffer; 792 }
841 } 793 fclose (fp);
842 fclose (fp); 794 }
843 } 795 } else
844 }
845 else
846 set_ksoftlevel (NULL); 796 set_ksoftlevel (NULL);
847 } 797 }
848 798
849 if (newlevel && 799 if (newlevel &&
850 (strcmp (newlevel, RC_LEVEL_REBOOT) == 0 || 800 (strcmp (newlevel, RC_LEVEL_REBOOT) == 0 ||
851 strcmp (newlevel, RC_LEVEL_SHUTDOWN) == 0 || 801 strcmp (newlevel, RC_LEVEL_SHUTDOWN) == 0 ||
852 strcmp (newlevel, RC_LEVEL_SINGLE) == 0)) 802 strcmp (newlevel, RC_LEVEL_SINGLE) == 0))
853 { 803 {
854 going_down = true; 804 going_down = true;
855 rc_set_runlevel (newlevel); 805 rc_set_runlevel (newlevel);
856 setenv ("RC_SOFTLEVEL", newlevel, 1); 806 setenv ("RC_SOFTLEVEL", newlevel, 1);
857 rc_plugin_run (rc_hook_runlevel_stop_in, newlevel); 807 rc_plugin_run (rc_hook_runlevel_stop_in, newlevel);
858 } 808 } else {
859 else
860 {
861 rc_plugin_run (rc_hook_runlevel_stop_in, runlevel); 809 rc_plugin_run (rc_hook_runlevel_stop_in, runlevel);
862 } 810 }
863 811
864 /* Check if runlevel is valid if we're changing */ 812 /* Check if runlevel is valid if we're changing */
865 if (newlevel && strcmp (runlevel, newlevel) != 0 && ! going_down) 813 if (newlevel && strcmp (runlevel, newlevel) != 0 && ! going_down) {
866 {
867 tmp = rc_strcatpaths (RC_RUNLEVELDIR, newlevel, (char *) NULL); 814 tmp = rc_strcatpaths (RC_RUNLEVELDIR, newlevel, (char *) NULL);
868 if (! rc_is_dir (tmp)) 815 if (! rc_is_dir (tmp))
869 eerrorx ("%s: is not a valid runlevel", newlevel); 816 eerrorx ("%s: is not a valid runlevel", newlevel);
870 CHAR_FREE (tmp); 817 CHAR_FREE (tmp);
871 } 818 }
872 819
873 /* Load our deptree now */ 820 /* Load our deptree now */
874 if ((deptree = rc_load_deptree ()) == NULL) 821 if ((deptree = rc_load_deptree ()) == NULL)
875 eerrorx ("failed to load deptree"); 822 eerrorx ("failed to load deptree");
876 823
877 /* Clean the failed services state dir now */ 824 /* Clean the failed services state dir now */
878 if (rc_is_dir (RC_SVCDIR "failed")) 825 if (rc_is_dir (RC_SVCDIR "failed"))
879 rc_rm_dir (RC_SVCDIR "failed", false); 826 rc_rm_dir (RC_SVCDIR "failed", false);
880 827
881 mkdir (RC_SVCDIR "/softscripts.new", 0755); 828 mkdir (RC_SVCDIR "/softscripts.new", 0755);
882 829
883#ifdef __linux__ 830#ifdef __linux__
884 /* udev likes to start services before we're ready when it does 831 /* udev likes to start services before we're ready when it does
885 its coldplugging thing. runscript knows when we're not ready so it 832 its coldplugging thing. runscript knows when we're not ready so it
886 stores a list of coldplugged services in DEVBOOT for us to pick up 833 stores a list of coldplugged services in DEVBOOT for us to pick up
887 here when we are ready for them */ 834 here when we are ready for them */
888 if (rc_is_dir (DEVBOOT)) 835 if (rc_is_dir (DEVBOOT)) {
889 {
890 start_services = rc_ls_dir (NULL, DEVBOOT, RC_LS_INITD); 836 start_services = rc_ls_dir (NULL, DEVBOOT, RC_LS_INITD);
891 rc_rm_dir (DEVBOOT, true); 837 rc_rm_dir (DEVBOOT, true);
892 838
893 STRLIST_FOREACH (start_services, service, i) 839 STRLIST_FOREACH (start_services, service, i)
894 if (rc_allow_plug (service)) 840 if (rc_allow_plug (service))
895 rc_mark_service (service, rc_service_coldplugged); 841 rc_mark_service (service, rc_service_coldplugged);
896 /* We need to dump this list now. 842 /* We need to dump this list now.
897 This may seem redunant, but only Linux needs this and saves on 843 This may seem redunant, but only Linux needs this and saves on
898 code bloat. */ 844 code bloat. */
899 rc_strlist_free (start_services); 845 rc_strlist_free (start_services);
900 start_services = NULL; 846 start_services = NULL;
901 } 847 }
902#else 848#else
903 /* BSD's on the other hand populate /dev automagically and use devd. 849 /* BSD's on the other hand populate /dev automagically and use devd.
904 The only downside of this approach and ours is that we have to hard code 850 The only downside of this approach and ours is that we have to hard code
905 the device node to the init script to simulate the coldplug into 851 the device node to the init script to simulate the coldplug into
906 runlevel for our dependency tree to work. */ 852 runlevel for our dependency tree to work. */
907 if (newlevel && strcmp (newlevel, RC_LEVEL_BOOT) == 0 && 853 if (newlevel && strcmp (newlevel, RC_LEVEL_BOOT) == 0 &&
908 (strcmp (runlevel, RC_LEVEL_SINGLE) == 0 || 854 (strcmp (runlevel, RC_LEVEL_SINGLE) == 0 ||
909 strcmp (runlevel, RC_LEVEL_SYSINIT) == 0) && 855 strcmp (runlevel, RC_LEVEL_SYSINIT) == 0) &&
910 rc_is_env ("RC_COLDPLUG", "yes")) 856 rc_is_env ("RC_COLDPLUG", "yes"))
911 { 857 {
912 /* The net interfaces are easy - they're all in net /dev/net :) */ 858 /* The net interfaces are easy - they're all in net /dev/net :) */
913 start_services = rc_ls_dir (NULL, "/dev/net", 0); 859 start_services = rc_ls_dir (NULL, "/dev/net", 0);
914 STRLIST_FOREACH (start_services, service, i) 860 STRLIST_FOREACH (start_services, service, i) {
915 {
916 j = (strlen ("net.") + strlen (service) + 1); 861 j = (strlen ("net.") + strlen (service) + 1);
917 tmp = rc_xmalloc (sizeof (char *) * j); 862 tmp = rc_xmalloc (sizeof (char *) * j);
918 snprintf (tmp, j, "net.%s", service); 863 snprintf (tmp, j, "net.%s", service);
919 if (rc_service_exists (tmp) && rc_allow_plug (tmp)) 864 if (rc_service_exists (tmp) && rc_allow_plug (tmp))
920 rc_mark_service (tmp, rc_service_coldplugged); 865 rc_mark_service (tmp, rc_service_coldplugged);
921 CHAR_FREE (tmp); 866 CHAR_FREE (tmp);
922 } 867 }
923 rc_strlist_free (start_services); 868 rc_strlist_free (start_services);
924 869
925 /* The mice are a little more tricky. 870 /* The mice are a little more tricky.
926 If we coldplug anything else, we'll probably do it here. */ 871 If we coldplug anything else, we'll probably do it here. */
927 start_services = rc_ls_dir (NULL, "/dev", 0); 872 start_services = rc_ls_dir (NULL, "/dev", 0);
928 STRLIST_FOREACH (start_services, service, i) 873 STRLIST_FOREACH (start_services, service, i) {
929 {
930 if (strncmp (service, "psm", 3) == 0 || 874 if (strncmp (service, "psm", 3) == 0 ||
931 strncmp (service, "ums", 3) == 0) 875 strncmp (service, "ums", 3) == 0)
932 { 876 {
933 char *p = service + 3; 877 char *p = service + 3;
934 if (p && isdigit (*p)) 878 if (p && isdigit (*p)) {
935 {
936 j = (strlen ("moused.") + strlen (service) + 1); 879 j = (strlen ("moused.") + strlen (service) + 1);
937 tmp = rc_xmalloc (sizeof (char *) * j); 880 tmp = rc_xmalloc (sizeof (char *) * j);
938 snprintf (tmp, j, "moused.%s", service); 881 snprintf (tmp, j, "moused.%s", service);
939 if (rc_service_exists (tmp) && rc_allow_plug (tmp)) 882 if (rc_service_exists (tmp) && rc_allow_plug (tmp))
940 rc_mark_service (tmp, rc_service_coldplugged); 883 rc_mark_service (tmp, rc_service_coldplugged);
941 CHAR_FREE (tmp); 884 CHAR_FREE (tmp);
942 } 885 }
943 } 886 }
944 } 887 }
945 rc_strlist_free (start_services); 888 rc_strlist_free (start_services);
946 start_services = NULL; 889 start_services = NULL;
947 } 890 }
948#endif 891#endif
949 892
950 /* Build a list of all services to stop and then work out the 893 /* Build a list of all services to stop and then work out the
951 correct order for stopping them */ 894 correct order for stopping them */
952 stop_services = rc_ls_dir (stop_services, RC_SVCDIR_STARTING, RC_LS_INITD); 895 stop_services = rc_ls_dir (stop_services, RC_SVCDIR_STARTING, RC_LS_INITD);
953 stop_services = rc_ls_dir (stop_services, RC_SVCDIR_INACTIVE, RC_LS_INITD); 896 stop_services = rc_ls_dir (stop_services, RC_SVCDIR_INACTIVE, RC_LS_INITD);
954 stop_services = rc_ls_dir (stop_services, RC_SVCDIR_STARTED, RC_LS_INITD); 897 stop_services = rc_ls_dir (stop_services, RC_SVCDIR_STARTED, RC_LS_INITD);
955 898
956 types = rc_strlist_add (NULL, "ineed"); 899 types = rc_strlist_add (NULL, "ineed");
957 types = rc_strlist_add (types, "iuse"); 900 types = rc_strlist_add (types, "iuse");
958 types = rc_strlist_add (types, "iafter"); 901 types = rc_strlist_add (types, "iafter");
959 deporder = rc_get_depends (deptree, types, stop_services, 902 deporder = rc_get_depends (deptree, types, stop_services,
960 runlevel, depoptions); 903 runlevel, depoptions);
961 rc_strlist_free (stop_services); 904 rc_strlist_free (stop_services);
962 rc_strlist_free (types); 905 rc_strlist_free (types);
963 stop_services = deporder; 906 stop_services = deporder;
964 deporder = NULL; 907 deporder = NULL;
965 types = NULL; 908 types = NULL;
966 rc_strlist_reverse (stop_services); 909 rc_strlist_reverse (stop_services);
967 910
968 /* Load our list of coldplugged services */ 911 /* Load our list of coldplugged services */
969 coldplugged_services = rc_ls_dir (coldplugged_services, 912 coldplugged_services = rc_ls_dir (coldplugged_services,
970 RC_SVCDIR_COLDPLUGGED, RC_LS_INITD); 913 RC_SVCDIR_COLDPLUGGED, RC_LS_INITD);
971 914
972 /* Load our start services now. 915 /* Load our start services now.
973 We have different rules dependent on runlevel. */ 916 We have different rules dependent on runlevel. */
974 if (newlevel && strcmp (newlevel, RC_LEVEL_BOOT) == 0) 917 if (newlevel && strcmp (newlevel, RC_LEVEL_BOOT) == 0) {
975 {
976 if (coldplugged_services) 918 if (coldplugged_services) {
977 {
978 einfon ("Device initiated services:"); 919 einfon ("Device initiated services:");
979 STRLIST_FOREACH (coldplugged_services, service, i) 920 STRLIST_FOREACH (coldplugged_services, service, i) {
980 { 921 printf (" %s", service);
981 printf (" %s", service);
982 start_services = rc_strlist_add (start_services, service); 922 start_services = rc_strlist_add (start_services, service);
983 } 923 }
984 printf ("\n"); 924 printf ("\n");
985 } 925 }
986 tmp = rc_strcatpaths (RC_RUNLEVELDIR, newlevel ? newlevel : runlevel, 926 tmp = rc_strcatpaths (RC_RUNLEVELDIR, newlevel ? newlevel : runlevel,
987 (char *) NULL); 927 (char *) NULL);
988 start_services = rc_ls_dir (start_services, tmp, RC_LS_INITD); 928 start_services = rc_ls_dir (start_services, tmp, RC_LS_INITD);
989 CHAR_FREE (tmp); 929 CHAR_FREE (tmp);
990 } 930 } else {
991 else
992 {
993 /* Store our list of coldplugged services */ 931 /* Store our list of coldplugged services */
994 coldplugged_services = rc_ls_dir (coldplugged_services, RC_SVCDIR_COLDPLUGGED, 932 coldplugged_services = rc_ls_dir (coldplugged_services, RC_SVCDIR_COLDPLUGGED,
995 RC_LS_INITD); 933 RC_LS_INITD);
996 if (strcmp (newlevel ? newlevel : runlevel, RC_LEVEL_SINGLE) != 0 && 934 if (strcmp (newlevel ? newlevel : runlevel, RC_LEVEL_SINGLE) != 0 &&
997 strcmp (newlevel ? newlevel : runlevel, RC_LEVEL_SHUTDOWN) != 0 && 935 strcmp (newlevel ? newlevel : runlevel, RC_LEVEL_SHUTDOWN) != 0 &&
998 strcmp (newlevel ? newlevel : runlevel, RC_LEVEL_REBOOT) != 0) 936 strcmp (newlevel ? newlevel : runlevel, RC_LEVEL_REBOOT) != 0)
999 { 937 {
1000 /* We need to include the boot runlevel services if we're not in it */ 938 /* We need to include the boot runlevel services if we're not in it */
1001 start_services = rc_ls_dir (start_services, RC_RUNLEVELDIR RC_LEVEL_BOOT, 939 start_services = rc_ls_dir (start_services, RC_RUNLEVELDIR RC_LEVEL_BOOT,
1002 RC_LS_INITD); 940 RC_LS_INITD);
1003 STRLIST_FOREACH (coldplugged_services, service, i) 941 STRLIST_FOREACH (coldplugged_services, service, i)
1004 start_services = rc_strlist_add (start_services, service); 942 start_services = rc_strlist_add (start_services, service);
1005 943
1006 tmp = rc_strcatpaths (RC_RUNLEVELDIR, 944 tmp = rc_strcatpaths (RC_RUNLEVELDIR,
1007 newlevel ? newlevel : runlevel, (char *) NULL); 945 newlevel ? newlevel : runlevel, (char *) NULL);
1008 start_services = rc_ls_dir (start_services, tmp, RC_LS_INITD); 946 start_services = rc_ls_dir (start_services, tmp, RC_LS_INITD);
1009 CHAR_FREE (tmp); 947 CHAR_FREE (tmp);
1010 } 948 }
1011 } 949 }
1012 950
1013 /* Save out softlevel now */ 951 /* Save out softlevel now */
1014 if (going_down) 952 if (going_down)
1015 rc_set_runlevel (newlevel); 953 rc_set_runlevel (newlevel);
1016 954
1017 types = rc_strlist_add (NULL, "needsme"); 955 types = rc_strlist_add (NULL, "needsme");
1018 types = rc_strlist_add (types, "usesme"); 956 types = rc_strlist_add (types, "usesme");
1019 /* Now stop the services that shouldn't be running */ 957 /* Now stop the services that shouldn't be running */
1020 STRLIST_FOREACH (stop_services, service, i) 958 STRLIST_FOREACH (stop_services, service, i) {
1021 {
1022 bool found = false; 959 bool found = false;
1023 char *conf = NULL; 960 char *conf = NULL;
1024 char **stopdeps = NULL; 961 char **stopdeps = NULL;
1025 char *svc1 = NULL; 962 char *svc1 = NULL;
1026 char *svc2 = NULL; 963 char *svc2 = NULL;
1027 int k; 964 int k;
1028 965
1029 if (rc_service_state (service, rc_service_stopped)) 966 if (rc_service_state (service, rc_service_stopped))
1030 continue; 967 continue;
1031 968
1032 /* We always stop the service when in these runlevels */ 969 /* We always stop the service when in these runlevels */
1033 if (going_down) 970 if (going_down) {
1034 {
1035 rc_stop_service (service); 971 rc_stop_service (service);
1036 continue; 972 continue;
1037 } 973 }
1038 974
1039 /* If we're in the start list then don't bother stopping us */ 975 /* If we're in the start list then don't bother stopping us */
1040 STRLIST_FOREACH (start_services, svc1, j) 976 STRLIST_FOREACH (start_services, svc1, j)
1041 if (strcmp (svc1, service) == 0) 977 if (strcmp (svc1, service) == 0) {
1042 { 978 found = true;
1043 found = true; 979 break;
1044 break; 980 }
1045 }
1046 981
1047 /* Unless we would use a different config file */ 982 /* Unless we would use a different config file */
1048 if (found) 983 if (found) {
1049 { 984 int len;
1050 int len; 985 if (! newlevel)
1051 if (! newlevel) 986 continue;
1052 continue;
1053 987
1054 len = strlen (service) + strlen (runlevel) + 2; 988 len = strlen (service) + strlen (runlevel) + 2;
1055 tmp = rc_xmalloc (sizeof (char *) * len); 989 tmp = rc_xmalloc (sizeof (char *) * len);
1056 snprintf (tmp, len, "%s.%s", service, runlevel); 990 snprintf (tmp, len, "%s.%s", service, runlevel);
1057 conf = rc_strcatpaths (RC_CONFDIR, tmp, (char *) NULL); 991 conf = rc_strcatpaths (RC_CONFDIR, tmp, (char *) NULL);
1058 found = rc_exists (conf); 992 found = rc_exists (conf);
1059 CHAR_FREE (conf); 993 CHAR_FREE (conf);
1060 CHAR_FREE (tmp); 994 CHAR_FREE (tmp);
1061 if (! found) 995 if (! found) {
1062 {
1063 len = strlen (service) + strlen (newlevel) + 2; 996 len = strlen (service) + strlen (newlevel) + 2;
1064 tmp = rc_xmalloc (sizeof (char *) * len); 997 tmp = rc_xmalloc (sizeof (char *) * len);
1065 snprintf (tmp, len, "%s.%s", service, newlevel); 998 snprintf (tmp, len, "%s.%s", service, newlevel);
1066 conf = rc_strcatpaths (RC_CONFDIR, tmp, (char *) NULL); 999 conf = rc_strcatpaths (RC_CONFDIR, tmp, (char *) NULL);
1067 found = rc_exists (conf); 1000 found = rc_exists (conf);
1068 CHAR_FREE (conf); 1001 CHAR_FREE (conf);
1069 CHAR_FREE (tmp); 1002 CHAR_FREE (tmp);
1070 if (!found) 1003 if (!found)
1071 continue; 1004 continue;
1072 } 1005 }
1073 } 1006 } else {
1074 else
1075 /* Allow coldplugged services not to be in the runlevels list */ 1007 /* Allow coldplugged services not to be in the runlevels list */
1076 {
1077 if (rc_service_state (service, rc_service_coldplugged)) 1008 if (rc_service_state (service, rc_service_coldplugged))
1078 continue; 1009 continue;
1079 } 1010 }
1080 1011
1081 /* We got this far! Or last check is to see if any any service that 1012 /* We got this far! Or last check is to see if any any service that
1082 going to be started depends on us */ 1013 going to be started depends on us */
1083 stopdeps = rc_strlist_add (stopdeps, service); 1014 stopdeps = rc_strlist_add (stopdeps, service);
1084 deporder = rc_get_depends (deptree, types, stopdeps, 1015 deporder = rc_get_depends (deptree, types, stopdeps,
1085 runlevel, RC_DEP_STRICT); 1016 runlevel, RC_DEP_STRICT);
1086 rc_strlist_free (stopdeps); 1017 rc_strlist_free (stopdeps);
1087 stopdeps = NULL; 1018 stopdeps = NULL;
1088 found = false; 1019 found = false;
1089 STRLIST_FOREACH (deporder, svc1, j) 1020 STRLIST_FOREACH (deporder, svc1, j) {
1090 {
1091 STRLIST_FOREACH (start_services, svc2, k) 1021 STRLIST_FOREACH (start_services, svc2, k)
1092 if (strcmp (svc1, svc2) == 0) 1022 if (strcmp (svc1, svc2) == 0) {
1093 { 1023 found = true;
1094 found = true; 1024 break;
1095 break; 1025 }
1096 } 1026 if (found)
1097 if (found) 1027 break;
1098 break; 1028 }
1099 }
1100 rc_strlist_free (deporder); 1029 rc_strlist_free (deporder);
1101 deporder = NULL; 1030 deporder = NULL;
1102 1031
1103 /* After all that we can finally stop the blighter! */ 1032 /* After all that we can finally stop the blighter! */
1104 if (! found) 1033 if (! found)
1105 rc_stop_service (service); 1034 rc_stop_service (service);
1106 } 1035 }
1107 rc_strlist_free (types); 1036 rc_strlist_free (types);
1108 types = NULL; 1037 types = NULL;
1109 1038
1110 /* Wait for our services to finish */ 1039 /* Wait for our services to finish */
1111 if (rc_is_env ("RC_PARALLEL_STARTUP", "yes")) 1040 if (rc_is_env ("RC_PARALLEL_STARTUP", "yes"))
1112 wait_for_services (); 1041 wait_for_services ();
1113 1042
1114 /* Notify the plugins we have finished */ 1043 /* Notify the plugins we have finished */
1115 rc_plugin_run (rc_hook_runlevel_stop_out, runlevel); 1044 rc_plugin_run (rc_hook_runlevel_stop_out, runlevel);
1116 1045
1117 rmdir (RC_SVCDIR "/softscripts.new"); 1046 rmdir (RC_SVCDIR "/softscripts.new");
1118 1047
1119 /* Store the new runlevel */ 1048 /* Store the new runlevel */
1120 if (newlevel) 1049 if (newlevel) {
1121 {
1122 rc_set_runlevel (newlevel); 1050 rc_set_runlevel (newlevel);
1123 runlevel = newlevel; 1051 runlevel = newlevel;
1124 setenv ("RC_SOFTLEVEL", runlevel, 1); 1052 setenv ("RC_SOFTLEVEL", runlevel, 1);
1125 } 1053 }
1126 1054
1127 /* Run the halt script if needed */ 1055 /* Run the halt script if needed */
1128 if (strcmp (runlevel, RC_LEVEL_SHUTDOWN) == 0 || 1056 if (strcmp (runlevel, RC_LEVEL_SHUTDOWN) == 0 ||
1129 strcmp (runlevel, RC_LEVEL_REBOOT) == 0) 1057 strcmp (runlevel, RC_LEVEL_REBOOT) == 0)
1130 { 1058 {
1131 mycmd = rc_xstrdup (HALTSH); 1059 mycmd = rc_xstrdup (HALTSH);
1132 myarg = rc_xstrdup (runlevel); 1060 myarg = rc_xstrdup (runlevel);
1133 execl (mycmd, mycmd, myarg, (char *) NULL); 1061 execl (mycmd, mycmd, myarg, (char *) NULL);
1134 eerrorx ("%s: unable to exec `%s': %s", 1062 eerrorx ("%s: unable to exec `%s': %s",
1135 applet, HALTSH, strerror (errno)); 1063 applet, HALTSH, strerror (errno));
1136 } 1064 }
1137 1065
1138 /* Single user is done now */ 1066 /* Single user is done now */
1139 if (strcmp (runlevel, RC_LEVEL_SINGLE) == 0) 1067 if (strcmp (runlevel, RC_LEVEL_SINGLE) == 0) {
1140 {
1141 if (rc_exists (INTERACTIVE)) 1068 if (rc_exists (INTERACTIVE))
1142 unlink (INTERACTIVE); 1069 unlink (INTERACTIVE);
1143 sulogin (false); 1070 sulogin (false);
1144 } 1071 }
1145 1072
1146 mkdir (RC_SVCDIR "softscripts.old", 0755); 1073 mkdir (RC_SVCDIR "softscripts.old", 0755);
1147 rc_plugin_run (rc_hook_runlevel_start_in, runlevel); 1074 rc_plugin_run (rc_hook_runlevel_start_in, runlevel);
1148 1075
1149 /* Re-add our coldplugged services if they stopped */ 1076 /* Re-add our coldplugged services if they stopped */
1150 STRLIST_FOREACH (coldplugged_services, service, i) 1077 STRLIST_FOREACH (coldplugged_services, service, i)
1151 rc_mark_service (service, rc_service_coldplugged); 1078 rc_mark_service (service, rc_service_coldplugged);
1152 1079
1153 /* Order the services to start */ 1080 /* Order the services to start */
1154 types = rc_strlist_add (NULL, "ineed"); 1081 types = rc_strlist_add (NULL, "ineed");
1155 types = rc_strlist_add (types, "iuse"); 1082 types = rc_strlist_add (types, "iuse");
1156 types = rc_strlist_add (types, "iafter"); 1083 types = rc_strlist_add (types, "iafter");
1157 deporder = rc_get_depends (deptree, types, start_services, 1084 deporder = rc_get_depends (deptree, types, start_services,
1158 runlevel, depoptions); 1085 runlevel, depoptions);
1159 rc_strlist_free (types); 1086 rc_strlist_free (types);
1160 types = NULL; 1087 types = NULL;
1161 rc_strlist_free (start_services); 1088 rc_strlist_free (start_services);
1162 start_services = deporder; 1089 start_services = deporder;
1163 deporder = NULL; 1090 deporder = NULL;
1164 1091
1165 STRLIST_FOREACH (start_services, service, i) 1092 STRLIST_FOREACH (start_services, service, i) {
1166 {
1167 if (rc_service_state (service, rc_service_stopped)) 1093 if (rc_service_state (service, rc_service_stopped)) {
1168 { 1094 if (! interactive)
1169 if (! interactive)
1170 interactive = want_interactive (); 1095 interactive = want_interactive ();
1171 1096
1172 if (interactive) 1097 if (interactive) {
1173 {
1174interactive_retry: 1098interactive_retry:
1175 printf ("\n"); 1099 printf ("\n");
1176 einfo ("About to start the service %s", service); 1100 einfo ("About to start the service %s", service);
1177 eindent (); 1101 eindent ();
1178 einfo ("1) Start the service\t\t2) Skip the service"); 1102 einfo ("1) Start the service\t\t2) Skip the service");
1179 einfo ("3) Continue boot process\t\t4) Exit to shell"); 1103 einfo ("3) Continue boot process\t\t4) Exit to shell");
1180 eoutdent (); 1104 eoutdent ();
1181interactive_option: 1105interactive_option:
1182 switch (read_key (true)) 1106 switch (read_key (true)) {
1183 { 1107 case '1': break;
1184 case '1': break; 1108 case '2': continue;
1185 case '2': continue;
1186 case '3': interactive = false; break; 1109 case '3': interactive = false; break;
1187 case '4': sulogin (true); goto interactive_retry; 1110 case '4': sulogin (true); goto interactive_retry;
1188 default: goto interactive_option; 1111 default: goto interactive_option;
1189 } 1112 }
1190 } 1113 }
1191 rc_start_service (service); 1114 rc_start_service (service);
1192 } 1115 }
1193 } 1116 }
1194 1117
1195 /* Wait for our services to finish */ 1118 /* Wait for our services to finish */
1196 if (rc_is_env ("RC_PARALLEL_STARTUP", "yes")) 1119 if (rc_is_env ("RC_PARALLEL_STARTUP", "yes"))
1197 wait_for_services (); 1120 wait_for_services ();
1198 1121
1199 rc_plugin_run (rc_hook_runlevel_start_out, runlevel); 1122 rc_plugin_run (rc_hook_runlevel_start_out, runlevel);
1200 1123
1201 /* Store our interactive status for boot */ 1124 /* Store our interactive status for boot */
1202 if (interactive && strcmp (runlevel, RC_LEVEL_BOOT) == 0) 1125 if (interactive && strcmp (runlevel, RC_LEVEL_BOOT) == 0)
1203 mark_interactive (); 1126 mark_interactive ();
1204 else 1127 else {
1205 {
1206 if (rc_exists (INTERACTIVE)) 1128 if (rc_exists (INTERACTIVE))
1207 unlink (INTERACTIVE); 1129 unlink (INTERACTIVE);
1208 } 1130 }
1209 1131
1210 return (EXIT_SUCCESS); 1132 return (EXIT_SUCCESS);
1211} 1133}
1212 1134

Legend:
Removed from v.2572  
changed lines
  Added in v.2577

  ViewVC Help
Powered by ViewVC 1.1.20