monitor.c revision 203b6bc547d6c59146be82686fe9e73d2b62dcaf
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen Service monitor
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen Copyright (C) Simo Sorce 2008
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen This program is free software; you can redistribute it and/or modify
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen it under the terms of the GNU General Public License as published by
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen the Free Software Foundation; either version 3 of the License, or
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen (at your option) any later version.
3a2f2adf5679aa383a2cab09f739d59233cada95Timo Sirainen This program is distributed in the hope that it will be useful,
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen but WITHOUT ANY WARRANTY; without even the implied warranty of
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen GNU General Public License for more details.
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen You should have received a copy of the GNU General Public License
bb2471ff14f01390b47cce63b407820b5547df1aTimo Sirainen along with this program. If not, see <http://www.gnu.org/licenses/>.
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen/* Needed for res_init() */
29543188462c9348f365ec29115d777ffe4769d3Timo Sirainen/* ping time cannot be less then once every few seconds or the
29543188462c9348f365ec29115d777ffe4769d3Timo Sirainen * monitor will get crazy hammering children with messages */
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen TALLOC_CTX *domain_ctx; /* Memory context for domain list */
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen TALLOC_CTX *service_ctx; /* Memory context for services */
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainenstatic int start_service(struct mt_svc *mt_svc);
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainenstatic int monitor_service_init(struct sbus_connection *conn, void *data);
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainenstatic int service_send_ping(struct mt_svc *svc);
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainenstatic int service_signal_reset_offline(struct mt_svc *svc);
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainenstatic void ping_check(DBusPendingCall *pending, void *data);
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainenstatic int service_check_alive(struct mt_svc *svc);
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainenstatic void set_tasks_checker(struct mt_svc *srv);
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainenstatic void set_global_checker(struct mt_ctx *ctx);
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainenstatic int monitor_kill_service (struct mt_svc *svc);
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainenstatic int get_service_config(struct mt_ctx *ctx, const char *name,
bb2471ff14f01390b47cce63b407820b5547df1aTimo Sirainenstatic int get_provider_config(struct mt_ctx *ctx, const char *name,
bb2471ff14f01390b47cce63b407820b5547df1aTimo Sirainenstatic int add_new_service(struct mt_ctx *ctx, const char *name);
bb2471ff14f01390b47cce63b407820b5547df1aTimo Sirainenstatic int add_new_provider(struct mt_ctx *ctx, const char *name);
bb2471ff14f01390b47cce63b407820b5547df1aTimo Sirainenstatic int mark_service_as_started(struct mt_svc *svc);
f663bdd9d345a86e6a7924d83319bd04b2fcb600Timo Sirainenstatic int monitor_cleanup(void);
f663bdd9d345a86e6a7924d83319bd04b2fcb600Timo Sirainenstatic void network_status_change_cb(enum network_change state,
f663bdd9d345a86e6a7924d83319bd04b2fcb600Timo Sirainen struct mt_ctx *ctx = (struct mt_ctx *) cb_data;
f663bdd9d345a86e6a7924d83319bd04b2fcb600Timo Sirainen DEBUG(9, ("A new route has appeared, signaling providers to reset offline status\n"));
f663bdd9d345a86e6a7924d83319bd04b2fcb600Timo Sirainen for (iter = ctx->svc_list; iter; iter = iter->next) {
f663bdd9d345a86e6a7924d83319bd04b2fcb600Timo Sirainen /* Don't signal services, only providers */
f663bdd9d345a86e6a7924d83319bd04b2fcb600Timo Sirainen/* dbus_get_monitor_version
f663bdd9d345a86e6a7924d83319bd04b2fcb600Timo Sirainen * Return the monitor version over D-BUS */
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainenstatic int get_monitor_version(DBusMessage *message,
f663bdd9d345a86e6a7924d83319bd04b2fcb600Timo Sirainen reply = dbus_message_new_method_return(message);
ca31fc1a8e48281c6882796fa7d4372acc2f97e5Timo Sirainen /* send reply back */
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainenstatic int add_svc_conn_spy(struct mt_svc *svc);
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen/* registers a new client.
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen * if operation is successful also sends back the Monitor version */
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainenstatic int client_registration(DBusMessage *message,
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen mini = talloc_get_type(data, struct mon_init_conn);
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen DEBUG(0, ("Connection holds no valid init data\n"));
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen /* First thing, cancel the timeout */
b056d19b7a07400b897104b146c8768280d24009Timo Sirainen dbret = dbus_message_get_args(message, &dbus_error,
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen DEBUG(1, ("Failed to parse message, killing connection\n"));
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen if (dbus_error_is_set(&dbus_error)) dbus_error_free(&dbus_error);
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen /* FIXME: should we just talloc_zfree(conn) ? */
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen DEBUG(4, ("Received ID registration: (%s,%d)\n", svc_name, svc_ver));
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen /* search this service in the list */
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen DEBUG(0, ("Unable to find peer [%s] in list of services,"
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen /* FIXME: should we just talloc_zfree(conn) ? */
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen /* Fill in svc structure with connection data */
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen DEBUG(1, ("Failed to mark service [%s]!\n", svc_name));
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen /* reply that all is ok */
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen reply = dbus_message_new_method_return(message);
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen /* send reply back */
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen /* init complete, get rid of temp init context */
58840b6cfccd09f0a7c6cd206437e52b6d8d386eTimo Sirainen struct mt_svc *svc = talloc_get_type(mem, struct mt_svc);
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen /* try to delist service */
58840b6cfccd09f0a7c6cd206437e52b6d8d386eTimo Sirainen /* svc is beeing freed, neutralize the spy */
3a177dbf62af83209f1e33fc28c620ea1fc14adaTimo Sirainen talloc_set_destructor((TALLOC_CTX *)svc->conn_spy, NULL);
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen struct svc_spy *spy = talloc_get_type(mem, struct svc_spy);
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen /* svc->conn has been freed, NULL the pointer in svc */
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainenstatic int add_svc_conn_spy(struct mt_svc *svc)
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen talloc_set_destructor((TALLOC_CTX *)spy, svc_spy_destructor);
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainenstatic int mark_service_as_started(struct mt_svc *svc)
bb2471ff14f01390b47cce63b407820b5547df1aTimo Sirainen DEBUG(5, ("Marking %s as started.\n", svc->name));
bb2471ff14f01390b47cce63b407820b5547df1aTimo Sirainen /* we need to attach a spy to the connection structure so that if some code
bb2471ff14f01390b47cce63b407820b5547df1aTimo Sirainen * frees it we can zero it out in the service structure. Otherwise we may
bb2471ff14f01390b47cce63b407820b5547df1aTimo Sirainen * try to access or even free, freed memory. */
bb2471ff14f01390b47cce63b407820b5547df1aTimo Sirainen /* check if all providers are up */
bb2471ff14f01390b47cce63b407820b5547df1aTimo Sirainen for (iter = ctx->svc_list; iter; iter = iter->next) {
bb2471ff14f01390b47cce63b407820b5547df1aTimo Sirainen DEBUG(5, ("Still waiting on %s provider.\n", iter->name));
bb2471ff14f01390b47cce63b407820b5547df1aTimo Sirainen /* there are still unstarted providers */
395aa4fe4639d13f37a470409d879f1c2b11254aTimo Sirainen /* then start all services */
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainenstatic void services_startup_timeout(struct tevent_context *ev,
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen struct mt_ctx *ctx = talloc_get_type(ptr, struct mt_ctx);
3a2f2adf5679aa383a2cab09f739d59233cada95Timo Sirainen "forcing services startup!\n"));
3a2f2adf5679aa383a2cab09f739d59233cada95Timo Sirainen /* then start all services */
3a2f2adf5679aa383a2cab09f739d59233cada95Timo Sirainenstatic int add_services_startup_timeout(struct mt_ctx *ctx)
3a2f2adf5679aa383a2cab09f739d59233cada95Timo Sirainen /* 5 seconds should be plenty */
3a2f2adf5679aa383a2cab09f739d59233cada95Timo Sirainen to = tevent_add_timer(ctx->ev, ctx, tv, services_startup_timeout, ctx);
3a2f2adf5679aa383a2cab09f739d59233cada95Timo Sirainen { MON_SRV_METHOD_VERSION, get_monitor_version },
3a2f2adf5679aa383a2cab09f739d59233cada95Timo Sirainen { MON_SRV_METHOD_REGISTER, client_registration },
3a2f2adf5679aa383a2cab09f739d59233cada95Timo Sirainenstruct sbus_interface monitor_server_interface = {
d71d05cf4417eaedb4d72491480a7d2bb46d8df3Timo Sirainen/* monitor_dbus_init
d71d05cf4417eaedb4d72491480a7d2bb46d8df3Timo Sirainen * Set up the monitor service as a D-BUS Server */
d71d05cf4417eaedb4d72491480a7d2bb46d8df3Timo Sirainenstatic int monitor_dbus_init(struct mt_ctx *ctx)
d71d05cf4417eaedb4d72491480a7d2bb46d8df3Timo Sirainen ret = monitor_get_sbus_address(ctx, &monitor_address);
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainenstatic void svc_try_restart(struct mt_svc *svc, time_t now)
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen if ((now - svc->last_restart) > 30) { /* TODO: get val from config */
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen /* it was long ago reset restart threshold */
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen /* restart the process */
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen if (svc->restarts > 3) { /* TODO: get val from config */
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen DEBUG(0, ("Process [%s], definitely stopped!\n", svc->name));
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen /* Shut down the current ping timer so it will restart
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen * cleanly in start_service()
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen DEBUG(0,("Failed to restart service '%s'\n", svc->name));
330865e1eb92715b34462af25c90c7308624c2afTimo Sirainenstatic void tasks_check_handler(struct tevent_context *ev,
bb2471ff14f01390b47cce63b407820b5547df1aTimo Sirainen struct mt_svc *svc = talloc_get_type(ptr, struct mt_svc);
330865e1eb92715b34462af25c90c7308624c2afTimo Sirainen /* all fine */
330865e1eb92715b34462af25c90c7308624c2afTimo Sirainen DEBUG(1,("Process (%s) is stopped!\n", svc->name));
bb2471ff14f01390b47cce63b407820b5547df1aTimo Sirainen /* TODO: should we tear down it ? */
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen DEBUG(1,("Checking for service %s(%d) failed!!\n",
291ce16fffca75e8598a8c9dceb08613413dcb07Timo Sirainen /* all fine */
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen DEBUG(1,("Child (%s) not responding! (yet)\n", svc->name));
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen /* TODO: should we tear it down ? */
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen DEBUG(1,("Sending a message to service (%s) failed!!\n", svc->name));
bb2471ff14f01390b47cce63b407820b5547df1aTimo Sirainen if ((now - svc->last_ping) > (svc->ping_time)) {
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen /* too long since we last heard of this process */
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen DEBUG(1, ("Killing service [%s], not responding to pings!\n",
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen /* all fine, set up the task checker again */
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainenstatic void set_tasks_checker(struct mt_svc *svc)
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen te = tevent_add_timer(svc->mt_ctx->ev, svc, tv, tasks_check_handler, svc);
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen DEBUG(0, ("failed to add event, monitor offline for [%s]!\n",
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen /* FIXME: shutdown ? */
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainenstatic void global_checks_handler(struct tevent_context *ev,
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen struct mt_ctx *ctx = talloc_get_type(ptr, struct mt_ctx);
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen DEBUG(0, ("waitpid returned -1 (errno:%d[%s])\n",
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen /* let's see if it is a known service, and try to restart it */
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen for (svc = ctx->svc_list; svc; svc = svc->next) {
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen DEBUG(1, ("Service [%s] did exit\n", svc->name));
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen DEBUG(0, ("Unknown child (%d) did exit\n", pid));
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainenstatic void set_global_checker(struct mt_ctx *ctx)
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen te = tevent_add_timer(ctx->ev, ctx, tv, global_checks_handler, ctx);
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen DEBUG(0, ("failed to add global checker event! PANIC TIME!\n"));
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen /* FIXME: is this right ? shoulkd we try to clean up first ?*/
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainenstatic int monitor_kill_service (struct mt_svc *svc)
90a2c5f48c5f88f07bbf0477e3023d2099252b92Timo Sirainen DEBUG(0,("Sending signal to child (%s:%d) failed! "
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen "Ignore and pretend child is dead.\n",
90a2c5f48c5f88f07bbf0477e3023d2099252b92Timo Sirainenstatic void reload_reply(DBusPendingCall *pending, void *data)
29543188462c9348f365ec29115d777ffe4769d3Timo Sirainen struct mt_svc *svc = talloc_get_type(data, struct mt_svc);
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen reply = dbus_pending_call_steal_reply(pending);
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen /* reply should never be null. This function shouldn't be called
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen * until reply is valid or timeout has occurred. If reply is NULL
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen * here, something is seriously wrong and we should bail out.
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen DEBUG(0, ("A reply callback was called but no reply was received"
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen " and no timeout occurred\n"));
90a2c5f48c5f88f07bbf0477e3023d2099252b92Timo Sirainen /* Destroy this connection */
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen /* TODO: Handle cases where the call has timed out or returned
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen * with an error.
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainenstatic int service_signal_dns_reload(struct mt_svc *svc);
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainenstatic int monitor_update_resolv(struct config_file_ctx *file_ctx,
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen DEBUG(2, ("Resolv.conf has been updated. Reloading.\n"));
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen /* Signal all services to reload their DNS configuration */
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen for(cur_svc = file_ctx->mt_ctx->svc_list; cur_svc; cur_svc = cur_svc->next) {
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainenstatic int service_signal(struct mt_svc *svc, const char *svc_signal)
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen if (svc->provider && strcasecmp(svc->provider, "local") == 0) {
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen /* The local provider requires no signaling */
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen /* Avoid a race condition where we are trying to
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen * order a service to reload that hasn't started
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen DEBUG(1,("Could not signal service [%s].\n", svc->name));
if (!msg) {
return ENOMEM;
return ret;
while (dom) {
return EINVAL;
while (other) {
return EOK;
while (dom) {
count++;
return EINVAL;
return EOK;
int ii;
for (i = 0; services[i]; i++) {
return services[i];
return NULL;
int ret;
int timeout_seconds;
return ret;
return ENOMEM;
return EINVAL;
return EINVAL;
return ENOMEM;
return ret;
return ret;
return ret;
return EOK;
int ret;
char *path;
if (!svc) {
return ENOMEM;
return ENOMEM;
return ENOMEM;
if (!path) {
return ENOMEM;
return ret;
return ENOMEM;
return ret;
return EOK;
int ret;
return ret;
return ret;
int ret;
char *path;
if (!svc) {
return ENOMEM;
return ENOMEM;
return ENOMEM;
if (!path) {
return ENOMEM;
return ret;
return ret;
return ret;
return EIO;
return ENOMEM;
return EOK;
int ret;
name));
return ret;
return ENOENT;
return ret;
int signum,
int count,
void *siginfo,
void *private_data)
static int monitor_cleanup(void)
char *file;
int ret;
return ENOMEM;
errno = 0;
return errno;
return EOK;
int signum,
int count,
void *siginfo,
void *private_data)
int status;
int kret;
bool killed;
killed = false;
errno = 0;
if (kret < 0) {
error = 0;
errno = 0;
} else if (pid != 0) {
error = 0;
killed = true;
if (!killed) {
} while (!killed);
#if HAVE_GETPGRP
error = 0;
errno = 0;
exit(0);
int signum,
int count,
void *siginfo,
void *private_data)
int signum,
int count,
void *siginfo,
void *private_data)
int ret;
config_file));
return ret;
const char *config_file,
if(!ctx) {
return ENOMEM;
goto done;
goto done;
goto done;
goto done;
goto done;
goto done;
goto done;
done:
return ret;
#ifdef HAVE_SYS_INOTIFY_H
if (!te) {
struct rewatch_ctx {
char *buf;
char *name;
if (!tmp_ctx) return;
if (!buf) {
goto done;
total_len = 0;
goto done;
if (!name) {
goto done;
total_len = 0;
goto done;
if (!cb) {
goto done;
if(!rw_ctx) {
goto done;
goto done;
done:
const char *file,
int err;
if (ret < 0) {
#ifdef HAVE_SYS_INOTIFY_H
return err;
if (fd_args < 0) {
return EINVAL;
if (ret < 0) {
return EINVAL;
file_ctx);
if (!tfd) {
return EIO;
if(!cb) {
return EIO;
return ENOMEM;
return err;
return EOK;
return EINVAL;
const char *file,
bool use_inotify;
if (ret < 0) {
return err;
true, &use_inotify);
return ret;
if (use_inotify) {
use_inotify = false;
if (!use_inotify) {
return ret;
const char *file,
if (ret < 0) {
return err;
if (!cb) {
return ENOMEM;
return ENOMEM;
return EIO;
return EOK;
const char *config_file)
int num_providers;
int ret;
return EIO;
return EIO;
return EIO;
return EIO;
return EIO;
return ret;
/* Watch for changes to the DNS resolv.conf */
return ret;
if (!tmp_ctx) {
return ENOMEM;
return ret;
return ret;
return ret;
num_providers = 0;
return ret;
if (num_providers > 0) {
return ret;
return EOK;
if (!mini) {
return ENOMEM;
return ENOMEM;
return EOK;
int ret;
return ENXIO;
if (!msg) {
return ENOMEM;
return ret;
const char *dbus_error_name;
int type;
if (!reply) {
goto done;
switch (type) {
case DBUS_MESSAGE_TYPE_ERROR:
done:
int status;
if (pid == 0) {
return EOK;
return EINVAL;
return ECHILD;
return ENOMEM;
return EOK;
char **args;
int opt;
int opt_daemon = 0;
int opt_interactive = 0;
int flags = 0;
int ret;
switch(opt) {
if (uid != 0) {
if (!tmp_ctx) {
if (opt_config_file)
if(!config_file)
if (debug_to_file) {
if (ret) {