Add flags to the Casper services.
CASPER_SERVICE_STDIO - Casper will not close the first three descriptors (stdin, stdout and stderr) this can be helpful for debugging. CASPER_SERVICE_FD - Capser will not close all other descriptors, this can be useful for a filesystem service.
This commit is contained in:
parent
311219368a
commit
920be817aa
@ -46,11 +46,11 @@ bool fd_is_valid(int fd);
|
||||
/* Private service functions. */
|
||||
struct service *service_alloc(const char *name,
|
||||
service_limit_func_t *limitfunc,
|
||||
service_command_func_t *commandfunc);
|
||||
service_command_func_t *commandfunc, uint64_t flags);
|
||||
void service_free(struct service *service);
|
||||
void service_message(struct service *service,
|
||||
struct service_connection *sconn);
|
||||
void service_start(struct service *service, int sock);
|
||||
void service_start(struct service *service, int sock, int procfd);
|
||||
const char *service_name(struct service *service);
|
||||
|
||||
/* Private service connection functions. */
|
||||
|
@ -73,7 +73,7 @@ service_find(const char *name)
|
||||
|
||||
struct casper_service *
|
||||
service_register(const char *name, service_limit_func_t *limitfunc,
|
||||
service_command_func_t *commandfunc)
|
||||
service_command_func_t *commandfunc, uint64_t flags)
|
||||
{
|
||||
struct casper_service *casserv;
|
||||
|
||||
@ -88,7 +88,8 @@ service_register(const char *name, service_limit_func_t *limitfunc,
|
||||
if (casserv == NULL)
|
||||
return (NULL);
|
||||
|
||||
casserv->cs_service = service_alloc(name, limitfunc, commandfunc);
|
||||
casserv->cs_service = service_alloc(name, limitfunc, commandfunc,
|
||||
flags);
|
||||
if (casserv->cs_service == NULL) {
|
||||
free(casserv);
|
||||
return (NULL);
|
||||
@ -141,11 +142,10 @@ service_execute(int chanfd)
|
||||
exit(1);
|
||||
service = (struct service *)(uintptr_t)nvlist_take_number(nvl,
|
||||
"service");
|
||||
//XXX: We should remove this?
|
||||
procfd = nvlist_take_descriptor(nvl, "procfd");
|
||||
nvlist_destroy(nvl);
|
||||
|
||||
service_start(service, chanfd);
|
||||
service_start(service, chanfd, procfd);
|
||||
/* Not reached. */
|
||||
exit(1);
|
||||
}
|
||||
@ -199,7 +199,7 @@ service_register_core(int fd)
|
||||
struct service_connection *sconn;
|
||||
|
||||
casserv = service_register(CORE_CASPER_NAME, casper_limit,
|
||||
casper_command);
|
||||
casper_command, 0);
|
||||
sconn = service_connection_add(casserv->cs_service, fd, NULL);
|
||||
if (sconn == NULL) {
|
||||
close(fd);
|
||||
|
@ -40,21 +40,25 @@ struct nvlist;
|
||||
typedef struct nvlist nvlist_t;
|
||||
#endif
|
||||
|
||||
#define CASPER_SERVICE_STDIO 0x00000001
|
||||
#define CASPER_SERVICE_FD 0x00000002
|
||||
|
||||
typedef int service_limit_func_t(const nvlist_t *, const nvlist_t *);
|
||||
typedef int service_command_func_t(const char *cmd, const nvlist_t *,
|
||||
nvlist_t *, nvlist_t *);
|
||||
|
||||
struct casper_service *service_register(const char *name,
|
||||
service_limit_func_t *limitfunc, service_command_func_t *commandfunc);
|
||||
service_limit_func_t *limitfunc, service_command_func_t *commandfunc,
|
||||
uint64_t flags);
|
||||
|
||||
#define __constructor __attribute__((constructor))
|
||||
#define CREATE_SERVICE(name, limit_func, command_func) \
|
||||
#define CREATE_SERVICE(name, limit_func, command_func, flags) \
|
||||
static __constructor void \
|
||||
init_casper_service(void) \
|
||||
{ \
|
||||
\
|
||||
(void)service_register(name, limit_func, \
|
||||
command_func); \
|
||||
(void)service_register(name, limit_func, command_func, \
|
||||
flags); \
|
||||
}
|
||||
|
||||
#endif /* !_LIBCASPER_SERVICE_H_ */
|
||||
|
@ -41,6 +41,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <paths.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@ -78,6 +79,7 @@ struct service_connection {
|
||||
struct service {
|
||||
int s_magic;
|
||||
char *s_name;
|
||||
uint64_t s_flags;
|
||||
service_limit_func_t *s_limit;
|
||||
service_command_func_t *s_command;
|
||||
TAILQ_HEAD(, service_connection) s_connections;
|
||||
@ -85,7 +87,7 @@ struct service {
|
||||
|
||||
struct service *
|
||||
service_alloc(const char *name, service_limit_func_t *limitfunc,
|
||||
service_command_func_t *commandfunc)
|
||||
service_command_func_t *commandfunc, uint64_t flags)
|
||||
{
|
||||
struct service *service;
|
||||
|
||||
@ -99,6 +101,7 @@ service_alloc(const char *name, service_limit_func_t *limitfunc,
|
||||
}
|
||||
service->s_limit = limitfunc;
|
||||
service->s_command = commandfunc;
|
||||
service->s_flags = flags;
|
||||
TAILQ_INIT(&service->s_connections);
|
||||
service->s_magic = SERVICE_MAGIC;
|
||||
|
||||
@ -338,8 +341,59 @@ service_name(struct service *service)
|
||||
return (service->s_name);
|
||||
}
|
||||
|
||||
static void
|
||||
stdnull(void)
|
||||
{
|
||||
int fd;
|
||||
|
||||
fd = open(_PATH_DEVNULL, O_RDWR);
|
||||
if (fd == -1)
|
||||
errx(1, "Unable to open %s", _PATH_DEVNULL);
|
||||
|
||||
if (setsid() == -1)
|
||||
errx(1, "Unable to detach from session");
|
||||
|
||||
if (dup2(fd, STDIN_FILENO) == -1)
|
||||
errx(1, "Unable to cover stdin");
|
||||
if (dup2(fd, STDOUT_FILENO) == -1)
|
||||
errx(1, "Unable to cover stdout");
|
||||
if (dup2(fd, STDERR_FILENO) == -1)
|
||||
errx(1, "Unable to cover stderr");
|
||||
|
||||
close(fd);
|
||||
}
|
||||
|
||||
static void
|
||||
service_clean(int sock, int procfd, uint64_t flags)
|
||||
{
|
||||
int fd, maxfd, minfd;
|
||||
|
||||
assert(sock > STDERR_FILENO);
|
||||
assert(procfd > STDERR_FILENO);
|
||||
assert(sock != procfd);
|
||||
|
||||
if ((flags & CASPER_SERVICE_STDIO) == 0)
|
||||
stdnull();
|
||||
|
||||
if ((flags & CASPER_SERVICE_FD) == 0) {
|
||||
if (procfd > sock) {
|
||||
maxfd = procfd;
|
||||
minfd = sock;
|
||||
} else {
|
||||
maxfd = sock;
|
||||
minfd = procfd;
|
||||
}
|
||||
|
||||
for (fd = STDERR_FILENO + 1; fd < maxfd; fd++) {
|
||||
if (fd != minfd)
|
||||
close(fd);
|
||||
}
|
||||
closefrom(maxfd + 1);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
service_start(struct service *service, int sock)
|
||||
service_start(struct service *service, int sock, int procfd)
|
||||
{
|
||||
struct service_connection *sconn, *sconntmp;
|
||||
fd_set fds;
|
||||
@ -348,6 +402,8 @@ service_start(struct service *service, int sock)
|
||||
assert(service != NULL);
|
||||
assert(service->s_magic == SERVICE_MAGIC);
|
||||
setproctitle("%s", service->s_name);
|
||||
service_clean(sock, procfd, service->s_flags);
|
||||
|
||||
if (service_connection_add(service, sock, NULL) == NULL)
|
||||
exit(1);
|
||||
|
||||
|
@ -40,7 +40,6 @@ __FBSDID("$FreeBSD$");
|
||||
#include <assert.h>
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <paths.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <strings.h>
|
||||
@ -51,28 +50,6 @@ __FBSDID("$FreeBSD$");
|
||||
/* Zygote info. */
|
||||
static int zygote_sock = -1;
|
||||
|
||||
static void
|
||||
stdnull(void)
|
||||
{
|
||||
int fd;
|
||||
|
||||
fd = open(_PATH_DEVNULL, O_RDWR);
|
||||
if (fd == -1)
|
||||
errx(1, "Unable to open %s", _PATH_DEVNULL);
|
||||
|
||||
if (setsid() == -1)
|
||||
errx(1, "Unable to detach from session");
|
||||
|
||||
if (dup2(fd, STDIN_FILENO) == -1)
|
||||
errx(1, "Unable to cover stdin");
|
||||
if (dup2(fd, STDOUT_FILENO) == -1)
|
||||
errx(1, "Unable to cover stdout");
|
||||
if (dup2(fd, STDERR_FILENO) == -1)
|
||||
errx(1, "Unable to cover stderr");
|
||||
|
||||
close(fd);
|
||||
}
|
||||
|
||||
int
|
||||
zygote_clone(zygote_func_t *func, int *chanfdp, int *procfdp)
|
||||
{
|
||||
@ -113,7 +90,7 @@ zygote_clone(zygote_func_t *func, int *chanfdp, int *procfdp)
|
||||
static void
|
||||
zygote_main(int sock)
|
||||
{
|
||||
int error, fd, procfd;
|
||||
int error, procfd;
|
||||
int chanfd[2];
|
||||
nvlist_t *nvlin, *nvlout;
|
||||
zygote_func_t *func;
|
||||
@ -123,11 +100,6 @@ zygote_main(int sock)
|
||||
|
||||
setproctitle("zygote");
|
||||
|
||||
stdnull();
|
||||
for (fd = STDERR_FILENO + 1; fd < sock; fd++)
|
||||
close(fd);
|
||||
closefrom(sock + 1);
|
||||
|
||||
for (;;) {
|
||||
nvlin = nvlist_recv(sock, 0);
|
||||
if (nvlin == NULL) {
|
||||
|
@ -759,4 +759,4 @@ dns_command(const char *cmd, const nvlist_t *limits, nvlist_t *nvlin,
|
||||
return (error);
|
||||
}
|
||||
|
||||
CREATE_SERVICE("system.dns", dns_limit, dns_command);
|
||||
CREATE_SERVICE("system.dns", dns_limit, dns_command, 0);
|
||||
|
@ -786,4 +786,4 @@ grp_command(const char *cmd, const nvlist_t *limits, nvlist_t *nvlin,
|
||||
return (error);
|
||||
}
|
||||
|
||||
CREATE_SERVICE("system.grp", grp_limit, grp_command);
|
||||
CREATE_SERVICE("system.grp", grp_limit, grp_command, 0);
|
||||
|
@ -780,4 +780,4 @@ pwd_command(const char *cmd, const nvlist_t *limits, nvlist_t *nvlin,
|
||||
return (error);
|
||||
}
|
||||
|
||||
CREATE_SERVICE("system.pwd", pwd_limit, pwd_command);
|
||||
CREATE_SERVICE("system.pwd", pwd_limit, pwd_command, 0);
|
||||
|
@ -114,4 +114,4 @@ random_command(const char *cmd, const nvlist_t *limits __unused,
|
||||
return (0);
|
||||
}
|
||||
|
||||
CREATE_SERVICE("system.random", NULL, random_command);
|
||||
CREATE_SERVICE("system.random", NULL, random_command, 0);
|
||||
|
@ -290,4 +290,4 @@ sysctl_command(const char *cmd, const nvlist_t *limits, nvlist_t *nvlin,
|
||||
return (0);
|
||||
}
|
||||
|
||||
CREATE_SERVICE("system.sysctl", sysctl_limit, sysctl_command);
|
||||
CREATE_SERVICE("system.sysctl", sysctl_limit, sysctl_command, 0);
|
||||
|
Loading…
x
Reference in New Issue
Block a user