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

Diff of /trunk/src/runscript.c

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

Revision 2573 Revision 2577
63#endif 63#endif
64 64
65#ifdef __linux__ 65#ifdef __linux__
66void setup_selinux (int argc, char **argv) 66void setup_selinux (int argc, char **argv)
67{ 67{
68 void *lib_handle = NULL; 68 void *lib_handle = NULL;
69 69
70 lib_handle = dlopen (SELINUX_LIB, RTLD_NOW | RTLD_GLOBAL); 70 lib_handle = dlopen (SELINUX_LIB, RTLD_NOW | RTLD_GLOBAL);
71 if (lib_handle) 71 if (lib_handle) {
72 {
73 /* FIXME: the below code generates the warning 72 /* FIXME: the below code generates the warning
74 ISO C forbids assignment between function pointer and 'void *' 73 ISO C forbids assignment between function pointer and 'void *'
75 which sucks ass 74 which sucks ass
76http://www.opengroup.org/onlinepubs/009695399/functions/dlsym.html */ 75http://www.opengroup.org/onlinepubs/009695399/functions/dlsym.html */
77 selinux_run_init_old = dlsym (lib_handle, "selinux_runscript"); 76 selinux_run_init_old = dlsym (lib_handle, "selinux_runscript");
78 selinux_run_init_new = dlsym (lib_handle, "selinux_runscript2"); 77 selinux_run_init_new = dlsym (lib_handle, "selinux_runscript2");
79 78
80 /* Use new run_init if it rc_exists, else fall back to old */ 79 /* Use new run_init if it rc_exists, else fall back to old */
81 if (selinux_run_init_new) 80 if (selinux_run_init_new)
82 selinux_run_init_new (argc, argv); 81 selinux_run_init_new (argc, argv);
83 else if (selinux_run_init_old) 82 else if (selinux_run_init_old)
84 selinux_run_init_old (); 83 selinux_run_init_old ();
85 else 84 else
86 /* This shouldnt happen... probably corrupt lib */ 85 /* This shouldnt happen... probably corrupt lib */
87 eerrorx ("run_init is missing from runscript_selinux.so!"); 86 eerrorx ("run_init is missing from runscript_selinux.so!");
88 } 87 }
89} 88}
90#endif 89#endif
91 90
92static void handle_signal (int sig) 91static void handle_signal (int sig)
93{ 92{
94 pid_t pid; 93 pid_t pid;
95 int status; 94 int status;
96 int serrno = errno; 95 int serrno = errno;
97 char signame[10] = { '\0' }; 96 char signame[10] = { '\0' };
98 97
99 switch (sig) 98 switch (sig) {
100 {
101 case SIGHUP: 99 case SIGHUP:
102 sighup = true; 100 sighup = true;
103 break; 101 break;
104 102
105 case SIGCHLD: 103 case SIGCHLD:
106 do 104 do {
107 {
108 pid = waitpid (-1, &status, WNOHANG); 105 pid = waitpid (-1, &status, WNOHANG);
109 if (pid < 0) 106 if (pid < 0) {
110 { 107 if (errno != ECHILD)
111 if (errno != ECHILD)
112 eerror ("waitpid: %s", strerror (errno)); 108 eerror ("waitpid: %s", strerror (errno));
113 return; 109 return;
114 } 110 }
115 } while (! WIFEXITED (status) && ! WIFSIGNALED (status)); 111 } while (! WIFEXITED (status) && ! WIFSIGNALED (status));
116 break; 112 break;
117 113
118 case SIGINT: 114 case SIGINT:
119 if (! signame[0]) 115 if (! signame[0])
120 snprintf (signame, sizeof (signame), "SIGINT"); 116 snprintf (signame, sizeof (signame), "SIGINT");
121 case SIGTERM: 117 case SIGTERM:
122 if (! signame[0]) 118 if (! signame[0])
123 snprintf (signame, sizeof (signame), "SIGTERM"); 119 snprintf (signame, sizeof (signame), "SIGTERM");
124 case SIGQUIT: 120 case SIGQUIT:
125 if (! signame[0]) 121 if (! signame[0])
126 snprintf (signame, sizeof (signame), "SIGQUIT"); 122 snprintf (signame, sizeof (signame), "SIGQUIT");
127 eerrorx ("%s: caught %s, aborting", applet, signame); 123 eerrorx ("%s: caught %s, aborting", applet, signame);
128 124
129 default: 125 default:
130 eerror ("%s: caught unknown signal %d", applet, sig); 126 eerror ("%s: caught unknown signal %d", applet, sig);
131 } 127 }
132 128
133 /* Restore errno */ 129 /* Restore errno */
134 errno = serrno; 130 errno = serrno;
135} 131}
136 132
137static time_t get_mtime (const char *pathname, bool follow_link) 133static time_t get_mtime (const char *pathname, bool follow_link)
138{ 134{
139 struct stat buf; 135 struct stat buf;
140 int retval; 136 int retval;
141 137
142 if (! pathname) 138 if (! pathname)
143 return (0); 139 return (0);
144 140
145 retval = follow_link ? stat (pathname, &buf) : lstat (pathname, &buf); 141 retval = follow_link ? stat (pathname, &buf) : lstat (pathname, &buf);
146 if (! retval) 142 if (! retval)
147 return (buf.st_mtime); 143 return (buf.st_mtime);
148 144
149 errno = 0; 145 errno = 0;
150 return (0); 146 return (0);
151} 147}
152 148
153static bool in_control () 149static bool in_control ()
154{ 150{
155 char *path; 151 char *path;
156 time_t mtime; 152 time_t mtime;
157 const char *tests[] = { "starting", "started", "stopping", 153 const char *tests[] = { "starting", "started", "stopping",
158 "inactive", "wasinactive", NULL }; 154 "inactive", "wasinactive", NULL };
159 int i = 0; 155 int i = 0;
160 156
161 if (sighup) 157 if (sighup)
162 return (false); 158 return (false);
163 159
164 if (! mtime_test || ! rc_exists (mtime_test)) 160 if (! mtime_test || ! rc_exists (mtime_test))
165 return (false); 161 return (false);
166 162
167 if (rc_service_state (applet, rc_service_stopped)) 163 if (rc_service_state (applet, rc_service_stopped))
168 return (false); 164 return (false);
169 165
170 if (! (mtime = get_mtime (mtime_test, false))) 166 if (! (mtime = get_mtime (mtime_test, false)))
171 return (false); 167 return (false);
172 168
173 while (tests[i]) 169 while (tests[i]) {
174 {
175 path = rc_strcatpaths (RC_SVCDIR, tests[i], applet, (char *) NULL); 170 path = rc_strcatpaths (RC_SVCDIR, tests[i], applet, (char *) NULL);
176 if (rc_exists (path)) 171 if (rc_exists (path)) {
177 {
178 time_t m = get_mtime (path, false); 172 time_t m = get_mtime (path, false);
179 if (mtime < m && m != 0) 173 if (mtime < m && m != 0) {
180 { 174 free (path);
181 free (path); 175 return (false);
182 return (false); 176 }
183 } 177 }
184 }
185 free (path); 178 free (path);
186 i++; 179 i++;
187 } 180 }
188 181
189 return (true); 182 return (true);
190} 183}
191 184
192static void uncoldplug (char *service) 185static void uncoldplug (char *service)
193{ 186{
194 char *cold = rc_strcatpaths (RC_SVCDIR "coldplugged", basename (service), 187 char *cold = rc_strcatpaths (RC_SVCDIR "coldplugged", basename (service),
195 (char *) NULL); 188 (char *) NULL);
196 if (rc_exists (cold) && unlink (cold) != 0) 189 if (rc_exists (cold) && unlink (cold) != 0)
197 eerror ("%s: unlink `%s': %s", applet, cold, strerror (errno)); 190 eerror ("%s: unlink `%s': %s", applet, cold, strerror (errno));
198 free (cold); 191 free (cold);
199} 192}
200 193
201static void cleanup (void) 194static void cleanup (void)
202{ 195{
203 /* Flush our buffered output if any */ 196 /* Flush our buffered output if any */
204 eflush (); 197 eflush ();
205 198
206 if (hook_out) 199 if (hook_out)
207 rc_plugin_run (hook_out, applet); 200 rc_plugin_run (hook_out, applet);
208 rc_plugin_unload (); 201 rc_plugin_unload ();
209 202
210 if (deptree) 203 if (deptree)
211 rc_free_deptree (deptree); 204 rc_free_deptree (deptree);
212 if (services) 205 if (services)
213 rc_strlist_free (services); 206 rc_strlist_free (services);
214 if (types) 207 if (types)
215 rc_strlist_free (types); 208 rc_strlist_free (types);
216 if (svclist) 209 if (svclist)
217 rc_strlist_free (svclist); 210 rc_strlist_free (svclist);
218 if (providelist) 211 if (providelist)
219 rc_strlist_free (providelist); 212 rc_strlist_free (providelist);
220 if (restart_services) 213 if (restart_services)
221 rc_strlist_free (restart_services); 214 rc_strlist_free (restart_services);
222 if (need_services) 215 if (need_services)
223 rc_strlist_free (need_services); 216 rc_strlist_free (need_services);
224 if (tmplist) 217 if (tmplist)
225 rc_strlist_free (tmplist); 218 rc_strlist_free (tmplist);
226 if (mycmd) 219 if (mycmd)
227 free (mycmd); 220 free (mycmd);
228 if (myarg1) 221 if (myarg1)
229 free (myarg1); 222 free (myarg1);
230 if (myarg2) 223 if (myarg2)
231 free (myarg2); 224 free (myarg2);
232 if (ibsave) 225 if (ibsave)
233 free (ibsave); 226 free (ibsave);
234 227
235 if (in_control ()) 228 if (in_control ()) {
236 {
237 if (rc_service_state (applet, rc_service_stopping)) 229 if (rc_service_state (applet, rc_service_stopping)) {
238 {
239 /* If the we're shutting down, do it cleanly */ 230 /* If the we're shutting down, do it cleanly */
240 if ((softlevel && 231 if ((softlevel &&
241 rc_runlevel_stopping () && 232 rc_runlevel_stopping () &&
242 (strcmp (softlevel, RC_LEVEL_SHUTDOWN) == 0 || 233 (strcmp (softlevel, RC_LEVEL_SHUTDOWN) == 0 ||
243 strcmp (softlevel, RC_LEVEL_REBOOT) == 0))) 234 strcmp (softlevel, RC_LEVEL_REBOOT) == 0)))
244 rc_mark_service (applet, rc_service_stopped); 235 rc_mark_service (applet, rc_service_stopped);
245 else if (rc_service_state (applet, rc_service_wasinactive)) 236 else if (rc_service_state (applet, rc_service_wasinactive))
246 rc_mark_service (applet, rc_service_inactive); 237 rc_mark_service (applet, rc_service_inactive);
247 else 238 else
248 rc_mark_service (applet, rc_service_started); 239 rc_mark_service (applet, rc_service_started);
249 } 240 }
250 else if (rc_service_state (applet, rc_service_starting)) 241 else if (rc_service_state (applet, rc_service_starting))
251 { 242 {
252 if (rc_service_state (applet, rc_service_wasinactive)) 243 if (rc_service_state (applet, rc_service_wasinactive))
253 rc_mark_service (applet, rc_service_inactive); 244 rc_mark_service (applet, rc_service_inactive);
254 else 245 else
255 rc_mark_service (applet, rc_service_stopped); 246 rc_mark_service (applet, rc_service_stopped);
256 } 247 }
257 if (exclusive && rc_exists (exclusive)) 248 if (exclusive && rc_exists (exclusive))
258 unlink (exclusive); 249 unlink (exclusive);
259 } 250 }
260 251
261 if (env) 252 if (env)
262 rc_strlist_free (env); 253 rc_strlist_free (env);
263 254
264 if (mtime_test) 255 if (mtime_test)
265 { 256 {
266 unlink (mtime_test); 257 unlink (mtime_test);
267 free (mtime_test); 258 free (mtime_test);
268 } 259 }
269 if (exclusive) 260 if (exclusive)
270 free (exclusive); 261 free (exclusive);
271 262
272 if (applet) 263 if (applet)
273 free (applet); 264 free (applet);
274} 265}
275 266
276static bool svc_exec (const char *service, const char *arg1, const char *arg2) 267static bool svc_exec (const char *service, const char *arg1, const char *arg2)
277{ 268{
278 int status = 0; 269 int status = 0;
279 pid_t pid; 270 pid_t pid;
280 271
281 /* We need to disable our child signal handler now so we block 272 /* We need to disable our child signal handler now so we block
282 until our script returns. */ 273 until our script returns. */
283 signal (SIGCHLD, NULL); 274 signal (SIGCHLD, NULL);
284 275
285 pid = fork(); 276 pid = fork();
286 277
287 if (pid == -1) 278 if (pid == -1)
288 eerrorx ("%s: fork: %s", service, strerror (errno)); 279 eerrorx ("%s: fork: %s", service, strerror (errno));
289 if (pid == 0) 280 if (pid == 0) {
290 {
291 mycmd = rc_xstrdup (service); 281 mycmd = rc_xstrdup (service);
292 myarg1 = rc_xstrdup (arg1); 282 myarg1 = rc_xstrdup (arg1);
293 if (arg2) 283 if (arg2)
294 myarg2 = rc_xstrdup (arg2); 284 myarg2 = rc_xstrdup (arg2);
295 285
296 if (rc_exists (RC_SVCDIR "runscript.sh")) 286 if (rc_exists (RC_SVCDIR "runscript.sh")) {
297 {
298 execl (RC_SVCDIR "runscript.sh", mycmd, mycmd, myarg1, myarg2, 287 execl (RC_SVCDIR "runscript.sh", mycmd, mycmd, myarg1, myarg2,
299 (char *) NULL); 288 (char *) NULL);
300 eerrorx ("%s: exec `" RC_SVCDIR "runscript.sh': %s", 289 eerrorx ("%s: exec `" RC_SVCDIR "runscript.sh': %s",
301 service, strerror (errno)); 290 service, strerror (errno));
302 } 291 } else {
303 else
304 {
305 execl (RC_LIBDIR "sh/runscript.sh", mycmd, mycmd, myarg1, myarg2, 292 execl (RC_LIBDIR "sh/runscript.sh", mycmd, mycmd, myarg1, myarg2,
306 (char *) NULL); 293 (char *) NULL);
307 eerrorx ("%s: exec `" RC_LIBDIR "sh/runscript.sh': %s", 294 eerrorx ("%s: exec `" RC_LIBDIR "sh/runscript.sh': %s",
308 service, strerror (errno)); 295 service, strerror (errno));
309 } 296 }
310 } 297 }
311 298
312 do 299 do {
313 {
314 if (waitpid (pid, &status, 0) < 0) 300 if (waitpid (pid, &status, 0) < 0) {
315 {
316 if (errno != ECHILD) 301 if (errno != ECHILD)
317 eerror ("waitpid: %s", strerror (errno)); 302 eerror ("waitpid: %s", strerror (errno));
318 break; 303 break;
319 } 304 }
320 } while (! WIFEXITED (status) && ! WIFSIGNALED (status)); 305 } while (! WIFEXITED (status) && ! WIFSIGNALED (status));
321 306
322 /* Done, so restore the signal handler */ 307 /* Done, so restore the signal handler */
323 signal (SIGCHLD, handle_signal); 308 signal (SIGCHLD, handle_signal);
324 309
325 if (WIFEXITED (status)) 310 if (WIFEXITED (status))
326 return (WEXITSTATUS (status) ? false : true); 311 return (WEXITSTATUS (status) ? false : true);
327 312
328 return (false); 313 return (false);
329} 314}
330 315
331static rc_service_state_t svc_status (const char *service) 316static rc_service_state_t svc_status (const char *service)
332{ 317{
333 char status[10]; 318 char status[10];
334 int (*e) (const char *fmt, ...) = &einfo; 319 int (*e) (const char *fmt, ...) = &einfo;
335 320
336 rc_service_state_t retval = rc_service_stopped; 321 rc_service_state_t retval = rc_service_stopped;
337 322
338 if (rc_service_state (service, rc_service_stopping)) 323 if (rc_service_state (service, rc_service_stopping)) {
339 {
340 snprintf (status, sizeof (status), "stopping"); 324 snprintf (status, sizeof (status), "stopping");
341 e = &ewarn; 325 e = &ewarn;
342 retval = rc_service_stopping; 326 retval = rc_service_stopping;
343 }
344 else if (rc_service_state (service, rc_service_starting)) 327 } else if (rc_service_state (service, rc_service_starting)) {
345 {
346 snprintf (status, sizeof (status), "starting"); 328 snprintf (status, sizeof (status), "starting");
347 e = &ewarn; 329 e = &ewarn;
348 retval = rc_service_starting; 330 retval = rc_service_starting;
349 }
350 else if (rc_service_state (service, rc_service_inactive)) 331 } else if (rc_service_state (service, rc_service_inactive)) {
351 {
352 snprintf (status, sizeof (status), "inactive"); 332 snprintf (status, sizeof (status), "inactive");
353 e = &ewarn; 333 e = &ewarn;
354 retval = rc_service_inactive; 334 retval = rc_service_inactive;
355 }
356 else if (rc_service_state (service, rc_service_crashed)) 335 } else if (rc_service_state (service, rc_service_crashed)) {
357 {
358 snprintf (status, sizeof (status), "crashed"); 336 snprintf (status, sizeof (status), "crashed");
359 e = &eerror; 337 e = &eerror;
360 retval = rc_service_crashed; 338 retval = rc_service_crashed;
361 }
362 else if (rc_service_state (service, rc_service_started)) 339 } else if (rc_service_state (service, rc_service_started)) {
363 {
364 snprintf (status, sizeof (status), "started"); 340 snprintf (status, sizeof (status), "started");
365 retval = rc_service_started; 341 retval = rc_service_started;
366 }
367 else 342 } else
368 snprintf (status, sizeof (status), "stopped"); 343 snprintf (status, sizeof (status), "stopped");
369 344
370 e ("status: %s", status); 345 e ("status: %s", status);
371 return (retval); 346 return (retval);
372} 347}
373 348
374static void make_exclusive (const char *service) 349static void make_exclusive (const char *service)
375{ 350{
376 char *path; 351 char *path;
377 int i; 352 int i;
378 353
379 /* We create a fifo so that other services can wait until we complete */ 354 /* We create a fifo so that other services can wait until we complete */
380 if (! exclusive) 355 if (! exclusive)
381 exclusive = rc_strcatpaths (RC_SVCDIR, "exclusive", applet, (char *) NULL); 356 exclusive = rc_strcatpaths (RC_SVCDIR, "exclusive", applet, (char *) NULL);
382 357
383 if (mkfifo (exclusive, 0600) != 0 && errno != EEXIST && 358 if (mkfifo (exclusive, 0600) != 0 && errno != EEXIST &&
384 (errno != EACCES || geteuid () == 0)) 359 (errno != EACCES || geteuid () == 0))
385 eerrorx ("%s: unable to create fifo `%s': %s", 360 eerrorx ("%s: unable to create fifo `%s': %s",
386 applet, exclusive, strerror (errno)); 361 applet, exclusive, strerror (errno));
387 362
388 path = rc_strcatpaths (RC_SVCDIR, "exclusive", applet, (char *) NULL); 363 path = rc_strcatpaths (RC_SVCDIR, "exclusive", applet, (char *) NULL);
389 i = strlen (path) + 16; 364 i = strlen (path) + 16;
390 mtime_test = rc_xmalloc (sizeof (char *) * i); 365 mtime_test = rc_xmalloc (sizeof (char *) * i);
391 snprintf (mtime_test, i, "%s.%d", path, getpid ()); 366 snprintf (mtime_test, i, "%s.%d", path, getpid ());
392 free (path); 367 free (path);
393 368
394 if (rc_exists (mtime_test) && unlink (mtime_test) != 0) 369 if (rc_exists (mtime_test) && unlink (mtime_test) != 0) {
395 {
396 eerror ("%s: unlink `%s': %s", 370 eerror ("%s: unlink `%s': %s",
397 applet, mtime_test, strerror (errno)); 371 applet, mtime_test, strerror (errno));
398 free (mtime_test); 372 free (mtime_test);
399 mtime_test = NULL; 373 mtime_test = NULL;
400 return; 374 return;
401 } 375 }
402 376
403 if (symlink (service, mtime_test) != 0) 377 if (symlink (service, mtime_test) != 0) {
404 {
405 eerror ("%s: symlink `%s' to `%s': %s", 378 eerror ("%s: symlink `%s' to `%s': %s",
406 applet, service, mtime_test, strerror (errno)); 379 applet, service, mtime_test, strerror (errno));
407 free (mtime_test); 380 free (mtime_test);
408 mtime_test = NULL; 381 mtime_test = NULL;
409 } 382 }
410} 383}
411 384
412static void unlink_mtime_test () 385static void unlink_mtime_test ()
413{ 386{
414 if (unlink (mtime_test) != 0) 387 if (unlink (mtime_test) != 0)
415 eerror ("%s: unlink `%s': %s", applet, mtime_test, strerror (errno)); 388 eerror ("%s: unlink `%s': %s", applet, mtime_test, strerror (errno));
416 free (mtime_test); 389 free (mtime_test);
417 mtime_test = NULL; 390 mtime_test = NULL;
418} 391}
419 392
420static void get_started_services () 393static void get_started_services ()
421{ 394{
422 char *service; 395 char *service;
423 int i; 396 int i;
424 397
425 rc_strlist_free (tmplist); 398 rc_strlist_free (tmplist);
426 tmplist = rc_services_in_state (rc_service_inactive); 399 tmplist = rc_services_in_state (rc_service_inactive);
427 400
428 rc_strlist_free (restart_services); 401 rc_strlist_free (restart_services);
429 restart_services = rc_services_in_state (rc_service_started); 402 restart_services = rc_services_in_state (rc_service_started);
430 403
431 STRLIST_FOREACH (tmplist, service, i) 404 STRLIST_FOREACH (tmplist, service, i)
432 restart_services = rc_strlist_addsort (restart_services, service); 405 restart_services = rc_strlist_addsort (restart_services, service);
433 406
434 rc_strlist_free (tmplist); 407 rc_strlist_free (tmplist);
435 tmplist = NULL; 408 tmplist = NULL;
436} 409}
437 410
438static void svc_start (const char *service, bool deps) 411static void svc_start (const char *service, bool deps)
439{ 412{
440 bool started; 413 bool started;
441 bool background = false; 414 bool background = false;
442 char *svc; 415 char *svc;
443 char *svc2; 416 char *svc2;
444 int i; 417 int i;
445 int j; 418 int j;
446 int depoptions = RC_DEP_TRACE; 419 int depoptions = RC_DEP_TRACE;
447 420
448 rc_plugin_run (rc_hook_service_start_in, applet); 421 rc_plugin_run (rc_hook_service_start_in, applet);
449 hook_out = rc_hook_service_start_out; 422 hook_out = rc_hook_service_start_out;
450 423
451 if (rc_is_env ("RC_STRICT_DEPEND", "yes")) 424 if (rc_is_env ("RC_STRICT_DEPEND", "yes"))
452 depoptions |= RC_DEP_STRICT; 425 depoptions |= RC_DEP_STRICT;
453 426
454 if (rc_is_env ("IN_HOTPLUG", "1") || in_background) 427 if (rc_is_env ("IN_HOTPLUG", "1") || in_background) {
455 {
456 if (! rc_service_state (service, rc_service_inactive)) 428 if (! rc_service_state (service, rc_service_inactive))
457 exit (EXIT_FAILURE); 429 exit (EXIT_FAILURE);
458 background = true; 430 background = true;
459 } 431 }
460 432
461 if (rc_service_state (service, rc_service_started)) 433 if (rc_service_state (service, rc_service_started))
462 ewarnx ("WARNING: %s has already been started", applet); 434 ewarnx ("WARNING: %s has already been started", applet);
463 else if (rc_service_state (service, rc_service_starting)) 435 else if (rc_service_state (service, rc_service_starting))
464 ewarnx ("WARNING: %s is already starting", applet); 436 ewarnx ("WARNING: %s is already starting", applet);
465 else if (rc_service_state (service, rc_service_stopping)) 437 else if (rc_service_state (service, rc_service_stopping))
466 ewarnx ("WARNING: %s is stopping", applet); 438 ewarnx ("WARNING: %s is stopping", applet);
467 else if (rc_service_state (service, rc_service_inactive) && ! background) 439 else if (rc_service_state (service, rc_service_inactive) && ! background)
468 ewarnx ("WARNING: %s has already started, but is inactive", applet); 440 ewarnx ("WARNING: %s has already started, but is inactive", applet);
469 441
470 if (! rc_mark_service (service, rc_service_starting)) 442 if (! rc_mark_service (service, rc_service_starting))
471 eerrorx ("ERROR: %s has been started by something else", applet); 443 eerrorx ("ERROR: %s has been started by something else", applet);
472 444
473 make_exclusive (service); 445 make_exclusive (service);
474 446
475 if (deps) 447 if (deps) {
476 {
477 if (! deptree && ((deptree = rc_load_deptree ()) == NULL)) 448 if (! deptree && ((deptree = rc_load_deptree ()) == NULL))
478 eerrorx ("failed to load deptree"); 449 eerrorx ("failed to load deptree");
479 450
480 rc_strlist_free (types); 451 rc_strlist_free (types);
481 types = rc_strlist_add (NULL, "broken"); 452 types = rc_strlist_add (NULL, "broken");
482 rc_strlist_free (svclist); 453 rc_strlist_free (svclist);
483 svclist = rc_strlist_add (NULL, applet); 454 svclist = rc_strlist_add (NULL, applet);
484 rc_strlist_free (services); 455 rc_strlist_free (services);
485 services = rc_get_depends (deptree, types, svclist, softlevel, 0); 456 services = rc_get_depends (deptree, types, svclist, softlevel, 0);
486 if (services) 457 if (services) {
487 {
488 eerrorn ("ERROR: `%s' needs ", applet); 458 eerrorn ("ERROR: `%s' needs ", applet);
489 STRLIST_FOREACH (services, svc, i) 459 STRLIST_FOREACH (services, svc, i) {
490 { 460 if (i > 0)
491 if (i > 0) 461 fprintf (stderr, ", ");
492 fprintf (stderr, ", ");
493 fprintf (stderr, "%s", svc); 462 fprintf (stderr, "%s", svc);
494 } 463 }
495 exit (EXIT_FAILURE); 464 exit (EXIT_FAILURE);
496 } 465 }
497 rc_strlist_free (services); 466 rc_strlist_free (services);
498 services = NULL; 467 services = NULL;
499 468
500 rc_strlist_free (types); 469 rc_strlist_free (types);
501 types = rc_strlist_add (NULL, "ineed"); 470 types = rc_strlist_add (NULL, "ineed");
502 rc_strlist_free (need_services); 471 rc_strlist_free (need_services);
503 need_services = rc_get_depends (deptree, types, svclist, 472 need_services = rc_get_depends (deptree, types, svclist,
504 softlevel, depoptions); 473 softlevel, depoptions);
505 types = rc_strlist_add (types, "iuse"); 474 types = rc_strlist_add (types, "iuse");
506 if (! rc_runlevel_starting ()) 475 if (! rc_runlevel_starting ()) {
507 {
508 services = rc_get_depends (deptree, types, svclist, 476 services = rc_get_depends (deptree, types, svclist,
509 softlevel, depoptions); 477 softlevel, depoptions);
510 STRLIST_FOREACH (services, svc, i) 478 STRLIST_FOREACH (services, svc, i)
511 if (rc_service_state (svc, rc_service_stopped)) 479 if (rc_service_state (svc, rc_service_stopped))
512 rc_start_service (svc); 480 rc_start_service (svc);
513 481
514 rc_strlist_free (services); 482 rc_strlist_free (services);
515 } 483 }
516 484
517 /* Now wait for them to start */ 485 /* Now wait for them to start */
518 types = rc_strlist_add (types, "iafter"); 486 types = rc_strlist_add (types, "iafter");
519 services = rc_get_depends (deptree, types, svclist, 487 services = rc_get_depends (deptree, types, svclist,
520 softlevel, depoptions); 488 softlevel, depoptions);
521 489
522 /* We use tmplist to hold our scheduled by list */ 490 /* We use tmplist to hold our scheduled by list */
523 rc_strlist_free (tmplist); 491 rc_strlist_free (tmplist);
524 tmplist = NULL; 492 tmplist = NULL;
525 493
526 STRLIST_FOREACH (services, svc, i) 494 STRLIST_FOREACH (services, svc, i) {
527 {
528 if (rc_service_state (svc, rc_service_started)) 495 if (rc_service_state (svc, rc_service_started))
529 continue; 496 continue;
530 if (! rc_wait_service (svc)) 497 if (! rc_wait_service (svc))
531 eerror ("%s: timed out waiting for %s", applet, svc); 498 eerror ("%s: timed out waiting for %s", applet, svc);
532 if (rc_service_state (svc, rc_service_started)) 499 if (rc_service_state (svc, rc_service_started))
533 continue; 500 continue;
534 501
535 STRLIST_FOREACH (need_services, svc2, j) 502 STRLIST_FOREACH (need_services, svc2, j)
536 if (strcmp (svc, svc2) == 0) 503 if (strcmp (svc, svc2) == 0) {
537 {
538 if (rc_service_state (svc, rc_service_inactive) || 504 if (rc_service_state (svc, rc_service_inactive) ||
539 rc_service_state (svc, rc_service_wasinactive)) 505 rc_service_state (svc, rc_service_wasinactive))
540 tmplist = rc_strlist_add (tmplist, svc); 506 tmplist = rc_strlist_add (tmplist, svc);
541 else 507 else
542 eerrorx ("ERROR: cannot start %s as %s would not start", 508 eerrorx ("ERROR: cannot start %s as %s would not start",
543 applet, svc); 509 applet, svc);
544 } 510 }
545 } 511 }
546 512
547 if (tmplist) 513 if (tmplist) {
548 { 514 int n = 0;
549 int n = 0; 515 int len = 0;
550 int len = 0; 516 char *p;
551 char *p;
552 517
553 /* Set the state now, then unlink our exclusive so that 518 /* Set the state now, then unlink our exclusive so that
554 our scheduled list is preserved */ 519 our scheduled list is preserved */
555 rc_mark_service (service, rc_service_stopped); 520 rc_mark_service (service, rc_service_stopped);
556 unlink_mtime_test (); 521 unlink_mtime_test ();
557 522
558 rc_strlist_free (types); 523 rc_strlist_free (types);
559 types = rc_strlist_add (NULL, "iprovide"); 524 types = rc_strlist_add (NULL, "iprovide");
560 STRLIST_FOREACH (tmplist, svc, i) 525 STRLIST_FOREACH (tmplist, svc, i) {
561 {
562 rc_schedule_start_service (svc, service); 526 rc_schedule_start_service (svc, service);
563 527
564 rc_strlist_free (svclist); 528 rc_strlist_free (svclist);
565 svclist = rc_strlist_add (NULL, svc); 529 svclist = rc_strlist_add (NULL, svc);
566 rc_strlist_free (providelist); 530 rc_strlist_free (providelist);
567 providelist = rc_get_depends (deptree, types, svclist, 531 providelist = rc_get_depends (deptree, types, svclist,
568 softlevel, depoptions); 532 softlevel, depoptions);
569 STRLIST_FOREACH (providelist, svc2, j) 533 STRLIST_FOREACH (providelist, svc2, j)
570 rc_schedule_start_service (svc2, service); 534 rc_schedule_start_service (svc2, service);
571 535
572 len += strlen (svc) + 2; 536 len += strlen (svc) + 2;
573 n++; 537 n++;
574 } 538 }
575 539
576 len += 5; 540 len += 5;
577 tmp = rc_xmalloc (sizeof (char *) * len); 541 tmp = rc_xmalloc (sizeof (char *) * len);
578 p = tmp; 542 p = tmp;
579 STRLIST_FOREACH (tmplist, svc, i) 543 STRLIST_FOREACH (tmplist, svc, i) {
580 { 544 if (i > 1) {
581 if (i > 1) 545 if (i == n - 1)
582 { 546 p += snprintf (p, len, " or ");
583 if (i == n - 1) 547 else
584 p += snprintf (p, len, " or "); 548 p += snprintf (p, len, ", ");
585 else 549 }
586 p += snprintf (p, len, ", ");
587 }
588 p += snprintf (p, len, "%s", svc); 550 p += snprintf (p, len, "%s", svc);
589 } 551 }
590 ewarnx ("WARNING: %s is scheduled to start when %s has started", 552 ewarnx ("WARNING: %s is scheduled to start when %s has started",
591 applet, tmp); 553 applet, tmp);
592 } 554 }
593 555
594 rc_strlist_free (services); 556 rc_strlist_free (services);
595 services = NULL; 557 services = NULL;
596 rc_strlist_free (types); 558 rc_strlist_free (types);
597 types = NULL; 559 types = NULL;
598 rc_strlist_free (svclist); 560 rc_strlist_free (svclist);
599 svclist = NULL; 561 svclist = NULL;
600 } 562 }
601 563
602 if (ibsave) 564 if (ibsave)
603 setenv ("IN_BACKGROUND", ibsave, 1); 565 setenv ("IN_BACKGROUND", ibsave, 1);
604 rc_plugin_run (rc_hook_service_start_now, applet); 566 rc_plugin_run (rc_hook_service_start_now, applet);
605 started = svc_exec (service, "start", NULL); 567 started = svc_exec (service, "start", NULL);
606 if (ibsave) 568 if (ibsave)
607 unsetenv ("IN_BACKGROUND"); 569 unsetenv ("IN_BACKGROUND");
608 570
609 if (in_control ()) 571 if (in_control ()) {
610 { 572 if (! started) {
611 if (! started)
612 {
613 if (rc_service_state (service, rc_service_wasinactive)) 573 if (rc_service_state (service, rc_service_wasinactive))
614 rc_mark_service (service, rc_service_inactive); 574 rc_mark_service (service, rc_service_inactive);
615 else 575 else {
616 {
617 rc_mark_service (service, rc_service_stopped); 576 rc_mark_service (service, rc_service_stopped);
618 if (rc_runlevel_starting ()) 577 if (rc_runlevel_starting ())
619 rc_mark_service (service, rc_service_failed); 578 rc_mark_service (service, rc_service_failed);
620 } 579 }
621 rc_plugin_run (rc_hook_service_start_done, applet); 580 rc_plugin_run (rc_hook_service_start_done, applet);
622 eerrorx ("ERROR: %s failed to start", applet); 581 eerrorx ("ERROR: %s failed to start", applet);
623 } 582 }
624 rc_mark_service (service, rc_service_started); 583 rc_mark_service (service, rc_service_started);
625 unlink_mtime_test (); 584 unlink_mtime_test ();
626 rc_plugin_run (rc_hook_service_start_done, applet); 585 rc_plugin_run (rc_hook_service_start_done, applet);
627 } 586 } else {
628 else
629 {
630 rc_plugin_run (rc_hook_service_start_done, applet); 587 rc_plugin_run (rc_hook_service_start_done, applet);
631 if (rc_service_state (service, rc_service_inactive)) 588 if (rc_service_state (service, rc_service_inactive))
632 ewarnx ("WARNING: %s has started, but is inactive", applet); 589 ewarnx ("WARNING: %s has started, but is inactive", applet);
633 else 590 else
634 ewarnx ("WARNING: %s not under our control, aborting", applet); 591 ewarnx ("WARNING: %s not under our control, aborting", applet);
635 } 592 }
636 593
637 /* Now start any scheduled services */ 594 /* Now start any scheduled services */
638 rc_strlist_free (services); 595 rc_strlist_free (services);
639 services = rc_services_scheduled (service); 596 services = rc_services_scheduled (service);
640 STRLIST_FOREACH (services, svc, i) 597 STRLIST_FOREACH (services, svc, i)
641 if (rc_service_state (svc, rc_service_stopped)) 598 if (rc_service_state (svc, rc_service_stopped))
642 rc_start_service (svc); 599 rc_start_service (svc);
643 rc_strlist_free (services); 600 rc_strlist_free (services);
644 services = NULL; 601 services = NULL;
645 602
646 /* Do the same for any services we provide */ 603 /* Do the same for any services we provide */
647 rc_strlist_free (types); 604 rc_strlist_free (types);
648 types = rc_strlist_add (NULL, "iprovide"); 605 types = rc_strlist_add (NULL, "iprovide");
649 rc_strlist_free (svclist); 606 rc_strlist_free (svclist);
650 svclist = rc_strlist_add (NULL, applet); 607 svclist = rc_strlist_add (NULL, applet);
651 rc_strlist_free (tmplist); 608 rc_strlist_free (tmplist);
652 tmplist = rc_get_depends (deptree, types, svclist, softlevel, depoptions); 609 tmplist = rc_get_depends (deptree, types, svclist, softlevel, depoptions);
653 610
654 STRLIST_FOREACH (tmplist, svc2, j) 611 STRLIST_FOREACH (tmplist, svc2, j) {
655 {
656 rc_strlist_free (services); 612 rc_strlist_free (services);
657 services = rc_services_scheduled (svc2); 613 services = rc_services_scheduled (svc2);
658 STRLIST_FOREACH (services, svc, i) 614 STRLIST_FOREACH (services, svc, i)
659 if (rc_service_state (svc, rc_service_stopped)) 615 if (rc_service_state (svc, rc_service_stopped))
660 rc_start_service (svc); 616 rc_start_service (svc);
661 } 617 }
662 618
663 hook_out = 0; 619 hook_out = 0;
664 rc_plugin_run (rc_hook_service_start_out, applet); 620 rc_plugin_run (rc_hook_service_start_out, applet);
665} 621}
666 622
667static void svc_stop (const char *service, bool deps) 623static void svc_stop (const char *service, bool deps)
668{ 624{
669 bool stopped; 625 bool stopped;
670 626
671 hook_out = rc_hook_service_stop_out; 627 hook_out = rc_hook_service_stop_out;
672 628
673 if (rc_runlevel_stopping () && 629 if (rc_runlevel_stopping () &&
674 rc_service_state (service, rc_service_failed)) 630 rc_service_state (service, rc_service_failed))
675 exit (EXIT_FAILURE); 631 exit (EXIT_FAILURE);
676 632
677 if (rc_is_env ("IN_HOTPLUG", "1") || in_background) 633 if (rc_is_env ("IN_HOTPLUG", "1") || in_background)
678 if (! rc_service_state (service, rc_service_started)) 634 if (! rc_service_state (service, rc_service_started))
679 exit (EXIT_FAILURE); 635 exit (EXIT_FAILURE);
680 636
681 if (rc_service_state (service, rc_service_stopped)) 637 if (rc_service_state (service, rc_service_stopped))
682 ewarnx ("WARNING: %s is already stopped", applet); 638 ewarnx ("WARNING: %s is already stopped", applet);
683 else if (rc_service_state (service, rc_service_stopping)) 639 else if (rc_service_state (service, rc_service_stopping))
684 ewarnx ("WARNING: %s is already stopping", applet); 640 ewarnx ("WARNING: %s is already stopping", applet);
685 641
686 if (! rc_mark_service (service, rc_service_stopping)) 642 if (! rc_mark_service (service, rc_service_stopping))
687 eerrorx ("ERROR: %s has been stopped by something else", applet); 643 eerrorx ("ERROR: %s has been stopped by something else", applet);
688 644
689 make_exclusive (service); 645 make_exclusive (service);
690 646
691 if (! rc_runlevel_stopping () && 647 if (! rc_runlevel_stopping () &&
692 rc_service_in_runlevel (service, RC_LEVEL_BOOT)) 648 rc_service_in_runlevel (service, RC_LEVEL_BOOT))
693 ewarn ("WARNING: you are stopping a boot service"); 649 ewarn ("WARNING: you are stopping a boot service");
694 650
695 if (deps || ! rc_service_state (service, rc_service_wasinactive)) 651 if (deps || ! rc_service_state (service, rc_service_wasinactive)) {
696 {
697 int depoptions = RC_DEP_TRACE; 652 int depoptions = RC_DEP_TRACE;
698 char *svc; 653 char *svc;
699 int i; 654 int i;
700 655
701 if (rc_is_env ("RC_STRICT_DEPEND", "yes")) 656 if (rc_is_env ("RC_STRICT_DEPEND", "yes"))
702 depoptions |= RC_DEP_STRICT; 657 depoptions |= RC_DEP_STRICT;
703 658
704 if (! deptree && ((deptree = rc_load_deptree ()) == NULL)) 659 if (! deptree && ((deptree = rc_load_deptree ()) == NULL))
705 eerrorx ("failed to load deptree"); 660 eerrorx ("failed to load deptree");
706 661
707 rc_strlist_free (types); 662 rc_strlist_free (types);
708 types = rc_strlist_add (NULL, "needsme"); 663 types = rc_strlist_add (NULL, "needsme");
709 rc_strlist_free (svclist); 664 rc_strlist_free (svclist);
710 svclist = rc_strlist_add (NULL, applet); 665 svclist = rc_strlist_add (NULL, applet);
711 rc_strlist_free (tmplist); 666 rc_strlist_free (tmplist);
712 tmplist = NULL; 667 tmplist = NULL;
713 rc_strlist_free (services); 668 rc_strlist_free (services);
714 services = rc_get_depends (deptree, types, svclist, 669 services = rc_get_depends (deptree, types, svclist,
715 softlevel, depoptions); 670 softlevel, depoptions);
716 rc_strlist_reverse (services); 671 rc_strlist_reverse (services);
717 STRLIST_FOREACH (services, svc, i) 672 STRLIST_FOREACH (services, svc, i) {
718 {
719 if (rc_service_state (svc, rc_service_started) || 673 if (rc_service_state (svc, rc_service_started) ||
720 rc_service_state (svc, rc_service_inactive)) 674 rc_service_state (svc, rc_service_inactive))
721 { 675 {
722 rc_wait_service (svc); 676 rc_wait_service (svc);
723 if (rc_service_state (svc, rc_service_started) || 677 if (rc_service_state (svc, rc_service_started) ||
724 rc_service_state (svc, rc_service_inactive)) 678 rc_service_state (svc, rc_service_inactive))
725 { 679 {
726 rc_stop_service (svc); 680 rc_stop_service (svc);
727 tmplist = rc_strlist_add (tmplist, svc); 681 tmplist = rc_strlist_add (tmplist, svc);
728 } 682 }
729 } 683 }
730 } 684 }
731 rc_strlist_free (services); 685 rc_strlist_free (services);
732 services = NULL; 686 services = NULL;
733 687
734 STRLIST_FOREACH (tmplist, svc, i) 688 STRLIST_FOREACH (tmplist, svc, i) {
735 {
736 if (rc_service_state (svc, rc_service_stopped)) 689 if (rc_service_state (svc, rc_service_stopped))
737 continue; 690 continue;
738 691
739 /* We used to loop 3 times here - maybe re-do this if needed */ 692 /* We used to loop 3 times here - maybe re-do this if needed */
740 rc_wait_service (svc); 693 rc_wait_service (svc);
741 if (! rc_service_state (svc, rc_service_stopped)) 694 if (! rc_service_state (svc, rc_service_stopped)) {
742 {
743 if (rc_runlevel_stopping ()) 695 if (rc_runlevel_stopping ())
744 rc_mark_service (svc, rc_service_failed); 696 rc_mark_service (svc, rc_service_failed);
745 eerrorx ("ERROR: cannot stop %s as %s is still up", 697 eerrorx ("ERROR: cannot stop %s as %s is still up",
746 applet, svc); 698 applet, svc);
747 } 699 }
748 } 700 }
749 rc_strlist_free (tmplist); 701 rc_strlist_free (tmplist);
750 tmplist = NULL; 702 tmplist = NULL;
751 703
752 /* We now wait for other services that may use us and are stopping 704 /* We now wait for other services that may use us and are stopping
753 This is important when a runlevel stops */ 705 This is important when a runlevel stops */
754 types = rc_strlist_add (types, "usesme"); 706 types = rc_strlist_add (types, "usesme");
755 types = rc_strlist_add (types, "ibefore"); 707 types = rc_strlist_add (types, "ibefore");
756 services = rc_get_depends (deptree, types, svclist, 708 services = rc_get_depends (deptree, types, svclist,
757 softlevel, depoptions); 709 softlevel, depoptions);
758 STRLIST_FOREACH (services, svc, i) 710 STRLIST_FOREACH (services, svc, i) {
759 {
760 if (rc_service_state (svc, rc_service_stopped)) 711 if (rc_service_state (svc, rc_service_stopped))
761 continue; 712 continue;
762 rc_wait_service (svc); 713 rc_wait_service (svc);
763 } 714 }
764 715
765 rc_strlist_free (services); 716 rc_strlist_free (services);
766 services = NULL; 717 services = NULL;
767 rc_strlist_free (types); 718 rc_strlist_free (types);
768 types = NULL; 719 types = NULL;
769 } 720 }
770 721
771 if (ibsave) 722 if (ibsave)
772 setenv ("IN_BACKGROUND", ibsave, 1); 723 setenv ("IN_BACKGROUND", ibsave, 1);
773 rc_plugin_run (rc_hook_service_stop_now, applet); 724 rc_plugin_run (rc_hook_service_stop_now, applet);
774 stopped = svc_exec (service, "stop", NULL); 725 stopped = svc_exec (service, "stop", NULL);
775 if (ibsave) 726 if (ibsave)
776 unsetenv ("IN_BACKGROUND"); 727 unsetenv ("IN_BACKGROUND");
777 728
778 if (! in_control ()) 729 if (! in_control ()) {
779 {
780 rc_plugin_run (rc_hook_service_stop_done, applet); 730 rc_plugin_run (rc_hook_service_stop_done, applet);
781 ewarnx ("WARNING: %s not under our control, aborting", applet); 731 ewarnx ("WARNING: %s not under our control, aborting", applet);
782 } 732 }
783 733
784 if (! stopped) 734 if (! stopped) {
785 {
786 if (rc_service_state (service, rc_service_wasinactive)) 735 if (rc_service_state (service, rc_service_wasinactive))
787 rc_mark_service (service, rc_service_inactive); 736 rc_mark_service (service, rc_service_inactive);
788 else 737 else
789 rc_mark_service (service, rc_service_started); 738 rc_mark_service (service, rc_service_started);
790 rc_plugin_run (rc_hook_service_stop_done, applet); 739 rc_plugin_run (rc_hook_service_stop_done, applet);
791 eerrorx ("ERROR: %s failed to stop", applet); 740 eerrorx ("ERROR: %s failed to stop", applet);
792 } 741 }
793 742
794 if (in_background) 743 if (in_background)
795 rc_mark_service (service, rc_service_inactive); 744 rc_mark_service (service, rc_service_inactive);
796 else 745 else
797 rc_mark_service (service, rc_service_stopped); 746 rc_mark_service (service, rc_service_stopped);
798 747
799 unlink_mtime_test (); 748 unlink_mtime_test ();
800 rc_plugin_run (rc_hook_service_stop_done, applet); 749 rc_plugin_run (rc_hook_service_stop_done, applet);
801 hook_out = 0; 750 hook_out = 0;
802 rc_plugin_run (rc_hook_service_stop_out, applet); 751 rc_plugin_run (rc_hook_service_stop_out, applet);
803} 752}
804 753
805static void svc_restart (const char *service, bool deps) 754static void svc_restart (const char *service, bool deps)
806{ 755{
807 char *svc; 756 char *svc;
808 int i; 757 int i;
809 bool inactive = false; 758 bool inactive = false;
810 759
811 /* This is hairly and a better way needs to be found I think! 760 /* This is hairly and a better way needs to be found I think!
812 The issue is this - openvpn need net and dns. net can restart 761 The issue is this - openvpn need net and dns. net can restart
813 dns via resolvconf, so you could have openvpn trying to restart dnsmasq 762 dns via resolvconf, so you could have openvpn trying to restart dnsmasq
814 which in turn is waiting on net which in turn is waiting on dnsmasq. 763 which in turn is waiting on net which in turn is waiting on dnsmasq.
815 The work around is for resolvconf to restart it's services with --nodeps 764 The work around is for resolvconf to restart it's services with --nodeps
816 which means just that. The downside is that there is a small window when 765 which means just that. The downside is that there is a small window when
817 our status is invalid. 766 our status is invalid.
818 One workaround would be to introduce a new status, or status locking. */ 767 One workaround would be to introduce a new status, or status locking. */
819 if (! deps) 768 if (! deps) {
820 {
821 if (rc_service_state (service, rc_service_started) || 769 if (rc_service_state (service, rc_service_started) ||
822 rc_service_state (service, rc_service_inactive)) 770 rc_service_state (service, rc_service_inactive))
823 svc_exec (service, "stop", "start"); 771 svc_exec (service, "stop", "start");
824 else 772 else
825 svc_exec (service, "start", NULL); 773 svc_exec (service, "start", NULL);
826 return; 774 return;
827 } 775 }
828 776
829 if (! rc_service_state (service, rc_service_stopped)) 777 if (! rc_service_state (service, rc_service_stopped)) {
830 {
831 get_started_services (); 778 get_started_services ();
832 svc_stop (service, deps); 779 svc_stop (service, deps);
833 780
834 /* Flush our buffered output if any */ 781 /* Flush our buffered output if any */
835 eflush (); 782 eflush ();
836 } 783 }
837 784
838 svc_start (service, deps); 785 svc_start (service, deps);
839 786
840 inactive = rc_service_state (service, rc_service_inactive); 787 inactive = rc_service_state (service, rc_service_inactive);
841 if (! inactive) 788 if (! inactive)
842 inactive = rc_service_state (service, rc_service_wasinactive); 789 inactive = rc_service_state (service, rc_service_wasinactive);
843 790
844 if (inactive || 791 if (inactive ||
845 rc_service_state (service, rc_service_starting) || 792 rc_service_state (service, rc_service_starting) ||
846 rc_service_state (service, rc_service_started)) 793 rc_service_state (service, rc_service_started))
847 { 794 {
848 STRLIST_FOREACH (restart_services, svc, i) 795 STRLIST_FOREACH (restart_services, svc, i) {
849 {
850 if (rc_service_state (svc, rc_service_stopped)) 796 if (rc_service_state (svc, rc_service_stopped)) {
851 { 797 if (inactive) {
852 if (inactive)
853 {
854 rc_schedule_start_service (service, svc); 798 rc_schedule_start_service (service, svc);
855 ewarn ("WARNING: %s is scheduled to started when %s has started", 799 ewarn ("WARNING: %s is scheduled to started when %s has started",
856 svc, basename (service)); 800 svc, basename (service));
857 } 801 } else
858 else 802 rc_start_service (svc);
859 rc_start_service (svc); 803 }
860 } 804 }
861 } 805 }
862 }
863} 806}
864 807
865int main (int argc, char **argv) 808int main (int argc, char **argv)
866{ 809{
867 const char *service = argv[1]; 810 const char *service = argv[1];
868 int i; 811 int i;
869 bool deps = true; 812 bool deps = true;
870 bool doneone = false; 813 bool doneone = false;
871 char pid[16]; 814 char pid[16];
872 int retval; 815 int retval;
873 bool ifstarted = false; 816 bool ifstarted = false;
874 817
875 applet = strdup (basename (service)); 818 applet = strdup (basename (service));
876 atexit (cleanup); 819 atexit (cleanup);
877 820
878 /* Show help if insufficient args */ 821 /* Show help if insufficient args */
879 if (argc < 3) 822 if (argc < 3) {
880 {
881 execl (RCSCRIPT_HELP, RCSCRIPT_HELP, service, (char *) NULL); 823 execl (RCSCRIPT_HELP, RCSCRIPT_HELP, service, (char *) NULL);
882 eerrorx ("%s: failed to exec `" RCSCRIPT_HELP "': %s", 824 eerrorx ("%s: failed to exec `" RCSCRIPT_HELP "': %s",
883 applet, strerror (errno)); 825 applet, strerror (errno));
884 } 826 }
885 827
886#ifdef __linux__ 828#ifdef __linux__
887 /* coldplug events can trigger init scripts, but we don't want to run them 829 /* coldplug events can trigger init scripts, but we don't want to run them
888 until after rc sysinit has completed so we punt them to the boot runlevel */ 830 until after rc sysinit has completed so we punt them to the boot runlevel */
889 if (rc_exists ("/dev/.rcsysinit")) 831 if (rc_exists ("/dev/.rcsysinit")) {
890 {
891 eerror ("%s: cannot run until sysvinit completes", applet); 832 eerror ("%s: cannot run until sysvinit completes", applet);
892 if (mkdir ("/dev/.rcboot", 0755) != 0 && errno != EEXIST) 833 if (mkdir ("/dev/.rcboot", 0755) != 0 && errno != EEXIST)
893 eerrorx ("%s: mkdir `/dev/.rcboot': %s", applet, strerror (errno)); 834 eerrorx ("%s: mkdir `/dev/.rcboot': %s", applet, strerror (errno));
894 tmp = rc_strcatpaths ("/dev/.rcboot", applet, (char *) NULL); 835 tmp = rc_strcatpaths ("/dev/.rcboot", applet, (char *) NULL);
895 symlink (service, tmp); 836 symlink (service, tmp);
896 exit (EXIT_FAILURE); 837 exit (EXIT_FAILURE);
897 } 838 }
898#endif 839#endif
899 840
900 if ((softlevel = getenv ("RC_SOFTLEVEL")) == NULL) 841 if ((softlevel = getenv ("RC_SOFTLEVEL")) == NULL) {
901 {
902 /* Ensure our environment is pure 842 /* Ensure our environment is pure
903 Also, add our configuration to it */ 843 Also, add our configuration to it */
904 env = rc_filter_env (); 844 env = rc_filter_env ();
905 env = rc_config_env (env); 845 env = rc_config_env (env);
906 846
907 if (env) 847 if (env) {
908 { 848 char *p;
909 char *p;
910 849
911#ifdef __linux__ 850#ifdef __linux__
912 /* clearenv isn't portable, but there's no harm in using it 851 /* clearenv isn't portable, but there's no harm in using it
913 if we have it */ 852 if we have it */
914 clearenv (); 853 clearenv ();
915#else 854#else
916 char *var; 855 char *var;
917 /* No clearenv present here then. 856 /* No clearenv present here then.
918 We could manipulate environ directly ourselves, but it seems that 857 We could manipulate environ directly ourselves, but it seems that
919 some kernels bitch about this according to the environ man pages 858 some kernels bitch about this according to the environ man pages
920 so we walk though environ and call unsetenv for each value. */ 859 so we walk though environ and call unsetenv for each value. */
921 while (environ[0]) 860 while (environ[0]) {
922 {
923 tmp = rc_xstrdup (environ[0]); 861 tmp = rc_xstrdup (environ[0]);
924 p = tmp; 862 p = tmp;
925 var = strsep (&p, "="); 863 var = strsep (&p, "=");
926 unsetenv (var); 864 unsetenv (var);
927 free (tmp); 865 free (tmp);
928 } 866 }
929 tmp = NULL; 867 tmp = NULL;
930#endif 868#endif
931 869
932 STRLIST_FOREACH (env, p, i) 870 STRLIST_FOREACH (env, p, i)
933 putenv (p); 871 putenv (p);
934 872
935 /* We don't free our list as that would be null in environ */ 873 /* We don't free our list as that would be null in environ */
936 } 874 }
937 875
938 softlevel = rc_get_runlevel (); 876 softlevel = rc_get_runlevel ();
939 877
940 /* If not called from RC or another service then don't be parallel */ 878 /* If not called from RC or another service then don't be parallel */
941 unsetenv ("RC_PARALLEL_STARTUP"); 879 unsetenv ("RC_PARALLEL_STARTUP");
942 } 880 }
943 881
944 setenv ("RC_ELOG", service, 1); 882 setenv ("RC_ELOG", service, 1);
945 setenv ("SVCNAME", applet, 1); 883 setenv ("SVCNAME", applet, 1);
946 884
947 /* Set an env var so that we always know our pid regardless of any 885 /* Set an env var so that we always know our pid regardless of any
948 subshells the init script may create so that our mark_service_* 886 subshells the init script may create so that our mark_service_*
949 functions can always instruct us of this change */ 887 functions can always instruct us of this change */
950 snprintf (pid, sizeof (pid), "%d", (int) getpid ()); 888 snprintf (pid, sizeof (pid), "%d", (int) getpid ());
951 setenv ("RC_RUNSCRIPT_PID", pid, 1); 889 setenv ("RC_RUNSCRIPT_PID", pid, 1);
952 890
953 if (rc_is_env ("RC_PARALLEL_STARTUP", "yes")) 891 if (rc_is_env ("RC_PARALLEL_STARTUP", "yes")) {
954 {
955 char ebname[PATH_MAX]; 892 char ebname[PATH_MAX];
956 char *eb; 893 char *eb;
957 894
958 snprintf (ebname, sizeof (ebname), "%s.%s", applet, pid); 895 snprintf (ebname, sizeof (ebname), "%s.%s", applet, pid);
959 eb = rc_strcatpaths (RC_SVCDIR "ebuffer", ebname, (char *) NULL); 896 eb = rc_strcatpaths (RC_SVCDIR "ebuffer", ebname, (char *) NULL);
960 setenv ("RC_EBUFFER", eb, 1); 897 setenv ("RC_EBUFFER", eb, 1);
961 free (eb); 898 free (eb);
962 } 899 }
963 900
964 /* Save the IN_BACKGROUND env flag so it's ONLY passed to the service 901 /* Save the IN_BACKGROUND env flag so it's ONLY passed to the service
965 that is being called and not any dependents */ 902 that is being called and not any dependents */
966 if (getenv ("IN_BACKGROUND")) 903 if (getenv ("IN_BACKGROUND")) {
967 {
968 in_background = rc_is_env ("IN_BACKGROUND", "true"); 904 in_background = rc_is_env ("IN_BACKGROUND", "true");
969 ibsave = strdup (getenv ("IN_BACKGROUND")); 905 ibsave = strdup (getenv ("IN_BACKGROUND"));
970 unsetenv ("IN_BACKGROUND"); 906 unsetenv ("IN_BACKGROUND");
971 } 907 }
972 908
973#ifdef __linux__ 909#ifdef __linux__
974 /* Ok, we are ready to go, so setup selinux if applicable */ 910 /* Ok, we are ready to go, so setup selinux if applicable */
975 setup_selinux (argc, argv); 911 setup_selinux (argc, argv);
976#endif 912#endif
977 913
978 /* Right then, parse any options there may be */ 914 /* Right then, parse any options there may be */
979 for (i = 2; i < argc; i++) 915 for (i = 2; i < argc; i++) {
980 {
981 if (strlen (argv[i]) < 2 || argv[i][0] != '-' || argv[i][1] != '-') 916 if (strlen (argv[i]) < 2 || argv[i][0] != '-' || argv[i][1] != '-')
982 continue; 917 continue;
983 918
984 if (strcmp (argv[i], "--debug") == 0) 919 if (strcmp (argv[i], "--debug") == 0)
985 setenv ("RC_DEBUG", "yes", 1); 920 setenv ("RC_DEBUG", "yes", 1);
986 else if (strcmp (argv[i], "--help") == 0) 921 else if (strcmp (argv[i], "--help") == 0) {
987 {
988 execl (RCSCRIPT_HELP, RCSCRIPT_HELP, service, (char *) NULL); 922 execl (RCSCRIPT_HELP, RCSCRIPT_HELP, service, (char *) NULL);
989 eerrorx ("%s: failed to exec `" RCSCRIPT_HELP "': %s", 923 eerrorx ("%s: failed to exec `" RCSCRIPT_HELP "': %s",
990 applet, strerror (errno)); 924 applet, strerror (errno));
991 }
992 else if (strcmp (argv[i],"--ifstarted") == 0) 925 } else if (strcmp (argv[i],"--ifstarted") == 0)
993 ifstarted = true; 926 ifstarted = true;
994 else if (strcmp (argv[i], "--nocolour") == 0 || 927 else if (strcmp (argv[i], "--nocolour") == 0 ||
995 strcmp (argv[i], "--nocolor") == 0) 928 strcmp (argv[i], "--nocolor") == 0)
996 setenv ("RC_NOCOLOR", "yes", 1); 929 setenv ("RC_NOCOLOR", "yes", 1);
997 else if (strcmp (argv[i], "--nodeps") == 0) 930 else if (strcmp (argv[i], "--nodeps") == 0)
998 deps = false; 931 deps = false;
999 else if (strcmp (argv[i], "--quiet") == 0) 932 else if (strcmp (argv[i], "--quiet") == 0)
1000 setenv ("RC_QUIET", "yes", 1); 933 setenv ("RC_QUIET", "yes", 1);
1001 else if (strcmp (argv[i], "--verbose") == 0) 934 else if (strcmp (argv[i], "--verbose") == 0)
1002 setenv ("RC_VERBOSE", "yes", 1); 935 setenv ("RC_VERBOSE", "yes", 1);
1003 else if (strcmp (argv[i], "--version") == 0) 936 else if (strcmp (argv[i], "--version") == 0)
1004 printf ("version me\n"); 937 printf ("version me\n");
1005 else 938 else
1006 eerror ("%s: unknown option `%s'", applet, argv[i]); 939 eerror ("%s: unknown option `%s'", applet, argv[i]);
1007 } 940 }
1008 941
1009 if (ifstarted && ! rc_service_state (applet, rc_service_started)) 942 if (ifstarted && ! rc_service_state (applet, rc_service_started)) {
1010 {
1011 if (! rc_is_env("RC_QUIET", "yes")) 943 if (! rc_is_env("RC_QUIET", "yes"))
1012 eerror ("ERROR: %s is not started", applet); 944 eerror ("ERROR: %s is not started", applet);
1013 exit (EXIT_FAILURE); 945 exit (EXIT_FAILURE);
1014 } 946 }
1015 947
1016 if (rc_is_env ("IN_HOTPLUG", "1")) 948 if (rc_is_env ("IN_HOTPLUG", "1")) {
1017 {
1018 if (! rc_is_env ("RC_HOTPLUG", "yes") || ! rc_allow_plug (applet)) 949 if (! rc_is_env ("RC_HOTPLUG", "yes") || ! rc_allow_plug (applet))
1019 eerrorx ("%s: not allowed to be hotplugged", applet); 950 eerrorx ("%s: not allowed to be hotplugged", applet);
1020 } 951 }
1021 952
1022 /* Setup a signal handler */ 953 /* Setup a signal handler */
1023 signal (SIGHUP, handle_signal); 954 signal (SIGHUP, handle_signal);
1024 signal (SIGINT, handle_signal); 955 signal (SIGINT, handle_signal);
1025 signal (SIGQUIT, handle_signal); 956 signal (SIGQUIT, handle_signal);
1026 signal (SIGTERM, handle_signal); 957 signal (SIGTERM, handle_signal);
1027 signal (SIGCHLD, handle_signal); 958 signal (SIGCHLD, handle_signal);
1028 959
1029 /* Load our plugins */ 960 /* Load our plugins */
1030 rc_plugin_load (); 961 rc_plugin_load ();
1031 962
1032 /* Now run each option */ 963 /* Now run each option */
1033 retval = EXIT_SUCCESS; 964 retval = EXIT_SUCCESS;
1034 for (i = 2; i < argc; i++) 965 for (i = 2; i < argc; i++) {
1035 {
1036 /* Abort on a sighup here */ 966 /* Abort on a sighup here */
1037 if (sighup) 967 if (sighup)
1038 exit (EXIT_FAILURE); 968 exit (EXIT_FAILURE);
1039 969
1040 if (strlen (argv[i]) < 2 || 970 if (strlen (argv[i]) < 2 ||
1041 (argv[i][0] == '-' && argv[i][1] == '-')) 971 (argv[i][0] == '-' && argv[i][1] == '-'))
1042 continue; 972 continue;
1043 973
1044 /* Export the command we're running. 974 /* Export the command we're running.
1045 This is important as we stamp on the restart function now but 975 This is important as we stamp on the restart function now but
1046 some start/stop routines still need to behave differently if 976 some start/stop routines still need to behave differently if
1047 restarting. */ 977 restarting. */
1048 unsetenv ("RC_CMD"); 978 unsetenv ("RC_CMD");
1049 setenv ("RC_CMD", argv[i], 1); 979 setenv ("RC_CMD", argv[i], 1);
1050 980
1051 doneone = true; 981 doneone = true;
1052 if (strcmp (argv[i], "conditionalrestart") == 0 || 982 if (strcmp (argv[i], "conditionalrestart") == 0 ||
1053 strcmp (argv[i], "condrestart") == 0) 983 strcmp (argv[i], "condrestart") == 0)
1054 { 984 {
1055 if (rc_service_state (service, rc_service_started)) 985 if (rc_service_state (service, rc_service_started))
1056 svc_restart (service, deps); 986 svc_restart (service, deps);
1057 } 987 }
1058 else if (strcmp (argv[i], "restart") == 0) 988 else if (strcmp (argv[i], "restart") == 0)
1059 svc_restart (service, deps); 989 svc_restart (service, deps);
1060 else if (strcmp (argv[i], "start") == 0) 990 else if (strcmp (argv[i], "start") == 0)
1061 svc_start (service, deps); 991 svc_start (service, deps);
1062 else if (strcmp (argv[i], "status") == 0) 992 else if (strcmp (argv[i], "status") == 0) {
1063 {
1064 rc_service_state_t r = svc_status (service); 993 rc_service_state_t r = svc_status (service);
1065 retval = (int) r; 994 retval = (int) r;
1066 }
1067 else if (strcmp (argv[i], "stop") == 0) 995 } else if (strcmp (argv[i], "stop") == 0) {
1068 { 996 if (in_background)
1069 if (in_background)
1070 get_started_services (); 997 get_started_services ();
1071 998
1072 svc_stop (service, deps); 999 svc_stop (service, deps);
1073 1000
1074 if (! in_background && 1001 if (! in_background &&
1075 ! rc_runlevel_stopping () && 1002 ! rc_runlevel_stopping () &&
1076 rc_service_state (service, rc_service_stopped)) 1003 rc_service_state (service, rc_service_stopped))
1077 uncoldplug (applet); 1004 uncoldplug (applet);
1078 1005
1079 if (in_background && 1006 if (in_background &&
1080 rc_service_state (service, rc_service_inactive)) 1007 rc_service_state (service, rc_service_inactive))
1081 { 1008 {
1082 char *svc; 1009 char *svc;
1083 int j; 1010 int j;
1084 STRLIST_FOREACH (restart_services, svc, j) 1011 STRLIST_FOREACH (restart_services, svc, j)
1085 if (rc_service_state (svc, rc_service_stopped)) 1012 if (rc_service_state (svc, rc_service_stopped))
1086 rc_schedule_start_service (service, svc); 1013 rc_schedule_start_service (service, svc);
1087 } 1014 }
1088 }
1089 else if (strcmp (argv[i], "zap") == 0) 1015 } else if (strcmp (argv[i], "zap") == 0) {
1090 {
1091 einfo ("Manually resetting %s to stopped state", applet); 1016 einfo ("Manually resetting %s to stopped state", applet);
1092 rc_mark_service (applet, rc_service_stopped); 1017 rc_mark_service (applet, rc_service_stopped);
1093 uncoldplug (applet); 1018 uncoldplug (applet);
1094 }
1095 else if (strcmp (argv[i], "help") == 0) 1019 } else if (strcmp (argv[i], "help") == 0) {
1096 {
1097 execl (RCSCRIPT_HELP, RCSCRIPT_HELP, service, "help", (char *) NULL); 1020 execl (RCSCRIPT_HELP, RCSCRIPT_HELP, service, "help", (char *) NULL);
1098 eerrorx ("%s: failed to exec `" RCSCRIPT_HELP "': %s", 1021 eerrorx ("%s: failed to exec `" RCSCRIPT_HELP "': %s",
1099 applet, strerror (errno)); 1022 applet, strerror (errno));
1100 } 1023 }else
1101 else
1102 svc_exec (service, argv[i], NULL); 1024 svc_exec (service, argv[i], NULL);
1103 1025
1104 /* Flush our buffered output if any */ 1026 /* Flush our buffered output if any */
1105 eflush (); 1027 eflush ();
1106 1028
1107 /* We should ensure this list is empty after an action is done */ 1029 /* We should ensure this list is empty after an action is done */
1108 rc_strlist_free (restart_services); 1030 rc_strlist_free (restart_services);
1109 restart_services = NULL; 1031 restart_services = NULL;
1110 } 1032 }
1111 1033
1112 if (! doneone) 1034 if (! doneone) {
1113 {
1114 execl (RCSCRIPT_HELP, RCSCRIPT_HELP, service, (char *) NULL); 1035 execl (RCSCRIPT_HELP, RCSCRIPT_HELP, service, (char *) NULL);
1115 eerrorx ("%s: failed to exec `" RCSCRIPT_HELP "': %s", 1036 eerrorx ("%s: failed to exec `" RCSCRIPT_HELP "': %s",
1116 applet, strerror (errno)); 1037 applet, strerror (errno));
1117 } 1038 }
1118 1039
1119 return (retval); 1040 return (retval);
1120} 1041}

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

  ViewVC Help
Powered by ViewVC 1.1.20