|
|
|
@@ -19,16 +19,29 @@
|
|
|
|
|
#include <poll.h>
|
|
|
|
|
#include <arpa/inet.h>
|
|
|
|
|
|
|
|
|
|
#include <stdarg.h>
|
|
|
|
|
#include <stdnoreturn.h>
|
|
|
|
|
|
|
|
|
|
static int sigchild_fd = -1;
|
|
|
|
|
|
|
|
|
|
static void handle_sigchld(int num) {
|
|
|
|
|
if(sigchild_fd >= 0) {
|
|
|
|
|
write(sigchild_fd, "\n", 1);
|
|
|
|
|
(void) !write(sigchild_fd, "\n", 1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#define die(...) error(EXIT_FAILURE, errno, __VA_ARGS__)
|
|
|
|
|
static void noreturn die(char *fmt, ...) {
|
|
|
|
|
va_list ap;
|
|
|
|
|
va_start(ap, fmt);
|
|
|
|
|
if(errno > 0) {
|
|
|
|
|
fprintf(stderr, "luad: %s: ", strerror(errno));
|
|
|
|
|
} else {
|
|
|
|
|
fprintf(stderr, "luad: ");
|
|
|
|
|
}
|
|
|
|
|
vfprintf(stderr, fmt, ap);
|
|
|
|
|
exit(1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int open_socket(char * pathname) {
|
|
|
|
|
struct sockaddr_un addr;
|
|
|
|
@@ -66,7 +79,7 @@ int * fds_from_msg(struct msghdr *msg, int * peer_fds) {
|
|
|
|
|
if(cmsg->cmsg_level == SOL_SOCKET &&
|
|
|
|
|
cmsg->cmsg_type == SCM_RIGHTS) {
|
|
|
|
|
int passed_fd_count = (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof (int);
|
|
|
|
|
if(i <= 3) {
|
|
|
|
|
if(i + passed_fd_count <= 3) {
|
|
|
|
|
memcpy(&peer_fds[i], CMSG_DATA(cmsg), passed_fd_count * sizeof(int));
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
@@ -94,7 +107,7 @@ int * fds_from_msg(struct msghdr *msg, int * peer_fds) {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int start_lua_child(lua_State *L,
|
|
|
|
|
void start_lua_child(lua_State *L,
|
|
|
|
|
char * command_line, int command_line_length,
|
|
|
|
|
int * fds) {
|
|
|
|
|
char * word = command_line;
|
|
|
|
@@ -104,7 +117,7 @@ int start_lua_child(lua_State *L,
|
|
|
|
|
|
|
|
|
|
fflush(stdout); fflush(stderr);
|
|
|
|
|
for(int i=0; i < 3; i++) {
|
|
|
|
|
if(fds[i] > 0) dup2(fds[i], i);
|
|
|
|
|
dup2(fds[i], i);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
lua_newtable(L); /* arg */
|
|
|
|
@@ -118,12 +131,13 @@ int start_lua_child(lua_State *L,
|
|
|
|
|
lua_seti(L, -2, i++);
|
|
|
|
|
word = word_end + 1;
|
|
|
|
|
}
|
|
|
|
|
if(! pathname) {
|
|
|
|
|
die("no script name received from client");
|
|
|
|
|
}
|
|
|
|
|
lua_setglobal(L, "arg");
|
|
|
|
|
int status = luaL_dofile(L, pathname);
|
|
|
|
|
if (status) {
|
|
|
|
|
die("Lua error: %s", lua_tostring(L, -1));
|
|
|
|
|
} else {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -132,8 +146,8 @@ pid_t fork_lua(lua_State *L,
|
|
|
|
|
int * fds) {
|
|
|
|
|
pid_t pid = fork();
|
|
|
|
|
if(pid == 0) {
|
|
|
|
|
exit(start_lua_child(L, command_line, command_line_length,
|
|
|
|
|
fds));
|
|
|
|
|
start_lua_child(L, command_line, command_line_length, fds);
|
|
|
|
|
exit(0);
|
|
|
|
|
} else if(pid > 0) {
|
|
|
|
|
free(command_line);
|
|
|
|
|
return pid;
|
|
|
|
@@ -148,12 +162,10 @@ struct peer_entry {
|
|
|
|
|
struct sockaddr_un addr;
|
|
|
|
|
} peer_entries[500];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool register_peer(pid_t pid, struct sockaddr_un *addr, int addrlen) {
|
|
|
|
|
if(addrlen > sizeof (struct sockaddr_un))
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
struct peer_entry *p = peer_entries;
|
|
|
|
|
int peer_entries_max = sizeof peer_entries / sizeof(peer_entries[0]);
|
|
|
|
|
|
|
|
|
|
for(int i=0; i < peer_entries_max; i++) {
|
|
|
|
@@ -208,7 +220,7 @@ int main(int argc, char **argv)
|
|
|
|
|
|
|
|
|
|
int socket = open_socket(socket_path);
|
|
|
|
|
struct sockaddr_un peer_addr;
|
|
|
|
|
socklen_t peer_addr_len;
|
|
|
|
|
|
|
|
|
|
char buf[1025];
|
|
|
|
|
struct iovec iov[1];
|
|
|
|
|
iov[0].iov_base = buf;
|
|
|
|
@@ -244,6 +256,8 @@ int main(int argc, char **argv)
|
|
|
|
|
if(pollfds[0].revents) {
|
|
|
|
|
if(find_peer(0)) {
|
|
|
|
|
int len = recvmsg(socket, &msg , 0);
|
|
|
|
|
if(len<=0) continue;
|
|
|
|
|
|
|
|
|
|
int peer_fds[3];
|
|
|
|
|
if(fds_from_msg(&msg, peer_fds)) {
|
|
|
|
|
char *argline = malloc(len);
|
|
|
|
@@ -253,9 +267,8 @@ int main(int argc, char **argv)
|
|
|
|
|
memmove(argline, buf, len);
|
|
|
|
|
|
|
|
|
|
pid_t child_pid = fork_lua(L, argline, len, peer_fds);
|
|
|
|
|
if(child_pid >= 0) {
|
|
|
|
|
register_peer(child_pid, &peer_addr, msg.msg_namelen);
|
|
|
|
|
}
|
|
|
|
|
register_peer(child_pid, &peer_addr, msg.msg_namelen);
|
|
|
|
|
|
|
|
|
|
/* close peer fds in parent */
|
|
|
|
|
close(peer_fds[0]);
|
|
|
|
|
close(peer_fds[1]);
|
|
|
|
@@ -268,8 +281,10 @@ int main(int argc, char **argv)
|
|
|
|
|
pid_t pid;
|
|
|
|
|
int wstatus;
|
|
|
|
|
|
|
|
|
|
read(pollfds[1].fd, buf, sizeof buf);
|
|
|
|
|
while((pid=waitpid(0, &wstatus, WNOHANG)) > 0) {
|
|
|
|
|
if(read(pollfds[1].fd, buf, sizeof buf) < 0)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
while((pid = waitpid(0, &wstatus, WNOHANG)) > 0) {
|
|
|
|
|
struct peer_entry *peer = find_peer(pid);
|
|
|
|
|
if(peer) {
|
|
|
|
|
uint32_t ret = 0;
|
|
|
|
|