| … | |
… | |
| 69 | |
69 | |
| 70 | STRLIST_FOREACH (dirs, dir, i) |
70 | STRLIST_FOREACH (dirs, dir, i) |
| 71 | { |
71 | { |
| 72 | char *path = rc_strcatpaths (RC_RUNLEVELDIR, dir, (char *) NULL); |
72 | char *path = rc_strcatpaths (RC_RUNLEVELDIR, dir, (char *) NULL); |
| 73 | if (rc_is_dir (path)) |
73 | if (rc_is_dir (path)) |
| 74 | runlevels = rc_strlist_addsort (runlevels, dir); |
74 | runlevels = rc_strlist_addsort (runlevels, dir); |
| 75 | free (path); |
75 | free (path); |
| 76 | } |
76 | } |
| 77 | rc_strlist_free (dirs); |
77 | rc_strlist_free (dirs); |
| 78 | |
78 | |
| 79 | return (runlevels); |
79 | return (runlevels); |
| … | |
… | |
| 92 | |
92 | |
| 93 | if (fgets (buffer, PATH_MAX, fp)) |
93 | if (fgets (buffer, PATH_MAX, fp)) |
| 94 | { |
94 | { |
| 95 | int i = strlen (buffer) - 1; |
95 | int i = strlen (buffer) - 1; |
| 96 | if (buffer[i] == '\n') |
96 | if (buffer[i] == '\n') |
| 97 | buffer[i] = 0; |
97 | buffer[i] = 0; |
| 98 | fclose (fp); |
98 | fclose (fp); |
| 99 | return (buffer); |
99 | return (buffer); |
| 100 | } |
100 | } |
| 101 | |
101 | |
| 102 | fclose (fp); |
102 | fclose (fp); |
| … | |
… | |
| 144 | if (! rc_is_link (file)) |
144 | if (! rc_is_link (file)) |
| 145 | { |
145 | { |
| 146 | free (file); |
146 | free (file); |
| 147 | file = rc_strcatpaths (RC_SVCDIR, "inactive", service, (char *) NULL); |
147 | file = rc_strcatpaths (RC_SVCDIR, "inactive", service, (char *) NULL); |
| 148 | if (! rc_is_link (file)) |
148 | if (! rc_is_link (file)) |
| 149 | { |
149 | { |
| 150 | free (file); |
150 | free (file); |
| 151 | file = NULL; |
151 | file = NULL; |
| 152 | } |
152 | } |
| 153 | } |
153 | } |
| 154 | |
154 | |
| 155 | memset (buffer, 0, sizeof (buffer)); |
155 | memset (buffer, 0, sizeof (buffer)); |
| 156 | if (file) |
156 | if (file) |
| 157 | { |
157 | { |
| 158 | r = readlink (file, buffer, sizeof (buffer)); |
158 | r = readlink (file, buffer, sizeof (buffer)); |
| 159 | free (file); |
159 | free (file); |
| 160 | if (r > 0) |
160 | if (r > 0) |
| 161 | return strdup (buffer); |
161 | return strdup (buffer); |
| 162 | } |
162 | } |
| 163 | |
163 | |
| 164 | snprintf (buffer, sizeof (buffer), RC_INITDIR "%s", service); |
164 | snprintf (buffer, sizeof (buffer), RC_INITDIR "%s", service); |
| 165 | return (strdup (buffer)); |
165 | return (strdup (buffer)); |
| 166 | } |
166 | } |
| … | |
… | |
| 199 | |
199 | |
| 200 | if (! rc_service_exists (service)) |
200 | if (! rc_service_exists (service)) |
| 201 | return (false); |
201 | return (false); |
| 202 | |
202 | |
| 203 | file = rc_strcatpaths (RC_RUNLEVELDIR, runlevel, basename (service), |
203 | file = rc_strcatpaths (RC_RUNLEVELDIR, runlevel, basename (service), |
| 204 | (char *) NULL); |
204 | (char *) NULL); |
| 205 | retval = rc_exists (file); |
205 | retval = rc_exists (file); |
| 206 | free (file); |
206 | free (file); |
| 207 | |
207 | |
| 208 | return (retval); |
208 | return (retval); |
| 209 | } |
209 | } |
| … | |
… | |
| 223 | base = basename (service); |
223 | base = basename (service); |
| 224 | |
224 | |
| 225 | if (state != rc_service_stopped) |
225 | if (state != rc_service_stopped) |
| 226 | { |
226 | { |
| 227 | if (! rc_is_file(init)) |
227 | if (! rc_is_file(init)) |
| 228 | { |
228 | { |
| 229 | free (init); |
229 | free (init); |
| 230 | return (false); |
230 | return (false); |
| 231 | } |
231 | } |
| 232 | |
232 | |
| 233 | file = rc_strcatpaths (RC_SVCDIR, rc_service_state_names[state], base, |
233 | file = rc_strcatpaths (RC_SVCDIR, rc_service_state_names[state], base, |
| 234 | (char *) NULL); |
234 | (char *) NULL); |
| 235 | if (rc_exists (file)) |
235 | if (rc_exists (file)) |
| 236 | unlink (file); |
236 | unlink (file); |
| 237 | i = symlink (init, file); |
237 | i = symlink (init, file); |
| 238 | if (i != 0) |
238 | if (i != 0) |
| 239 | { |
239 | { |
| 240 | free (file); |
240 | free (file); |
| 241 | free (init); |
241 | free (init); |
| 242 | einfo ("%d %s %s", state, rc_service_state_names[state], base); |
242 | einfo ("%d %s %s", state, rc_service_state_names[state], base); |
| 243 | eerror ("symlink `%s' to `%s': %s", init, file, strerror (errno)); |
243 | eerror ("symlink `%s' to `%s': %s", init, file, strerror (errno)); |
| 244 | return (false); |
244 | return (false); |
| 245 | } |
245 | } |
| 246 | |
246 | |
| 247 | free (file); |
247 | free (file); |
| 248 | skip_state = state; |
248 | skip_state = state; |
| 249 | } |
249 | } |
| 250 | |
250 | |
| … | |
… | |
| 257 | /* Remove any old states now */ |
257 | /* Remove any old states now */ |
| 258 | i = 0; |
258 | i = 0; |
| 259 | while (rc_service_state_names[i]) |
259 | while (rc_service_state_names[i]) |
| 260 | { |
260 | { |
| 261 | if ((i != skip_state && |
261 | if ((i != skip_state && |
| 262 | i != rc_service_stopped && |
262 | i != rc_service_stopped && |
| 263 | i != rc_service_coldplugged && |
263 | i != rc_service_coldplugged && |
| 264 | i != rc_service_crashed) && |
264 | i != rc_service_crashed) && |
| 265 | (! skip_wasinactive || i != rc_service_wasinactive)) |
265 | (! skip_wasinactive || i != rc_service_wasinactive)) |
| 266 | { |
266 | { |
| 267 | file = rc_strcatpaths (RC_SVCDIR, rc_service_state_names[i], base, |
267 | file = rc_strcatpaths (RC_SVCDIR, rc_service_state_names[i], base, |
| 268 | (char *) NULL); |
268 | (char *) NULL); |
| 269 | if (rc_exists (file)) |
269 | if (rc_exists (file)) |
| 270 | { |
270 | { |
| 271 | if ((state == rc_service_starting || |
271 | if ((state == rc_service_starting || |
| 272 | state == rc_service_stopping) && |
272 | state == rc_service_stopping) && |
| 273 | i == rc_service_inactive) |
273 | i == rc_service_inactive) |
| 274 | { |
274 | { |
| 275 | char *wasfile = rc_strcatpaths (RC_SVCDIR, |
275 | char *wasfile = rc_strcatpaths (RC_SVCDIR, |
| 276 | rc_service_state_names[rc_service_wasinactive], |
276 | rc_service_state_names[rc_service_wasinactive], |
| 277 | base, (char *) NULL); |
277 | base, (char *) NULL); |
| 278 | |
278 | |
| 279 | if (symlink (init, wasfile) != 0) |
279 | if (symlink (init, wasfile) != 0) |
| 280 | eerror ("symlink `%s' to `%s': %s", init, wasfile, |
280 | eerror ("symlink `%s' to `%s': %s", init, wasfile, |
| 281 | strerror (errno)); |
281 | strerror (errno)); |
| 282 | |
282 | |
| 283 | skip_wasinactive = true; |
283 | skip_wasinactive = true; |
| 284 | free (wasfile); |
284 | free (wasfile); |
| 285 | } |
285 | } |
| 286 | |
286 | |
| 287 | errno = 0; |
287 | errno = 0; |
| 288 | if (unlink (file) != 0 && errno != ENOENT) |
288 | if (unlink (file) != 0 && errno != ENOENT) |
| 289 | eerror ("failed to delete `%s': %s", file, |
289 | eerror ("failed to delete `%s': %s", file, |
| 290 | strerror (errno)); |
290 | strerror (errno)); |
| 291 | } |
291 | } |
| 292 | free (file); |
292 | free (file); |
| 293 | } |
293 | } |
| 294 | i++; |
294 | i++; |
| 295 | } |
295 | } |
| 296 | |
296 | |
| 297 | /* Remove the exclusive state if we're inactive */ |
297 | /* Remove the exclusive state if we're inactive */ |
| 298 | if (state == rc_service_started || |
298 | if (state == rc_service_started || |
| 299 | state == rc_service_stopped || |
299 | state == rc_service_stopped || |
| 300 | state == rc_service_inactive) |
300 | state == rc_service_inactive) |
| 301 | { |
301 | { |
| 302 | file = rc_strcatpaths (RC_SVCDIR, "exclusive", base, (char *) NULL); |
302 | file = rc_strcatpaths (RC_SVCDIR, "exclusive", base, (char *) NULL); |
| 303 | if (rc_exists (file)) |
303 | if (rc_exists (file)) |
| 304 | if (unlink (file) != 0) |
304 | if (unlink (file) != 0) |
| 305 | eerror ("unlink `%s': %s", file, strerror (errno)); |
305 | eerror ("unlink `%s': %s", file, strerror (errno)); |
| 306 | free (file); |
306 | free (file); |
| 307 | } |
307 | } |
| 308 | |
308 | |
| 309 | /* Remove any options and daemons the service may have stored */ |
309 | /* Remove any options and daemons the service may have stored */ |
| 310 | if (state == rc_service_stopped) |
310 | if (state == rc_service_stopped) |
| 311 | { |
311 | { |
| 312 | char *dir = rc_strcatpaths (RC_SVCDIR, "options", base, (char *) NULL); |
312 | char *dir = rc_strcatpaths (RC_SVCDIR, "options", base, (char *) NULL); |
| 313 | |
313 | |
| 314 | if (rc_is_dir (dir)) |
314 | if (rc_is_dir (dir)) |
| 315 | rc_rm_dir (dir, true); |
315 | rc_rm_dir (dir, true); |
| 316 | free (dir); |
316 | free (dir); |
| 317 | |
317 | |
| 318 | dir = rc_strcatpaths (RC_SVCDIR, "daemons", base, (char *) NULL); |
318 | dir = rc_strcatpaths (RC_SVCDIR, "daemons", base, (char *) NULL); |
| 319 | if (rc_is_dir (dir)) |
319 | if (rc_is_dir (dir)) |
| 320 | rc_rm_dir (dir, true); |
320 | rc_rm_dir (dir, true); |
| 321 | free (dir); |
321 | free (dir); |
| 322 | |
322 | |
| 323 | rc_schedule_clear (service); |
323 | rc_schedule_clear (service); |
| 324 | } |
324 | } |
| 325 | |
325 | |
| 326 | /* These are final states, so remove us from scheduled */ |
326 | /* These are final states, so remove us from scheduled */ |
| 327 | if (state == rc_service_started || state == rc_service_stopped) |
327 | if (state == rc_service_started || state == rc_service_stopped) |
| … | |
… | |
| 330 | char **dirs = rc_ls_dir (NULL, sdir, 0); |
330 | char **dirs = rc_ls_dir (NULL, sdir, 0); |
| 331 | char *dir; |
331 | char *dir; |
| 332 | int serrno; |
332 | int serrno; |
| 333 | |
333 | |
| 334 | STRLIST_FOREACH (dirs, dir, i) |
334 | STRLIST_FOREACH (dirs, dir, i) |
| 335 | { |
335 | { |
| 336 | char *bdir = rc_strcatpaths (sdir, dir, (char *) NULL); |
336 | char *bdir = rc_strcatpaths (sdir, dir, (char *) NULL); |
| 337 | file = rc_strcatpaths (bdir, base, (char *) NULL); |
337 | file = rc_strcatpaths (bdir, base, (char *) NULL); |
| 338 | if (rc_exists (file)) |
338 | if (rc_exists (file)) |
| 339 | if (unlink (file) != 0) |
339 | if (unlink (file) != 0) |
| 340 | eerror ("unlink `%s': %s", file, strerror (errno)); |
340 | eerror ("unlink `%s': %s", file, strerror (errno)); |
| 341 | free (file); |
341 | free (file); |
| 342 | |
342 | |
| 343 | /* Try and remove the dir - we don't care about errors */ |
343 | /* Try and remove the dir - we don't care about errors */ |
| 344 | serrno = errno; |
344 | serrno = errno; |
| 345 | rmdir (bdir); |
345 | rmdir (bdir); |
| 346 | errno = serrno; |
346 | errno = serrno; |
| 347 | free (bdir); |
347 | free (bdir); |
| 348 | } |
348 | } |
| 349 | rc_strlist_free (dirs); |
349 | rc_strlist_free (dirs); |
| 350 | free (sdir); |
350 | free (sdir); |
| 351 | } |
351 | } |
| 352 | |
352 | |
| 353 | free (init); |
353 | free (init); |
| … | |
… | |
| 364 | return (state == rc_service_stopped ? true : false); |
364 | return (state == rc_service_stopped ? true : false); |
| 365 | |
365 | |
| 366 | /* We check stopped state by not being in any of the others */ |
366 | /* We check stopped state by not being in any of the others */ |
| 367 | if (state == rc_service_stopped) |
367 | if (state == rc_service_stopped) |
| 368 | return ( ! (rc_service_state (service, rc_service_started) || |
368 | return ( ! (rc_service_state (service, rc_service_started) || |
| 369 | rc_service_state (service, rc_service_starting) || |
369 | rc_service_state (service, rc_service_starting) || |
| 370 | rc_service_state (service, rc_service_stopping) || |
370 | rc_service_state (service, rc_service_stopping) || |
| 371 | rc_service_state (service, rc_service_inactive))); |
371 | rc_service_state (service, rc_service_inactive))); |
| 372 | |
372 | |
| 373 | /* The crashed state and scheduled states are virtual */ |
373 | /* The crashed state and scheduled states are virtual */ |
| 374 | if (state == rc_service_crashed) |
374 | if (state == rc_service_crashed) |
| 375 | return (rc_service_daemons_crashed (service)); |
375 | return (rc_service_daemons_crashed (service)); |
| 376 | else if (state == rc_service_scheduled) |
376 | else if (state == rc_service_scheduled) |
| 377 | { |
377 | { |
| 378 | char **services = rc_services_scheduled_by (service); |
378 | char **services = rc_services_scheduled_by (service); |
| 379 | retval = (services); |
379 | retval = (services); |
| 380 | if (services) |
380 | if (services) |
| 381 | free (services); |
381 | free (services); |
| 382 | return (retval); |
382 | return (retval); |
| 383 | } |
383 | } |
| 384 | |
384 | |
| 385 | /* Now we just check if a file by the service name rc_exists |
385 | /* Now we just check if a file by the service name rc_exists |
| 386 | in the state dir */ |
386 | in the state dir */ |
| 387 | file = rc_strcatpaths (RC_SVCDIR, rc_service_state_names[state], |
387 | file = rc_strcatpaths (RC_SVCDIR, rc_service_state_names[state], |
| 388 | basename (service), (char*) NULL); |
388 | basename (service), (char*) NULL); |
| 389 | retval = rc_exists (file); |
389 | retval = rc_exists (file); |
| 390 | free (file); |
390 | free (file); |
| 391 | return (retval); |
391 | return (retval); |
| 392 | } |
392 | } |
| 393 | |
393 | |
| 394 | bool rc_get_service_option (const char *service, const char *option, |
394 | bool rc_get_service_option (const char *service, const char *option, |
| 395 | char *value) |
395 | char *value) |
| 396 | { |
396 | { |
| 397 | FILE *fp; |
397 | FILE *fp; |
| 398 | char buffer[RC_LINEBUFFER]; |
398 | char buffer[RC_LINEBUFFER]; |
| 399 | char *file = rc_strcatpaths (RC_SVCDIR, "options", service, option, |
399 | char *file = rc_strcatpaths (RC_SVCDIR, "options", service, option, |
| 400 | (char *) NULL); |
400 | (char *) NULL); |
| 401 | bool retval = false; |
401 | bool retval = false; |
| 402 | |
402 | |
| 403 | if (rc_exists (file)) |
403 | if (rc_exists (file)) |
| 404 | { |
404 | { |
| 405 | if ((fp = fopen (file, "r")) == NULL) |
405 | if ((fp = fopen (file, "r")) == NULL) |
| 406 | eerror ("fopen `%s': %s", file, strerror (errno)); |
406 | eerror ("fopen `%s': %s", file, strerror (errno)); |
| 407 | else |
407 | else |
| 408 | { |
408 | { |
| 409 | memset (buffer, 0, sizeof (buffer)); |
409 | memset (buffer, 0, sizeof (buffer)); |
| 410 | while (fgets (buffer, RC_LINEBUFFER, fp)) |
410 | while (fgets (buffer, RC_LINEBUFFER, fp)) |
| 411 | { |
411 | { |
| 412 | memcpy (value, buffer, strlen (buffer)); |
412 | memcpy (value, buffer, strlen (buffer)); |
| 413 | value += strlen (buffer); |
413 | value += strlen (buffer); |
| 414 | } |
414 | } |
| 415 | fclose (fp); |
415 | fclose (fp); |
| 416 | retval = true; |
416 | retval = true; |
| 417 | } |
417 | } |
| 418 | } |
418 | } |
| 419 | |
419 | |
| 420 | free (file); |
420 | free (file); |
| 421 | return (retval); |
421 | return (retval); |
| 422 | } |
422 | } |
| 423 | |
423 | |
| 424 | bool rc_set_service_option (const char *service, const char *option, |
424 | bool rc_set_service_option (const char *service, const char *option, |
| 425 | const char *value) |
425 | const char *value) |
| 426 | { |
426 | { |
| 427 | FILE *fp; |
427 | FILE *fp; |
| 428 | char *path = rc_strcatpaths (RC_SVCDIR, "options", service, (char *) NULL); |
428 | char *path = rc_strcatpaths (RC_SVCDIR, "options", service, (char *) NULL); |
| 429 | char *file = rc_strcatpaths (path, option, (char *) NULL); |
429 | char *file = rc_strcatpaths (path, option, (char *) NULL); |
| 430 | bool retval = false; |
430 | bool retval = false; |
| 431 | |
431 | |
| 432 | if (! rc_is_dir (path)) |
432 | if (! rc_is_dir (path)) |
| 433 | { |
433 | { |
| 434 | if (mkdir (path, 0755) != 0) |
434 | if (mkdir (path, 0755) != 0) |
| 435 | { |
435 | { |
| 436 | eerror ("mkdir `%s': %s", path, strerror (errno)); |
436 | eerror ("mkdir `%s': %s", path, strerror (errno)); |
| 437 | free (path); |
437 | free (path); |
| 438 | free (file); |
438 | free (file); |
| 439 | return (false); |
439 | return (false); |
| 440 | } |
440 | } |
| 441 | } |
441 | } |
| 442 | |
442 | |
| 443 | if ((fp = fopen (file, "w")) == NULL) |
443 | if ((fp = fopen (file, "w")) == NULL) |
| 444 | eerror ("fopen `%s': %s", file, strerror (errno)); |
444 | eerror ("fopen `%s': %s", file, strerror (errno)); |
| 445 | else |
445 | else |
| 446 | { |
446 | { |
| 447 | if (value) |
447 | if (value) |
| 448 | fprintf (fp, "%s", value); |
448 | fprintf (fp, "%s", value); |
| 449 | fclose (fp); |
449 | fclose (fp); |
| 450 | retval = true; |
450 | retval = true; |
| 451 | } |
451 | } |
| 452 | |
452 | |
| 453 | free (path); |
453 | free (path); |
| … | |
… | |
| 471 | return (0); |
471 | return (0); |
| 472 | } |
472 | } |
| 473 | |
473 | |
| 474 | /* We create a fifo so that other services can wait until we complete */ |
474 | /* We create a fifo so that other services can wait until we complete */ |
| 475 | fifo = rc_strcatpaths (RC_SVCDIR, "exclusive", basename (service), |
475 | fifo = rc_strcatpaths (RC_SVCDIR, "exclusive", basename (service), |
| 476 | (char *) NULL); |
476 | (char *) NULL); |
| 477 | |
477 | |
| 478 | if (mkfifo (fifo, 0600) != 0 && errno != EEXIST) |
478 | if (mkfifo (fifo, 0600) != 0 && errno != EEXIST) |
| 479 | { |
479 | { |
| 480 | eerror ("unable to create fifo `%s': %s", fifo, strerror (errno)); |
480 | eerror ("unable to create fifo `%s': %s", fifo, strerror (errno)); |
| 481 | free (fifo); |
481 | free (fifo); |
| … | |
… | |
| 511 | errno = 0; |
511 | errno = 0; |
| 512 | do |
512 | do |
| 513 | { |
513 | { |
| 514 | pid = waitpid (savedpid, &status, 0); |
514 | pid = waitpid (savedpid, &status, 0); |
| 515 | if (pid < 0) |
515 | if (pid < 0) |
| 516 | { |
516 | { |
| 517 | if (errno != ECHILD) |
517 | if (errno != ECHILD) |
| 518 | eerror ("waitpid %d: %s", savedpid, strerror (errno)); |
518 | eerror ("waitpid %d: %s", savedpid, strerror (errno)); |
| 519 | return (-1); |
519 | return (-1); |
| 520 | } |
520 | } |
| 521 | } while (! WIFEXITED (status) && ! WIFSIGNALED (status)); |
521 | } while (! WIFEXITED (status) && ! WIFSIGNALED (status)); |
| 522 | |
522 | |
| 523 | return (0); |
523 | return (0); |
| 524 | } |
524 | } |
| 525 | |
525 | |
| … | |
… | |
| 539 | |
539 | |
| 540 | return (_exec_service (service, "start")); |
540 | return (_exec_service (service, "start")); |
| 541 | } |
541 | } |
| 542 | |
542 | |
| 543 | void rc_schedule_start_service (const char *service, |
543 | void rc_schedule_start_service (const char *service, |
| 544 | const char *service_to_start) |
544 | const char *service_to_start) |
| 545 | { |
545 | { |
| 546 | char *dir; |
546 | char *dir; |
| 547 | char *init; |
547 | char *init; |
| 548 | char *file; |
548 | char *file; |
| 549 | |
549 | |
| 550 | if (! rc_service_exists (service) || ! rc_service_exists (service_to_start)) |
550 | if (! rc_service_exists (service) || ! rc_service_exists (service_to_start)) |
| 551 | return; |
551 | return; |
| 552 | |
552 | |
| 553 | dir = rc_strcatpaths (RC_SVCDIR, "scheduled", basename (service), |
553 | dir = rc_strcatpaths (RC_SVCDIR, "scheduled", basename (service), |
| 554 | (char *) NULL); |
554 | (char *) NULL); |
| 555 | if (! rc_is_dir (dir)) |
555 | if (! rc_is_dir (dir)) |
| 556 | if (mkdir (dir, 0755) != 0) |
556 | if (mkdir (dir, 0755) != 0) |
| 557 | { |
557 | { |
| 558 | eerror ("mkdir `%s': %s", dir, strerror (errno)); |
558 | eerror ("mkdir `%s': %s", dir, strerror (errno)); |
| 559 | free (dir); |
559 | free (dir); |
| 560 | return; |
560 | return; |
| 561 | } |
561 | } |
| 562 | |
562 | |
| 563 | init = rc_resolve_service (service_to_start); |
563 | init = rc_resolve_service (service_to_start); |
| 564 | file = rc_strcatpaths (dir, basename (service_to_start), (char *) NULL); |
564 | file = rc_strcatpaths (dir, basename (service_to_start), (char *) NULL); |
| 565 | if (! rc_exists (file) && symlink (init, file) != 0) |
565 | if (! rc_exists (file) && symlink (init, file) != 0) |
| … | |
… | |
| 571 | } |
571 | } |
| 572 | |
572 | |
| 573 | void rc_schedule_clear (const char *service) |
573 | void rc_schedule_clear (const char *service) |
| 574 | { |
574 | { |
| 575 | char *dir = rc_strcatpaths (RC_SVCDIR, "scheduled", basename (service), |
575 | char *dir = rc_strcatpaths (RC_SVCDIR, "scheduled", basename (service), |
| 576 | (char *) NULL); |
576 | (char *) NULL); |
| 577 | |
577 | |
| 578 | if (rc_is_dir (dir)) |
578 | if (rc_is_dir (dir)) |
| 579 | rc_rm_dir (dir, true); |
579 | rc_rm_dir (dir, true); |
| 580 | free (dir); |
580 | free (dir); |
| 581 | } |
581 | } |
| 582 | |
582 | |
| 583 | bool rc_wait_service (const char *service) |
583 | bool rc_wait_service (const char *service) |
| 584 | { |
584 | { |
| 585 | char *fifo = rc_strcatpaths (RC_SVCDIR, "exclusive", basename (service), |
585 | char *fifo = rc_strcatpaths (RC_SVCDIR, "exclusive", basename (service), |
| 586 | (char *) NULL); |
586 | (char *) NULL); |
| 587 | struct timeval tv; |
587 | struct timeval tv; |
| 588 | struct timeval stopat; |
588 | struct timeval stopat; |
| 589 | struct timeval now; |
589 | struct timeval now; |
| 590 | bool retval = false; |
590 | bool retval = false; |
| 591 | |
591 | |
| … | |
… | |
| 597 | stopat.tv_sec += WAIT_MAX; |
597 | stopat.tv_sec += WAIT_MAX; |
| 598 | |
598 | |
| 599 | while (true) |
599 | while (true) |
| 600 | { |
600 | { |
| 601 | if (! rc_exists (fifo)) |
601 | if (! rc_exists (fifo)) |
| 602 | { |
602 | { |
| 603 | retval = true; |
603 | retval = true; |
| 604 | break; |
604 | break; |
| 605 | } |
605 | } |
| 606 | |
606 | |
| 607 | tv.tv_sec = 0; |
607 | tv.tv_sec = 0; |
| 608 | tv.tv_usec = WAIT_INTERVAL; |
608 | tv.tv_usec = WAIT_INTERVAL; |
| 609 | if (select (0, 0, 0, 0, &tv) < 0) |
609 | if (select (0, 0, 0, 0, &tv) < 0) |
| 610 | { |
610 | { |
| 611 | if (errno != EINTR) |
611 | if (errno != EINTR) |
| 612 | eerror ("select: %s",strerror (errno)); |
612 | eerror ("select: %s",strerror (errno)); |
| 613 | break; |
613 | break; |
| 614 | } |
614 | } |
| 615 | |
615 | |
| 616 | /* Don't hang around forever */ |
616 | /* Don't hang around forever */ |
| 617 | if (gettimeofday (&now, NULL) != 0) |
617 | if (gettimeofday (&now, NULL) != 0) |
| 618 | { |
618 | { |
| 619 | eerror ("gettimeofday: %s", strerror (errno)); |
619 | eerror ("gettimeofday: %s", strerror (errno)); |
| 620 | break; |
620 | break; |
| 621 | } |
621 | } |
| 622 | if (timercmp (&now, &stopat, >)) |
622 | if (timercmp (&now, &stopat, >)) |
| 623 | break; |
623 | break; |
| 624 | } |
624 | } |
| 625 | |
625 | |
| 626 | free (fifo); |
626 | free (fifo); |
| 627 | return (retval); |
627 | return (retval); |
| 628 | } |
628 | } |
| … | |
… | |
| 640 | strcmp (runlevel, RC_LEVEL_SINGLE) == 0) |
640 | strcmp (runlevel, RC_LEVEL_SINGLE) == 0) |
| 641 | return (NULL); |
641 | return (NULL); |
| 642 | |
642 | |
| 643 | dir = rc_strcatpaths (RC_RUNLEVELDIR, runlevel, (char *) NULL); |
643 | dir = rc_strcatpaths (RC_RUNLEVELDIR, runlevel, (char *) NULL); |
| 644 | if (! rc_is_dir (dir)) |
644 | if (! rc_is_dir (dir)) |
| 645 | eerror ("runlevel `%s' does not exist", runlevel); |
645 | eerror ("runlevel `%s' does not exist", runlevel); |
| 646 | else |
646 | else |
| 647 | list = rc_ls_dir (list, dir, RC_LS_INITD); |
647 | list = rc_ls_dir (list, dir, RC_LS_INITD); |
| 648 | |
648 | |
| 649 | free (dir); |
649 | free (dir); |
| 650 | return (list); |
650 | return (list); |
| 651 | } |
651 | } |
| 652 | |
652 | |
| 653 | char **rc_services_in_state (rc_service_state_t state) |
653 | char **rc_services_in_state (rc_service_state_t state) |
| 654 | { |
654 | { |
| 655 | char *dir = rc_strcatpaths (RC_SVCDIR, rc_service_state_names[state], |
655 | char *dir = rc_strcatpaths (RC_SVCDIR, rc_service_state_names[state], |
| 656 | (char *) NULL); |
656 | (char *) NULL); |
| 657 | char **list = NULL; |
657 | char **list = NULL; |
| 658 | |
658 | |
| 659 | if (rc_is_dir (dir)) |
659 | if (rc_is_dir (dir)) |
| 660 | list = rc_ls_dir (list, dir, RC_LS_INITD); |
660 | list = rc_ls_dir (list, dir, RC_LS_INITD); |
| 661 | |
661 | |
| … | |
… | |
| 672 | if (! rc_runlevel_exists (runlevel)) |
672 | if (! rc_runlevel_exists (runlevel)) |
| 673 | { |
673 | { |
| 674 | errno = ENOENT; |
674 | errno = ENOENT; |
| 675 | return (false); |
675 | return (false); |
| 676 | } |
676 | } |
| 677 | |
677 | |
| 678 | if (rc_service_in_runlevel (service, runlevel)) |
678 | if (rc_service_in_runlevel (service, runlevel)) |
| 679 | { |
679 | { |
| 680 | errno = EEXIST; |
680 | errno = EEXIST; |
| 681 | return (false); |
681 | return (false); |
| 682 | } |
682 | } |
| 683 | |
683 | |
| 684 | init = rc_resolve_service (service); |
684 | init = rc_resolve_service (service); |
| 685 | file = rc_strcatpaths (RC_RUNLEVELDIR, runlevel, basename (service), |
685 | file = rc_strcatpaths (RC_RUNLEVELDIR, runlevel, basename (service), |
| 686 | (char *) NULL); |
686 | (char *) NULL); |
| 687 | retval = (symlink (init, file) == 0); |
687 | retval = (symlink (init, file) == 0); |
| 688 | free (init); |
688 | free (init); |
| 689 | free (file); |
689 | free (file); |
| 690 | return (retval); |
690 | return (retval); |
| 691 | } |
691 | } |
| … | |
… | |
| 695 | char *file; |
695 | char *file; |
| 696 | bool retval = false; |
696 | bool retval = false; |
| 697 | |
697 | |
| 698 | if (! runlevel || ! service) |
698 | if (! runlevel || ! service) |
| 699 | return (false); |
699 | return (false); |
| 700 | |
700 | |
| 701 | file = rc_strcatpaths (RC_RUNLEVELDIR, runlevel, basename (service), |
701 | file = rc_strcatpaths (RC_RUNLEVELDIR, runlevel, basename (service), |
| 702 | (char *) NULL); |
702 | (char *) NULL); |
| 703 | if (unlink (file) == 0) |
703 | if (unlink (file) == 0) |
| 704 | retval = true; |
704 | retval = true; |
| 705 | |
705 | |
| 706 | free (file); |
706 | free (file); |
| 707 | return (retval); |
707 | return (retval); |
| 708 | } |
708 | } |
| 709 | |
709 | |
| 710 | char **rc_services_scheduled_by (const char *service) |
710 | char **rc_services_scheduled_by (const char *service) |
| … | |
… | |
| 715 | int i; |
715 | int i; |
| 716 | |
716 | |
| 717 | STRLIST_FOREACH (dirs, dir, i) |
717 | STRLIST_FOREACH (dirs, dir, i) |
| 718 | { |
718 | { |
| 719 | char *file = rc_strcatpaths (RC_SVCDIR "scheduled", dir, service, |
719 | char *file = rc_strcatpaths (RC_SVCDIR "scheduled", dir, service, |
| 720 | (char *) NULL); |
720 | (char *) NULL); |
| 721 | if (rc_exists (file)) |
721 | if (rc_exists (file)) |
| 722 | list = rc_strlist_add (list, file); |
722 | list = rc_strlist_add (list, file); |
| 723 | free (file); |
723 | free (file); |
| 724 | } |
724 | } |
| 725 | rc_strlist_free (dirs); |
725 | rc_strlist_free (dirs); |
| 726 | |
726 | |
| 727 | return (list); |
727 | return (list); |
| 728 | } |
728 | } |
| 729 | |
729 | |
| 730 | char **rc_services_scheduled (const char *service) |
730 | char **rc_services_scheduled (const char *service) |
| 731 | { |
731 | { |
| 732 | char *dir = rc_strcatpaths (RC_SVCDIR, "scheduled", basename (service), |
732 | char *dir = rc_strcatpaths (RC_SVCDIR, "scheduled", basename (service), |
| 733 | (char *) NULL); |
733 | (char *) NULL); |
| 734 | char **list = NULL; |
734 | char **list = NULL; |
| 735 | |
735 | |
| 736 | if (rc_is_dir (dir)) |
736 | if (rc_is_dir (dir)) |
| 737 | list = rc_ls_dir (list, dir, RC_LS_INITD); |
737 | list = rc_ls_dir (list, dir, RC_LS_INITD); |
| 738 | |
738 | |
| … | |
… | |
| 755 | p = list; |
755 | p = list; |
| 756 | while ((token = strsep (&p, " "))) |
756 | while ((token = strsep (&p, " "))) |
| 757 | { |
757 | { |
| 758 | bool truefalse = true; |
758 | bool truefalse = true; |
| 759 | if (token[0] == '!') |
759 | if (token[0] == '!') |
| 760 | { |
760 | { |
| 761 | truefalse = false; |
761 | truefalse = false; |
| 762 | token++; |
762 | token++; |
| 763 | } |
763 | } |
| 764 | |
764 | |
| 765 | star = strchr (token, '*'); |
765 | star = strchr (token, '*'); |
| 766 | if (star) |
766 | if (star) |
| 767 | { |
767 | { |
| 768 | if (strncmp (service, token, star - token) == 0) |
768 | if (strncmp (service, token, star - token) == 0) |
| 769 | { |
769 | { |
| 770 | allow = truefalse; |
770 | allow = truefalse; |
| 771 | break; |
771 | break; |
| 772 | } |
772 | } |
| 773 | } |
773 | } |
| 774 | else |
774 | else |
| 775 | { |
775 | { |
| 776 | if (strcmp (service, token) == 0) |
776 | if (strcmp (service, token) == 0) |
| 777 | { |
777 | { |
| 778 | allow = truefalse; |
778 | allow = truefalse; |
| 779 | break; |
779 | break; |
| 780 | } |
780 | } |
| 781 | } |
781 | } |
| 782 | } |
782 | } |
| 783 | |
783 | |
| 784 | free (list); |
784 | free (list); |
| 785 | return (allow); |
785 | return (allow); |
| 786 | } |
786 | } |