/*
SSSD
Service monitor
Copyright (C) Simo Sorce 2008
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include "../events/events.h"
#include "util/util.h"
#include "service.h"
struct mt_ctx {
struct task_server *task;
struct fd_event *test_fde;
int test_fd;
};
static void set_nonblocking(int fd)
{
unsigned v;
v = fcntl(fd, F_GETFL, 0);
fcntl(fd, F_SETFL, v | O_NONBLOCK);
}
static void set_close_on_exec(int fd)
{
unsigned v;
v = fcntl(fd, F_GETFD, 0);
fcntl(fd, F_SETFD, v | FD_CLOEXEC);
}
static void set_test_timed_event(struct event_context *ev,
struct mt_ctx *ctx);
static void test_timed_handler(struct event_context *ev,
struct timed_event *te,
struct timeval t, void *ptr)
{
struct mt_ctx *ctx = talloc_get_type(ptr, struct mt_ctx);
fprintf(stdout, ".");
fflush(stdout);
set_test_timed_event(ev, ctx);
}
static void set_test_timed_event(struct event_context *ev,
struct mt_ctx *ctx)
{
struct timed_event *te = NULL;
struct timeval tv;
gettimeofday(&tv, NULL);
tv.tv_sec += 2;
tv.tv_usec = 0;
te = event_add_timed(ev, ctx, tv, test_timed_handler, ctx);
if (te == NULL) {
DEBUG(0, ("failed to add event!\n"));
task_server_terminate(ctx->task, "fatal error initializing service\n");
}
}
static void test_fd_handler(struct event_context *ev,
struct fd_event *fde,
uint16_t flags, void *ptr)
{
/* accept and close */
struct mt_ctx *ctx = talloc_get_type(ptr, struct mt_ctx);
struct sockaddr_un addr;
socklen_t len;
int fd;
memset(&addr, 0, sizeof(addr));
len = sizeof(addr);
fd = accept(ctx->test_fd, (struct sockaddr *)&addr, &len);
if (fd == -1) {
return;
}
close(fd);
return;
}
/* create a unix socket and listen to it */
static void set_test_fd_event(struct event_context *ev,
struct mt_ctx *ctx)
{
struct sockaddr_un addr;
const char *sock_name = "/tmp/foo/test_sock";
/* make sure we have no old sockets around */
unlink(sock_name);
ctx->test_fd = socket(AF_UNIX, SOCK_STREAM, 0);
if (ctx->test_fd == -1) {
return;
}
set_nonblocking(ctx->test_fd);
set_close_on_exec(ctx->test_fd);
memset(&addr, 0, sizeof(addr));
addr.sun_family = AF_UNIX;
strncpy(addr.sun_path, sock_name, sizeof(addr.sun_path));
if (bind(ctx->test_fd, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
DEBUG(0,("Unable to bind on socket '%s'\n", sock_name));
goto failed;
}
if (listen(ctx->test_fd, 10) != 0) {
DEBUG(0,("Unable to listen on socket '%s'\n", sock_name));
goto failed;
}
ctx->test_fde = event_add_fd(ev, ctx, ctx->test_fd,
EVENT_FD_READ, test_fd_handler, ctx);
return;
failed:
close(ctx->test_fd);
}
void monitor_task_init(struct task_server *task)
{
struct mt_ctx *ctx;
task_server_set_title(task, "sssd[monitor]");
ctx = talloc_zero(task, struct mt_ctx);
if (!ctx) {
task_server_terminate(task, "fatal error initializing mt_ctx\n");
return;
}
ctx->task = task;
/* without an fd event the event system just exits.
* We must always have at least one file base event around
*/
set_test_fd_event(task->event_ctx, ctx);
/* our test timed event */
set_test_timed_event(task->event_ctx, ctx);
fprintf(stdout, "test monitor process started!\n");
}