_public_ int sd_bus_reply_method_errno( sd_bus_message *call, int error, const sd_bus_error *p) { _cleanup_bus_error_free_ sd_bus_error berror = SD_BUS_ERROR_NULL; assert_return(call, -EINVAL); assert_return(call->sealed, -EPERM); assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL); assert_return(call->bus, -EINVAL); assert_return(!bus_pid_changed(call->bus), -ECHILD); if (!BUS_IS_OPEN(call->bus->state)) return -ENOTCONN; if (call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED) return 0; if (sd_bus_error_is_set(p)) return sd_bus_reply_method_error(call, p); sd_bus_error_set_errno(&berror, error); return sd_bus_reply_method_error(call, &berror); }
_public_ int sd_bus_reply_method_errnof( sd_bus_message *call, int error, const char *format, ...) { _cleanup_bus_error_free_ sd_bus_error berror = SD_BUS_ERROR_NULL; va_list ap; assert_return(call, -EINVAL); assert_return(call->sealed, -EPERM); assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL); assert_return(call->bus, -EINVAL); assert_return(!bus_pid_changed(call->bus), -ECHILD); if (!BUS_IS_OPEN(call->bus->state)) return -ENOTCONN; if (call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED) return 0; va_start(ap, format); bus_error_set_errnofv(&berror, error, format, ap); va_end(ap); return sd_bus_reply_method_error(call, &berror); }
static int operation_done(sd_event_source *s, const siginfo_t *si, void *userdata) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; Operation *o = userdata; int r; assert(o); assert(si); log_debug("Operating " PID_FMT " is now complete with code=%s status=%i", o->pid, sigchld_code_to_string(si->si_code), si->si_status); o->pid = 0; if (si->si_code != CLD_EXITED) { r = sd_bus_error_setf(&error, SD_BUS_ERROR_FAILED, "Child died abnormally."); goto fail; } if (si->si_status == EXIT_SUCCESS) r = 0; else if (read(o->errno_fd, &r, sizeof(r)) != sizeof(r)) { /* Try to acquire error code for failed operation */ r = sd_bus_error_setf(&error, SD_BUS_ERROR_FAILED, "Child failed."); goto fail; } if (o->done) { /* A completion routine is set for this operation, call it. */ r = o->done(o, r, &error); if (r < 0) { if (!sd_bus_error_is_set(&error)) sd_bus_error_set_errno(&error, r); goto fail; } } else { /* The default operation when done is to simply return an error on failure or an empty success * message on success. */ if (r < 0) { sd_bus_error_set_errno(&error, r); goto fail; } r = sd_bus_reply_method_return(o->message, NULL); if (r < 0) log_error_errno(r, "Failed to reply to message: %m"); } operation_free(o); return 0; fail: r = sd_bus_reply_method_error(o->message, &error); if (r < 0) log_error_errno(r, "Failed to reply to message: %m"); operation_free(o); return 0; }
static int cc_Smartie_hangup_thunk( CC_IGNORE_BUS_ARG sd_bus_message *m, void *userdata, sd_bus_error *error) { int result = 0; struct cc_server_Smartie *ii = (struct cc_server_Smartie *) userdata; int32_t status; CC_LOG_DEBUG("invoked cc_Smartie_hangup_thunk()\n"); assert(m); assert(ii && ii->impl); CC_LOG_DEBUG("with path='%s'\n", sd_bus_message_get_path(m)); result = sd_bus_message_read(m, ""); if (result < 0) { CC_LOG_ERROR("unable to read method parameters: %s\n", strerror(-result)); return result; } if (!ii->impl->hangup) { CC_LOG_ERROR("unsupported method invoked: %s\n", "Smartie.hangup"); sd_bus_error_set( error, SD_BUS_ERROR_NOT_SUPPORTED, "instance does not support method Smartie.hangup"); sd_bus_reply_method_error(m, error); return -ENOTSUP; } result = ii->impl->hangup(ii, &status); if (result < 0) { CC_LOG_ERROR("failed to execute method: %s\n", strerror(-result)); sd_bus_error_setf( error, SD_BUS_ERROR_FAILED, "method implementation failed with error=%d", result); sd_bus_reply_method_error(m, error); return result; } result = sd_bus_reply_method_return(m, "i", status); if (result < 0) { CC_LOG_ERROR("unable to send method reply: %s\n", strerror(-result)); return result; } /* Successful method invocation must return >0 */ return 1; }
int bus_maybe_reply_error(sd_bus_message *m, int r, sd_bus_error *error) { assert(m); if (r < 0) { if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL) sd_bus_reply_method_errno(m, r, error); } else if (sd_bus_error_is_set(error)) { if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL) sd_bus_reply_method_error(m, error); } else return r; log_debug("Failed to process message [type=%s sender=%s path=%s interface=%s member=%s signature=%s]: %s", bus_message_type_to_string(m->header->type), strna(m->sender), strna(m->path), strna(m->interface), strna(m->member), strna(m->root_container.signature), bus_error_message(error, r)); return 1; }
static int server(sd_bus *bus) { int r; bool client1_gone = false, client2_gone = false; while (!client1_gone || !client2_gone) { _cleanup_bus_message_unref_ sd_bus_message *m = NULL; pid_t pid = 0; const char *label = NULL; r = sd_bus_process(bus, &m); if (r < 0) { log_error_errno(r, "Failed to process requests: %m"); goto fail; } if (r == 0) { r = sd_bus_wait(bus, (uint64_t) -1); if (r < 0) { log_error_errno(r, "Failed to wait: %m"); goto fail; } continue; } if (!m) continue; sd_bus_creds_get_pid(sd_bus_message_get_creds(m), &pid); sd_bus_creds_get_selinux_context(sd_bus_message_get_creds(m), &label); log_info("Got message! member=%s pid="PID_FMT" label=%s", strna(sd_bus_message_get_member(m)), pid, strna(label)); /* bus_message_dump(m); */ /* sd_bus_message_rewind(m, true); */ if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "LowerCase")) { const char *hello; _cleanup_free_ char *lowercase = NULL; r = sd_bus_message_read(m, "s", &hello); if (r < 0) { log_error_errno(r, "Failed to get parameter: %m"); goto fail; } lowercase = strdup(hello); if (!lowercase) { r = log_oom(); goto fail; } ascii_strlower(lowercase); r = sd_bus_reply_method_return(m, "s", lowercase); if (r < 0) { log_error_errno(r, "Failed to send reply: %m"); goto fail; } } else if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "ExitClient1")) { r = sd_bus_reply_method_return(m, NULL); if (r < 0) { log_error_errno(r, "Failed to send reply: %m"); goto fail; } client1_gone = true; } else if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "ExitClient2")) { r = sd_bus_reply_method_return(m, NULL); if (r < 0) { log_error_errno(r, "Failed to send reply: %m"); goto fail; } client2_gone = true; } else if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "Slow")) { sleep(1); r = sd_bus_reply_method_return(m, NULL); if (r < 0) { log_error_errno(r, "Failed to send reply: %m"); goto fail; } } else if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "FileDescriptor")) { int fd; static const char x = 'X'; r = sd_bus_message_read(m, "h", &fd); if (r < 0) { log_error_errno(r, "Failed to get parameter: %m"); goto fail; } log_info("Received fd=%d", fd); if (write(fd, &x, 1) < 0) { log_error_errno(errno, "Failed to write to fd: %m"); safe_close(fd); goto fail; } r = sd_bus_reply_method_return(m, NULL); if (r < 0) { log_error_errno(r, "Failed to send reply: %m"); goto fail; } } else if (sd_bus_message_is_method_call(m, NULL, NULL)) { r = sd_bus_reply_method_error( m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_UNKNOWN_METHOD, "Unknown method.")); if (r < 0) { log_error_errno(r, "Failed to send reply: %m"); goto fail; } } } r = 0; fail: if (bus) { sd_bus_flush(bus); sd_bus_unref(bus); } return r; }
static int reply_query_state(DnsQuery *q) { _cleanup_free_ char *ip = NULL; const char *name; int r; if (q->request_hostname) name = q->request_hostname; else { r = in_addr_to_string(q->request_family, &q->request_address, &ip); if (r < 0) return r; name = ip; } switch (q->state) { case DNS_TRANSACTION_NO_SERVERS: return sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_NAME_SERVERS, "No appropriate name servers or networks for name found"); case DNS_TRANSACTION_TIMEOUT: return sd_bus_reply_method_errorf(q->request, SD_BUS_ERROR_TIMEOUT, "Query timed out"); case DNS_TRANSACTION_ATTEMPTS_MAX_REACHED: return sd_bus_reply_method_errorf(q->request, SD_BUS_ERROR_TIMEOUT, "All attempts to contact name servers or networks failed"); case DNS_TRANSACTION_INVALID_REPLY: return sd_bus_reply_method_errorf(q->request, BUS_ERROR_INVALID_REPLY, "Received invalid reply"); case DNS_TRANSACTION_RESOURCES: return sd_bus_reply_method_errorf(q->request, BUS_ERROR_NO_RESOURCES, "Not enough resources"); case DNS_TRANSACTION_ABORTED: return sd_bus_reply_method_errorf(q->request, BUS_ERROR_ABORTED, "Query aborted"); case DNS_TRANSACTION_FAILURE: { _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; if (q->answer_rcode == DNS_RCODE_NXDOMAIN) sd_bus_error_setf(&error, _BUS_ERROR_DNS "NXDOMAIN", "'%s' not found", name); else { const char *rc, *n; char p[3]; /* the rcode is 4 bits long */ rc = dns_rcode_to_string(q->answer_rcode); if (!rc) { sprintf(p, "%i", q->answer_rcode); rc = p; } n = strappenda(_BUS_ERROR_DNS, rc); sd_bus_error_setf(&error, n, "Could not resolve '%s', server or network returned error %s", name, rc); } return sd_bus_reply_method_error(q->request, &error); } case DNS_TRANSACTION_NULL: case DNS_TRANSACTION_PENDING: case DNS_TRANSACTION_SUCCESS: default: assert_not_reached("Impossible state"); } }