/* * Debug Trace */ void CVmBifT3::debug_trace(VMG_ uint argc) { /* make sure we have at least one argument */ if (argc < 1) err_throw(VMERR_WRONG_NUM_OF_ARGS); /* pop the flags and see what we're being asked to do */ switch(pop_int_val(vmg0_)) { case T3DBG_CHECK: /* check arguments */ check_argc(vmg_ argc, 1); /* we're just being asked if the debugger is present - it is */ retval_true(vmg0_); break; case T3DBG_BREAK: /* check arguments */ check_argc(vmg_ argc, 1); /* tell the debugger to activate debug-trace mode */ G_debugger->set_debug_trace(); /* tell the caller we were successful */ retval_true(vmg0_); break; default: /* anything else just returns nil, to allow for future expansion */ G_stk->discard(argc - 1); retval_nil(vmg0_); break; } }
/* * Get the Unicode character code of the first character of a string */ void CVmBifT3Test::get_charcode(VMG_ uint argc) { const char *str; /* one argument required */ check_argc(vmg_ argc, 1); /* get the object ID as an integer */ str = pop_str_val(vmg0_); /* * if the string is empty, return nil; otherwise, return the Unicode * character code of the first character */ if (vmb_get_len(str) == 0) { /* empty string - return nil */ retval_nil(vmg0_); } else { /* * get the character code of the first character and return it * as an integer */ retval_int(vmg_ (int)utf8_ptr::s_getch(str + VMB_LEN)); } }
/* * get the VM version number */ void CVmBifT3::get_vm_vsn(VMG_ uint argc) { /* no arguments are allowed */ check_argc(vmg_ argc, 0); /* set the integer return value */ retval_int(vmg_ T3VM_VSN_NUMBER); }
/* * get the VM identification string */ void CVmBifT3::get_vm_id(VMG_ uint argc) { /* no arguments are allowed */ check_argc(vmg_ argc, 0); /* set the integer return value */ retval_str(vmg_ T3VM_IDENTIFICATION); }
/* * get the VM banner string */ void CVmBifT3::get_vm_banner(VMG_ uint argc) { /* no arguments are allowed */ check_argc(vmg_ argc, 0); /* return the string */ retval_str(vmg_ T3VM_BANNER_STRING); }
/* * get the 'preinit' status - true if preinit, nil if normal */ void CVmBifT3::get_vm_preinit_mode(VMG_ uint argc) { /* no arguments allowed */ check_argc(vmg_ argc, 0); /* return the preinit mode */ retval_int(vmg_ G_preinit_mode); }
/* * allocate a new property ID */ void CVmBifT3::alloc_new_prop(VMG_ uint argc) { /* check arguments */ check_argc(vmg_ argc, 0); /* allocate and return a new property ID */ retval_prop(vmg_ G_image_loader->alloc_new_prop(vmg0_)); }
/* * run the garbage collector */ void CVmBifT3::run_gc(VMG_ uint argc) { /* no arguments are allowed */ check_argc(vmg_ argc, 0); /* run the garbage collector */ G_obj_table->gc_full(vmg0_); }
bool Keypad_action(ia_t ia, unsigned argc, const char **argv) { action_debug("Keypad", ia, argc, argv); if (check_argc("Keypad", argc, 0, 0) < 0) { return false; } pop_up_keypad(true); return true; }
/* * Get an object's internal ID. Takes an object instance and returns an * integer giving the object's VM ID number. This is effectively an * address that can be used to refer to the object. Because this value * is returned as an integer, it is NOT a reference to the object for * the purposes of garbage collection or finalization. */ void CVmBifT3Test::get_obj_id(VMG_ uint argc) { vm_val_t val; /* one argument required */ check_argc(vmg_ argc, 1); /* get the object value */ G_interpreter->pop_obj(vmg_ &val); /* return the object ID as an integer */ retval_int(vmg_ (long)val.val.obj); }
static int my_cmd_demo(int argc, char **argv) { char *usage[] = { "set load demo (1 | 2 | 3)", "get print current demo configuration", 0 }; if (check_cmd(argc, "demo", usage)) // check for existing arguments return -1; if (strcmp("get", argv[0]) == 0) { if (check_argc(argc, 1, 1, "")) // check # of arguments return -1; // get demo configuration xil_printf("demo configuration %d\n", get_demo()); } else if (strcmp("set", argv[0]) == 0) { if (check_argc(argc, 2, 2, "demo set ID")) // check # of args: 2 required return -1; // set demo configuration unsigned long val = wsh_extract_val(argv[1]); // extract numeric value if ((val < 1) || (val > 3)) { print_unknown_arg(argv[1]); return -1; } set_demo(val); xil_printf("selecting demo %d\n", get_demo()); } else { print_unknown_cmd(argv[0]); return -1; } return 0; }
/* * Get an object's garbage collection state. Takes an object ID (NOT an * object reference -- this is the integer value returned by get_obj_id) * and returns a bit mask with the garbage collector state. * * (retval & 0x000F) gives the free state. 0 is free, 1 is in use. * * (retval & 0x00F0) gives the reachable state. 0x00 is unreachable, * 0x10 is finalizer-reachable, and 0x20 is fully reachable. * * (retval & 0x0F00) gives the finalizer state. 0x000 is unfinalizable, * 0x100 is finalizable, and 0x200 is finalized. * * (retval & 0xF000) gives the object ID validity. 0 is valid, 0xF000 * is invalid. */ void CVmBifT3Test::get_obj_gc_state(VMG_ uint argc) { vm_val_t val; /* one argument required */ check_argc(vmg_ argc, 1); /* pop the string */ G_interpreter->pop_int(vmg_ &val); /* return the internal garbage collector state of the object */ retval_int(vmg_ (long)G_obj_table->get_obj_internal_state(val.val.intval)); }
void SVMLightRunner::processRequest( SVMConfiguration &config ) { int argc = 0; char** argv = 0; arma::mat unique_labels = arma::unique(config.target); if(unique_labels.size() !=2 && !config.use_transductive_learning){ COUT("Passed 3 labels to svmlight without use_transductive_learning"); EXIT(1); } if((unique_labels.size() <2 || unique_labels.size() > 3) && config.use_transductive_learning){ COUT("Passed incorred # of labels to svmlight (<2 || >3) for transductive learning"); EXIT(1); } if(unique_labels.size() == 2){ if(unique_labels[0] != -1 && unique_labels[1] != 1){ COUT("Please pass negative class as -1 and positive as 1"); EXIT(1); } } if(unique_labels.size() == 3){ if(unique_labels[0] != 0 && unique_labels[1] != -1 && unique_labels[2] != 1 ){ COUT("Please pass negative class as -1 and positive as 1"); EXIT(1); } } config.neg_target = -1; config.pos_target = 1; if (!config.svm_options.empty()) { argc = check_argc(std::string("gmum ") + config.svm_options); argv = to_argv(std::string("gmum ") + config.svm_options); } if (!config.isPrediction()) { // Learning librarySVMLearnMain(argc, argv, true, config); } else { // Predict librarySVMClassifyMain(argc, argv, true, config); // Convert sign to label resultsToLabels(config); } }
/* * Get the local host name */ void CVmBifNet::get_hostname(VMG_ uint oargc) { /* check arguments */ check_argc(vmg_ oargc, 0); /* check the network safety levels */ int client_level, server_level; G_host_ifc->get_net_safety(&client_level, &server_level); /* * If the network safety level doesn't allow outside network access for * either client or server, return "localhost". If they don't allow * any network access at all, return nil. * * If there's a host name defined in the web configuration, return that * host name. Otherwise, return the default host name from the OS. */ if (client_level >= VM_NET_SAFETY_MAXIMUM && server_level >= VM_NET_SAFETY_MAXIMUM) { /* no network access is allowed - return nil */ retval_nil(vmg0_); } else if (client_level >= VM_NET_SAFETY_LOCALHOST && server_level >= VM_NET_SAFETY_LOCALHOST) { /* localhost access only - return "localhost" */ retval_str(vmg_ "localhost"); } else { /* * the network safety level allows outside network access, so we * can return the actual host name - get it from the system */ char buf[256]; if (os_get_hostname(buf, sizeof(buf))) { /* got it - return the string */ retval_ui_str(vmg_ buf); } else { /* no host name available - return nil */ retval_nil(vmg0_); } } }
/* * Get the launching host address */ void CVmBifNet::get_launch_host_addr(VMG_ uint oargc) { /* check arguments */ check_argc(vmg_ oargc, 0); /* get the launch host name from the network configuration */ const char *host = (G_net_config != 0 ? G_net_config->get("hostname") : 0); /* if there's a host name, return it, otherwise return nil */ if (host != 0) retval_str(vmg_ host); else retval_nil(vmg0_); }
void LibSVMRunner::parseCommandLine( SVMConfiguration& config, svm_parameter& param ) { int argc = 0; char** argv = 0; if (!config.svm_options.empty()) { argc = check_argc(std::string("gmum ") + config.svm_options); argv = to_argv(std::string("gmum ") + config.svm_options); char input_file_name[1024]; char model_file_name[1024]; LibSVMRunner::libraryParseCommandLine( config, param, argc, argv, input_file_name, model_file_name); } }
/* * Get the local host IP address */ void CVmBifNet::get_host_ip(VMG_ uint oargc) { /* check arguments */ check_argc(vmg_ oargc, 0); /* check the network safety levels */ int client_level, server_level; G_host_ifc->get_net_safety(&client_level, &server_level); /* * If the network safety level doesn't allow outside network access for * either client or server, return "localhost". If they don't allow * any network access at all, return nil. */ if (client_level >= VM_NET_SAFETY_MAXIMUM && server_level >= VM_NET_SAFETY_MAXIMUM) { /* no network access is allowed - return nil */ retval_nil(vmg0_); } else if (client_level >= VM_NET_SAFETY_LOCALHOST && server_level >= VM_NET_SAFETY_LOCALHOST) { /* localhost access only - return the standard localhost IP address */ retval_str(vmg_ "127.0.0.1"); } else { /* retrieve the host IP address for the default host */ char buf[256]; if (os_get_local_ip(buf, sizeof(buf), 0)) { /* got it - return the string */ retval_ui_str(vmg_ buf); } else { /* no host name available - return nil */ retval_nil(vmg0_); } } }
void CVmBifNet::get_net_config(VMG_ uint oargc) { /* check arguments */ check_argc(vmg_ oargc, 1); /* get the variable name */ char name[256]; pop_str_val_buf(vmg_ name, sizeof(name)); /* look up the name */ const char *val = 0; if (G_net_config != 0) val = G_net_config->get(name); /* if we found a value, return it; otherwise return nil */ if (val != 0) retval_str(vmg_ val); else retval_nil(vmg0_); }
/* get the storage server URL */ void CVmBifNet::get_storage_url(VMG_ uint oargc) { /* check arguments */ check_argc(vmg_ oargc, 1); /* set a default nil return in case we can't build the path */ retval_nil(vmg0_); /* get the resource name */ const char *page = G_stk->get(0)->get_as_string(vmg0_); if (page == 0) err_throw(VMERR_STRING_VAL_REQD); /* get the resource name length and buffer pointer */ size_t pagelen = vmb_get_len(page); page += VMB_LEN; /* if there's a network configuration, build the resource path */ const char *host = 0, *rootpath = 0; if (G_net_config != 0) { /* get the storage server host name and root path */ host = G_net_config->get("storage.domain"); rootpath = G_net_config->get("storage.rootpath", "/"); } /* we must have a host name to proceed */ if (host != 0) { /* build the full string */ G_interpreter->push_stringf(vmg_ "http://%s%s%.*s", host, rootpath, (int)pagelen, page); /* pop it into R0 */ G_stk->pop(G_interpreter->get_r0()); } /* discard arguments */ G_stk->discard(); }
/* * Enable/disable system menu commands */ void CVmBifTIOExt::enable_sys_menu_cmd(VMG_ uint argc) { vm_val_t *valp; int stat; int cnt; /* check arguments */ check_argc(vmg_ argc, 2); /* the second argument is the new status - retrieve it as an integer */ G_stk->push(G_stk->get(1)); stat = pop_int_val(vmg0_); /* * The first argument is either a single menu ID, or a list of menu * IDs. Check what we have. */ valp = G_stk->get(0); if (valp->is_listlike(vmg0_) && (cnt = valp->ll_length(vmg0_)) >= 0) { /* set the status for each element */ for (int i = 1 ; i <= cnt ; ++i) { /* get this element value */ vm_val_t ele; valp->ll_index(vmg_ &ele, i); /* set the status */ enable_sys_menu_cmd_item(vmg_ &ele, stat); } } else if (valp->typ == VM_INT) { /* it's a single value - handle it individually */ enable_sys_menu_cmd_item(vmg_ valp, stat); } /* discard the arguments, and we're done */ G_stk->discard(2); }
int cmd_config(int argc, const char **argv, const char *prefix) { int nongit = !startup_info->have_repository; char *value; given_config_file = getenv(CONFIG_ENVIRONMENT); argc = parse_options(argc, argv, prefix, builtin_config_options, builtin_config_usage, PARSE_OPT_STOP_AT_NON_OPTION); if (use_global_config + use_system_config + use_local_config + !!given_config_file > 1) { error("only one config file at a time."); usage_with_options(builtin_config_usage, builtin_config_options); } if (use_global_config) { char *user_config = NULL; char *xdg_config = NULL; home_config_paths(&user_config, &xdg_config, "config"); if (access(user_config, R_OK) && !access(xdg_config, R_OK)) given_config_file = xdg_config; else if (user_config) given_config_file = user_config; else die("$HOME not set"); } else if (use_system_config) given_config_file = git_etc_gitconfig(); else if (use_local_config) given_config_file = git_pathdup("config"); else if (given_config_file) { if (!is_absolute_path(given_config_file) && prefix) given_config_file = xstrdup(prefix_filename(prefix, strlen(prefix), given_config_file)); } if (respect_includes == -1) respect_includes = !given_config_file; if (end_null) { term = '\0'; delim = '\n'; key_delim = '\n'; } if (HAS_MULTI_BITS(types)) { error("only one type at a time."); usage_with_options(builtin_config_usage, builtin_config_options); } if (get_color_slot) actions |= ACTION_GET_COLOR; if (get_colorbool_slot) actions |= ACTION_GET_COLORBOOL; if ((get_color_slot || get_colorbool_slot) && types) { error("--get-color and variable type are incoherent"); usage_with_options(builtin_config_usage, builtin_config_options); } if (HAS_MULTI_BITS(actions)) { error("only one action at a time."); usage_with_options(builtin_config_usage, builtin_config_options); } if (actions == 0) switch (argc) { case 1: actions = ACTION_GET; break; case 2: actions = ACTION_SET; break; case 3: actions = ACTION_SET_ALL; break; default: usage_with_options(builtin_config_usage, builtin_config_options); } if (actions == ACTION_LIST) { check_argc(argc, 0, 0); if (git_config_with_options(show_all_config, NULL, given_config_file, respect_includes) < 0) { if (given_config_file) die_errno("unable to read config file '%s'", given_config_file); else die("error processing config file(s)"); } } else if (actions == ACTION_EDIT) { check_argc(argc, 0, 0); if (!given_config_file && nongit) die("not in a git directory"); git_config(git_default_config, NULL); launch_editor(given_config_file ? given_config_file : git_path("config"), NULL, NULL); } else if (actions == ACTION_SET) { int ret; check_argc(argc, 2, 2); value = normalize_value(argv[0], argv[1]); ret = git_config_set_in_file(given_config_file, argv[0], value); if (ret == CONFIG_NOTHING_SET) error("cannot overwrite multiple values with a single value\n" " Use a regexp, --add or --replace-all to change %s.", argv[0]); return ret; } else if (actions == ACTION_SET_ALL) { check_argc(argc, 2, 3); value = normalize_value(argv[0], argv[1]); return git_config_set_multivar_in_file(given_config_file, argv[0], value, argv[2], 0); } else if (actions == ACTION_ADD) { check_argc(argc, 2, 2); value = normalize_value(argv[0], argv[1]); return git_config_set_multivar_in_file(given_config_file, argv[0], value, "^$", 0); } else if (actions == ACTION_REPLACE_ALL) { check_argc(argc, 2, 3); value = normalize_value(argv[0], argv[1]); return git_config_set_multivar_in_file(given_config_file, argv[0], value, argv[2], 1); } else if (actions == ACTION_GET) { check_argc(argc, 1, 2); return get_value(argv[0], argv[1]); } else if (actions == ACTION_GET_ALL) { do_all = 1; check_argc(argc, 1, 2); return get_value(argv[0], argv[1]); } else if (actions == ACTION_GET_REGEXP) { show_keys = 1; use_key_regexp = 1; do_all = 1; check_argc(argc, 1, 2); return get_value(argv[0], argv[1]); } else if (actions == ACTION_UNSET) { check_argc(argc, 1, 2); if (argc == 2) return git_config_set_multivar_in_file(given_config_file, argv[0], NULL, argv[1], 0); else return git_config_set_in_file(given_config_file, argv[0], NULL); } else if (actions == ACTION_UNSET_ALL) { check_argc(argc, 1, 2); return git_config_set_multivar_in_file(given_config_file, argv[0], NULL, argv[1], 1); } else if (actions == ACTION_RENAME_SECTION) { int ret; check_argc(argc, 2, 2); ret = git_config_rename_section_in_file(given_config_file, argv[0], argv[1]); if (ret < 0) return ret; if (ret == 0) die("No such section!"); } else if (actions == ACTION_REMOVE_SECTION) { int ret; check_argc(argc, 1, 1); ret = git_config_rename_section_in_file(given_config_file, argv[0], NULL); if (ret < 0) return ret; if (ret == 0) die("No such section!"); } else if (actions == ACTION_GET_COLOR) { get_color(argv[0]); } else if (actions == ACTION_GET_COLORBOOL) { if (argc == 1) color_stdout_is_tty = git_config_bool("command line", argv[0]); return get_colorbool(argc != 0); } return 0; }
/* let's go... */ int main(int argc, char *argv[]) { int c = 0; ctrl_t *ctrl = NULL; /* banner is very important */ banner(); check_argc(argc); ctrl = alloc_structs(); ctrl = set_ctrl_defaults(ctrl); while ((c = getopt(argc, argv, "h:t:s:m:p:vVH")) != -1) { switch (c) { case 'h': check_host(optarg); ctrl->packet->host = convert_host(optarg); break; case 't': check_pkt_type(ctrl, optarg); ctrl->packet->type = (unsigned char) ATOI(optarg); break; case 's': check_shell_mode(ctrl, optarg); ctrl->shell->mode = (unsigned char) ATOI(optarg); break; case 'm': ctrl->packet->payload = optarg; break; case 'p': check_port(ctrl, ATOI(optarg)); ctrl->packet->port = (uint16_t) ATOI(optarg); break; case 'v': ctrl->verbose = VERBOSE; break; case 'V': puts(VERSION); __EXIT_SUCCESS; break; case 'H': usage(); __EXIT_SUCCESS; break; default: __EXIT_FAILURE; } } /* few checks before we can go on */ __VERBOSE_ARGS; check_args(ctrl); check_uid(ctrl); /* install signal handler */ install_signals(); /* let's go */ start_trixd00r(ctrl); end_trixd00r(ctrl); return 0; }
/* * readText() - read text from the keyboard and return it as a string. */ void CVmBifSample::read_text(VMG_ uint argc) { char buf[128]; size_t len; vm_obj_id_t str_id; CVmObjString *str_obj; /* check to make sure we have the right number of arguments */ check_argc(vmg_ argc, 0); /* * Read a string from the keyboard. Use fgets() rather than plain * gets(), because fgets() lets us limit the buffer size and thus avoid * any chance of a buffer overflow. (Someone should tell the people at * Microsoft about this - it would probably cut out about eighty * percent of those emergency internet security alerts that require * everyone to download an IE patch every couple of weeks. :) */ fgets(buf, sizeof(buf), stdin); /* * One small detail about fgets: if the input ended with a newline, * there will be a newline in the buffer. Remove it if it's there. */ if ((len = strlen(buf)) != 0 && buf[len - 1] == '\n') buf[len-1] = '\0'; /* * As in display_text(), we have to deal with character set mapping * before we can send the string back to the TADS program. This time, * we want to perform the conversion from the local character set to * Unicode. Again, T3 provides a handy conversion object for our * convenience - this time, it's called G_cmap_from_ui. * * In order to return a string to the TADS program, we have to allocate * a new string object. First, let's see how big a string we need to * allocate, by calling the character mapper with no buffer space at * all - the mapper will run through the string and check to see how * big it will be after conversion, but it won't actually store * anything. */ len = G_cmap_from_ui->map_str(0, 0, buf); /* * Allocate a new string to contain the return value. This gives us * back an "object ID" value, which we can convert into an internal C++ * string object pointer using the vm_objp() formula shown. */ str_id = CVmObjString::create(vmg_ FALSE, len); str_obj = (CVmObjString *)vm_objp(vmg_ str_id); /* * The string object has a buffer of the size we requested, which is * the size we already know we need to contain the mapped string. So, * we can call the mapper again to have it perform the actual mapping * into our string buffer. */ G_cmap_from_ui->map_str(str_obj->cons_get_buf(), len, buf); /* * One last step: we must return the string object to the caller. To * do this, use the retval_obj() function to return the ID of the * string object. */ retval_obj(vmg_ str_id); }
void CVmBifT3::set_say(VMG_ uint argc) { vm_val_t *arg = G_stk->get(0); vm_val_t val; /* one argument is required */ check_argc(vmg_ argc, 1); /* check to see if we're setting the default display method */ if (arg->typ == VM_PROP || (arg->typ == VM_INT && arg->val.intval == SETSAY_NO_METHOD)) { vm_prop_id_t prop; /* * the return value is the old property pointer (or * SETSAY_NO_METHOD if there was no valid property set previously) */ prop = G_interpreter->get_say_method(); if (prop != VM_INVALID_PROP) retval_prop(vmg_ prop); else retval_int(vmg_ SETSAY_NO_METHOD); /* get the new value */ G_stk->pop(&val); /* if it's SETSAY_NO_METHOD, set it to the invalid prop ID */ if (val.typ == VM_INT) val.set_propid(VM_INVALID_PROP); /* set the method */ G_interpreter->set_say_method(val.val.prop); } else if (arg->typ == VM_FUNCPTR || arg->typ == VM_OBJ || arg->typ == VM_BIFPTR || (arg->typ == VM_INT && arg->val.intval == SETSAY_NO_FUNC)) { /* * the return value is the old function (or SETSAY_NO_FUNC if the * old function was nil) */ G_interpreter->get_say_func(&val); if (val.typ != VM_NIL) retval(vmg_ &val); else retval_int(vmg_ SETSAY_NO_FUNC); /* get the new function value */ G_stk->pop(&val); /* if it's SETSAY_NO_FUNC, set the function to nil */ if (val.typ == VM_INT) val.set_nil(); /* set the new function */ G_interpreter->set_say_func(vmg_ &val); } else { /* invalid type */ err_throw(VMERR_BAD_TYPE_BIF); } }
/* * Show a popup menu */ void CVmBifTIOExt::show_popup_menu(VMG_ uint argc) { int x, y, default_pos; char *txt; os_event_info_t evt; int ret; int elecnt; vm_obj_id_t lst_obj; CVmObjList *lst; vm_val_t val; /* check arguments */ check_argc(vmg_ argc, 3); /* get the x,y coordinates */ if (G_stk->get(0)->typ == VM_NIL) { /* nil x,y - use default position */ default_pos = TRUE; x = y = 0; /* discard the nil x,y values */ G_stk->discard(2); } else { /* pop the x,y positions */ x = pop_int_val(vmg0_); y = pop_int_val(vmg0_); } /* get the HTML text for the contents of the window */ txt = pop_str_val_ui(vmg_ 0, 0); /* flush the console display output */ G_console->flush_all(vmg_ VM_NL_NONE); /* show the window */ ret = os_show_popup_menu(default_pos, x, y, txt, strlen(txt), &evt); /* free the HTML text buffer we allocated */ t3free(txt); /* see what we have */ switch (ret) { case OSPOP_FAIL: case OSPOP_CANCEL: case OSPOP_EOF: default: elecnt = 1; break; case OSPOP_HREF: elecnt = 2; break; } /* allocate the return list */ lst_obj = CVmObjList::create(vmg_ FALSE, elecnt); lst = (CVmObjList *)vm_objp(vmg_ lst_obj); lst->cons_clear(); /* protect the list from garbage collection */ val.set_obj(lst_obj); G_stk->push(&val); /* set the first element to the main return code */ val.set_int(ret); lst->cons_set_element(0, &val); /* set additional elements according to the return code */ switch (ret) { case OSPOP_HREF: /* add the HREF element */ val.set_obj(str_from_ui_str(vmg_ evt.href)); lst->cons_set_element(1, &val); break; default: /* there aren't any other elements for other return codes */ break; } /* return the list */ retval_obj(vmg_ lst_obj); /* discard the GC protection */ G_stk->discard(); }
static int capture_command(shell_t *shell, shell_argv_t *cmd_argv, char *tag) { int argc = cmd_argv->argc; char **argv = cmd_argv->argv; char *hdr = log_hdr_(tag); frame_t *root = frame_command_display->root; capture_t *capture = root->capture; int ret = 0; /* Set error reporting tag */ error_default_tag(tag); /* Check number of arguments */ if ( check_argc(shell, cmd_argv, tag, 2, 3) ) return -1; /* Operation 'geometry': change capture active window */ if ( strcmp(argv[1], "geometry") == 0 ) { frame_geometry_t g; if ( argc > 2 ) { char *s_geom = argv[2]; /* Retrieve frame geometry */ if ( strcmp(s_geom, "full") != 0 ) { if ( frame_rgb_parse_geometry(&(root->hdr.fb->rgb), s_geom, &g) ) { error(NULL, "geometry: Syntax error"); return -1; } } else { g = root->hdr.g0; } if ( frame_display_geometry(frame_command_display, &g) == 0 ) { capture_set_window(capture, &g); capture_refresh(capture); } else { error(tag, "geometry: Illegal parameters"); ret = -1; } } capture_get_window(capture, &g); printf("%sGEOMETRY %s\n", hdr, frame_geometry_str(&g)); } /* Operation 'refresh': change capture refresh rate */ else if ( strcmp(argv[1], "refresh") == 0 ) { if ( argc > 2 ) { char *s = argv[2]; if ( strcmp(s, "now") == 0 ) { capture_refresh(capture); printf("%sREFRESH now\n", hdr); return 0; } else { int period = capture_set_period(capture, atoi(s)); if ( period >= 0 ) { frame_display_period(frame_command_display, period); } else if ( period < 0 ) { error(tag, "Refresh period should be %d to %d ms\n", CAPTURE_PERIOD_MIN, CAPTURE_PERIOD_MAX); ret = -1; } } } printf("%sREFRESH %ld ms\n", hdr, capture_get_period(capture)); } /* Operation 'attr': get/set capture device attribute */ else if ( strcmp(argv[1], "attr") == 0 ) { char *key = NULL; int nmemb = 0; capture_attr_t *tab; int i; if ( argc > 2 ) { char *value; key = argv[2]; value = strchr(key, '='); if ( value != NULL ) { *(value++) = '\0'; if ( capture_attr_set(capture, key, value) ) { error(tag, "Cannot set attribute '%s'\n", key); return -1; } } } tab = capture_attr_get(capture, key, &nmemb); if ( tab == NULL ) { if ( key != NULL ) error(tag, "Cannot get attribute '%s'\n", key); else error(tag, "Cannot get attributes\n"); return -1; } for (i = 0; i < nmemb; i++) { printf("%sATTR %s", hdr, tab[i].key); if ( tab[i].value != NULL ) printf("=%s", tab[i].value); printf("\n"); } } /* Unknown operation */ else { error(tag, "Unknown qualifier '%s'", argv[1]); shell_std_help(shell, argv[0]); return -1; } return ret; }
int main(int argc, char *argv[]) { if (argc < 1) { dprintf(STDERR_FILENO, "wrun called without argument\n"); terminate_nocore(); } shift(&argc, &argv); if (argc > 1 && !strcmp(argv[0], "--tool_name")) { shift(&argc, &argv); tool_name = shift(&argc, &argv); } fill_std_fd_info_identity(STDIN_FILENO); fill_std_fd_info_identity(STDOUT_FILENO); fill_std_fd_info_identity(STDERR_FILENO); bool force_redirects = false; bool silent_breakaway = false; int port; bool terminate = !get_outbash_infos(&port, &force_redirects); struct string outbash_command = string_create(""); if (argc && !strcmp(argv[0], ":")) { shift(&argc, &argv); string_append(&outbash_command, "cd:~\n"); } else { char* cwd = agetcwd(); if (is_absolute_drive_fs_path(cwd)) { char* cwd_win32 = convert_drive_fs_path_to_win32(cwd); string_append(&outbash_command, "cd:"); string_append(&outbash_command, cwd_win32); string_append(&outbash_command, "\n"); free(cwd_win32); } free(cwd); } while (argc && !strncmp(argv[0], "--", 2)) { if (!strcmp(argv[0], "--")) { shift(&argc, &argv); break; } if (!strcmp(argv[0], "--env")) { shift(&argc, &argv); while (argc && strncmp(argv[0], "--", 2) != 0 && *argv[0] != '\0' && strchr(argv[0] + 1, '=')) { string_append(&outbash_command, "env:"); string_append(&outbash_command, argv[0]); string_append(&outbash_command, "\n"); shift(&argc, &argv); } } else if (!strcmp(argv[0], "--force-redirects")) { force_redirects = true; shift(&argc, &argv); } else if (!strcmp(argv[0], "--silent-breakaway")) { silent_breakaway = true; shift(&argc, &argv); } else if (!strcmp(argv[0], "--help")) { print_help(); exit(1); } else { dprintf(STDERR_FILENO, "%s: unknown command line option: %s\n", tool_name, argv[0]); dprintf(STDERR_FILENO, "type %s --help for more information.\n", tool_name); terminate_nocore(); } } if (terminate) terminate_nocore(); check_argc(argc); decide_will_redirect(STDIN_FILENO, force_redirects); decide_will_redirect(STDOUT_FILENO, force_redirects); decide_will_redirect(STDERR_FILENO, force_redirects); int sock_ctrl = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (sock_ctrl < 0) { dprintf(STDERR_FILENO, "%s: socket() failed: %s\n", tool_name, my_strerror(errno)); terminate_nocore(); } #define STDIN_NEEDS_SOCKET_REDIRECT 1 #define STDOUT_NEEDS_SOCKET_REDIRECT 2 #define STDERR_NEEDS_SOCKET_REDIRECT 4 #define STDERR_SOCKREDIR_TO_STDOUT 8 int redirects = (needs_socket_redirect(STDIN_FILENO) ? STDIN_NEEDS_SOCKET_REDIRECT : 0) | (needs_socket_redirect(STDOUT_FILENO) ? STDOUT_NEEDS_SOCKET_REDIRECT : 0); if (needs_socket_redirect(STDERR_FILENO)) { if ((redirects & STDOUT_NEEDS_SOCKET_REDIRECT) && are_stdfd_to_same_thing(STDOUT_FILENO, STDERR_FILENO)) redirects |= STDERR_SOCKREDIR_TO_STDOUT; else redirects |= STDERR_NEEDS_SOCKET_REDIRECT; } struct listening_socket lsock_in = NO_LISTENING_SOCKET; struct listening_socket lsock_out = NO_LISTENING_SOCKET; struct listening_socket lsock_err = NO_LISTENING_SOCKET; if (redirects & STDIN_NEEDS_SOCKET_REDIRECT) lsock_in = socket_listen_one_loopback(); if (redirects & STDOUT_NEEDS_SOCKET_REDIRECT) lsock_out = socket_listen_one_loopback(); if (redirects & STDERR_NEEDS_SOCKET_REDIRECT) lsock_err = socket_listen_one_loopback(); ask_redirect(&outbash_command, "stdin:", STDIN_FILENO, lsock_in.port); ask_redirect(&outbash_command, "stdout:", STDOUT_FILENO, lsock_out.port); ask_redirect(&outbash_command, "stderr:", STDERR_FILENO, (redirects & STDERR_NEEDS_SOCKET_REDIRECT) ? lsock_err.port : lsock_out.port); if (silent_breakaway) string_append(&outbash_command, "silent_breakaway:1\n"); char* win32_module; if (is_absolute_drive_fs_path(argv[0])) { win32_module = convert_drive_fs_path_to_win32(argv[0]); string_append(&outbash_command, "module:"); string_append(&outbash_command, win32_module); string_append(&outbash_command, "\n"); } else { win32_module = convert_slash_to_backslash(argv[0]); } const bool module_need_quotes = (NULL != strpbrk(win32_module, " \t")); string_append(&outbash_command, "run:"); if (module_need_quotes) string_append(&outbash_command, "\""); string_append(&outbash_command, win32_module); if (module_need_quotes) string_append(&outbash_command, "\""); free(win32_module); for (int i = 1; i < argc; i++) { string_append(&outbash_command, " "); string_append(&outbash_command, argv[i]); } string_append(&outbash_command, "\n\n"); //dprintf(STDOUT_FILENO, "%s", outbash_command.str); //return EXIT_FAILURE; signal(SIGPIPE, SIG_IGN); sigset_t signal_set, orig_mask; //////////////////////////// unblock SIGUSR1 sigemptyset(&signal_set); sigaddset(&signal_set, SIGUSR1); pthread_sigmask(SIG_UNBLOCK, &signal_set, NULL); //////////////////////////// block SIGTSTP sigemptyset(&signal_set); sigaddset(&signal_set, SIGTSTP); pthread_sigmask(SIG_BLOCK, &signal_set, &orig_mask); //////////////////////////// install custom SIGTSTP handler if signal was not ignored struct sigaction sa; sigaction(SIGTSTP, NULL, &sa); const bool ignore_sigtstp = (sa.sa_handler == SIG_IGN); if (!ignore_sigtstp) { sa.sa_handler = tstop_handler; sigemptyset(&sa.sa_mask); sa.sa_flags = 0; sigaction(SIGTSTP, &sa, NULL); } //////////////////////////// install custom SIGUSR1 handler to wake-up blocked IO forwarding threads // NOTE: the handler itself do nothing, but any blocked syscall will return with EINTR error sa.sa_handler = noop_handler; sigemptyset(&sa.sa_mask); sa.sa_flags = 0; sigaction(SIGUSR1, &sa, NULL); struct sockaddr_in serv_addr; memset(&serv_addr, 0, sizeof(serv_addr)); serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); serv_addr.sin_port = htons(port); if (connect(sock_ctrl, (const struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0) { // NOTE: I'm not sure that WSL does what Linux does concerning // http://www.madore.org/~david/computers/connect-intr.html // for now we do not expect to recover after an interruption here. dprintf(STDERR_FILENO, "%s: connect() failed: %s\n", tool_name, my_strerror(errno)); terminate_nocore(); } if (send_all(sock_ctrl, outbash_command.str, outbash_command.length, 0) < 0) { dprintf(STDERR_FILENO, "%s: send_all() failed: %s\n", tool_name, my_strerror(errno)); terminate_nocore(); } string_destroy(&outbash_command); static struct forward_state fs[3]; fs_init_accept_as_needed(&fs[STDIN_FILENO], &lsock_in, redirects & STDIN_NEEDS_SOCKET_REDIRECT, STDIN_FILENO, "stdin"); fs_init_accept_as_needed(&fs[STDOUT_FILENO], &lsock_out, redirects & STDOUT_NEEDS_SOCKET_REDIRECT, STDOUT_FILENO, "stdout"); fs_init_accept_as_needed(&fs[STDERR_FILENO], &lsock_err, redirects & STDERR_NEEDS_SOCKET_REDIRECT, STDERR_FILENO, "stderr"); char *line = ctrl_readln(sock_ctrl, NULL); if (!line || strcmp(line, "connected")) { dprintf(STDERR_FILENO, "%s: did not receive connection validation from outbash.exe\n", tool_name); terminate_nocore(); } close_listener(&lsock_in); close_listener(&lsock_out); close_listener(&lsock_err); enum state_e state = RUNNING; int program_return_code = 255; pthread_t forward_threads[3]; bool active_threads[3] = {0}; for (int i = 0; i < 3; i++) { if ((!fs[i].dead_in) || (!fs[i].dead_out)) { int err = pthread_create(&forward_threads[i], NULL, forward_one_stream, &fs[i]); if (err != 0) { dprintf(STDERR_FILENO, "%s: pthread_create() failed: %s\n", tool_name, my_strerror(err)); terminate_nocore(); } active_threads[i] = true; } } int nfds = sock_ctrl + 1; while (state != TERMINATED) { fd_set rfds; FD_ZERO(&rfds); if (sock_ctrl < 0 || sock_ctrl >= FD_SETSIZE) { dprintf(STDERR_FILENO, "%s: sock_ctrl=%d out of range\n", tool_name, sock_ctrl); abort(); } FD_SET(sock_ctrl, &rfds); int pselect_res = pselect(nfds, &rfds, NULL, NULL, NULL, &orig_mask); // tstop_handler can run here int pselect_errno = errno; if (tstop_req && state == RUNNING) { int r = send_all(sock_ctrl, "suspend\n", strlen("suspend\n"), 0); if (r < 0 && err_is_connection_broken(errno)) { // We will never be able to ask outbash to suspend the // Windows process, the expected reason is that it actually // has already terminated and we don't know yet about that, // so stop the suspend forwarding mechanism and suspend // ourselves immediately. shutdown(sock_ctrl, SHUT_WR); // also we can't send anything anymore // XXX to comment for WSL bug workaround? proba low here... signal(SIGTSTP, SIG_DFL); state = DYING; raise(SIGTSTP); pthread_sigmask(SIG_SETMASK, &orig_mask, NULL); } else if (r < 0) { // other errors dprintf(STDERR_FILENO, "%s: send_all(\"suspend\\n\") failed: %s\n", tool_name, my_strerror(errno)); abort(); } else { // OK // It's up to outbash now, just wait for its "suspend_ok" // answer after it has suspended the Windows process. state = SUSPEND_PENDING; } } if (pselect_res < 0 && pselect_errno == EINTR) { // "On error, -1 is returned, and errno is set appropriately; // the sets and timeout become undefined, so do not rely on // their contents after an error." continue; } if (pselect_res < 0) { dprintf(STDERR_FILENO, "%s: pselect() failed: %s\n", tool_name, my_strerror(pselect_errno)); abort(); } if (FD_ISSET(sock_ctrl, &rfds)) { while (1) { int nonblock_marker; line = ctrl_readln(sock_ctrl, &nonblock_marker); if (!line && nonblock_marker) break; if (line && !strcmp(line, "suspend_ok")) { if (state == SUSPEND_PENDING) { signal(SIGTSTP, SIG_DFL); raise(SIGTSTP); sigset_t previous_mask; pthread_sigmask(SIG_SETMASK, &orig_mask, &previous_mask); // >>> Process will Stop here, until SIGCONT <<< pthread_sigmask(SIG_SETMASK, &previous_mask, NULL); tstop_req = 0; int r = send_all(sock_ctrl, "resume\n", strlen("resume\n"), 0); if (r < 0 && err_is_connection_broken(errno)) { // killed when suspended (if this is possible?) // or maybe just before an attempt? shutdown(sock_ctrl, SHUT_WR); // XXX to comment for WSL bug workaround? proba low here... state = DYING; pthread_sigmask(SIG_SETMASK, &orig_mask, NULL); } else if (r < 0) { dprintf(STDERR_FILENO, "%s: send_all(\"resume\\n\") failed: %s\n", tool_name, my_strerror(errno)); abort(); } else { state = RUNNING; sa.sa_handler = tstop_handler; sigemptyset(&sa.sa_mask); sa.sa_flags = 0; sigaction(SIGTSTP, &sa, NULL); } } else { dprintf(STDERR_FILENO, "%s: spurious \"suspend_ok\" received\n", tool_name); } } else { // not "suspend_ok" => for now only other cases are exit conditions program_return_code = get_return_code(line); shutdown(sock_ctrl, SHUT_RDWR); signal(SIGTSTP, ignore_sigtstp ? SIG_IGN : SIG_DFL); if ((tstop_req && state == RUNNING) || state == SUSPEND_PENDING) { // We expect to stop soon, but not without flushing the OS TCP // buffers and our owns, and other WSL processes in a pipe might // already be suspended, so we better honor suspend requests ASAP. raise(SIGTSTP); } pthread_sigmask(SIG_SETMASK, &orig_mask, NULL); tstop_req = 0; state = TERMINATED; break; } } } } // XXX: this is not ideal if the Win32 side managed to maintain the // redirection socket beyond the lifetime of the launched process, // however things seem to already be not reliable for Windows reasons // in this case if (active_threads[0]) { __sync_fetch_and_add(&fs[0].ask_terminate, 1); useconds_t usec_sleep = 1000; while (!__sync_fetch_and_add(&fs[0].finished, 0)) { pthread_kill(forward_threads[0], SIGUSR1); usleep(usec_sleep); usec_sleep *= 2; if (usec_sleep > 60000000) usec_sleep = 60000000; } } for (int i = 0; i < 3; i++) if (active_threads[i]) pthread_join(forward_threads[i], NULL); return program_return_code; }
/* * Connect to the Web UI */ void CVmBifNet::connect_ui(VMG_ uint oargc) { /* check arguments */ check_argc(vmg_ oargc, 2); /* get the server object */ vm_val_t *srv = G_stk->get(0); if (srv->typ != VM_OBJ || !CVmObjHTTPServer::is_httpsrv_obj(vmg_ srv->val.obj)) err_throw(VMERR_BAD_TYPE_BIF); /* get the object pointer properly cast */ CVmObjHTTPServer *srvp = (CVmObjHTTPServer *)vm_objp(vmg_ srv->val.obj); /* get the URL path */ const char *path = G_stk->get(1)->get_as_string(vmg0_); if (path == 0) err_throw(VMERR_BAD_TYPE_BIF); /* make a null-terminated copy of the path */ char *pathb = lib_copy_str(path + VMB_LEN, vmb_get_len(path)); /* get the server network address information */ char *errmsg = 0; char *addr = 0, *ip = 0; int port; int ok = srvp->get_listener_addr(addr, ip, port); /* * If we don't have a network configuration yet, create one. This * notifies other subsystems that we have an active web UI; for * example, the presence of a network UI disables the regular console * UI, since all UI actions have to go through the web UI once it's * established. * * The interpreter startup creates a network configuration if it * receives command-line information telling it that the game was * launched by a Web server in response to an incoming client request. * When the user launches the game in stand-alone mode directly from * the operating system shell, there's no Web server launch * information, so the startup code doesn't create a net config object. * So, if we get here and find we don't have this object, it means that * we're running in local standalone mode. */ if (G_net_config == 0) G_net_config = new TadsNetConfig(); /* connect */ if (ok) { /* connect */ ok = osnet_connect_webui(vmg_ addr, port, pathb, &errmsg); } else { /* couldn't get the server address */ errmsg = lib_copy_str( "No address information available for HTTPServer"); } /* free strings */ lib_free_str(pathb); lib_free_str(addr); lib_free_str(ip); /* if there's an error, throw it */ if (!ok) { G_interpreter->push_string(vmg_ errmsg); lib_free_str(errmsg); G_interpreter->throw_new_class(vmg_ G_predef->net_exception, 1, "Error connecting to Web UI"); } /* no return value */ retval_nil(vmg0_); }
/* * displayText(str) - display a text string. */ void CVmBifSample::display_text(VMG_ uint argc) { const char *strp; size_t len; /* * Check to make sure we have the right number of arguments. 'argc' * tells us how many arguments we received from the T3 program. */ check_argc(vmg_ argc, 1); /* * Get the first argument, which is the string to display. * * This will give us a pointer to a string in internal format, which * has a two-byte length prefix. So, once we have the string, we must * get the length from the string pointer, and then skip the length * prefix to get to the real text of the string. * * Arguments from the T3 program to a native function always appear on * the VM stack, which we can access using the pop_xxx_val() functions. * The arguments appear on the stack in order such that the first * pop_xxx_val() gives us the first argument, the second pop_xxx_val() * gives us the second argument, and so on. The pop_xxx_val() * functions REMOVE an argument from the stack - once it's removed, we * can get to the next one. We MUST remove EXACTLY the number of * arguments that we receive before we return. */ strp = pop_str_val(vmg0_); len = vmb_get_len(strp); strp += VMB_LEN; /* * Okay, we have our string, but it's in UTF-8 format, which is an * encoding format for Unicode. We don't want to display Unicode; we * want to display the local character set. How do we do this? * Fortunately, T3 provides a handy character mapping subsystem that * will let us convert the string fairly automatically. The VM also * gives us a pre-loaded mapper for this specific kind of conversion, * in the object G_cmap_to_ui. G_cmap_to_ui will map characters from * UTF-8 to the local User Interface character set. * * To avoid the need to allocate a gigantic string buffer to convert * the characters, the mapper lets us map in chunks of any size. So, * we'll simply map and display chunks until we run out of string. */ while (len != 0) { char buf[128]; size_t cur_out; size_t cur_in; /* * Map as much as we can into our buffer. This will set cur_out to * the number of bytes in the local character set (the output of * the conversion), and will set cur_in to the number of bytes we * used from the Unicode string (the input). */ cur_out = G_cmap_to_ui->map_utf8(buf, sizeof(buf), strp, len, &cur_in); /* * Show the local characters. * * "%.*s" is just like "%s", but the ".*" tells printf to show * exactly the number of characters in the int argument before the * string, instead of showing everything until it finds a null byte * in the string. This is important because map_utf8 does NOT * null-terminate the result. */ printf("%.*s", (int)cur_out, buf); /* * skip the characters of input we just translated, so that on the * next iteration of this loop we'll translate the next bunch of * characters */ strp += cur_in; len -= cur_in; } }
/* * Retrieve a list of the named argument names. */ void CVmBifT3::get_named_arg_list(VMG_ uint argc) { /* check arguments */ check_argc(vmg_ argc, 0); /* create the result list; we'll expand as necessary later */ G_stk->push()->set_obj(CVmObjList::create(vmg_ FALSE, 10)); CVmObjList *lst = (CVmObjList *)vm_objp(vmg_ G_stk->get(0)->val.obj); /* clear it out, since we're building it incrementally */ lst->cons_clear(); /* we haven't added any elements yet */ int idx = 0; /* scan the stack and populate the name list from the tables we find */ for (vm_val_t *fp = G_interpreter->get_frame_ptr() ; fp != 0 ; fp = G_interpreter->get_enclosing_frame_ptr(vmg_ fp)) { /* look for a named argument table in this frame */ vm_val_t *argp; const uchar *t = CVmRun::get_named_args_from_frame(vmg_ fp, &argp); if (t != 0) { /* get the number of table entries */ int n = osrp2(t); t += 2; /* * Build the list. The compiler generates the list in * right-to-left order (the order of pushing the arguments). * For readability, reverse this: generate the list left to * right, so that it appears in the original source code order. */ argp += n - 1; for (int i = (n-1)*2 ; i >= 0 ; i -= 2, --argp) { /* get this string's offset and figure its length */ uint ofs = osrp2(t + i); uint len = osrp2(t + i + 2) - ofs; /* create a string from the name */ vm_val_t str; str.set_obj(CVmObjString::create( vmg_ FALSE, (const char *)t + ofs, len)); /* add it to the list */ lst->cons_ensure_space(vmg_ idx, 10); lst->cons_set_element(idx, &str); ++idx; } } } /* set the final list length */ lst->cons_set_len(idx); /* keep only the unique elements */ lst->cons_uniquify(vmg0_); /* return the results */ retval_pop(vmg0_); }