int set_resolution(int init) { int width, height, fs, ms; option_t *option = config_get_option("resolution"); config_resolution_t *res = option->selected->data; option = config_get_option("full_screen"); fs = option->selected->index; option = config_get_option("multisampling"); ms = option->selected->index * 2; if (res) { width = res->w; height = res->h; } else { /* Custom */ option = config_get_option("custom_resolution_width"); width = option->value; option = config_get_option("custom_resolution_height"); height = option->value; } if (init) return ui->create_window(width, height, fs, ms); else return ui->resize(width, height, fs, ms); }
static int dialog_title_music_vol(gg_widget_t *widget, gg_widget_t *emitter, void *data, void *extra_data) { option_t *option = config_get_option("music_volume"); option_select_value_by_index(option, gg_option_get_selected(GG_OPTION(widget))); audio_set_music_volume(option->selected->index); return 1; }
static int dialog_close_cb(gg_widget_t *widget, gg_widget_t *emitter, void *data, void *extra_data) { option_t *option = config_get_option("first_engine"); free(option->string); option->string = strdup(gg_entry_get_text(GG_ENTRY(entry))); config_save(); gg_dialog_close(); return 1; }
static int say_welcome(int sock_fd) { const char* welcome = config_get_option("welcomeline"); if (config_get_option("welcomeline")) { char* welcmsg; welcmsg = prependcode(welcome, 220); enough_mem(welcmsg); jlog(9, "Saying this text as welcomeline: %s", welcmsg); say(sock_fd, welcmsg); free(welcmsg); } else { say(sock_fd, "220 Joe FTP Proxy Server/Gateway (v"JFTPGW_VERSION") ready\r\n"); } return 0; }
const char * config_get_value (void * session, const char * valuename) { XML * mark = config_get_option (session, valuename); if (mark) return (xml_attrval (mark, "value")); if (!strcmp (valuename, "pdrep.localxml.directory")) return PROCDEF_DIRECTORY; if (!strcmp (valuename, "dsrep.localxml.directory")) return DATASHEET_DIRECTORY; if (!strcmp (valuename, "user.localxml.directory")) return USER_DIRECTORY; if (!strcmp (valuename, "group.localxml.directory")) return GROUP_DIRECTORY; if (!strcmp (valuename, "taskindex.odbc.?.conn")) return ODBC_CONNECTION; return ""; }
static int mod_http_chroot(void) { calipso_config_t *config = calipso_get_config(); /* Check wether chroot()-ing is required, chroot is default behaviour */ const char *chrootenable = config_get_option(config, "chroot", NULL); const char *chrootpath = config_get_option(config, "chrootpath", NULL); if (chrootenable == NULL) { if ( calipso_get_uid() ) printf("Chroot() must be disabled as non privileged user."); if (chrootpath == NULL) printf("Chroot() directive enabled, but no ChrootPath() set."); if (chroot(chrootpath) < 0) printf("chroot() call failure in %s.", __func__); if (chdir("/") < 0) printf("chdir() call failure in %s.", __func__); } return CPO_OK; }
int config_get_noption(calipso_config_t *config, const char *opt , const char *section) { const char *val = config_get_option(config, opt , section ); return val ? atoi(val) : 0; }
// NOTE: this function needs to call RegisterServiceCtrlHandlerEx and // SetServiceStatus in all circumstances if brickd is running as service static int generic_main(bool log_to_file, bool debug, bool libusb_debug) { int exit_code = EXIT_FAILURE; const char *mutex_name = "Global\\Tinkerforge-Brick-Daemon-Single-Instance"; HANDLE mutex_handle = NULL; bool fatal_error = false; DWORD service_exit_code = NO_ERROR; int rc; char filename[1024]; int i; FILE *log_file = NULL; WSADATA wsa_data; DEV_BROADCAST_DEVICEINTERFACE notification_filter; HDEVNOTIFY notification_handle; mutex_handle = OpenMutex(SYNCHRONIZE, FALSE, mutex_name); if (mutex_handle == NULL) { rc = GetLastError(); if (rc == ERROR_ACCESS_DENIED) { rc = service_is_running(); if (rc < 0) { fatal_error = true; // FIXME: set service_exit_code goto error_mutex; } else if (rc) { fatal_error = true; service_exit_code = ERROR_SERVICE_ALREADY_RUNNING; log_error("Could not start as %s, another instance is already running as service", _run_as_service ? "service" : "console application"); goto error_mutex; } } if (rc != ERROR_FILE_NOT_FOUND) { fatal_error = true; // FIXME: set service_exit_code rc += ERRNO_WINAPI_OFFSET; log_error("Could not open single instance mutex: %s (%d)", get_errno_name(rc), rc); goto error_mutex; } } if (mutex_handle != NULL) { fatal_error = true; service_exit_code = ERROR_SERVICE_ALREADY_RUNNING; log_error("Could not start as %s, another instance is already running", _run_as_service ? "service" : "console application"); goto error_mutex; } mutex_handle = CreateMutex(NULL, FALSE, mutex_name); if (mutex_handle == NULL) { fatal_error = true; // FIXME: set service_exit_code rc = ERRNO_WINAPI_OFFSET + GetLastError(); log_error("Could not create single instance mutex: %s (%d)", get_errno_name(rc), rc); goto error_mutex; } if (log_to_file) { if (GetModuleFileName(NULL, filename, sizeof(filename)) == 0) { rc = ERRNO_WINAPI_OFFSET + GetLastError(); log_warn("Could not get module file name: %s (%d)", get_errno_name(rc), rc); } else { i = strlen(filename); if (i < 4) { log_warn("Module file name '%s' is too short", filename); } else { filename[i - 3] = '\0'; string_append(filename, "log", sizeof(filename)); log_file = fopen(filename, "a+"); if (log_file == NULL) { log_warn("Could not open log file '%s'", filename); } else { printf("Logging to '%s'\n", filename); log_set_file(log_file); } } } } else if (_run_as_service) { log_set_file(NULL); } if (!_run_as_service && !SetConsoleCtrlHandler(console_ctrl_handler, TRUE)) { rc = ERRNO_WINAPI_OFFSET + GetLastError(); log_warn("Could not set console control handler: %s (%d)", get_errno_name(rc), rc); } log_set_debug_override(debug); log_set_level(LOG_CATEGORY_EVENT, config_get_option("log_level.event")->value.log_level); log_set_level(LOG_CATEGORY_USB, config_get_option("log_level.usb")->value.log_level); log_set_level(LOG_CATEGORY_NETWORK, config_get_option("log_level.network")->value.log_level); log_set_level(LOG_CATEGORY_HOTPLUG, config_get_option("log_level.hotplug")->value.log_level); log_set_level(LOG_CATEGORY_HARDWARE, config_get_option("log_level.hardware")->value.log_level); log_set_level(LOG_CATEGORY_WEBSOCKET, config_get_option("log_level.websocket")->value.log_level); log_set_level(LOG_CATEGORY_OTHER, config_get_option("log_level.other")->value.log_level); if (config_has_error()) { log_error("Error(s) in config file '%s', run with --check-config option for details", _config_filename); fatal_error = true; goto error_config; } if (_run_as_service) { log_info("Brick Daemon %s started (as service)", VERSION_STRING); } else { log_info("Brick Daemon %s started", VERSION_STRING); } if (config_has_warning()) { log_warn("Warning(s) in config file '%s', run with --check-config option for details", _config_filename); } // initialize service status error_config: error_mutex: if (_run_as_service) { if (service_init(service_control_handler) < 0) { // FIXME: set service_exit_code goto error; } if (!fatal_error) { // service is starting service_set_status(SERVICE_START_PENDING, NO_ERROR); } } if (fatal_error) { goto error; } // initialize WinSock2 if (WSAStartup(MAKEWORD(2, 2), &wsa_data) != 0) { // FIXME: set service_exit_code rc = ERRNO_WINAPI_OFFSET + WSAGetLastError(); log_error("Could not initialize Windows Sockets 2.2: %s (%d)", get_errno_name(rc), rc); goto error_event; } if (event_init() < 0) { // FIXME: set service_exit_code goto error_event; } if (hardware_init() < 0) { // FIXME: set service_exit_code goto error_hardware; } if (usb_init(libusb_debug) < 0) { // FIXME: set service_exit_code goto error_usb; } // create notification pipe if (pipe_create(&_notification_pipe) < 0) { // FIXME: set service_exit_code log_error("Could not create notification pipe: %s (%d)", get_errno_name(errno), errno); goto error_pipe; } if (event_add_source(_notification_pipe.read_end, EVENT_SOURCE_TYPE_GENERIC, EVENT_READ, forward_notifications, NULL) < 0) { // FIXME: set service_exit_code goto error_pipe_add; } // register device notification ZeroMemory(¬ification_filter, sizeof(notification_filter)); notification_filter.dbcc_size = sizeof(notification_filter); notification_filter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE; notification_filter.dbcc_classguid = GUID_DEVINTERFACE_USB_DEVICE; if (_run_as_service) { notification_handle = RegisterDeviceNotification((HANDLE)service_get_status_handle(), ¬ification_filter, DEVICE_NOTIFY_SERVICE_HANDLE); } else { if (message_pump_start() < 0) { // FIXME: set service_exit_code goto error_pipe_add; } notification_handle = RegisterDeviceNotification(_message_pump_hwnd, ¬ification_filter, DEVICE_NOTIFY_WINDOW_HANDLE); } if (notification_handle == NULL) { // FIXME: set service_exit_code rc = ERRNO_WINAPI_OFFSET + GetLastError(); log_error("Could not register for device notification: %s (%d)", get_errno_name(rc), rc); goto error_notification; } if (network_init() < 0) { // FIXME: set service_exit_code goto error_network; } // running if (_run_as_service) { service_set_status(SERVICE_RUNNING, NO_ERROR); } if (event_run(network_cleanup_clients_and_zombies) < 0) { // FIXME: set service_exit_code goto error_run; } exit_code = EXIT_SUCCESS; error_run: network_exit(); error_network: UnregisterDeviceNotification(notification_handle); error_notification: if (!_run_as_service) { message_pump_stop(); } event_remove_source(_notification_pipe.read_end, EVENT_SOURCE_TYPE_GENERIC); error_pipe_add: pipe_destroy(&_notification_pipe); error_pipe: usb_exit(); error_usb: hardware_exit(); error_hardware: event_exit(); error_event: log_info("Brick Daemon %s stopped", VERSION_STRING); error: if (!_run_as_service) { // unregister the console handler before exiting the log. otherwise a // control event might be send to the control handler after the log // is not available anymore and the control handler tries to write a // log messages triggering a crash. this situation could easily be // created by clicking the close button of the command prompt window // while the getch call is waiting for the user to press a key. SetConsoleCtrlHandler(console_ctrl_handler, FALSE); } log_exit(); config_exit(); if (_run_as_service) { // because the service process can be terminated at any time after // entering SERVICE_STOPPED state the mutex is closed beforehand, // even though this creates a tiny time window in which the service // is still running but the mutex is not held anymore if (mutex_handle != NULL) { CloseHandle(mutex_handle); } // service is now stopped service_set_status(SERVICE_STOPPED, service_exit_code); } else { if (_pause_before_exit) { printf("Press any key to exit...\n"); getch(); } if (mutex_handle != NULL) { CloseHandle(mutex_handle); } } return exit_code; }
int main(int argc, char **argv) { int exit_code = EXIT_FAILURE; int i; bool help = false; bool version = false; bool check_config = false; bool daemon = false; bool debug = false; bool libusb_debug = false; int pid_fd = -1; #ifdef BRICKD_WITH_LIBUDEV bool initialized_udev = false; #endif for (i = 1; i < argc; ++i) { if (strcmp(argv[i], "--help") == 0) { help = true; } else if (strcmp(argv[i], "--version") == 0) { version = true; } else if (strcmp(argv[i], "--check-config") == 0) { check_config = true; } else if (strcmp(argv[i], "--daemon") == 0) { daemon = true; } else if (strcmp(argv[i], "--debug") == 0) { debug = true; } else if (strcmp(argv[i], "--libusb-debug") == 0) { libusb_debug = true; } else { fprintf(stderr, "Unknown option '%s'\n\n", argv[i]); print_usage(); return EXIT_FAILURE; } } if (help) { print_usage(); return EXIT_SUCCESS; } if (version) { printf("%s\n", VERSION_STRING); return EXIT_SUCCESS; } if (prepare_paths() < 0) { return EXIT_FAILURE; } if (check_config) { return config_check(_config_filename) < 0 ? EXIT_FAILURE : EXIT_SUCCESS; } config_init(_config_filename); log_init(); if (daemon) { pid_fd = daemon_start(_log_filename, _pid_filename, true); } else { pid_fd = pid_file_acquire(_pid_filename, getpid()); if (pid_fd == PID_FILE_ALREADY_ACQUIRED) { fprintf(stderr, "Already running according to '%s'\n", _pid_filename); } } if (pid_fd < 0) { goto error_log; } log_set_debug_override(debug); log_set_level(LOG_CATEGORY_EVENT, config_get_option("log_level.event")->value.log_level); log_set_level(LOG_CATEGORY_USB, config_get_option("log_level.usb")->value.log_level); log_set_level(LOG_CATEGORY_NETWORK, config_get_option("log_level.network")->value.log_level); log_set_level(LOG_CATEGORY_HOTPLUG, config_get_option("log_level.hotplug")->value.log_level); log_set_level(LOG_CATEGORY_HARDWARE, config_get_option("log_level.hardware")->value.log_level); log_set_level(LOG_CATEGORY_WEBSOCKET, config_get_option("log_level.websocket")->value.log_level); #ifdef BRICKD_WITH_RED_BRICK log_set_level(LOG_CATEGORY_RED_BRICK, config_get_option("log_level.red_brick")->value.log_level); log_set_level(LOG_CATEGORY_SPI, config_get_option("log_level.spi")->value.log_level); log_set_level(LOG_CATEGORY_RS485, config_get_option("log_level.rs485")->value.log_level); #endif log_set_level(LOG_CATEGORY_OTHER, config_get_option("log_level.other")->value.log_level); if (config_has_error()) { log_error("Error(s) in config file '%s', run with --check-config option for details", _config_filename); goto error_config; } if (daemon) { log_info("Brick Daemon %s started (daemonized)", VERSION_STRING); } else { log_info("Brick Daemon %s started", VERSION_STRING); } if (config_has_warning()) { log_error("Warning(s) in config file '%s', run with --check-config option for details", _config_filename); } if (event_init() < 0) { goto error_event; } if (signal_init(handle_sigusr1) < 0) { goto error_signal; } if (hardware_init() < 0) { goto error_hardware; } if (usb_init(libusb_debug) < 0) { goto error_usb; } #ifdef BRICKD_WITH_LIBUDEV if (!usb_has_hotplug()) { if (udev_init() < 0) { goto error_udev; } initialized_udev = true; } #endif if (network_init() < 0) { goto error_network; } #ifdef BRICKD_WITH_RED_BRICK if (gpio_init() < 0) { goto error_gpio; } if (red_usb_gadget_init() < 0) { goto error_red_usb_gadget; } if (redapid_init() < 0) { goto error_redapid; } if (red_stack_init() < 0) { goto error_red_stack; } if (rs485_extension_init() < 0) { goto error_rs485_extension; } #endif if (event_run(network_cleanup_clients_and_zombies) < 0) { goto error_run; } exit_code = EXIT_SUCCESS; error_run: #ifdef BRICKD_WITH_RED_BRICK rs485_extension_exit(); error_rs485_extension: red_stack_exit(); error_red_stack: redapid_exit(); error_redapid: red_usb_gadget_exit(); error_red_usb_gadget: //gpio_exit(); error_gpio: #endif network_exit(); error_network: #ifdef BRICKD_WITH_LIBUDEV if (initialized_udev) { udev_exit(); } error_udev: #endif usb_exit(); error_usb: hardware_exit(); error_hardware: signal_exit(); error_signal: event_exit(); error_event: log_info("Brick Daemon %s stopped", VERSION_STRING); error_config: error_log: log_exit(); if (pid_fd >= 0) { pid_file_release(_pid_filename, pid_fd); } config_exit(); return exit_code; }
/** * Print given option to stdout * @param cfg: config * @param opt: option name without trailing :. * This is different from config_set_option. */ static void print_option(struct config_file* cfg, const char* opt) { if(!config_get_option(cfg, opt, config_print_func, stdout)) fatal_exit("cannot print option '%s'", opt); }
static int login_setforward_user(struct clientinfo* clntinfo) { const char* forward; struct slist_t* forward_list, *forward_list_cur; char* tmp; int newsize; int config_state = TAG_GLOBAL | TAG_FROM | TAG_PORT | TAG_TIME | TAG_SERVERTYPE | TAG_PROXYIP | TAG_PROXYPORT; /* this is already a forward */ if ( clntinfo->before_forward.user ) { return CMD_HANDLED; } if ( clntinfo->destination ) { config_state |= TAG_TO; } if ( clntinfo->user ) { config_state |= TAG_USER; } config_shrink_config(get_uint_ip(GET_IP_CLIENT, clntinfo), get_uint_ip(GET_IP_SERVER, clntinfo), clntinfo->destination, clntinfo->destinationport, clntinfo->user, -1, /* before_forward.dest_ip */ (char*) 0, /* before_forward.destination */ 0, /* before_forward.destinationport */ (char*) 0, /* before_forward.user */ 0, /* set no specific time */ clntinfo->proxy_ip, clntinfo->proxy_port, srvinfo.servertype, &hostcache, config_state); if (config_compare_option("access", "allow") == 0) { say(clntinfo->clientsocket, "531 You are not allowed to " "connect to that host. Goodbye.\r\n"); jlog(5, "%s was not allowed to connect.", conv_ip_to_char(clntinfo->client_ip)); return CMD_ERROR; } /* see if there is an option for the forward */ forward = config_get_option("forward"); if (! forward) { /* no forward */ lcs.userlogin = strnulldup(clntinfo->user); lcs.usereffective = strnulldup(clntinfo->user); if (lcs.userforwarded) { free(lcs.userforwarded); } lcs.userforwarded = strdup("<no forward>"); enough_mem(lcs.userforwarded); return CMD_HANDLED; } /* * <user ftp> * forward [email protected] * forward [email protected],3949,p * forward [email protected] * johnspass * forward [email protected] JiKe94 johnspass * </user> * forward *@fooserver.com:2378 * forward %@fooserver.com:2378 */ /* split the list into tokens */ if ( ! (forward_list = config_split_line( forward, WHITESPACES )) ) { return CMD_HANDLED; } /* if we have a defaultforward setting, the variable user has to be * defined so that we can decide if we can use defaultforward at * all. If this is not the case, but there is a defaultforward * setting, skip this whole part. This can happen by setting * logintime to "connect" */ if (!clntinfo->user && forward_list->value && forward_list->value[0] == '%' && forward_list->value[1] == '@') { slist_destroy(forward_list); return CMD_HANDLED; } /* if there is a defaultforward but we already have a destination * set, we can quit here as well */ if (clntinfo->destination && forward_list->value && forward_list->value[0] == '%' && forward_list->value[1] == '@') { /* no forward is being used */ lcs.userlogin = strnulldup(clntinfo->user); lcs.usereffective = strnulldup(clntinfo->user); if (lcs.userforwarded) { free(lcs.userforwarded); } lcs.userforwarded = strdup("<no forward>"); enough_mem(lcs.userforwarded); slist_destroy(forward_list); return CMD_HANDLED; } forward_list_cur = forward_list; /* read and save the values */ clntinfo->forward.login = strdup(forward_list_cur->value); enough_mem(clntinfo->forward.login); forward_list_cur = forward_list_cur->next; if (forward_list_cur && forward_list_cur->value) { clntinfo->forward.accept_pw = strdup(forward_list_cur->value); enough_mem(clntinfo->forward.accept_pw); } else { clntinfo->forward.accept_pw = (char*) 0; } if (forward_list_cur) { forward_list_cur = forward_list_cur->next; } if (forward_list_cur && forward_list_cur->value) { clntinfo->forward.send_pw = strdup(forward_list_cur->value); enough_mem(clntinfo->forward.send_pw); } else { clntinfo->forward.send_pw = (char*) 0; } /* destroy the list again, we have saved the values into * clntinfo->forward.<field> */ slist_destroy(forward_list); /* delete those configuration values that are evaluated by the * parsing routine - they are not necessary anymore */ config_option_list_delete("transparent-forward"); config_option_list_delete("forward"); /* back up */ clntinfo->before_forward.user = strnulldup(clntinfo->user); clntinfo->before_forward.destination = strnulldup(clntinfo->destination); clntinfo->before_forward.destinationport = clntinfo->destinationport; clntinfo->before_forward.dest_ip = get_uint_ip(GET_IP_SERVER,clntinfo); /* special case: We don't have set a username. The client could have * used logintime == connect and has a forward that already matches */ if ( ! clntinfo->before_forward.user ) { clntinfo->before_forward.user = malloc(2); enough_mem(clntinfo->before_forward.user); clntinfo->before_forward.user[0] = '*'; clntinfo->before_forward.user[1] = '\0'; } /* if there was only a new destination but no new username given, * prepend the old one */ if ( ! strchr(clntinfo->forward.login, '@') && clntinfo->before_forward.user) { newsize = strlen(clntinfo->before_forward.user) + 1 /* @ */ + strlen(clntinfo->forward.login) + 1 /* term */; tmp = (char*) malloc(newsize); enough_mem(tmp); snprintf( tmp, newsize, "%s@%s", clntinfo->before_forward.user, clntinfo->forward.login); free(clntinfo->forward.login); clntinfo->forward.login = tmp; } if (clntinfo->forward.login[0] == '*' && clntinfo->forward.login[1] == '@') { /* passauth */ clntinfo->forward.passauth = 1; } /* If there is still no destination, see if we have a defaultforward * setting */ if (clntinfo->destination == (char*) 0 && clntinfo->user && clntinfo->forward.login[0] == '%' && clntinfo->forward.login[1] == '@') { /* defaultforward */ int newsize = strlen(&(clntinfo->forward.login[1])) + strlen(clntinfo->user) + 1; char* tmp = (char*) malloc(newsize); enough_mem(tmp); snprintf(tmp, newsize, "%s%s", clntinfo->user, &(clntinfo->forward.login[1])); free(clntinfo->forward.login); clntinfo->forward.login = tmp; jlog(8, "No destination was set. Using %s because of defaultforward setting", clntinfo->forward.login); } /* call the parsing routine and let it set the values */ if (set_userdest(clntinfo->forward.login, 0, clntinfo, "@,: \t") < 0) { return CMD_ERROR; } /* set values for log info struct */ lcs.userlogin = strnulldup(clntinfo->before_forward.user); lcs.usereffective = strnulldup(clntinfo->user); lcs.userforwarded = strnulldup(clntinfo->forward.login); /* shrink the configuration again - with TAG_FORWARDED this time */ config_shrink_config(get_uint_ip(GET_IP_CLIENT, clntinfo), /* these are the original values */ /* see above (1) */ clntinfo->before_forward.dest_ip, clntinfo->before_forward.destination, clntinfo->before_forward.destinationport, clntinfo->before_forward.user, /* these are the values set by the forward */ /* pass them as well, if we are in the * forwarded_tag, config_match_section() * will overwrite the previous with the * following values */ get_uint_ip(GET_IP_SERVER, clntinfo), clntinfo->destination, clntinfo->destinationport, clntinfo->user, 0, /* set no specific time */ clntinfo->proxy_ip, clntinfo->proxy_port, srvinfo.servertype, &hostcache, TAG_ALL); return CMD_HANDLED; }
static int login_mayconnect(struct clientinfo* clntinfo) { int allowed = 0; unsigned long int target; unsigned long int host_ip; unsigned long int client_ip, server_ip; int tags; allowed = 0; /* we don't know yet if clntinfo->destination is a hostname like * "somehost.foo.com" or if it is an IP in a char* like * "212.117.232.20" * * So call inet_addr(), it should make the decision :-) * * */ target = inet_addr(clntinfo->destination); /* get the client_ip by asking information about the socket the * client is connected */ client_ip = get_uint_ip(GET_IP_CLIENT, clntinfo); server_ip = (unsigned long int) UINT_MAX; if (target == (unsigned long int) UINT_MAX) { /* clntinfo->destination may be a hostname, but it needn't. * It may also be an invalid IP: "393.39.239.500" or * anything else. Look it up. * */ host_ip = hostent_get_ip(&hostcache, clntinfo->destination); if (host_ip != (unsigned long int) UINT_MAX) { /* successful lookup */ server_ip = host_ip; } else { /* it's not a valid IP and we could not look it up, * so we could not get valid information about the * destination host */ jlog(7, "Nonsense destination (no IP and could not look up hostname): %s", clntinfo->destination); jlog(8, "Please check your nameserver configuration. This may also happen if your chroot-environment does not contain the necessary files which the libc needs for a lookup"); allowed = 0; } } else { /* okay, it's an IP */ server_ip = inet_addr(clntinfo->destination); } if (server_ip != (unsigned long) UINT_MAX) { /* we could get a valid IP, now we can evaluate if client * is allowed to connect to the destination host */ jlog(9, "Checking all tags"); tags = TAG_ALL_NOT_FORWARDED; if (clntinfo->before_forward.user) { /* if we are treating a forward, add this value, it * won't come up in the option list otherwise */ tags |= TAG_FORWARDED; } /* checking of the configuration works such: * * no forward: do not evaluate <forwarded> * always check the normal values * * forward: evaluate <forwarded> * if (!in_forwarded_tag) { * (1) check before_forward.* values * } else { * (2) check normal values * } */ if (clntinfo->before_forward.user) { /* Yes, there was a forward applied */ config_shrink_config(client_ip, /* this are the original values */ /* see above (1) */ clntinfo->before_forward.dest_ip, clntinfo->before_forward.destination, clntinfo->before_forward.destinationport, clntinfo->before_forward.user, /* these are the values set by the forward */ /* pass them as well, if we are in the * forwarded_tag, config_match_section() * will overwrite the previous with the * following values */ server_ip, clntinfo->destination, clntinfo->destinationport, clntinfo->user, 0, /* set no specific time */ clntinfo->proxy_ip, clntinfo->proxy_port, srvinfo.servertype, &hostcache, tags); } else { /* not a forward */ config_shrink_config(client_ip, server_ip, clntinfo->destination, clntinfo->destinationport, clntinfo->user, clntinfo->before_forward.dest_ip, clntinfo->before_forward.destination, clntinfo->before_forward.destinationport, clntinfo->before_forward.user, 0, /* set no specific time */ clntinfo->proxy_ip, clntinfo->proxy_port, srvinfo.servertype, &hostcache, tags); } allowed = strcmp(config_get_option("access"), "allow") == 0; } if (!allowed) { say(clntinfo->clientsocket, "531 You are not allowed to connect to that host.\r\n"); jlog(8, "Not allowed to connect to %s", clntinfo->destination); lcs.respcode = 531; return CMD_ERROR; } /* if the client was allowed, save the clients original IP */ if (!clntinfo->before_forward.user) { clntinfo->before_forward.dest_ip = server_ip; } return allowed; /* a positive int */ }
int main(int argc, char **argv) { cl_options_t cl_options = {0}; dbg_init(); DBG_LOG("Version %s", g_version); ui = &ui_sdlgl; printf("DreamChess %s\n", g_version); parse_options(argc, argv, &ui, &cl_options); config_init(); set_cl_options(&cl_options); if (!ui) { DBG_ERROR("Failed to find a user interface driver"); exit(1); } ui->init(); init_resolution(); while (1) { board_t board; int pgn_slot; option_t *option; if (!(config = ui->config(&pgn_slot))) break; ch_userdir(); option = config_get_option("first_engine"); #ifdef __APPLE__ char temp1[200]; char temp2[200]; if (!strcmp(option->string, "dreamer") || !strcmp(option->string, "Dreamer")) { CFBundleRef mainBundle = CFBundleGetMainBundle(); CFURLRef bundledir = CFBundleCopyBundleURL(mainBundle); CFStringRef stringref = CFURLCopyFileSystemPath(bundledir, kCFURLPOSIXPathStyle); CFStringGetCString(stringref, temp1, 200, kCFStringEncodingMacRoman); snprintf(temp2, sizeof(temp2), "%s/contents/MacOS/dreamer", temp1); game_set_engine_error(comm_init(temp2)); } else game_set_engine_error(comm_init(option->string)); #else game_set_engine_error(comm_init(option->string)); #endif comm_send("xboard\n"); comm_send("new\n"); comm_send("random\n"); comm_send("sd %i\n", config->cpu_level); comm_send("depth %i\n", config->cpu_level); if (config->difficulty == 0) comm_send("noquiesce\n"); if (config->player[WHITE] == PLAYER_UI && config->player[BLACK] == PLAYER_UI) comm_send("force\n"); if (config->player[WHITE] == PLAYER_ENGINE) comm_send("go\n"); in_game = 1; board_setup(&board); history = history_init(&board); move_list_init(&san_list); move_list_init(&fan_list); move_list_init(&fullalg_list); if (pgn_slot >= 0) if (game_load(pgn_slot)) { DBG_ERROR("Failed to load savegame in slot %i", pgn_slot); exit(1); } ui->update(history->view->board, NULL); while (in_game) { char *s; if ((s = comm_poll())) { DBG_LOG("Message from engine: '%s'", s); if (!history->result) { if ((!strncmp(s, "move ", 4) || strstr(s, "... ")) && config->player[history->last->board->turn] == PLAYER_ENGINE) { char *move_str = strrchr(s, ' ') + 1; board_t new_board = *history->last->board; move_t *engine_move; DBG_LOG("Parsing move string '%s'", move_str); engine_move = san_to_move(&new_board, move_str); if (!engine_move) engine_move = fullalg_to_move(&new_board, move_str); if (engine_move) { audio_play_sound(AUDIO_MOVE); do_move(engine_move, 1); free(engine_move); } else DBG_ERROR("Failed to parse move string '%s'", move_str); } else if (strstr(s, "llegal move")) game_undo(); /* Ignore result message if we've already determined a result ourselves. */ else { char *start = strchr(s, '{'); char *end = strchr(s, '}'); if (start && end && end > start) { char *comment = malloc(end - start); history->result = malloc(sizeof(result_t)); strncpy(comment, start + 1, end - start - 1); comment[end - start - 1] = '\0'; history->result->reason = comment; if (strstr(s, "1-0")) { history->result->code = RESULT_WHITE_WINS; ui->show_result(history->result); } else if (strstr(s, "1/2-1/2")) { history->result->code = RESULT_DRAW; ui->show_result(history->result); } else if (strstr(s, "0-1")) { history->result->code = RESULT_BLACK_WINS; ui->show_result(history->result); } else { free(history->result->reason); free(history->result); history->result = NULL; } } } } free(s); } ui->poll(); } comm_send("quit\n"); comm_exit(); history_exit(history); move_list_exit(&san_list); move_list_exit(&fan_list); move_list_exit(&fullalg_list); } ui->exit(); dbg_exit(); return 0; }
void toggle_fullscreen(void) { option_t *option = config_get_option("full_screen"); option_select_value_by_index(option, 1 - option->selected->index); set_resolution(0); }
static int dialog_title_theme(gg_widget_t *widget, gg_widget_t *emitter, void *data, void *extra_data) { option_t *option = config_get_option("theme"); option_select_value_by_index(option, gg_option_get_selected(GG_OPTION(widget))); return 1; }
static int child_setup(int sock_fd, struct clientinfo *clntinfo) { struct sockaddr_in t_in; struct sockaddr_in c_in; unsigned long int peer_ip = get_uint_peer_ip(sock_fd); struct sigaction sa; int i, ret; #ifdef HAVE_LIBWRAP struct request_info req; int libwrap_allow = 0; #endif if (peer_ip == (unsigned long int) UINT_MAX) { return -1; } if (stage_action("connect") < 0) { say(sock_fd, "421 Error setting up (see logfile)\r\n"); return -1; } /* The clients ignore the SIGHUP signal. Thus * the user can issue a killall -HUP jftpgw * and the master jftpgw process rereads its * configuration file without affecting the * child servers */ sa.sa_handler = SIG_IGN; sigemptyset(&sa.sa_mask); sa.sa_flags = 0; sigaction(SIGHUP, &sa, 0); /* And they just reap the status of exited children */ sa.sa_handler = reap_chld_info; sigemptyset(&sa.sa_mask); #ifndef WINDOWS sa.sa_flags = SA_RESTART; #endif sigaction(SIGCHLD, &sa, 0); for (i = 0; i < clntinfo->boundsocket_niface; i++) { close(clntinfo->boundsocket_list[i]); } free(clntinfo->boundsocket_list); clntinfo->boundsocket_list = (int*) 0; clntinfo->forward.passauth = 0; clntinfo->serversocket = -1; clntinfo->clientsocket = sock_fd; jlog(7, "Connection from %s", get_char_peer_ip(sock_fd)); c_in = socketinfo_get_local_sin(sock_fd); jlog(7, "Client tried to connect to %s on port %d", inet_ntoa(c_in.sin_addr), ntohs(c_in.sin_port)); clntinfo->addr_to_client = c_in.sin_addr.s_addr; clntinfo->proxy_ip = c_in.sin_addr.s_addr; clntinfo->proxy_port = ntohs(c_in.sin_port); /* see if we are in transparent mode */ t_in = socketinfo_get_transparent_target_sin(sock_fd); jlog(7, "Transparent target seems to be %s on port %d", inet_ntoa(t_in.sin_addr), ntohs(t_in.sin_port)); jlog(9, "Checking TAG_GLOBAL | TAG_FROM | TAG_PROXYIP | TAG_PROXYPORT | TAG_TIME | TAG_SERVERTYPE"); ret = config_shrink_config(peer_ip, /* source IP */ -1, /* dest IP */ (char*) 0, /* dest name */ 0, /* dest port */ (char*) 0, /* dest user */ -1, /* forwarded IP */ (char*) 0, /* forwarded destination */ 0, /* forwarded destinationport */ (char*) 0, /* forwarded username */ 0, /* set no specific time */ clntinfo->proxy_ip, /* ip of proxy if */ clntinfo->proxy_port, /* port of proxy if */ srvinfo.servertype, /* global variable */ &hostcache, TAG_CONNECTED ); if (ret != 0) { jlog(2, "Error shrinking config data"); return ret; } #ifndef HAVE_LIBWRAP srvinfo.tcp_wrapper = 0; #endif if (srvinfo.tcp_wrapper) { #ifdef HAVE_LIBWRAP /* use libwrap(tcp_wrapper) for access control * patch by <*****@*****.**>. * It is useful to check both keywords "jftpgw" and "ftp-gw" * for TIS Gauntlet flabour. */ request_init(&req, RQ_DAEMON, "ftp-gw", RQ_CLIENT_ADDR, conv_ip_to_char(peer_ip), NULL); libwrap_allow = hosts_access(&req); request_init(&req, RQ_DAEMON, "jftpgw", RQ_CLIENT_ADDR, conv_ip_to_char(peer_ip), NULL); if (libwrap_allow || hosts_access(&req)) { jlog(5, "%s is allowed by libwrap to connect.", conv_ip_to_char(peer_ip)); } else { say(sock_fd, "500 You are not allowed by libwrap to " "connect. Goodbye.\r\n"); jlog(5, "%s was not allowed to connect.", conv_ip_to_char(peer_ip)); close(sock_fd); return -2; } #endif } else { if ( ! config_get_option("access") || ! strcmp(config_get_option("access"), "allow") == 0) { say(sock_fd, "500 You are not allowed to " "connect. Goodbye.\r\n"); jlog(5, "%s was not allowed to connect.", conv_ip_to_char(peer_ip)); close(sock_fd); return -2; } else { jlog(6, "%s is allowed to connect.", conv_ip_to_char(peer_ip)); } } if (config_get_bool("transparent-proxy") && get_uint_peer_ip(sock_fd) == t_in.sin_addr.s_addr) { jlog(4, "proxy loop detected - machine connects to itself, disabling transparent proxy support"); } jlog(9, "Proxy loop check: peer_ip: %s, t_in_ip: %s", get_char_peer_ip(sock_fd), inet_ntoa(t_in.sin_addr)); #ifdef HAVE_LINUX_NETFILTER_IPV4_H jlog(9, "HAVE_LINUX_NETFILTER_IPV4_H true, c_in_ip: %s, t_in_port: %d, " "c_in_port: %d", inet_ntoa(c_in.sin_addr), ntohs(t_in.sin_port), ntohs(c_in.sin_port)); #endif if (config_get_bool("transparent-proxy") && /* see if the proxy loops. It loops when the source has the * same IP as the destination. There is no need for such a * configuration "in the wild". Is there? */ (!(get_uint_peer_ip(sock_fd) == t_in.sin_addr.s_addr) #ifdef HAVE_LINUX_NETFILTER_IPV4_H && !(t_in.sin_addr.s_addr == c_in.sin_addr.s_addr && t_in.sin_port == c_in.sin_port) #endif )) { jlog(9, "Enabling transparent proxy"); clntinfo->transparent = TRANSPARENT_YES; clntinfo->transparent_destination = t_in; } else { jlog(9, "No transparent proxy support"); clntinfo->transparent = TRANSPARENT_NO; clntinfo->transparent_destination.sin_port = 0; clntinfo->transparent_destination.sin_addr.s_addr = 0; } if (stage_action("connectsetup") < 0) { say(sock_fd, "421 Error setting up (see logfile)\r\n"); return -1; } /* set the target for the transparent proxy */ if (clntinfo->transparent == TRANSPARENT_YES) { char* colon; long int dport; if (config_get_option("transparent-forward") && config_compare_option("logintime", "connect")) { clntinfo->destination = strdup(config_get_option("transparent-forward")); jlog(9, "Enabling transparent forward to %s", clntinfo->destination); } else { clntinfo->destination = socketinfo_get_transparent_target_char(sock_fd); } colon = strchr(clntinfo->destination, ':'); if (!colon) { /* abort, shouldnt happen */ jlog(9, "Could not get transparent target properly"); clntinfo->transparent = TRANSPARENT_NO; return say_welcome(sock_fd); } *colon = '\0'; /* terminate destination */ colon++; /* skip to port number */ dport = strtol(colon, NULL, 10); if (errno == ERANGE && (dport == LONG_MIN || dport == LONG_MAX)) { clntinfo->destinationport = config_get_ioption("serverport", DEFAULTSERVERPORT); /* reverse for logging */ colon--; *colon = ':'; jlog(6, "Could not parse dest/port to connect to: %s", clntinfo->destination); return -1; } else { clntinfo->destinationport = dport; } } if ( ! config_compare_option("logintime", "connect") ) { ret = say_welcome(sock_fd); } else { ret = login(clntinfo, LOGIN_ST_CONNECTED); } /* seed the random number generator */ srand(time(NULL)); return ret; }
int waitclient(const char* hostnames, struct clientinfo* clntinfo) { int chldpid =0; const char* option = 0; int ahandle, i; struct sigaction sa; struct descriptor_set d_set; unsigned int peer_ip; struct sockaddr_in c_in; time_t now; if (srvinfo.multithread) { daemonize(); } if (changeid(UNPRIV, EUID, "Changing id back (socket(), bind())") < 0) { return -1; } d_set = listen_on_ifaces(hostnames, clntinfo); if (d_set.maxfd < 0) { jlog(8, "d_set.maxfd was negative: %d", d_set.maxfd); return -1; } /* we have successfully bound */ /* become root again - use our function instead of plain * setuid() for the logging */ if (changeid(PRIV, UID, "Changing ID to root (pidfile)") < 0) { return -1; } option = config_get_option("pidfile"); if (option) { FILE* pidf; umask(022); pidf = fopen(option, "w"); if (pidf) { fprintf(pidf, "%ld\n", (long) getpid()); fclose(pidf); /* if successful register function to remove the * pidfile */ atexit(removepidfile); } else { jlog(2, "Error creating pidfile %s", option); } } /* this has to be done for the daemonization. We do it now after * the pidfile has been created */ umask(0); srvinfo.ready_to_serve = SVR_LAUNCH_READY; if (stage_action("startsetup") < 0) { return -1; } sa.sa_handler = childterm; chlds_exited = 0; sigemptyset (&sa.sa_mask); #ifndef WINDOWS sa.sa_flags = SA_RESTART; #endif sigaction (SIGCHLD, &sa, 0); /* Close stdin,stdout,stderr */ for(i = 0; i <= 2 && srvinfo.multithread; i++) { close(i); } srvinfo.main_server_pid = getpid(); atexit(sayterminating); while(1) { ahandle = get_connecting_socket(d_set); if (ahandle == -1) { /* either select() or accept() failed */ /* I don't try resume here because we are in an * endless loop. The danger of the programm falling * into an infinite loop consuming all cpu time is * too big... */ jlog(8, "get_connecting_socket() returned error code"); return -1; } c_in = socketinfo_get_local_sin(ahandle); peer_ip = get_uint_peer_ip(ahandle); now = time(NULL); config_counter_increase(peer_ip, /* from ip */ c_in.sin_addr.s_addr, /* proxy_ip */ ntohs(c_in.sin_port), /* proxy_port */ now); /* specific_time */ if (config_check_limit_violation()) { say(ahandle, "500 Too many connections, sorry\r\n"); close(ahandle); config_counter_decrease(peer_ip, /* from ip */ c_in.sin_addr.s_addr, /* proxy_ip */ ntohs(c_in.sin_port), /* proxy_port */ now); /* specific_time */ continue; } if (srvinfo.multithread) { if ((chldpid = fork()) < 0) { jlog(1, "Error forking: %s", strerror(errno)); close(ahandle); return -1; } if (chldpid > 0) { /* parent process */ /* register the PID */ register_pid(chldpid, peer_ip, c_in.sin_addr.s_addr, /* proxy_ip */ ntohs(c_in.sin_port), /* proxy_port */ now); /* specific_time */ close(ahandle); } if (chldpid == 0) { /* child process */ jlog(8, "forked to pid %d", getpid()); } } if (!srvinfo.multithread || chldpid == 0) { return child_setup(ahandle, clntinfo); } } }
double config_get_foption(calipso_config_t *config, const char *opt , const char *section) { const char *val = config_get_option(config, opt , section); return val ? atof(val) : 0.0; }
int main(int argc, char** argv) { const char* pcap_file; const char* capture_interface; const char* tmp; int is_live = 0; int snaplen = 65535; uint32_t packet_pool_size = 1; pthread_t worker_id; uint32_t conn_no = 0; uint32_t conn_max = 0; uint32_t flow_timeout = 0; int print_stats_enabled = 0; if (argc != 2) { usage(argv[0]); return -1; } msg_setlevel(MSG_INFO); // install signal handler if (SIG_ERR == signal(SIGINT, sig_handler)) { msg(MSG_ERROR, "Could not install signal handler for SIGINT."); return -1; } if (SIG_ERR == signal(SIGCHLD, sig_chld_handler)) { msg(MSG_ERROR, "Could not install signal handler for SIGCHLD"); return -1; } struct dumpers dumps; dumpers_init(&dumps); struct config* conf = config_new(argv[1]); if (!conf) { msg(MSG_ERROR, "Invalid config. Abort!"); return 0; } // check if we should have any output over msg // quite mode is necessary when we are dumping to stdout tmp = config_get_option(conf, MAIN_NAME, "quiet"); if (tmp) { if (!strcmp(tmp, "yes")) { msg_setlevel(-1); } } // check if we have a config statement that changes message level tmp = config_get_option(conf, MAIN_NAME, "msg_level"); if (tmp) { if (!strcmp(tmp, "fatal")) { msg_setlevel(MSG_FATAL); } else if (!strcmp(tmp, "error")) { msg_setlevel(MSG_ERROR); } else if (!strcmp(tmp, "debug")) { msg_setlevel(MSG_DEBUG); } else if (!strcmp(tmp, "info")) { msg_setlevel(MSG_INFO); } else if (!strcmp(tmp, "stats")) { msg_setlevel(MSG_STATS); } else { msg(MSG_FATAL, "Unknown msg level ..."); } } // do we want to periodically output statistics on dropped/received packets? tmp = config_get_option(conf, "MAIN_NAME", "packet_stats"); if (tmp) { if (!strcmp(tmp, "yes")) { print_stats_enabled = 1; } } msg(MSG_INFO, "%s is initializing ...", argv[2]); pcap_file = config_get_option(conf, MAIN_NAME, "pcapfile"); capture_interface = config_get_option(conf, MAIN_NAME, "interface"); if (!pcap_file && !capture_interface) { msg(MSG_FATAL, "main: Neither \"pcapfile\" nor \"interface\" given in config file."); exit(-1); } if (pcap_file && capture_interface) { msg(MSG_FATAL, "main: Got \'pcapfile\" *and* \"interface\". Please decide whether you want to work on- or offline!"); exit(-1); } tmp = config_get_option(conf, MAIN_NAME, "max_packet_size"); if (tmp) { snaplen = atoi(tmp); } tmp = config_get_option(conf, MAIN_NAME, "packet_pool"); if (tmp) { packet_pool_size = atoi(tmp); } // init connection pool if (!config_get_option(conf, MAIN_NAME, "init_connection_pool")) { msg(MSG_ERROR, "main: \"init_connection_pool\" missing in section %s", MAIN_NAME); return -1; } conn_no = atoi(config_get_option(conf, MAIN_NAME, "init_connection_pool")); if (!config_get_option(conf, MAIN_NAME, "max_connection_pool")) { msg(MSG_ERROR, "main: \"max_connection_pool\" missing in section %s", MAIN_NAME); return -1; } conn_max = atoi(config_get_option(conf, MAIN_NAME, "max_connection_pool")); if (!config_get_option(conf, MAIN_NAME, "flow_timeout")) { msg(MSG_ERROR, "main: \"flow_timeout\" missing in section %s", MAIN_NAME); return -1; } flow_timeout = atoi(config_get_option(conf, MAIN_NAME, "flow_timeout")); connection_init_pool(conn_no, conn_max, flow_timeout); struct packet_pool* packet_pool = packet_pool_init(packet_pool_size, snaplen); struct thread_data worker_data; worker_data.pool = packet_pool; worker_data.dumpers = &dumps; pcap_t* pfile; if (pcap_file) { pfile = open_pcap(pcap_file, 0, snaplen); dumpers_create_all(&dumps, conf, pcap_datalink(pfile), snaplen); if (!dumps.count) { msg(MSG_FATAL, "Could not configure any modules."); return -1; } if (pthread_create(&worker_id, NULL, worker_thread, &worker_data)) { msg(MSG_FATAL, "Could not create worker thread: %s", strerror(errno)); return -1; } } else { is_live = 1; pfile = open_pcap(capture_interface, 1, snaplen); dumpers_create_all(&dumps, conf, pcap_datalink(pfile), snaplen); if (!dumps.count) { msg(MSG_FATAL, "Could not configure any modules."); return -1; } // the dumper creating can take a significant amount of time. // We could not read any packets during this initialization phase and // could therefore drop a significant amount of packets (depending on // the link speed). We therefore close and reopen the pcap descriptor // in order to reset the statistics and get more accurate packet // drop statistice (we had to open the pcap interface for retrieving the // interface link type which is important for module initialization pcap_close(pfile); if (pthread_create(&worker_id, NULL, worker_thread, &worker_data)) { msg(MSG_FATAL, "Could not create worker thread: %s", strerror(errno)); return -1; } pfile = open_pcap(capture_interface, 1, snaplen); } msg(MSG_INFO, "%s is up and running. Starting to consume packets ...", argv[0]); struct pcap_pkthdr pcap_hdr; time_t last_stats = 0; time_t stats_interval = 10; uint64_t captured = 0; const unsigned char* data = NULL; while (running) { if (NULL != (data = pcap_next(pfile, &pcap_hdr))) { captured++; if (print_stats_enabled) { if (pcap_hdr.ts.tv_sec - last_stats > stats_interval && is_live) { last_stats = pcap_hdr.ts.tv_sec; print_stats(pfile, captured, packet_pool); } } packet_new(packet_pool, &pcap_hdr, data); } else { if (!is_live) running = 0; } } msg(MSG_INFO, "%s finished reading packets ...", argv[0]); // TODO: this is a hack! we might need to wake the worker thread // because it might be blocked at a mutex waiting for new packets // we have to insert a packet in order to wake the thread from the // mutex. Hence, we re-include the last packet into the pool again ... // FIXME: The hack can result in a segmentation fault if no packet // has been read from the pcap_t ... unsigned char* useless = malloc(snaplen); packet_new(packet_pool, &pcap_hdr, useless); free(useless); pthread_join(worker_id, NULL); // ok, the second worker is stopped right now // we are therefore the only thread that works on the connection pool. // lets timeout all active connnections to update the statistics (e.g. for stats_module) connection_flush_all_active_conns(); dumpers_finish(&dumps); connection_deinit_pool(); packet_pool_deinit(packet_pool); config_free(conf); return 0; }
static void parse_options(int argc, char **argv, ui_driver_t **ui_driver, cl_options_t *cl_options) { int c; #ifdef HAVE_GETOPT_LONG int optindex; struct option options[] = {{"help", no_argument, NULL, 'h'}, {"fullscreen", no_argument, NULL, 'f'}, {"width", required_argument, NULL, 'W'}, {"height", required_argument, NULL, 'H'}, {"1st-engine", required_argument, NULL, '1'}, {0, 0, 0, 0}}; /* On macOS (under certain circumstances) a process serial number will be passed in. In this * case we skip parsing the command line options. */ if (argc > 1 && strncmp(argv[1], "-psn_", 5) == 0) { DBG_WARN("Received '%s'; ignoring all command line arguments", argv[1]); return; } while ((c = getopt_long(argc, argv, "1:fhW:H:", options, &optindex)) > -1) { #else while ((c = getopt(argc, argv, "1:fhW:H:")) > -1) { #endif /* HAVE_GETOPT_LONG */ switch (c) { case 'h': printf("Usage: dreamchess [options]\n\n" "An xboard-compatible chess interface.\n\n" "Options:\n" OPTION_TEXT("--help\t", "-h\t", "show help") OPTION_TEXT("--fullscreen\t", "-f\t", "run fullscreen") OPTION_TEXT("--width\t", "-W<num>", "set screen width") OPTION_TEXT("--height\t", "-H<num>", "set screen height") OPTION_TEXT("--1st-engine <eng>", "-1<eng>", "use <eng> as first chess engine") OPTION_TEXT("\t\t", "\t", " defaults to 'dreamer'")); exit(0); case '1': cl_options->engine = optarg; break; case 'f': cl_options->fs = 1; break; case 'W': cl_options->width = atoi(optarg); break; case 'H': cl_options->height = atoi(optarg); } } } static void set_cl_options(cl_options_t *cl_options) { option_t *option; if (cl_options->engine) { option = config_get_option("first_engine"); option_string_set_text(option, cl_options->engine); } if (cl_options->fs) { option = config_get_option("full_screen"); option_select_value_by_name(option, "On"); } if (cl_options->width) { option = config_get_option("custom_resolution_width"); option->value = cl_options->width; option = config_get_option("resolution"); option_select_value_by_name(option, "Custom"); } if (cl_options->height) { option = config_get_option("custom_resolution_height"); option->value = cl_options->height; option = config_get_option("resolution"); option_select_value_by_name(option, "Custom"); } }