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

Diff of /trunk/src/librc.c

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

Revision 2573 Revision 2577
37#define WAIT_MAX 60 37#define WAIT_MAX 60
38 38
39#define SOFTLEVEL RC_SVCDIR "softlevel" 39#define SOFTLEVEL RC_SVCDIR "softlevel"
40 40
41static const char *rc_service_state_names[] = { 41static const char *rc_service_state_names[] = {
42 "started", 42 "started",
43 "stopped", 43 "stopped",
44 "starting", 44 "starting",
45 "stopping", 45 "stopping",
46 "inactive", 46 "inactive",
47 "wasinactive", 47 "wasinactive",
48 "coldplugged", 48 "coldplugged",
49 "failed", 49 "failed",
50 "scheduled", 50 "scheduled",
51 NULL 51 NULL
52}; 52};
53 53
54bool rc_runlevel_starting (void) 54bool rc_runlevel_starting (void)
55{ 55{
56 return (rc_is_dir (RC_SVCDIR "softscripts.old")); 56 return (rc_is_dir (RC_SVCDIR "softscripts.old"));
57} 57}
58 58
59bool rc_runlevel_stopping (void) 59bool rc_runlevel_stopping (void)
60{ 60{
61 return (rc_is_dir (RC_SVCDIR "softscripts.new")); 61 return (rc_is_dir (RC_SVCDIR "softscripts.new"));
62} 62}
63 63
64char **rc_get_runlevels (void) 64char **rc_get_runlevels (void)
65{ 65{
66 char **dirs = rc_ls_dir (NULL, RC_RUNLEVELDIR, 0); 66 char **dirs = rc_ls_dir (NULL, RC_RUNLEVELDIR, 0);
67 char **runlevels = NULL; 67 char **runlevels = NULL;
68 int i; 68 int i;
69 char *dir; 69 char *dir;
70 70
71 STRLIST_FOREACH (dirs, dir, i) 71 STRLIST_FOREACH (dirs, dir, i) {
72 {
73 char *path = rc_strcatpaths (RC_RUNLEVELDIR, dir, (char *) NULL); 72 char *path = rc_strcatpaths (RC_RUNLEVELDIR, dir, (char *) NULL);
74 if (rc_is_dir (path)) 73 if (rc_is_dir (path))
75 runlevels = rc_strlist_addsort (runlevels, dir); 74 runlevels = rc_strlist_addsort (runlevels, dir);
76 free (path); 75 free (path);
77 } 76 }
78 rc_strlist_free (dirs); 77 rc_strlist_free (dirs);
79 78
80 return (runlevels); 79 return (runlevels);
81} 80}
82 81
83char *rc_get_runlevel (void) 82char *rc_get_runlevel (void)
84{ 83{
85 FILE *fp; 84 FILE *fp;
86 static char buffer [PATH_MAX]; 85 static char buffer [PATH_MAX];
87 86
88 if (! (fp = fopen (SOFTLEVEL, "r"))) 87 if (! (fp = fopen (SOFTLEVEL, "r"))) {
89 {
90 snprintf (buffer, sizeof (buffer), "sysinit"); 88 snprintf (buffer, sizeof (buffer), "sysinit");
91 return (buffer); 89 return (buffer);
92 } 90 }
93 91
94 if (fgets (buffer, PATH_MAX, fp)) 92 if (fgets (buffer, PATH_MAX, fp)) {
95 {
96 int i = strlen (buffer) - 1; 93 int i = strlen (buffer) - 1;
97 if (buffer[i] == '\n') 94 if (buffer[i] == '\n')
98 buffer[i] = 0; 95 buffer[i] = 0;
99 fclose (fp); 96 fclose (fp);
100 return (buffer); 97 return (buffer);
101 } 98 }
102 99
103 fclose (fp); 100 fclose (fp);
104 snprintf (buffer, sizeof (buffer), "sysinit"); 101 snprintf (buffer, sizeof (buffer), "sysinit");
105 return (buffer); 102 return (buffer);
106} 103}
107 104
108void rc_set_runlevel (const char *runlevel) 105void rc_set_runlevel (const char *runlevel)
109{ 106{
110 FILE *fp = fopen (SOFTLEVEL, "w"); 107 FILE *fp = fopen (SOFTLEVEL, "w");
111 if (! fp) 108 if (! fp)
112 eerrorx ("failed to open `" SOFTLEVEL "': %s", strerror (errno)); 109 eerrorx ("failed to open `" SOFTLEVEL "': %s", strerror (errno));
113 fprintf (fp, "%s", runlevel); 110 fprintf (fp, "%s", runlevel);
114 fclose (fp); 111 fclose (fp);
115} 112}
116 113
117bool rc_runlevel_exists (const char *runlevel) 114bool rc_runlevel_exists (const char *runlevel)
118{ 115{
119 char *path; 116 char *path;
120 bool retval; 117 bool retval;
121 118
122 if (! runlevel) 119 if (! runlevel)
123 return (false); 120 return (false);
124 121
125 path = rc_strcatpaths (RC_RUNLEVELDIR, runlevel, (char *) NULL); 122 path = rc_strcatpaths (RC_RUNLEVELDIR, runlevel, (char *) NULL);
126 retval = rc_is_dir (path); 123 retval = rc_is_dir (path);
127 free (path); 124 free (path);
128 return (retval); 125 return (retval);
129} 126}
130 127
131/* Resolve a service name to it's full path */ 128/* Resolve a service name to it's full path */
132char *rc_resolve_service (const char *service) 129char *rc_resolve_service (const char *service)
133{ 130{
134 char buffer[PATH_MAX]; 131 char buffer[PATH_MAX];
135 char *file; 132 char *file;
136 int r = 0; 133 int r = 0;
137 134
138 if (! service) 135 if (! service)
139 return (NULL); 136 return (NULL);
140 137
141 if (service[0] == '/') 138 if (service[0] == '/')
142 return (strdup (service)); 139 return (strdup (service));
143 140
144 file = rc_strcatpaths (RC_SVCDIR, "started", service, (char *) NULL); 141 file = rc_strcatpaths (RC_SVCDIR, "started", service, (char *) NULL);
145 if (! rc_is_link (file)) 142 if (! rc_is_link (file)) {
146 {
147 free (file); 143 free (file);
148 file = rc_strcatpaths (RC_SVCDIR, "inactive", service, (char *) NULL); 144 file = rc_strcatpaths (RC_SVCDIR, "inactive", service, (char *) NULL);
149 if (! rc_is_link (file)) 145 if (! rc_is_link (file)) {
150 { 146 free (file);
151 free (file); 147 file = NULL;
152 file = NULL; 148 }
153 } 149 }
154 }
155 150
156 memset (buffer, 0, sizeof (buffer)); 151 memset (buffer, 0, sizeof (buffer));
157 if (file) 152 if (file) {
158 {
159 r = readlink (file, buffer, sizeof (buffer)); 153 r = readlink (file, buffer, sizeof (buffer));
160 free (file); 154 free (file);
161 if (r > 0) 155 if (r > 0)
162 return strdup (buffer); 156 return strdup (buffer);
163 } 157 }
164 158
165 snprintf (buffer, sizeof (buffer), RC_INITDIR "%s", service); 159 snprintf (buffer, sizeof (buffer), RC_INITDIR "%s", service);
166 return (strdup (buffer)); 160 return (strdup (buffer));
167} 161}
168 162
169bool rc_service_exists (const char *service) 163bool rc_service_exists (const char *service)
170{ 164{
171 char *file; 165 char *file;
172 bool retval = false; 166 bool retval = false;
173 int len; 167 int len;
174 168
175 if (! service) 169 if (! service)
176 return (false); 170 return (false);
177 171
178 len = strlen (service); 172 len = strlen (service);
179 173
180 /* .sh files are not init scripts */ 174 /* .sh files are not init scripts */
181 if (len > 2 && service[len - 3] == '.' && 175 if (len > 2 && service[len - 3] == '.' &&
182 service[len - 2] == 's' && 176 service[len - 2] == 's' &&
183 service[len - 1] == 'h') 177 service[len - 1] == 'h')
184 return (false); 178 return (false);
185 179
186 file = rc_resolve_service (service); 180 file = rc_resolve_service (service);
187 if (rc_exists (file)) 181 if (rc_exists (file))
188 retval = rc_is_exec (file); 182 retval = rc_is_exec (file);
189 free (file); 183 free (file);
190 return (retval); 184 return (retval);
191} 185}
192 186
193bool rc_service_in_runlevel (const char *service, const char *runlevel) 187bool rc_service_in_runlevel (const char *service, const char *runlevel)
194{ 188{
195 char *file; 189 char *file;
196 bool retval; 190 bool retval;
197 191
198 if (! runlevel || ! service) 192 if (! runlevel || ! service)
199 return (false); 193 return (false);
200 194
201 if (! rc_service_exists (service)) 195 if (! rc_service_exists (service))
202 return (false); 196 return (false);
203 197
204 file = rc_strcatpaths (RC_RUNLEVELDIR, runlevel, basename (service), 198 file = rc_strcatpaths (RC_RUNLEVELDIR, runlevel, basename (service),
205 (char *) NULL); 199 (char *) NULL);
206 retval = rc_exists (file); 200 retval = rc_exists (file);
207 free (file); 201 free (file);
208 202
209 return (retval); 203 return (retval);
210} 204}
211 205
212bool rc_mark_service (const char *service, const rc_service_state_t state) 206bool rc_mark_service (const char *service, const rc_service_state_t state)
213{ 207{
214 char *file; 208 char *file;
215 int i = 0; 209 int i = 0;
216 int skip_state = -1; 210 int skip_state = -1;
217 char *base; 211 char *base;
218 char *init = rc_resolve_service (service); 212 char *init = rc_resolve_service (service);
219 bool skip_wasinactive = false; 213 bool skip_wasinactive = false;
220 214
221 if (! service) 215 if (! service)
222 return (false); 216 return (false);
223 217
224 base = basename (service); 218 base = basename (service);
225 219
226 if (state != rc_service_stopped) 220 if (state != rc_service_stopped) {
227 {
228 if (! rc_is_file(init)) 221 if (! rc_is_file(init)) {
229 { 222 free (init);
230 free (init); 223 return (false);
231 return (false); 224 }
232 }
233 225
234 file = rc_strcatpaths (RC_SVCDIR, rc_service_state_names[state], base, 226 file = rc_strcatpaths (RC_SVCDIR, rc_service_state_names[state], base,
235 (char *) NULL); 227 (char *) NULL);
236 if (rc_exists (file)) 228 if (rc_exists (file))
237 unlink (file); 229 unlink (file);
238 i = symlink (init, file); 230 i = symlink (init, file);
239 if (i != 0) 231 if (i != 0) {
240 { 232 free (file);
241 free (file); 233 free (init);
242 free (init);
243 einfo ("%d %s %s", state, rc_service_state_names[state], base); 234 einfo ("%d %s %s", state, rc_service_state_names[state], base);
244 eerror ("symlink `%s' to `%s': %s", init, file, strerror (errno)); 235 eerror ("symlink `%s' to `%s': %s", init, file, strerror (errno));
245 return (false); 236 return (false);
246 } 237 }
247 238
248 free (file); 239 free (file);
249 skip_state = state; 240 skip_state = state;
250 } 241 }
251 242
252 if (state == rc_service_coldplugged) 243 if (state == rc_service_coldplugged) {
253 {
254 free (init); 244 free (init);
255 return (true); 245 return (true);
256 } 246 }
257 247
258 /* Remove any old states now */ 248 /* Remove any old states now */
259 i = 0; 249 i = 0;
260 while (rc_service_state_names[i]) 250 while (rc_service_state_names[i]) {
261 {
262 if ((i != skip_state && 251 if ((i != skip_state &&
263 i != rc_service_stopped && 252 i != rc_service_stopped &&
264 i != rc_service_coldplugged && 253 i != rc_service_coldplugged &&
265 i != rc_service_scheduled && 254 i != rc_service_scheduled &&
266 i != rc_service_crashed) && 255 i != rc_service_crashed) &&
267 (! skip_wasinactive || i != rc_service_wasinactive)) 256 (! skip_wasinactive || i != rc_service_wasinactive))
268 { 257 {
269 file = rc_strcatpaths (RC_SVCDIR, rc_service_state_names[i], base, 258 file = rc_strcatpaths (RC_SVCDIR, rc_service_state_names[i], base,
270 (char *) NULL); 259 (char *) NULL);
271 if (rc_exists (file)) 260 if (rc_exists (file)) {
272 {
273 if ((state == rc_service_starting || 261 if ((state == rc_service_starting ||
274 state == rc_service_stopping) && 262 state == rc_service_stopping) &&
275 i == rc_service_inactive) 263 i == rc_service_inactive)
276 { 264 {
277 char *wasfile = rc_strcatpaths (RC_SVCDIR, 265 char *wasfile = rc_strcatpaths (RC_SVCDIR,
278 rc_service_state_names[rc_service_wasinactive], 266 rc_service_state_names[rc_service_wasinactive],
279 base, (char *) NULL); 267 base, (char *) NULL);
280 268
281 if (symlink (init, wasfile) != 0) 269 if (symlink (init, wasfile) != 0)
282 eerror ("symlink `%s' to `%s': %s", init, wasfile, 270 eerror ("symlink `%s' to `%s': %s", init, wasfile,
283 strerror (errno)); 271 strerror (errno));
284 272
285 skip_wasinactive = true; 273 skip_wasinactive = true;
286 free (wasfile); 274 free (wasfile);
287 } 275 }
288 276
289 errno = 0; 277 errno = 0;
290 if (unlink (file) != 0 && errno != ENOENT) 278 if (unlink (file) != 0 && errno != ENOENT)
291 eerror ("failed to delete `%s': %s", file, 279 eerror ("failed to delete `%s': %s", file,
292 strerror (errno)); 280 strerror (errno));
293 } 281 }
294 free (file); 282 free (file);
295 } 283 }
296 i++; 284 i++;
297 } 285 }
298 286
299 /* Remove the exclusive state if we're inactive */ 287 /* Remove the exclusive state if we're inactive */
300 if (state == rc_service_started || 288 if (state == rc_service_started ||
301 state == rc_service_stopped || 289 state == rc_service_stopped ||
302 state == rc_service_inactive) 290 state == rc_service_inactive)
303 { 291 {
304 file = rc_strcatpaths (RC_SVCDIR, "exclusive", base, (char *) NULL); 292 file = rc_strcatpaths (RC_SVCDIR, "exclusive", base, (char *) NULL);
305 if (rc_exists (file)) 293 if (rc_exists (file))
306 if (unlink (file) != 0) 294 if (unlink (file) != 0)
307 eerror ("unlink `%s': %s", file, strerror (errno)); 295 eerror ("unlink `%s': %s", file, strerror (errno));
308 free (file); 296 free (file);
309 } 297 }
310 298
311 /* Remove any options and daemons the service may have stored */ 299 /* Remove any options and daemons the service may have stored */
312 if (state == rc_service_stopped) 300 if (state == rc_service_stopped) {
313 {
314 char *dir = rc_strcatpaths (RC_SVCDIR, "options", base, (char *) NULL); 301 char *dir = rc_strcatpaths (RC_SVCDIR, "options", base, (char *) NULL);
315 302
316 if (rc_is_dir (dir)) 303 if (rc_is_dir (dir))
317 rc_rm_dir (dir, true); 304 rc_rm_dir (dir, true);
318 free (dir); 305 free (dir);
319 306
320 dir = rc_strcatpaths (RC_SVCDIR, "daemons", base, (char *) NULL); 307 dir = rc_strcatpaths (RC_SVCDIR, "daemons", base, (char *) NULL);
321 if (rc_is_dir (dir)) 308 if (rc_is_dir (dir))
322 rc_rm_dir (dir, true); 309 rc_rm_dir (dir, true);
323 free (dir); 310 free (dir);
324 311
325 rc_schedule_clear (service); 312 rc_schedule_clear (service);
326 } 313 }
327 314
328 /* These are final states, so remove us from scheduled */ 315 /* These are final states, so remove us from scheduled */
329 if (state == rc_service_started || state == rc_service_stopped) 316 if (state == rc_service_started || state == rc_service_stopped) {
330 {
331 char *sdir = rc_strcatpaths (RC_SVCDIR, "scheduled", (char *) NULL); 317 char *sdir = rc_strcatpaths (RC_SVCDIR, "scheduled", (char *) NULL);
332 char **dirs = rc_ls_dir (NULL, sdir, 0); 318 char **dirs = rc_ls_dir (NULL, sdir, 0);
333 char *dir; 319 char *dir;
334 int serrno; 320 int serrno;
335 321
336 STRLIST_FOREACH (dirs, dir, i) 322 STRLIST_FOREACH (dirs, dir, i) {
337 {
338 char *bdir = rc_strcatpaths (sdir, dir, (char *) NULL); 323 char *bdir = rc_strcatpaths (sdir, dir, (char *) NULL);
339 file = rc_strcatpaths (bdir, base, (char *) NULL); 324 file = rc_strcatpaths (bdir, base, (char *) NULL);
340 if (rc_exists (file)) 325 if (rc_exists (file))
341 if (unlink (file) != 0) 326 if (unlink (file) != 0)
342 eerror ("unlink `%s': %s", file, strerror (errno)); 327 eerror ("unlink `%s': %s", file, strerror (errno));
343 free (file); 328 free (file);
344 329
345 /* Try and remove the dir - we don't care about errors */ 330 /* Try and remove the dir - we don't care about errors */
346 serrno = errno; 331 serrno = errno;
347 rmdir (bdir); 332 rmdir (bdir);
348 errno = serrno; 333 errno = serrno;
349 free (bdir); 334 free (bdir);
350 } 335 }
351 rc_strlist_free (dirs); 336 rc_strlist_free (dirs);
352 free (sdir); 337 free (sdir);
353 } 338 }
354 339
355 free (init); 340 free (init);
356 return (true); 341 return (true);
357} 342}
358 343
359bool rc_service_state (const char *service, const rc_service_state_t state) 344bool rc_service_state (const char *service, const rc_service_state_t state)
360{ 345{
361 char *file; 346 char *file;
362 bool retval; 347 bool retval;
363 348
364 /* If the init script does not exist then we are stopped */ 349 /* If the init script does not exist then we are stopped */
365 if (! rc_service_exists (service)) 350 if (! rc_service_exists (service))
366 return (state == rc_service_stopped ? true : false); 351 return (state == rc_service_stopped ? true : false);
367 352
368 /* We check stopped state by not being in any of the others */ 353 /* We check stopped state by not being in any of the others */
369 if (state == rc_service_stopped) 354 if (state == rc_service_stopped)
370 return ( ! (rc_service_state (service, rc_service_started) || 355 return ( ! (rc_service_state (service, rc_service_started) ||
371 rc_service_state (service, rc_service_starting) || 356 rc_service_state (service, rc_service_starting) ||
372 rc_service_state (service, rc_service_stopping) || 357 rc_service_state (service, rc_service_stopping) ||
373 rc_service_state (service, rc_service_inactive))); 358 rc_service_state (service, rc_service_inactive)));
374 359
375 /* The crashed state and scheduled states are virtual */ 360 /* The crashed state and scheduled states are virtual */
376 if (state == rc_service_crashed) 361 if (state == rc_service_crashed)
377 return (rc_service_daemons_crashed (service)); 362 return (rc_service_daemons_crashed (service));
378 else if (state == rc_service_scheduled) 363 else if (state == rc_service_scheduled) {
379 {
380 char **services = rc_services_scheduled_by (service); 364 char **services = rc_services_scheduled_by (service);
381 retval = (services); 365 retval = (services);
382 if (services) 366 if (services)
383 free (services); 367 free (services);
384 return (retval); 368 return (retval);
385 } 369 }
386 370
387 /* Now we just check if a file by the service name rc_exists 371 /* Now we just check if a file by the service name rc_exists
388 in the state dir */ 372 in the state dir */
389 file = rc_strcatpaths (RC_SVCDIR, rc_service_state_names[state], 373 file = rc_strcatpaths (RC_SVCDIR, rc_service_state_names[state],
390 basename (service), (char*) NULL); 374 basename (service), (char*) NULL);
391 retval = rc_exists (file); 375 retval = rc_exists (file);
392 free (file); 376 free (file);
393 return (retval); 377 return (retval);
394} 378}
395 379
396bool rc_get_service_option (const char *service, const char *option, 380bool rc_get_service_option (const char *service, const char *option,
397 char *value) 381 char *value)
398{ 382{
399 FILE *fp; 383 FILE *fp;
400 char buffer[RC_LINEBUFFER]; 384 char buffer[RC_LINEBUFFER];
401 char *file = rc_strcatpaths (RC_SVCDIR, "options", service, option, 385 char *file = rc_strcatpaths (RC_SVCDIR, "options", service, option,
402 (char *) NULL); 386 (char *) NULL);
403 bool retval = false; 387 bool retval = false;
404 388
405 if (rc_exists (file)) 389 if (rc_exists (file)) {
406 {
407 if ((fp = fopen (file, "r")) == NULL) 390 if ((fp = fopen (file, "r")) == NULL)
408 eerror ("fopen `%s': %s", file, strerror (errno)); 391 eerror ("fopen `%s': %s", file, strerror (errno));
409 else 392 else {
410 {
411 memset (buffer, 0, sizeof (buffer)); 393 memset (buffer, 0, sizeof (buffer));
412 while (fgets (buffer, RC_LINEBUFFER, fp)) 394 while (fgets (buffer, RC_LINEBUFFER, fp)) {
413 {
414 memcpy (value, buffer, strlen (buffer)); 395 memcpy (value, buffer, strlen (buffer));
415 value += strlen (buffer); 396 value += strlen (buffer);
416 } 397 }
417 fclose (fp); 398 fclose (fp);
418 retval = true; 399 retval = true;
419 } 400 }
420 } 401 }
421 402
422 free (file); 403 free (file);
423 return (retval); 404 return (retval);
424} 405}
425 406
426bool rc_set_service_option (const char *service, const char *option, 407bool rc_set_service_option (const char *service, const char *option,
427 const char *value) 408 const char *value)
428{ 409{
429 FILE *fp; 410 FILE *fp;
430 char *path = rc_strcatpaths (RC_SVCDIR, "options", service, (char *) NULL); 411 char *path = rc_strcatpaths (RC_SVCDIR, "options", service, (char *) NULL);
431 char *file = rc_strcatpaths (path, option, (char *) NULL); 412 char *file = rc_strcatpaths (path, option, (char *) NULL);
432 bool retval = false; 413 bool retval = false;
433 414
434 if (! rc_is_dir (path)) 415 if (! rc_is_dir (path)) {
435 {
436 if (mkdir (path, 0755) != 0) 416 if (mkdir (path, 0755) != 0) {
437 {
438 eerror ("mkdir `%s': %s", path, strerror (errno)); 417 eerror ("mkdir `%s': %s", path, strerror (errno));
439 free (path); 418 free (path);
440 free (file); 419 free (file);
441 return (false); 420 return (false);
442 } 421 }
443 } 422 }
444 423
445 if ((fp = fopen (file, "w")) == NULL) 424 if ((fp = fopen (file, "w")) == NULL)
446 eerror ("fopen `%s': %s", file, strerror (errno)); 425 eerror ("fopen `%s': %s", file, strerror (errno));
447 else 426 else {
448 { 427 if (value)
449 if (value)
450 fprintf (fp, "%s", value); 428 fprintf (fp, "%s", value);
451 fclose (fp); 429 fclose (fp);
452 retval = true; 430 retval = true;
453 } 431 }
454 432
455 free (path); 433 free (path);
456 free (file); 434 free (file);
457 return (retval); 435 return (retval);
458} 436}
459 437
460static pid_t _exec_service (const char *service, const char *arg) 438static pid_t _exec_service (const char *service, const char *arg)
461{ 439{
462 char *file; 440 char *file;
463 char *fifo; 441 char *fifo;
464 pid_t pid = -1; 442 pid_t pid = -1;
465 pid_t savedpid; 443 pid_t savedpid;
466 int status; 444 int status;
467 445
468 file = rc_resolve_service (service); 446 file = rc_resolve_service (service);
469 if (! rc_is_file (file)) 447 if (! rc_is_file (file)) {
470 {
471 rc_mark_service (service, rc_service_stopped); 448 rc_mark_service (service, rc_service_stopped);
472 free (file); 449 free (file);
473 return (0); 450 return (0);
474 } 451 }
475 452
476 /* We create a fifo so that other services can wait until we complete */ 453 /* We create a fifo so that other services can wait until we complete */
477 fifo = rc_strcatpaths (RC_SVCDIR, "exclusive", basename (service), 454 fifo = rc_strcatpaths (RC_SVCDIR, "exclusive", basename (service),
478 (char *) NULL); 455 (char *) NULL);
479 456
480 if (mkfifo (fifo, 0600) != 0 && errno != EEXIST) 457 if (mkfifo (fifo, 0600) != 0 && errno != EEXIST) {
481 {
482 eerror ("unable to create fifo `%s': %s", fifo, strerror (errno)); 458 eerror ("unable to create fifo `%s': %s", fifo, strerror (errno));
483 free (fifo); 459 free (fifo);
484 free (file); 460 free (file);
485 return (-1); 461 return (-1);
486 } 462 }
487 463
488 if ((pid = fork ()) == 0) 464 if ((pid = fork ()) == 0) {
489 {
490 char *myarg = strdup (arg); 465 char *myarg = strdup (arg);
491 int e = 0; 466 int e = 0;
492 execl (file, file, myarg, (char *) NULL); 467 execl (file, file, myarg, (char *) NULL);
493 e = errno; 468 e = errno;
494 free (myarg); 469 free (myarg);
495 unlink (fifo); 470 unlink (fifo);
496 free (fifo); 471 free (fifo);
497 eerrorx ("unable to exec `%s': %s", file, strerror (errno)); 472 eerrorx ("unable to exec `%s': %s", file, strerror (errno));
498 } 473 }
499 474
500 free (fifo); 475 free (fifo);
501 free (file); 476 free (file);
502 477
503 if (pid == -1) 478 if (pid == -1) {
504 {
505 eerror ("unable to fork: %s", strerror (errno)); 479 eerror ("unable to fork: %s", strerror (errno));
506 return (pid); 480 return (pid);
507 } 481 }
508 482
509 if (rc_is_env ("RC_PARALLEL_STARTUP", "yes")) 483 if (rc_is_env ("RC_PARALLEL_STARTUP", "yes"))
510 return (pid); 484 return (pid);
511 485
512 savedpid = pid; 486 savedpid = pid;
513 errno = 0; 487 errno = 0;
514 do 488 do {
515 {
516 pid = waitpid (savedpid, &status, 0); 489 pid = waitpid (savedpid, &status, 0);
517 if (pid < 0) 490 if (pid < 0) {
518 {
519 if (errno != ECHILD) 491 if (errno != ECHILD)
520 eerror ("waitpid %d: %s", savedpid, strerror (errno)); 492 eerror ("waitpid %d: %s", savedpid, strerror (errno));
521 return (-1); 493 return (-1);
522 } 494 }
523 } while (! WIFEXITED (status) && ! WIFSIGNALED (status)); 495 } while (! WIFEXITED (status) && ! WIFSIGNALED (status));
524 496
525 return (0); 497 return (0);
526} 498}
527 499
528pid_t rc_stop_service (const char *service) 500pid_t rc_stop_service (const char *service)
529{ 501{
530 if (rc_service_state (service, rc_service_stopped)) 502 if (rc_service_state (service, rc_service_stopped))
531 return (0); 503 return (0);
532 504
533 return (_exec_service (service, "stop")); 505 return (_exec_service (service, "stop"));
534} 506}
535 507
536 508
537pid_t rc_start_service (const char *service) 509pid_t rc_start_service (const char *service)
538{ 510{
539 if (! rc_service_state (service, rc_service_stopped)) 511 if (! rc_service_state (service, rc_service_stopped))
540 return (0); 512 return (0);
541 513
542 return (_exec_service (service, "start")); 514 return (_exec_service (service, "start"));
543} 515}
544 516
545void rc_schedule_start_service (const char *service, 517void rc_schedule_start_service (const char *service,
546 const char *service_to_start) 518 const char *service_to_start)
547{ 519{
548 char *dir; 520 char *dir;
549 char *init; 521 char *init;
550 char *file; 522 char *file;
551 523
552 /* service may be a provided service, like net */ 524 /* service may be a provided service, like net */
553 if (! service || ! rc_service_exists (service_to_start)) 525 if (! service || ! rc_service_exists (service_to_start))
554 return; 526 return;
555 527
556 dir = rc_strcatpaths (RC_SVCDIR, "scheduled", basename (service), 528 dir = rc_strcatpaths (RC_SVCDIR, "scheduled", basename (service),
557 (char *) NULL); 529 (char *) NULL);
558 if (! rc_is_dir (dir)) 530 if (! rc_is_dir (dir))
559 if (mkdir (dir, 0755) != 0) 531 if (mkdir (dir, 0755) != 0) {
560 {
561 eerror ("mkdir `%s': %s", dir, strerror (errno)); 532 eerror ("mkdir `%s': %s", dir, strerror (errno));
562 free (dir); 533 free (dir);
563 return; 534 return;
564 } 535 }
565 536
566 init = rc_resolve_service (service_to_start); 537 init = rc_resolve_service (service_to_start);
567 file = rc_strcatpaths (dir, basename (service_to_start), (char *) NULL); 538 file = rc_strcatpaths (dir, basename (service_to_start), (char *) NULL);
568 if (! rc_exists (file) && symlink (init, file) != 0) 539 if (! rc_exists (file) && symlink (init, file) != 0)
569 eerror ("symlink `%s' to `%s': %s", init, file, strerror (errno)); 540 eerror ("symlink `%s' to `%s': %s", init, file, strerror (errno));
570 541
571 free (init); 542 free (init);
572 free (file); 543 free (file);
573 free (dir); 544 free (dir);
574} 545}
575 546
576void rc_schedule_clear (const char *service) 547void rc_schedule_clear (const char *service)
577{ 548{
578 char *dir = rc_strcatpaths (RC_SVCDIR, "scheduled", basename (service), 549 char *dir = rc_strcatpaths (RC_SVCDIR, "scheduled", basename (service),
579 (char *) NULL); 550 (char *) NULL);
580 551
581 if (rc_is_dir (dir)) 552 if (rc_is_dir (dir))
582 rc_rm_dir (dir, true); 553 rc_rm_dir (dir, true);
583 free (dir); 554 free (dir);
584} 555}
585 556
586bool rc_wait_service (const char *service) 557bool rc_wait_service (const char *service)
587{ 558{
588 char *fifo = rc_strcatpaths (RC_SVCDIR, "exclusive", basename (service), 559 char *fifo = rc_strcatpaths (RC_SVCDIR, "exclusive", basename (service),
589 (char *) NULL); 560 (char *) NULL);
590 struct timeval tv; 561 struct timeval tv;
591 struct timeval stopat; 562 struct timeval stopat;
592 struct timeval now; 563 struct timeval now;
593 bool retval = false; 564 bool retval = false;
594 565
595 if (gettimeofday (&stopat, NULL) != 0) 566 if (gettimeofday (&stopat, NULL) != 0) {
596 {
597 eerror ("gettimeofday: %s", strerror (errno)); 567 eerror ("gettimeofday: %s", strerror (errno));
598 return (false); 568 return (false);
599 } 569 }
600 stopat.tv_sec += WAIT_MAX; 570 stopat.tv_sec += WAIT_MAX;
601 571
602 while (true) 572 while (true) {
603 {
604 if (! rc_exists (fifo)) 573 if (! rc_exists (fifo)) {
605 { 574 retval = true;
606 retval = true; 575 break;
607 break; 576 }
608 }
609 577
610 tv.tv_sec = 0; 578 tv.tv_sec = 0;
611 tv.tv_usec = WAIT_INTERVAL; 579 tv.tv_usec = WAIT_INTERVAL;
612 if (select (0, 0, 0, 0, &tv) < 0) 580 if (select (0, 0, 0, 0, &tv) < 0) {
613 { 581 if (errno != EINTR)
614 if (errno != EINTR)
615 eerror ("select: %s",strerror (errno)); 582 eerror ("select: %s",strerror (errno));
616 break; 583 break;
617 } 584 }
618 585
619 /* Don't hang around forever */ 586 /* Don't hang around forever */
620 if (gettimeofday (&now, NULL) != 0) 587 if (gettimeofday (&now, NULL) != 0) {
621 {
622 eerror ("gettimeofday: %s", strerror (errno)); 588 eerror ("gettimeofday: %s", strerror (errno));
623 break; 589 break;
624 } 590 }
591
625 if (timercmp (&now, &stopat, >)) 592 if (timercmp (&now, &stopat, >))
626 break; 593 break;
627 } 594 }
628 595
629 free (fifo); 596 free (fifo);
630 return (retval); 597 return (retval);
631} 598}
632 599
633char **rc_services_in_runlevel (const char *runlevel) 600char **rc_services_in_runlevel (const char *runlevel)
634{ 601{
635 char *dir; 602 char *dir;
636 char **list = NULL; 603 char **list = NULL;
637 604
638 if (! runlevel) 605 if (! runlevel)
639 return (rc_ls_dir (NULL, RC_INITDIR, RC_LS_INITD)); 606 return (rc_ls_dir (NULL, RC_INITDIR, RC_LS_INITD));
640 607
641 /* These special levels never contain any services */ 608 /* These special levels never contain any services */
642 if (strcmp (runlevel, RC_LEVEL_SYSINIT) == 0 || 609 if (strcmp (runlevel, RC_LEVEL_SYSINIT) == 0 ||
643 strcmp (runlevel, RC_LEVEL_SINGLE) == 0) 610 strcmp (runlevel, RC_LEVEL_SINGLE) == 0)
644 return (NULL); 611 return (NULL);
645 612
646 dir = rc_strcatpaths (RC_RUNLEVELDIR, runlevel, (char *) NULL); 613 dir = rc_strcatpaths (RC_RUNLEVELDIR, runlevel, (char *) NULL);
647 if (! rc_is_dir (dir)) 614 if (! rc_is_dir (dir))
648 eerror ("runlevel `%s' does not exist", runlevel); 615 eerror ("runlevel `%s' does not exist", runlevel);
649 else 616 else
650 list = rc_ls_dir (list, dir, RC_LS_INITD); 617 list = rc_ls_dir (list, dir, RC_LS_INITD);
651 618
652 free (dir); 619 free (dir);
653 return (list); 620 return (list);
654} 621}
655 622
656char **rc_services_in_state (rc_service_state_t state) 623char **rc_services_in_state (rc_service_state_t state)
657{ 624{
658 char *dir = rc_strcatpaths (RC_SVCDIR, rc_service_state_names[state], 625 char *dir = rc_strcatpaths (RC_SVCDIR, rc_service_state_names[state],
659 (char *) NULL); 626 (char *) NULL);
660 char **list = NULL; 627 char **list = NULL;
661 628
662 if (state == rc_service_scheduled) 629 if (state == rc_service_scheduled) {
663 {
664 char **dirs = rc_ls_dir (NULL, dir, 0); 630 char **dirs = rc_ls_dir (NULL, dir, 0);
665 char *d; 631 char *d;
666 int i; 632 int i;
667 633
668 STRLIST_FOREACH (dirs, d, i) 634 STRLIST_FOREACH (dirs, d, i) {
669 {
670 char *p = rc_strcatpaths (dir, d, (char *) NULL); 635 char *p = rc_strcatpaths (dir, d, (char *) NULL);
671 char **entries = rc_ls_dir (NULL, p, RC_LS_INITD); 636 char **entries = rc_ls_dir (NULL, p, RC_LS_INITD);
672 char *e; 637 char *e;
673 int j; 638 int j;
674 639
675 STRLIST_FOREACH (entries, e, j) 640 STRLIST_FOREACH (entries, e, j)
676 list = rc_strlist_addsortu (list, e); 641 list = rc_strlist_addsortu (list, e);
677 642
678 if (entries) 643 if (entries)
679 free (entries); 644 free (entries);
680 } 645 }
681 646
682 if (dirs) 647 if (dirs)
683 free (dirs); 648 free (dirs);
684 } 649 } else {
685 else
686 {
687 if (rc_is_dir (dir)) 650 if (rc_is_dir (dir))
688 list = rc_ls_dir (list, dir, RC_LS_INITD); 651 list = rc_ls_dir (list, dir, RC_LS_INITD);
689 } 652 }
690 653
691 free (dir); 654 free (dir);
692 return (list); 655 return (list);
693} 656}
694 657
695bool rc_service_add (const char *runlevel, const char *service) 658bool rc_service_add (const char *runlevel, const char *service)
696{ 659{
697 bool retval; 660 bool retval;
698 char *init; 661 char *init;
699 char *file; 662 char *file;
700 663
701 if (! rc_runlevel_exists (runlevel)) 664 if (! rc_runlevel_exists (runlevel)) {
702 {
703 errno = ENOENT; 665 errno = ENOENT;
704 return (false); 666 return (false);
705 } 667 }
706 668
707 if (rc_service_in_runlevel (service, runlevel)) 669 if (rc_service_in_runlevel (service, runlevel)) {
708 {
709 errno = EEXIST; 670 errno = EEXIST;
710 return (false); 671 return (false);
711 } 672 }
712 673
713 init = rc_resolve_service (service); 674 init = rc_resolve_service (service);
714 file = rc_strcatpaths (RC_RUNLEVELDIR, runlevel, basename (service), 675 file = rc_strcatpaths (RC_RUNLEVELDIR, runlevel, basename (service),
715 (char *) NULL); 676 (char *) NULL);
716 retval = (symlink (init, file) == 0); 677 retval = (symlink (init, file) == 0);
717 free (init); 678 free (init);
718 free (file); 679 free (file);
719 return (retval); 680 return (retval);
720} 681}
721 682
722bool rc_service_delete (const char *runlevel, const char *service) 683bool rc_service_delete (const char *runlevel, const char *service)
723{ 684{
724 char *file; 685 char *file;
725 bool retval = false; 686 bool retval = false;
726 687
727 if (! runlevel || ! service) 688 if (! runlevel || ! service)
728 return (false); 689 return (false);
729 690
730 file = rc_strcatpaths (RC_RUNLEVELDIR, runlevel, basename (service), 691 file = rc_strcatpaths (RC_RUNLEVELDIR, runlevel, basename (service),
731 (char *) NULL); 692 (char *) NULL);
732 if (unlink (file) == 0) 693 if (unlink (file) == 0)
733 retval = true; 694 retval = true;
734 695
735 free (file); 696 free (file);
736 return (retval); 697 return (retval);
737} 698}
738 699
739char **rc_services_scheduled_by (const char *service) 700char **rc_services_scheduled_by (const char *service)
740{ 701{
741 char **dirs = rc_ls_dir (NULL, RC_SVCDIR "scheduled", 0); 702 char **dirs = rc_ls_dir (NULL, RC_SVCDIR "scheduled", 0);
742 char **list = NULL; 703 char **list = NULL;
743 char *dir; 704 char *dir;
744 int i; 705 int i;
745 706
746 STRLIST_FOREACH (dirs, dir, i) 707 STRLIST_FOREACH (dirs, dir, i) {
747 {
748 char *file = rc_strcatpaths (RC_SVCDIR "scheduled", dir, service, 708 char *file = rc_strcatpaths (RC_SVCDIR "scheduled", dir, service,
749 (char *) NULL); 709 (char *) NULL);
750 if (rc_exists (file)) 710 if (rc_exists (file))
751 list = rc_strlist_add (list, file); 711 list = rc_strlist_add (list, file);
752 free (file); 712 free (file);
753 } 713 }
754 rc_strlist_free (dirs); 714 rc_strlist_free (dirs);
755 715
756 return (list); 716 return (list);
757} 717}
758 718
759char **rc_services_scheduled (const char *service) 719char **rc_services_scheduled (const char *service)
760{ 720{
761 char *dir = rc_strcatpaths (RC_SVCDIR, "scheduled", basename (service), 721 char *dir = rc_strcatpaths (RC_SVCDIR, "scheduled", basename (service),
762 (char *) NULL); 722 (char *) NULL);
763 char **list = NULL; 723 char **list = NULL;
764 724
765 if (rc_is_dir (dir)) 725 if (rc_is_dir (dir))
766 list = rc_ls_dir (list, dir, RC_LS_INITD); 726 list = rc_ls_dir (list, dir, RC_LS_INITD);
767 727
768 free (dir); 728 free (dir);
769 return (list); 729 return (list);
770} 730}
771 731
772bool rc_allow_plug (char *service) 732bool rc_allow_plug (char *service)
773{ 733{
774 char *list; 734 char *list;
775 char *p; 735 char *p;
776 char *star; 736 char *star;
777 char *token; 737 char *token;
778 bool allow = true; 738 bool allow = true;
779 char *match = getenv ("RC_PLUG_SERVICES"); 739 char *match = getenv ("RC_PLUG_SERVICES");
780 if (! match) 740 if (! match)
781 return true; 741 return true;
782 742
783 list = strdup (match); 743 list = strdup (match);
784 p = list; 744 p = list;
785 while ((token = strsep (&p, " "))) 745 while ((token = strsep (&p, " "))) {
786 {
787 bool truefalse = true; 746 bool truefalse = true;
788 if (token[0] == '!') 747 if (token[0] == '!') {
789 { 748 truefalse = false;
790 truefalse = false; 749 token++;
791 token++; 750 }
792 }
793 751
794 star = strchr (token, '*'); 752 star = strchr (token, '*');
795 if (star) 753 if (star) {
796 {
797 if (strncmp (service, token, star - token) == 0) 754 if (strncmp (service, token, star - token) == 0) {
798 { 755 allow = truefalse;
799 allow = truefalse; 756 break;
800 break; 757 }
801 } 758 } else {
802 }
803 else
804 {
805 if (strcmp (service, token) == 0) 759 if (strcmp (service, token) == 0) {
806 { 760 allow = truefalse;
807 allow = truefalse; 761 break;
808 break; 762 }
809 } 763 }
810 } 764 }
811 }
812 765
813 free (list); 766 free (list);
814 return (allow); 767 return (allow);
815} 768}

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

  ViewVC Help
Powered by ViewVC 1.1.20