bool dispatch_command(struct watchman_client *client, json_t *args) { watchman_command_func func; const char *cmd_name; w_string_t *cmd; if (!json_array_size(args)) { send_error_response(client, "invalid command (expected an array with some elements!)"); return false; } cmd_name = json_string_value(json_array_get(args, 0)); if (!cmd_name) { send_error_response(client, "invalid command: expected element 0 to be the command name"); return false; } cmd = w_string_new(cmd_name); func = (watchman_command_func)w_ht_get(command_funcs, (w_ht_val_t)cmd); w_string_delref(cmd); if (func) { func(client, args); return true; } send_error_response(client, "unknown command %s", cmd_name); return false; }
static void handle_flush(const char *req, int *req_index) { char dirstr[MAXATOMLEN]; if (ei_decode_atom(req, req_index, dirstr) < 0) { send_error_response("einval"); return; } enum uart_direction direction; if (strcmp(dirstr, "receive") == 0) direction = UART_DIRECTION_RECEIVE; else if (strcmp(dirstr, "transmit") == 0) direction = UART_DIRECTION_TRANSMIT; else if (strcmp(dirstr, "both") == 0) direction = UART_DIRECTION_BOTH; else { send_error_response("einval"); return; } if (!uart_is_open(uart)) { send_error_response("ebadf"); return; } if (uart_flush(uart, direction) >= 0) send_ok_response(); else send_error_response(uart_last_error()); }
/* since /root <timestamp> [patterns] */ static void cmd_since(struct watchman_client* client, const json_ref& args) { const char *clockspec; /* resolve the root */ if (json_array_size(args) < 3) { send_error_response(client, "not enough arguments for 'since'"); return; } auto root = resolve_root_or_err(client, args, 1, false); if (!root) { return; } auto clock_ele = json_array_get(args, 2); clockspec = json_string_value(clock_ele); if (!clockspec) { send_error_response(client, "expected argument 2 to be a valid clockspec"); return; } auto query = w_query_parse_legacy(root, args, 3, nullptr, clockspec, nullptr); auto res = w_query_execute(query.get(), root, nullptr); auto response = make_response(); response.set({{"is_fresh_instance", json_boolean(res.is_fresh_instance)}, {"clock", res.clockAtStartOfQuery.toJson()}, {"files", std::move(res.resultsArray)}}); add_root_warnings_to_response(response, root); send_and_dispose_response(client, std::move(response)); }
static void handle_signals(const char *req, int *req_index) { // No arguments (void) req; (void) req_index; if (!uart_is_open(uart)) { send_error_response("ebadf"); return; } struct uart_signals sig; if (uart_get_signals(uart, &sig) >= 0) { char resp[128]; int resp_index = sizeof(uint16_t); resp[resp_index++] = response_id; ei_encode_version(resp, &resp_index); ei_encode_tuple_header(resp, &resp_index, 2); ei_encode_atom(resp, &resp_index, "ok"); ei_encode_map_header(resp, &resp_index, 8); encode_kv_bool(resp, &resp_index, "dsr", sig.dsr); encode_kv_bool(resp, &resp_index, "dtr", sig.dtr); encode_kv_bool(resp, &resp_index, "rts", sig.rts); encode_kv_bool(resp, &resp_index, "st", sig.st); encode_kv_bool(resp, &resp_index, "sr", sig.sr); encode_kv_bool(resp, &resp_index, "cts", sig.cts); encode_kv_bool(resp, &resp_index, "cd", sig.cd); encode_kv_bool(resp, &resp_index, "rng", sig.rng); erlcmd_send(resp, resp_index); } else send_error_response(uart_last_error()); }
/*! * \brief Handles the SOAP requests to querry the state variables. * This functionality has been deprecated in the UPnP V1.0 architecture. */ static UPNP_INLINE void handle_query_variable( IN SOCKINFO *info, IN http_message_t *request, IN IXML_Document *xml_doc) { UpnpStateVarRequest *variable = UpnpStateVarRequest_new(); Upnp_FunPtr soap_event_callback; void *cookie; char var_name[LINE_SIZE]; const char *err_str; int err_code; if (get_var_name(xml_doc, var_name) != 0) { send_error_response(info, SOAP_INVALID_VAR, Soap_Invalid_Var, request); return; } /* get info for event */ err_code = get_device_info(request, 1, xml_doc, info->foreign_sockaddr.ss_family, (UpnpString *)UpnpStateVarRequest_get_DevUDN(variable), (UpnpString *)UpnpStateVarRequest_get_ServiceID(variable), &soap_event_callback, &cookie); if (err_code != 0) { send_error_response(info, SOAP_INVALID_VAR, Soap_Invalid_Var, request); return; } UpnpStateVarRequest_set_ErrCode(variable, UPNP_E_SUCCESS); UpnpStateVarRequest_strcpy_StateVarName(variable, var_name); UpnpStateVarRequest_set_CtrlPtIPAddr(variable, &info->foreign_sockaddr); /* send event */ soap_event_callback(UPNP_CONTROL_GET_VAR_REQUEST, variable, cookie); UpnpPrintf(UPNP_INFO, SOAP, __FILE__, __LINE__, "Return from callback for var request\n"); /* validate, and handle result */ if (UpnpStateVarRequest_get_CurrentVal(variable) == NULL) { err_code = SOAP_ACTION_FAILED; err_str = Soap_Action_Failed; send_error_response(info, SOAP_INVALID_VAR, Soap_Invalid_Var, request); return; } if (UpnpStateVarRequest_get_ErrCode(variable) != UPNP_E_SUCCESS) { if (UpnpString_get_Length(UpnpStateVarRequest_get_ErrStr(variable)) > 0) { err_code = SOAP_INVALID_VAR; err_str = Soap_Invalid_Var; } else { err_code = UpnpStateVarRequest_get_ErrCode(variable); err_str = UpnpStateVarRequest_get_ErrStr_cstr(variable); } send_error_response(info, err_code, err_str, request); return; } /* send response */ send_var_query_response(info, UpnpStateVarRequest_get_CurrentVal(variable), request); UpnpStateVarRequest_delete(variable); }
/* find /root [patterns] */ static void cmd_find(struct watchman_client *client, json_t *args) { w_root_t *root; w_query *query; char *errmsg = NULL; struct w_query_field_list field_list; w_query_res res; json_t *response; json_t *file_list; char clockbuf[128]; /* resolve the root */ if (json_array_size(args) < 2) { send_error_response(client, "not enough arguments for 'find'"); return; } root = resolve_root_or_err(client, args, 1, false); if (!root) { return; } query = w_query_parse_legacy(root, args, &errmsg, 2, NULL, NULL, NULL); if (errmsg) { send_error_response(client, "%s", errmsg); free(errmsg); w_root_delref(root); return; } w_query_legacy_field_list(&field_list); if (client->client_mode) { query->sync_timeout = 0; } if (!w_query_execute(query, root, &res, NULL, NULL)) { send_error_response(client, "query failed: %s", res.errmsg); w_query_result_free(&res); w_root_delref(root); w_query_delref(query); return; } w_query_delref(query); file_list = w_query_results_to_json(&field_list, res.num_results, res.results); w_query_result_free(&res); response = make_response(); if (clock_id_string(res.root_number, res.ticks, clockbuf, sizeof(clockbuf))) { set_prop(response, "clock", json_string_nocheck(clockbuf)); } set_prop(response, "files", file_list); send_and_dispose_response(client, response); w_root_delref(root); }
/* trigger /root triggername [watch patterns] -- cmd to run * Sets up a trigger so that we can execute a command when a change * is detected */ void cmd_trigger(struct watchman_client *client, json_t *args) { w_root_t *root; struct watchman_trigger_command *cmd; json_t *resp; json_t *trig; char *errmsg = NULL; root = resolve_root_or_err(client, args, 1, true); if (!root) { return; } if (json_array_size(args) < 3) { send_error_response(client, "not enough arguments"); goto done; } trig = json_array_get(args, 2); if (json_is_string(trig)) { trig = build_legacy_trigger(client, args); if (!trig) { goto done; } } else { // Add a ref so that we don't need to conditionally decref later // for the legacy case later json_incref(trig); } cmd = w_build_trigger_from_def(root, trig, &errmsg); json_decref(trig); if (!cmd) { send_error_response(client, "%s", errmsg); goto done; } w_root_lock(root); w_ht_replace(root->commands, w_ht_ptr_val(cmd->triggername), w_ht_ptr_val(cmd)); w_root_unlock(root); w_state_save(); resp = make_response(); set_prop(resp, "triggerid", json_string_nocheck(cmd->triggername->buf)); send_and_dispose_response(client, resp); done: if (errmsg) { free(errmsg); } w_root_delref(root); }
static json_t *build_legacy_trigger( w_root_t *root, struct watchman_client *client, json_t *args) { json_t *trig, *expr; json_t *command; char *errmsg; uint32_t next_arg = 0; uint32_t i; size_t n; w_query *query; trig = json_pack("{s:O, s:b, s:[s, s, s, s, s]}", "name", json_array_get(args, 2), "append_files", true, "stdin", // [ "name", "exists", "new", "size", "mode" // ] ); query = w_query_parse_legacy(root, args, &errmsg, 3, &next_arg, NULL, &expr); if (!query) { send_error_response(client, "invalid rule spec: %s", errmsg); free(errmsg); json_decref(trig); return NULL; } w_query_delref(query); json_object_set(trig, "expression", json_object_get(expr, "expression")); json_decref(expr); if (next_arg >= json_array_size(args)) { send_error_response(client, "no command was specified"); json_decref(trig); return NULL; } n = json_array_size(args) - next_arg; command = json_array_of_size(n); for (i = 0; i < n; i++) { json_t *ele = json_array_get(args, i + next_arg); if (!json_is_string(ele)) { send_error_response(client, "expected argument %d to be a string", i); json_decref(trig); return NULL; } json_array_append(command, ele); } json_object_set_new(trig, "command", command); return trig; }
bool dispatch_command(struct watchman_client *client, json_t *args, int mode) { struct watchman_command_handler_def *def; char *errmsg = NULL; bool result = false; char sample_name[128]; // Stash a reference to the current command to make it easier to log // the command context in some of the error paths client->current_command = args; json_incref(client->current_command); def = lookup(args, &errmsg, mode); if (!def) { send_error_response(client, "%s", errmsg); goto done; } if (poisoned_reason && (def->flags & CMD_POISON_IMMUNE) == 0) { send_error_response(client, "%s", poisoned_reason); goto done; } if (!client->client_is_owner && (def->flags & CMD_ALLOW_ANY_USER) == 0) { send_error_response(client, "you must be the process owner to execute '%s'", def->name); return false; } w_log(W_LOG_DBG, "dispatch_command: %s\n", def->name); snprintf(sample_name, sizeof(sample_name), "dispatch_command:%s", def->name); w_perf_start(&client->perf_sample, sample_name); w_perf_set_wall_time_thresh( &client->perf_sample, cfg_get_double(NULL, "slow_command_log_threshold_seconds", 1.0)); result = true; def->func(client, args); if (w_perf_finish(&client->perf_sample)) { json_incref(args); w_perf_add_meta(&client->perf_sample, "args", args); w_perf_log(&client->perf_sample); } else { w_log(W_LOG_DBG, "dispatch_command: %s (completed)\n", def->name); } done: free(errmsg); json_decref(client->current_command); client->current_command = NULL; w_perf_destroy(&client->perf_sample); return result; }
static void handle_drain(const char *req, int *req_index) { (void) req; (void) req_index; if (!uart_is_open(uart)) { send_error_response("ebadf"); return; } if (uart_drain(uart) >= 0) send_ok_response(); else send_error_response(uart_last_error()); }
static void handle_configure(const char *req, int *req_index) { struct uart_config config = current_config; if (parse_option_list(req, req_index, &config) < 0) { send_error_response("einval"); return; } if (uart_configure(uart, &config) >= 0) { current_config = config; send_ok_response(); } else { send_error_response(uart_last_error()); } }
/* unsubscribe /root subname * Cancels a subscription */ static void cmd_unsubscribe( struct watchman_client* clientbase, const json_ref& args) { const char *name; bool deleted{false}; struct watchman_user_client *client = (struct watchman_user_client *)clientbase; auto root = resolve_root_or_err(client, args, 1, false); if (!root) { return; } auto jstr = json_array_get(args, 2); name = json_string_value(jstr); if (!name) { send_error_response( client, "expected 2nd parameter to be subscription name"); return; } auto sname = json_to_w_string(jstr); deleted = client->unsubByName(sname); auto resp = make_response(); resp.set({{"unsubscribe", typed_string_to_json(name)}, {"deleted", json_boolean(deleted)}}); send_and_dispose_response(client, std::move(resp)); }
/* debug-ageout */ static void cmd_debug_ageout( struct watchman_client* client, const json_ref& args) { /* resolve the root */ if (json_array_size(args) != 3) { send_error_response(client, "wrong number of arguments for 'debug-ageout'"); return; } auto root = resolve_root_or_err(client, args, 1, false); if (!root) { return; } std::chrono::seconds min_age(json_integer_value(json_array_get(args, 2))); auto resp = make_response(); root->performAgeOut(min_age); resp.set("ageout", json_true()); send_and_dispose_response(client, std::move(resp)); }
/* find /root [patterns] */ static void cmd_find(struct watchman_client* client, const json_ref& args) { /* resolve the root */ if (json_array_size(args) < 2) { send_error_response(client, "not enough arguments for 'find'"); return; } auto root = resolve_root_or_err(client, args, 1, false); if (!root) { return; } auto query = w_query_parse_legacy(root, args, 2, nullptr, nullptr, nullptr); if (client->client_mode) { query->sync_timeout = std::chrono::milliseconds(0); } auto res = w_query_execute(query.get(), root, nullptr); auto response = make_response(); response.set({{"clock", res.clockAtStartOfQuery.toJson()}, {"files", std::move(res.resultsArray)}}); send_and_dispose_response(client, std::move(response)); }
/* watch /root */ static void cmd_watch(struct watchman_client *client, json_t *args) { w_root_t *root; json_t *resp; /* resolve the root */ if (json_array_size(args) != 2) { send_error_response(client, "wrong number of arguments to 'watch'"); return; } root = resolve_root_or_err(client, args, 1, true); if (!root) { return; } resp = make_response(); w_root_lock(root); if (root->failure_reason) { set_prop(resp, "error", json_string_nocheck(root->failure_reason->buf)); } else if (root->cancelled) { set_prop(resp, "error", json_string_nocheck("root was cancelled")); } else { set_prop(resp, "watch", json_string_nocheck(root->root_path->buf)); } send_and_dispose_response(client, resp); w_root_unlock(root); w_root_delref(root); }
/* debug-ageout */ static void cmd_debug_ageout(struct watchman_client *client, json_t *args) { w_root_t *root; json_t *resp; int min_age; /* resolve the root */ if (json_array_size(args) != 3) { send_error_response(client, "wrong number of arguments for 'debug-ageout'"); return; } root = resolve_root_or_err(client, args, 1, false); if (!root) { return; } min_age = json_integer_value(json_array_get(args, 2)); resp = make_response(); w_root_lock(root); w_root_perform_age_out(root, min_age); w_root_unlock(root); set_prop(resp, "ageout", json_true()); send_and_dispose_response(client, resp); w_root_delref(root); }
static void cmd_debug_recrawl(struct watchman_client *client, json_t *args) { w_root_t *root; json_t *resp; /* resolve the root */ if (json_array_size(args) != 2) { send_error_response(client, "wrong number of arguments for 'debug-recrawl'"); return; } root = resolve_root_or_err(client, args, 1, false); if (!root) { return; } resp = make_response(); w_root_lock(root); w_root_schedule_recrawl(root, "debug-recrawl"); w_root_unlock(root); set_prop(resp, "recrawl", json_true()); send_and_dispose_response(client, resp); w_root_delref(root); }
static void cmd_debug_show_cursors(struct watchman_client *client, json_t *args) { w_root_t *root; json_t *resp, *cursors; w_ht_iter_t i; /* resolve the root */ if (json_array_size(args) != 2) { send_error_response(client, "wrong number of arguments for 'debug-show-cursors'"); return; } root = resolve_root_or_err(client, args, 1, false); if (!root) { return; } resp = make_response(); w_root_lock(root); cursors = json_object_of_size(w_ht_size(root->cursors)); if (w_ht_first(root->cursors, &i)) do { w_string_t *name = w_ht_val_ptr(i.key); set_prop(cursors, name->buf, json_integer(i.value)); } while (w_ht_next(root->cursors, &i)); w_root_unlock(root); set_prop(resp, "cursors", cursors); send_and_dispose_response(client, resp); w_root_delref(root); }
static void printfile(const char *path, pConnInfo conn_info) { char *mod_time_str ; char *file_mod_time = get_file_time(path); if((mod_time_str = get_header_param("If-Modified-Since", conn_info->request_header))) { if(!is_expire(mod_time_str, file_mod_time)) { conn_info->status_code = 304; send_error_response(conn_info); return; } } FILE* file = fopen(path, "r"); fseek(file, 0, SEEK_END); header_body.content_len = ftell(file); rewind(file); add_header_param("Last-Modified", file_mod_time, conn_info->response_header); uws_free(file_mod_time); header_body.content = (char*) uws_malloc (header_body.content_len * sizeof(char)); size_t read_size = fread(header_body.content, sizeof(char), header_body.content_len, file); fclose(file); }
static void handle_write(const char *req, int *req_index) { if (!uart_is_open(uart)) { send_error_response("ebadf"); return; } int term_size; if (ei_decode_tuple_header(req, req_index, &term_size) < 0 || term_size != 2) errx(EXIT_FAILURE, "expecting {data, timeout}"); int term_type; if (ei_get_type(req, req_index, &term_type, &term_size) < 0 || term_type != ERL_BINARY_EXT) errx(EXIT_FAILURE, "expecting data as a binary"); uint8_t *to_write = malloc(term_size); long amount_to_write; if (ei_decode_binary(req, req_index, to_write, &amount_to_write) < 0) errx(EXIT_FAILURE, "decode binary error?"); long timeout; if (ei_decode_long(req, req_index, &timeout) < 0) errx(EXIT_FAILURE, "expecting timeout"); // uart_write always invokes a callback when it completes (error or no error). uart_write(uart, to_write, amount_to_write, timeout); }
static void cmd_debug_show_cursors( struct watchman_client* client, const json_ref& args) { json_ref cursors; /* resolve the root */ if (json_array_size(args) != 2) { send_error_response(client, "wrong number of arguments for 'debug-show-cursors'"); return; } auto root = resolve_root_or_err(client, args, 1, false); if (!root) { return; } auto resp = make_response(); { auto map = root->inner.cursors.rlock(); cursors = json_object_of_size(map->size()); for (const auto& it : *map) { const auto& name = it.first; const auto& ticks = it.second; cursors.set(name.c_str(), json_integer(ticks)); } } resp.set("cursors", std::move(cursors)); send_and_dispose_response(client, std::move(resp)); }
w_root_t *resolve_root_or_err(struct watchman_client *client, json_t *args, int root_index, bool create) { w_root_t *root; const char *root_name; char *errmsg = NULL; json_t *ele; ele = json_array_get(args, root_index); if (!ele) { send_error_response(client, "wrong number of arguments"); return NULL; } root_name = json_string_value(ele); if (!root_name) { send_error_response(client, "invalid value for argument %d, expected " "a string naming the root dir", root_index); return NULL; } if (client->client_mode) { root = w_root_resolve_for_client_mode(root_name, &errmsg); } else { if (!client->client_is_owner) { // Only the owner is allowed to create watches create = false; } root = w_root_resolve(root_name, create, &errmsg); } if (!root) { if (!client->client_is_owner) { send_error_response(client, "unable to resolve root %s: %s (this may be " "because you are not the process owner)", root_name, errmsg); } else { send_error_response(client, "unable to resolve root %s: %s", root_name, errmsg); } free(errmsg); } else { w_perf_add_root_meta(&client->perf_sample, root); } return root; }
static void handle_set_break(const char *req, int *req_index) { int val; if (ei_decode_boolean(req, req_index, &val) < 0) { send_error_response("einval"); return; } if (!uart_is_open(uart)) { send_error_response("ebadf"); return; } if (uart_set_break(uart, !!val) >= 0) send_ok_response(); else send_error_response(uart_last_error()); }
static void handle_write_completed(int rc, const uint8_t *data) { free((uint8_t *) data); if (rc == 0) send_ok_response(); else send_error_response(uart_last_error()); }
/* trigger-del /root triggername * Delete a trigger from a root */ static void cmd_trigger_delete(struct watchman_client *client, json_t *args) { w_root_t *root; json_t *resp; json_t *jname; w_string_t *tname; bool res; root = resolve_root_or_err(client, args, 1, false); if (!root) { return; } if (json_array_size(args) != 3) { send_error_response(client, "wrong number of arguments"); w_root_delref(root); return; } jname = json_array_get(args, 2); if (!json_is_string(jname)) { send_error_response(client, "expected 2nd parameter to be trigger name"); w_root_delref(root); return; } tname = json_to_w_string_incref(jname); w_root_lock(root, "trigger-del"); res = w_ht_del(root->commands, w_ht_ptr_val(tname)); w_root_unlock(root); if (res) { w_state_save(); } w_string_delref(tname); resp = make_response(); set_prop(resp, "deleted", json_boolean(res)); json_incref(jname); set_prop(resp, "trigger", jname); send_and_dispose_response(client, resp); w_root_delref(root); }
static void cmd_debug_set_subscriptions_paused( struct watchman_client* clientbase, const json_ref& args) { auto client = (struct watchman_user_client*)clientbase; const auto& paused = args.at(1); auto& paused_map = paused.object(); for (auto& it : paused_map) { auto sub_iter = client->subscriptions.find(it.first); if (sub_iter == client->subscriptions.end()) { send_error_response( client, "this client does not have a subscription named '%s'", it.first.c_str()); return; } if (!json_is_boolean(it.second)) { send_error_response( client, "new value for subscription '%s' not a boolean", it.first.c_str()); return; } } auto states = json_object(); for (auto& it : paused_map) { auto sub_iter = client->subscriptions.find(it.first); bool old_paused = sub_iter->second->debug_paused; bool new_paused = json_is_true(it.second); sub_iter->second->debug_paused = new_paused; states.set( it.first, json_object({{"old", json_boolean(old_paused)}, {"new", it.second}})); } auto resp = make_response(); resp.set("paused", std::move(states)); send_and_dispose_response(clientbase, std::move(resp)); }
bool dispatch_command(struct watchman_client *client, json_t *args, int mode) { struct watchman_command_handler_def *def; char *errmsg = NULL; def = lookup(args, &errmsg, mode); if (!def) { send_error_response(client, "%s", errmsg); free(errmsg); return false; } if (poisoned_reason && (def->flags & CMD_POISON_IMMUNE) == 0) { send_error_response(client, "%s", poisoned_reason); return false; } def->func(client, args); return true; }
w_root_t *resolve_root_or_err( struct watchman_client *client, json_t *args, int root_index, bool create) { w_root_t *root; const char *root_name; char *errmsg = NULL; json_t *ele; ele = json_array_get(args, root_index); if (!ele) { send_error_response(client, "wrong number of arguments"); return NULL; } root_name = json_string_value(ele); if (!root_name) { send_error_response(client, "invalid value for argument %d, expected " "a string naming the root dir", root_index); return NULL; } if (client->client_mode) { root = w_root_resolve_for_client_mode(root_name, &errmsg); } else { root = w_root_resolve(root_name, create, &errmsg); } if (!root) { send_error_response(client, "unable to resolve root %s: %s", root_name, errmsg); free(errmsg); } return root; }
/* trigger-del /root triggername * Delete a trigger from a root */ void cmd_trigger_delete(struct watchman_client *client, json_t *args) { w_root_t *root; json_t *resp; const char *name; w_string_t *tname; bool res; root = resolve_root_or_err(client, args, 1, false); if (!root) { return; } if (json_array_size(args) != 3) { send_error_response(client, "wrong number of arguments"); w_root_delref(root); return; } name = json_string_value(json_array_get(args, 2)); if (!name) { send_error_response(client, "expected 2nd parameter to be trigger name"); w_root_delref(root); return; } tname = w_string_new(name); w_root_lock(root); res = w_ht_del(root->commands, (w_ht_val_t)tname); w_root_unlock(root); w_state_save(); w_string_delref(tname); resp = make_response(); set_prop(resp, "deleted", json_boolean(res)); set_prop(resp, "trigger", json_string_nocheck(name)); send_and_dispose_response(client, resp); w_root_delref(root); }
/* * Handle {name, kv_list} * * name is the serial port name * kv_list a list of configuration values (speed, parity, etc.) */ static void handle_open(const char *req, int *req_index) { int term_type; int term_size; if (ei_decode_tuple_header(req, req_index, &term_size) < 0 || term_size != 2) errx(EXIT_FAILURE, ":open requires a 2-tuple"); char name[32]; long binary_len; if (ei_get_type(req, req_index, &term_type, &term_size) < 0 || term_type != ERL_BINARY_EXT || term_size >= (int) sizeof(name) || ei_decode_binary(req, req_index, name, &binary_len) < 0) { // The name is almost certainly too long, so report that it // doesn't exist. send_error_response("enoent"); return; } name[term_size] = '\0'; struct uart_config config = current_config; if (parse_option_list(req, req_index, &config) < 0) { send_error_response("einval"); return; } // If the uart was already open, close and open it again if (uart_is_open(uart)) uart_close(uart); if (uart_open(uart, name, &config) >= 0) { current_config = config; send_ok_response(); } else { send_error_response(uart_last_error()); } }