4 * Copyright (C) 2013 Felix Fietkau <nbd@openwrt.org>
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 #include <libubox/uloop.h>
20 #include <libubox/runqueue.h>
25 #include <sys/types.h>
29 #include <libubox/ustream.h>
34 static struct runqueue q
;
38 struct runqueue_process proc
;
43 static void pipe_cb(struct ustream
*s
, int bytes
)
45 struct ustream_buf
*buf
= s
->r
.head
;
50 str
= ustream_get_read_buf(s
, NULL
);
53 newline
= strchr(buf
->data
, '\n');
57 len
= newline
+ 1 - str
;
59 ustream_consume(s
, len
);
63 static void q_initd_run(struct runqueue
*q
, struct runqueue_task
*t
)
65 struct initd
*s
= container_of(t
, struct initd
, proc
.task
);
69 DEBUG(1, "start %s %s \n", s
->file
, s
->param
);
70 if (pipe(pipefd
) == -1) {
71 ERROR("Failed to create pipe\n");
81 s
->fd
.stream
.string_data
= true,
82 s
->fd
.stream
.notify_read
= pipe_cb
,
83 runqueue_process_add(q
, &s
->proc
, pid
);
84 ustream_fd_init(&s
->fd
, pipefd
[0]);
88 dup2(pipefd
[1], STDOUT_FILENO
);
89 dup2(pipefd
[1], STDERR_FILENO
);
91 execlp(s
->file
, s
->file
, s
->param
, NULL
);
95 static void q_initd_complete(struct runqueue
*q
, struct runqueue_process
*p
, int ret
)
97 struct initd
*s
= container_of(p
, struct initd
, proc
);
99 DEBUG(1, "stop %s %s \n", s
->file
, s
->param
);
100 ustream_free(&s
->fd
.stream
);
105 static void add_initd(char *file
, char *param
)
107 static const struct runqueue_task_type initd_type
= {
109 .cancel
= runqueue_process_cancel_cb
,
110 .kill
= runqueue_process_kill_cb
,
114 s
= calloc(1, sizeof(*s
));
115 s
->proc
.task
.type
= &initd_type
;
116 s
->proc
.complete
= q_initd_complete
;
119 runqueue_task_add(&q
, &s
->proc
.task
, false);
122 int rcS(char *pattern
, char *param
, void (*q_empty
)(struct runqueue
*))
129 q
.empty_cb
= q_empty
;
130 q
.max_running_tasks
= 1;
132 DEBUG(1, "running /etc/rc.d/%s %s\n", pattern
, param
);
133 snprintf(dir
, sizeof(dir
), "/etc/rc.d/%s*", pattern
);
134 if (glob(dir
, GLOB_NOESCAPE
| GLOB_MARK
, NULL
, &gl
)) {
135 printf("glob failed on %s\n", dir
);
139 for (j
= 0; j
< gl
.gl_pathc
; j
++)
140 add_initd(gl
.gl_pathv
[j
], param
);