static void func_new (NCDModuleInst *i) { // allocate instance struct instance *o = malloc(sizeof(*o)); if (!o) { ModuleLog(i, BLOG_ERROR, "failed to allocate instance"); goto fail0; } NCDModuleInst_Backend_SetUser(i, o); // init arguments o->i = i; // check arguments NCDValue *template_name_arg; NCDValue *args_arg; if (!NCDValue_ListRead(o->i->args, 2, &template_name_arg, &args_arg)) { ModuleLog(o->i, BLOG_ERROR, "wrong arity"); goto fail1; } if (NCDValue_Type(template_name_arg) != NCDVALUE_STRING || NCDValue_Type(args_arg) != NCDVALUE_LIST) { ModuleLog(o->i, BLOG_ERROR, "wrong type"); goto fail1; } // signal up. // Do it before creating the process so that the process starts initializing before our own process continues. NCDModuleInst_Backend_Up(o->i); // copy arguments NCDValue args; if (!NCDValue_InitCopy(&args, args_arg)) { ModuleLog(o->i, BLOG_ERROR, "NCDValue_InitCopy failed"); goto fail1; } // create process if (!NCDModuleProcess_Init(&o->process, o->i, NCDValue_StringValue(template_name_arg), args, o, (NCDModuleProcess_handler_event)process_handler_event)) { ModuleLog(o->i, BLOG_ERROR, "NCDModuleProcess_Init failed"); NCDValue_Free(&args); goto fail1; } // set state working o->state = STATE_WORKING; return; fail1: free(o); fail0: NCDModuleInst_Backend_SetError(i); NCDModuleInst_Backend_Dead(i); }
static void func_new_from_value (NCDModuleInst *i) { // read arguments NCDValue *arg_value; if (!NCDValue_ListRead(i->args, 1, &arg_value)) { ModuleLog(i, BLOG_ERROR, "wrong arity"); goto fail0; } if (NCDValue_Type(arg_value) != NCDVALUE_STRING) { ModuleLog(i, BLOG_ERROR, "wrong type"); goto fail0; } // parse value uintmax_t value; if (!parse_unsigned_integer(NCDValue_StringValue(arg_value), &value)) { ModuleLog(i, BLOG_ERROR, "wrong value"); goto fail0; } // check overflow if (value > SIZE_MAX) { ModuleLog(i, BLOG_ERROR, "value too large"); goto fail0; } func_new_templ(i, value); return; fail0: NCDModuleInst_Backend_SetError(i); NCDModuleInst_Backend_Dead(i); }
static void func_new (NCDModuleInst *i) { // allocate instance struct instance *o = malloc(sizeof(*o)); if (!o) { ModuleLog(i, BLOG_ERROR, "failed to allocate instance"); goto fail0; } NCDModuleInst_Backend_SetUser(i, o); // init arguments o->i = i; // init string ExpString s; if (!ExpString_Init(&s)) { ModuleLog(i, BLOG_ERROR, "ExpString_Init failed"); goto fail1; } // append arguments NCDValue *arg = NCDValue_ListFirst(o->i->args); while (arg) { if (NCDValue_Type(arg) != NCDVALUE_STRING) { ModuleLog(i, BLOG_ERROR, "wrong type"); goto fail2; } if (!ExpString_Append(&s, NCDValue_StringValue(arg))) { ModuleLog(i, BLOG_ERROR, "ExpString_Append failed"); goto fail2; } arg = NCDValue_ListNext(o->i->args, arg); } // set string o->string = ExpString_Get(&s); // signal up NCDModuleInst_Backend_Up(o->i); return; fail2: ExpString_Free(&s); fail1: free(o); fail0: NCDModuleInst_Backend_SetError(i); NCDModuleInst_Backend_Dead(i); }
int build_cmdline (struct instance *o, CmdLine *c) { // init cmdline if (!CmdLine_Init(c)) { goto fail0; } // append stdbuf part if (!build_stdbuf_cmdline(c, o->exec)) { goto fail1; } // append user arguments NCDValue *arg = NCDValue_ListFirst(o->args); while (arg) { if (NCDValue_Type(arg) != NCDVALUE_STRING) { ModuleLog(o->i, BLOG_ERROR, "wrong type"); goto fail1; } // append argument if (!CmdLine_Append(c, NCDValue_StringValue(arg))) { goto fail1; } arg = NCDValue_ListNext(o->args, arg); } // append interface name if (!CmdLine_Append(c, "-i") || !CmdLine_Append(c, o->ifname)) { goto fail1; } // append config file if (!CmdLine_Append(c, "-c") || !CmdLine_Append(c, o->conf)) { goto fail1; } // terminate cmdline if (!CmdLine_Finish(c)) { goto fail1; } return 1; fail1: CmdLine_Free(c); fail0: return 0; }
static void func_new (NCDModuleInst *i) { // allocate instance struct instance *o = malloc(sizeof(*o)); if (!o) { ModuleLog(i, BLOG_ERROR, "failed to allocate instance"); goto fail0; } NCDModuleInst_Backend_SetUser(i, o); // init arguments o->i = i; // check arguments NCDValue *template_name_arg; NCDValue *args_arg; if (!NCDValue_ListRead(o->i->args, 2, &template_name_arg, &args_arg)) { ModuleLog(o->i, BLOG_ERROR, "wrong arity"); goto fail1; } if (NCDValue_Type(template_name_arg) != NCDVALUE_STRING || NCDValue_Type(args_arg) != NCDVALUE_LIST) { ModuleLog(o->i, BLOG_ERROR, "wrong type"); goto fail1; } char *template_name = NCDValue_StringValue(template_name_arg); // calling none? if (!strcmp(template_name, "<none>")) { // signal up NCDModuleInst_Backend_Up(o->i); // set state none o->state = STATE_NONE; } else { // copy arguments NCDValue args; if (!NCDValue_InitCopy(&args, args_arg)) { ModuleLog(o->i, BLOG_ERROR, "NCDValue_InitCopy failed"); goto fail1; } // create process if (!NCDModuleProcess_Init(&o->process, o->i, template_name, args, o, (NCDModuleProcess_handler_event)process_handler_event)) { ModuleLog(o->i, BLOG_ERROR, "NCDModuleProcess_Init failed"); NCDValue_Free(&args); goto fail1; } // set special functions NCDModuleProcess_SetSpecialFuncs(&o->process, (NCDModuleProcess_func_getspecialobj)process_func_getspecialobj); // set callrefhere o->crh = (o->i->method_user ? ((NCDModuleInst *)i->method_user)->inst_user : NULL); // add to callrefhere's calls list if (o->crh) { LinkedList0_Prepend(&o->crh->calls_list, &o->calls_list_node); } // set state working o->state = STATE_WORKING; } return; fail1: free(o); fail0: NCDModuleInst_Backend_SetError(i); NCDModuleInst_Backend_Dead(i); }
static void func_new (NCDModuleInst *i) { // allocate instance struct instance *o = malloc(sizeof(*o)); if (!o) { ModuleLog(i, BLOG_ERROR, "failed to allocate instance"); goto fail0; } NCDModuleInst_Backend_SetUser(i, o); // init arguments o->i = i; // read arguments NCDValue *arg_choices; NCDValue *arg_default_result; if (!NCDValue_ListRead(i->args, 2, &arg_choices, &arg_default_result)) { ModuleLog(i, BLOG_ERROR, "wrong arity"); goto fail1; } if (NCDValue_Type(arg_choices) != NCDVALUE_LIST) { ModuleLog(i, BLOG_ERROR, "wrong type"); goto fail1; } // set no result o->result = NULL; // iterate choices for (NCDValue *c = NCDValue_ListFirst(arg_choices); c; c = NCDValue_ListNext(arg_choices, c)) { // check choice type if (NCDValue_Type(c) != NCDVALUE_LIST) { ModuleLog(i, BLOG_ERROR, "wrong choice type"); goto fail1; } // read choice NCDValue *c_cond; NCDValue *c_result; if (!NCDValue_ListRead(c, 2, &c_cond, &c_result)) { ModuleLog(i, BLOG_ERROR, "wrong choice contents arity"); goto fail1; } if (NCDValue_Type(c_cond) != NCDVALUE_STRING) { ModuleLog(i, BLOG_ERROR, "wrong choice condition type"); goto fail1; } // update result if (!o->result && !strcmp(NCDValue_StringValue(c_cond), "true")) { o->result = c_result; } } // default? if (!o->result) { o->result = arg_default_result; } // signal up NCDModuleInst_Backend_Up(o->i); return; fail1: free(o); fail0: NCDModuleInst_Backend_SetError(i); NCDModuleInst_Backend_Dead(i); }
static void func_new (NCDModuleInst *i) { // allocate instance struct instance *o = malloc(sizeof(*o)); if (!o) { ModuleLog(i, BLOG_ERROR, "failed to allocate instance"); goto fail0; } NCDModuleInst_Backend_SetUser(i, o); // init arguments o->i = i; // read arguments NCDValue *ifname_arg; NCDValue *user_arg; NCDValue *exec_arg; NCDValue *args_arg; if (!NCDValue_ListRead(o->i->args, 4, &ifname_arg, &user_arg, &exec_arg, &args_arg)) { ModuleLog(o->i, BLOG_ERROR, "wrong arity"); goto fail1; } if (NCDValue_Type(ifname_arg) != NCDVALUE_STRING || NCDValue_Type(user_arg) != NCDVALUE_STRING || NCDValue_Type(exec_arg) != NCDVALUE_STRING || NCDValue_Type(args_arg) != NCDVALUE_LIST) { ModuleLog(o->i, BLOG_ERROR, "wrong type"); goto fail1; } o->ifname = NCDValue_StringValue(ifname_arg); o->user = NCDValue_StringValue(user_arg); o->exec = NCDValue_StringValue(exec_arg); o->args = args_arg; // check arguments NCDValue *arg = NCDValue_ListFirst(o->args); while (arg) { if (NCDValue_Type(arg) != NCDVALUE_STRING) { ModuleLog(o->i, BLOG_ERROR, "wrong type"); goto fail1; } arg = NCDValue_ListNext(o->args, arg); } // create TAP device if (!NCDIfConfig_make_tuntap(o->ifname, o->user, 0)) { ModuleLog(o->i, BLOG_ERROR, "failed to create TAP device"); goto fail1; } // set device up if (!NCDIfConfig_set_up(o->ifname)) { ModuleLog(o->i, BLOG_ERROR, "failed to set device up"); goto fail2; } // set not dying o->dying = 0; // init timer BTimer_Init(&o->timer, RETRY_TIME, (BTimer_handler)timer_handler, o); // signal up NCDModuleInst_Backend_Up(o->i); // try starting process try_process(o); return; fail2: if (!NCDIfConfig_remove_tuntap(o->ifname, 0)) { ModuleLog(o->i, BLOG_ERROR, "failed to remove TAP device"); } fail1: free(o); fail0: NCDModuleInst_Backend_SetError(i); NCDModuleInst_Backend_Dead(i); }
static int generate_val (NCDValue *value, ExpString *out_str) { switch (NCDValue_Type(value)) { case NCDVALUE_STRING: { const char *str = NCDValue_StringValue(value); size_t len = NCDValue_StringLength(value); if (!ExpString_AppendChar(out_str, '"')) { goto fail; } for (size_t i = 0; i < len; i++) { if (str[i] == '\0') { char buf[5]; snprintf(buf, sizeof(buf), "\\x%02"PRIx8, (uint8_t)str[i]); if (!ExpString_Append(out_str, buf)) { goto fail; } continue; } if (str[i] == '"' || str[i] == '\\') { if (!ExpString_AppendChar(out_str, '\\')) { goto fail; } } if (!ExpString_AppendChar(out_str, str[i])) { goto fail; } } if (!ExpString_AppendChar(out_str, '"')) { goto fail; } } break; case NCDVALUE_LIST: { if (!ExpString_AppendChar(out_str, '{')) { goto fail; } int is_first = 1; for (NCDValue *e = NCDValue_ListFirst(value); e; e = NCDValue_ListNext(value, e)) { if (!is_first) { if (!ExpString_Append(out_str, ", ")) { goto fail; } } if (!generate_val(e, out_str)) { goto fail; } is_first = 0; } if (!ExpString_AppendChar(out_str, '}')) { goto fail; } } break; case NCDVALUE_MAP: { if (!ExpString_AppendChar(out_str, '[')) { goto fail; } int is_first = 1; for (NCDValue *ekey = NCDValue_MapFirstKey(value); ekey; ekey = NCDValue_MapNextKey(value, ekey)) { NCDValue *eval = NCDValue_MapKeyValue(value, ekey); if (!is_first) { if (!ExpString_Append(out_str, ", ")) { goto fail; } } if (!generate_val(ekey, out_str)) { goto fail; } if (!ExpString_AppendChar(out_str, ':')) { goto fail; } if (!generate_val(eval, out_str)) { goto fail; } is_first = 0; } if (!ExpString_AppendChar(out_str, ']')) { goto fail; } } break; case NCDVALUE_VAR: { if (!ExpString_Append(out_str, NCDValue_VarName(value))) { goto fail; } } break; case NCDVALUE_INVOC: { if (!generate_val(NCDValue_InvocFunc(value), out_str)) { goto fail; } if (!ExpString_AppendChar(out_str, '(')) { goto fail; } if (!generate_val(NCDValue_InvocArg(value), out_str)) { goto fail; } if (!ExpString_AppendChar(out_str, ')')) { goto fail; } } break; default: ASSERT(0); } return 1; fail: return 0; }
static int build_cmdline (NCDModuleInst *i, NCDValue *cmd_arg, char **exec, CmdLine *cl) { if (NCDValue_Type(cmd_arg) != NCDVALUE_LIST) { ModuleLog(i, BLOG_ERROR, "wrong type"); goto fail0; } // read exec NCDValue *exec_arg = NCDValue_ListFirst(cmd_arg); if (!exec_arg) { ModuleLog(i, BLOG_ERROR, "missing executable name"); goto fail0; } if (NCDValue_Type(exec_arg) != NCDVALUE_STRING) { ModuleLog(i, BLOG_ERROR, "wrong type"); goto fail0; } if (!(*exec = strdup(NCDValue_StringValue(exec_arg)))) { ModuleLog(i, BLOG_ERROR, "strdup failed"); goto fail0; } // start cmdline if (!CmdLine_Init(cl)) { ModuleLog(i, BLOG_ERROR, "CmdLine_Init failed"); goto fail1; } // add header if (!CmdLine_Append(cl, *exec)) { ModuleLog(i, BLOG_ERROR, "CmdLine_Append failed"); goto fail2; } // add additional arguments NCDValue *arg = exec_arg; while (arg = NCDValue_ListNext(cmd_arg, arg)) { if (NCDValue_Type(arg) != NCDVALUE_STRING) { ModuleLog(i, BLOG_ERROR, "wrong type"); goto fail2; } if (!CmdLine_Append(cl, NCDValue_StringValue(arg))) { ModuleLog(i, BLOG_ERROR, "CmdLine_Append failed"); goto fail2; } } // finish if (!CmdLine_Finish(cl)) { ModuleLog(i, BLOG_ERROR, "CmdLine_Finish failed"); goto fail2; } return 1; fail2: CmdLine_Free(cl); fail1: free(*exec); fail0: return 0; }
static void func_new (NCDModuleInst *i) { // allocate instance struct instance *o = malloc(sizeof(*o)); if (!o) { ModuleLog(i, BLOG_ERROR, "failed to allocate instance"); goto fail0; } NCDModuleInst_Backend_SetUser(i, o); // init arguments o->i = i; o->term_on_deinit = 0; // read arguments NCDValue *cmd_arg; NCDValue *opts_arg = NULL; if (!NCDValue_ListRead(i->args, 1, &cmd_arg) && !NCDValue_ListRead(i->args, 2, &cmd_arg, &opts_arg)) { ModuleLog(i, BLOG_ERROR, "wrong arity"); goto fail1; } if (opts_arg && NCDValue_Type(opts_arg) != NCDVALUE_LIST) { ModuleLog(i, BLOG_ERROR, "wrong type"); goto fail1; } int keep_stdout = 0; int keep_stderr = 0; int do_setsid = 0; // read options for (NCDValue *opt = (opts_arg ? NCDValue_ListFirst(opts_arg) : NULL); opt; opt = NCDValue_ListNext(opts_arg, opt)) { // read name if (NCDValue_Type(opt) != NCDVALUE_STRING) { ModuleLog(o->i, BLOG_ERROR, "wrong option name type"); goto fail1; } char *optname = NCDValue_StringValue(opt); if (!strcmp(optname, "term_on_deinit")) { o->term_on_deinit = 1; } else if (!strcmp(optname, "keep_stdout")) { keep_stdout = 1; } else if (!strcmp(optname, "keep_stderr")) { keep_stderr = 1; } else if (!strcmp(optname, "do_setsid")) { do_setsid = 1; } else { ModuleLog(o->i, BLOG_ERROR, "unknown option name"); goto fail1; } } // build cmdline char *exec; CmdLine cl; if (!build_cmdline(o->i, cmd_arg, &exec, &cl)) { goto fail1; } // build fd mapping int fds[3]; int fds_map[2]; int nfds = 0; if (keep_stdout) { fds[nfds] = 1; fds_map[nfds++] = 1; } if (keep_stderr) { fds[nfds] = 2; fds_map[nfds++] = 2; } fds[nfds] = -1; // build params struct BProcess_params params; params.username = NULL; params.fds = fds; params.fds_map = fds_map; params.do_setsid = do_setsid; // start process if (!BProcess_Init2(&o->process, o->i->params->manager, (BProcess_handler)process_handler, o, exec, CmdLine_Get(&cl), params)) { ModuleLog(i, BLOG_ERROR, "BProcess_Init failed"); CmdLine_Free(&cl); free(exec); goto fail1; } CmdLine_Free(&cl); free(exec); // set state o->state = STATE_RUNNING; return; fail1: free(o); fail0: NCDModuleInst_Backend_SetError(i); NCDModuleInst_Backend_Dead(i); }