char *my_readline(t_shell *shell, char *prompt) { t_rl *base; char *output; base = &shell->rl; init_readline(base); output = NULL; if (!(CHCK(base->flags, 0x01))) { xfree(prompt); return (get_next_line(STDIN_FILENO)); } else if (prompt) { if (signal(SIGWINCH, term_size) == SIG_ERR) perror("42sh"); #ifdef __HREACT_ON__ hreact_displaying(shell); #endif print_prompt(base, prompt); output = getline(base, shell); save_to_history(shell, output); } reset_readline(base); return (output); }
int slsh_use_readline (char *app_name, int use_readline, int is_interactive) { Use_Readline = use_readline; #if USE_SLANG_READLINE if (is_interactive) { if (-1 == init_readline (app_name)) return -1; } #endif return 0; }
int readConsole(Client cntxt) { /* execute from stdin */ struct stat statb; char *buf; if (cntxt->promptlength == 0 || !(fstat(fileno(stdin), &statb) == 0 && S_ISCHR(statb.st_mode)) ) return -1; /* read lines and move string to client buffer. */ #ifdef HAVE_LIBREADLINE if( initReadline ==0){ init_readline(); using_history(); stifle_history(1000); initReadline =1 ; } #endif buf= getConsoleInput(cntxt, cntxt->prompt, 0, 1); if( buf) { size_t len= strlen(buf); if( len >= cntxt->fdin->size) { /* extremly dirty inplace buffer overwriting */ cntxt->fdin->buf= realloc(cntxt->fdin->buf, len+1); if( cntxt->fdin->buf == NULL) { GDKerror("readConsole: " MAL_MALLOC_FAIL); free(buf); goto bailout; } cntxt->fdin->size = len; } strcpy(cntxt->fdin->buf, buf); cntxt->fdin->pos = 0; cntxt->fdin->len = len; free(buf); return 1; } bailout: cntxt->fdin->eof = 1; #ifdef HAVE_LIBREADLINE if( initReadline ){ deinit_readline(); initReadline= 0; } #endif return -1; }
obj read_console_line( obj completions, const char *prompt ) { char *buffer = NULL; static rs_bool init_yet = NO; obj result; if (!init_yet) init_readline(); the_completions = completions; buffer = readline( prompt ); if (!buffer) return FALSE_OBJ; result = make_string(buffer); free(buffer); return result; }
int repl() { global_env = null_import_environment(); environment_t *env = global_env; print_banner(env); #if HAVE_LIBREADLINE init_readline(); #endif for(;;) { static char *input = reinterpret_cast<char*>(1); /* * input == 1 is the ugliest hack ever to * disoplay the imported_defaults message below, * and also because of ANOTHER hack, the home-brewed * exception system using longjumps. I think I need to * rewrite... :) */ if ( input != reinterpret_cast<char*>(1) ) { if ( (input = readline("#; mickey> ")) == NULL ) break; // end of input stream if ( *trimr(input) == '\0' ) continue; // empty command #ifdef HAVE_LIBREADLINE add_history(input); #endif if ( exception_raised() ) { backtrace(); backtrace_clear(); continue; } } else input = strdup(""); TRY { /* * Must wrap import_defaults in try-catch */ { static bool imported_defaults = false; if ( !imported_defaults ) { printf("\n"); printf(" To quit, hit CTRL+D or type (exit). Use (help) for an introduction.\n"); printf(" Distributed under the LGPL 2.1; see LICENSE\n"); printf("\n"); printf(" WARNING: There's no garbage collector in Mickey yet!\n"); printf("|#\n\n"); import_defaults(env); imported_defaults = true; // import (help) and (top-level) etc. if ( !global_opts.empty_repl_env ) import(env, exports_repl, "(scheme repl)"); } } program_t *p = parse(input, env); if ( p->parens < 0 ) raise(runtime_exception(format( "parser: unbalanced parenthesis -> %ld", p->parens))); // Read until we have balanced parenthesis std::string s(input); while ( p->parens != 0 ) { if ( (input = readline("")) == NULL ) break; if ( *trimr(input) == '\0' ) continue; s += " "; s += input; delete p; #ifdef HAVE_LIBREADLINE free(input); input = NULL; #endif p = parse(s.c_str(), env); } #ifdef HAVE_LIBREADLINE if ( input ) free(input); #endif for ( cons_t *i = p->root; !nullp(i); i = cdr(i) ) { cons_t *result = eval(car(i), p->globals); if ( circularp(result) ) { fflush(stdout); fprintf(stderr, "Warning: List is circular\n"); cons_t *l = list(), *end = l; for ( int n=0; n < MAX_CIRCULAR_DISPLAY_ITEMS; ++n ) { end->car = car(result); end->cdr = cons(nil()); end = cdr(end); result = cdr(result); } end->car = symbol("...etc"); end->cdr = cons(nil()); printf("%s\n", sprint(l).c_str()); } else { std::string s = sprint(result); if ( !s.empty() ) printf("%s\n", s.c_str()); } } delete p; } CATCH (const exception_t& e) { if ( *e.what() != '\0' ) fprintf(stderr, "%s\n", e.what()); backtrace(); backtrace_clear(); } } printf("\n"); return 0; }
int main(int argc, char *argv[]) { /* Uncomment to debug and attach */ #if 0 int c; read(0, &c, 1); #endif parse_long_options(&argc, &argv); current_line = ibuf_init(); cgdbrc_init(); if (create_and_init_pair() == -1) { fprintf(stderr, "%s:%d Unable to create PTY pair", __FILE__, __LINE__); exit(-1); } /* First create tgdb, because it has the error log */ if (start_gdb(argc, argv) == -1) { fprintf(stderr, "%s:%d Unable to invoke GDB", __FILE__, __LINE__); exit(-1); } /* From here on, the logger is initialized */ /* Create the home directory */ if (init_home_dir() == -1) { logger_write_pos(logger, __FILE__, __LINE__, "Unable to create home dir ~/.cgdb"); cleanup(); exit(-1); } if (init_readline() == -1) { logger_write_pos(logger, __FILE__, __LINE__, "Unable to init readline"); cleanup(); exit(-1); } if (tty_cbreak(STDIN_FILENO, &term_attributes) == -1) { logger_write_pos(logger, __FILE__, __LINE__, "tty_cbreak error"); cleanup(); exit(-1); } if (init_kui() == -1) { logger_write_pos(logger, __FILE__, __LINE__, "init_kui error"); cleanup(); exit(-1); } /* Initialize the display */ switch (if_init()) { case 1: logger_write_pos(logger, __FILE__, __LINE__, "Unable to initialize the curses library"); cleanup(); exit(-1); case 2: logger_write_pos(logger, __FILE__, __LINE__, "Unable to handle signal: SIGWINCH"); cleanup(); exit(-1); case 3: logger_write_pos(logger, __FILE__, __LINE__, "Unable to setup highlighting groups"); cleanup(); exit(-1); case 4: logger_write_pos(logger, __FILE__, __LINE__, "New GDB window failed -- out of memory?"); cleanup(); exit(-1); } /* Initialize the pipe that is used for resize */ if (init_resize_pipe() == -1) { logger_write_pos(logger, __FILE__, __LINE__, "init_resize_pipe error"); cleanup(); exit(-1); } { char config_file[FSUTIL_PATH_MAX]; FILE *config; fs_util_get_path(cgdb_home_dir, "cgdbrc", config_file); config = fopen(config_file, "r"); if (config) { command_parse_file(config); fclose(config); } } /* Enter main loop */ main_loop(); /* Shut down curses and exit */ cleanup(); return 0; }
int shell(void) { fd_set readset; FD_ZERO(&g_context.readsave); if(g_verbose) { fprintf(stderr, "Opening connection to %s port %d\n", g_context.args.ip, g_context.args.port); } if((g_context.sock = connect_to(g_context.args.ip, g_context.args.port)) < 0) { return 1; } if(g_context.args.notty == 0) { if((g_context.outsock = connect_to(g_context.args.ip, g_context.args.port+2)) < 0) { fprintf(stderr, "Could not connect to stdout channel\n"); } if((g_context.errsock = connect_to(g_context.args.ip, g_context.args.port+3)) < 0) { fprintf(stderr, "Could not connect to stderr channel\n"); } } /* if((g_context.fssock == connect_to(g_context.args.ip, g_context.args.port+8)) < 0) { fprintf(stderr, "Could not connect to fs admin channel\n"); } */ if(!g_context.args.script) { init_readline(); read_history(g_context.history_file); history_set_pos(history_length); FD_SET(STDIN_FILENO, &g_context.readsave); } /* Change to the current directory, should return our path */ execute_line("cd ."); while(!g_context.exit) { int ret; readset = g_context.readsave; ret = select(FD_SETSIZE, &readset, NULL, NULL, NULL); if(ret < 0) { if(errno == EINTR) { continue; } perror("select"); break; } else if(ret == 0) { continue; } else { if(!g_context.args.script) { if(FD_ISSET(STDIN_FILENO, &readset)) { rl_callback_read_char(); } } if(FD_ISSET(g_context.sock, &readset)) { /* Do read */ if(read_socket(g_context.sock) < 0) { close(g_context.sock); g_context.sock = -1; break; } } if((g_context.outsock >= 0) && FD_ISSET(g_context.outsock, &readset)) { if(read_outsocket(g_context.outsock) < 0) { FD_CLR(g_context.outsock, &g_context.readsave); close(g_context.outsock); g_context.outsock = -1; } } if((g_context.errsock >= 0) && FD_ISSET(g_context.errsock, &readset)) { if(read_errsocket(g_context.errsock) < 0) { FD_CLR(g_context.errsock, &g_context.readsave); close(g_context.errsock); g_context.errsock = -1; } } if((g_context.fssock >= 0) && FD_ISSET(g_context.fssock, &readset)) { if(read_fssocket(g_context.fssock) < 0) { FD_CLR(g_context.fssock, &g_context.readsave); close(g_context.fssock); g_context.fssock = -1; } } } } if(!g_context.args.script) { write_history(g_context.history_file); rl_callback_handler_remove(); } return 0; }
/* * main loop: listen on stdin (for user input) and master pty (for command output), * and try to write output_queue to master_pty (if it is not empty) * This function never returns. */ void main_loop() { int nfds; fd_set readfds; fd_set writefds; int nread; char buf[BUFFSIZE], *timeoutstr, *old_raw_prompt, *new_output_minus_prompt; int promptlen = 0; int leave_prompt_alone; sigset_t no_signals_blocked; struct timespec select_timeout, *select_timeoutptr; struct timespec immediately = { 0, 0 }; /* zero timeout when child is dead */ struct timespec wait_a_little = {0, 0xBadf00d }; /* tv_usec field will be filled in when initialising */ struct timespec *forever = NULL; wait_a_little.tv_nsec = 1000 * 1000 * wait_before_prompt; sigemptyset(&no_signals_blocked); init_readline(""); last_minute_checks(); pass_through_filter(TAG_OUTPUT,""); /* If something is wrong with filter, get the error NOW */ set_echo(FALSE); /* This will also put the terminal in CBREAK mode */ test_main(); /* ------------------------------ main loop -------------------------------*/ while (TRUE) { /* listen on both stdin and pty_fd */ FD_ZERO(&readfds); FD_SET(STDIN_FILENO, &readfds); FD_SET(master_pty_fd, &readfds); /* try to write output_queue to master_pty (but only if it is nonempty) */ FD_ZERO(&writefds); if (output_queue_is_nonempty()) FD_SET(master_pty_fd, &writefds); DPRINTF1(DEBUG_AD_HOC, "prompt_is_still_uncooked = %d", prompt_is_still_uncooked); if (command_is_dead || ignore_queued_input) { select_timeout = immediately; select_timeoutptr = &select_timeout; timeoutstr = "immediately"; } else if (prompt_is_still_uncooked) { select_timeout = wait_a_little; select_timeoutptr = &select_timeout; timeoutstr = "wait_a_little"; } else { select_timeoutptr = forever; /* NULL */ timeoutstr = "forever"; } DPRINTF1(DEBUG_TERMIO, "calling select() with timeout %s", timeoutstr); nfds = my_pselect(1 + master_pty_fd, &readfds, &writefds, NULL, select_timeoutptr, &no_signals_blocked); DPRINTF3(DEBUG_TERMIO, "select() returned %d (stdin|pty in|pty out = %03d), within_line_edit=%d", nfds, 100*(FD_ISSET(STDIN_FILENO, &readfds)?1:0) + 10*(FD_ISSET(master_pty_fd, &readfds)?1:0) + (FD_ISSET(master_pty_fd, &writefds)?1:0), within_line_edit); assert(!filter_pid || filter_is_dead || kill(filter_pid,0) == 0); assert(command_is_dead || kill(command_pid,0) == 0); /* check flags that may have been set by signal handlers */ if (filter_is_dead) filters_last_words(); /* will call myerror with last words */ if (received_WINCH) { /* received_WINCH flag means we've had a WINCH while within_line_edit was FALSE */ DPRINTF0(DEBUG_READLINE, "Starting line edit as a result of WINCH "); within_line_edit = TRUE; restore_rl_state(); received_WINCH = FALSE; continue; } if (nfds < 0) { /* exception */ if (errno == EINTR) { /* interrupted by signal */ continue; } else myerror("select received exception"); } else if (nfds == 0) { /* timeout, which can only happen when .. */ if (ignore_queued_input) { /* ... we have read all the input keystrokes that should be ignored (i.e. those that accumulated on stdin while we were calling an external editor) */ ignore_queued_input = FALSE; continue; } else if (command_is_dead) { /* ... or else, if child is dead, ... */ DPRINTF2(DEBUG_SIGNALS, "select returned 0, command_is_dead=%d, commands_exit_status=%d", command_is_dead, commands_exit_status); cleanup_rlwrap_and_exit(EXIT_SUCCESS); } else if (prompt_is_still_uncooked) { /* cooking time? */ if (we_just_got_a_signal_or_EOF) { we_just_got_a_signal_or_EOF = FALSE; /* 1. If we got a signal/EOF before cooking time, we don't need special action to preserve the cooked prompt. 2. Reset we_just_got_a_signal_or_EOF after a signal or EOF that didn't kill command */ continue; } if (!skip_rlwrap()) { /* ... or else, it is time to cook the prompt */ if (pre_given && accepted_lines == 0) { saved_rl_state.input_buffer = mysavestring(pre_given); /* stuff pre-given text into edit buffer */ saved_rl_state.point = strlen(pre_given); DPRINTF0(DEBUG_READLINE, "Starting line edit (because of -P option)"); within_line_edit = TRUE; restore_rl_state(); continue; } if (accepted_lines == 1 && one_shot_rlwrap) cleanup_rlwrap_and_exit(EXIT_SUCCESS); move_cursor_to_start_of_prompt(ERASE); /* cooked prompt may be shorter than raw prompt, hence the ERASE */ /* move and erase before cooking, as we need to move/erase according to the raw prompt */ cook_prompt_if_necessary(); DPRINTF2(DEBUG_READLINE,"After cooking, raw_prompt=%s, cooked=%s", mangle_string_for_debug_log(saved_rl_state.raw_prompt, MANGLE_LENGTH), mangle_string_for_debug_log(saved_rl_state.cooked_prompt, MANGLE_LENGTH)); my_putstr(saved_rl_state.cooked_prompt); rlwrap_already_prompted = TRUE; } prompt_is_still_uncooked = FALSE; } else { myerror("unexpected select() timeout"); } } else if (nfds > 0) { /* Hah! something to read or write */ /* -------------------------- read pty --------------------------------- */ if (FD_ISSET(master_pty_fd, &readfds)) { /* there is something to read on master pty: */ if ((nread = read(master_pty_fd, buf, BUFFSIZE - 1)) <= 0) { /* read it */ if (command_is_dead || nread == 0) { /* child is dead or has closed its stdout */ if (promptlen > 0) /* commands dying words were not terminated by \n ... */ my_putchar('\n'); /* provide the missing \n */ cleanup_rlwrap_and_exit(EXIT_SUCCESS); } else if (errno == EINTR) /* interrupted by signal ...*/ continue; /* ... don't worry */ else myerror("read error on master pty"); } completely_mirror_slaves_output_settings(); /* some programs (e.g. joe) need this. Gasp!! */ if (skip_rlwrap()) { /* Race condition here! The client may just have finished an emacs session and returned to cooked mode, while its ncurses-riddled output is stil waiting for us to be processed. */ write_patiently(STDOUT_FILENO, buf, nread, "to stdout"); DPRINTF2(DEBUG_TERMIO, "read from pty and wrote to stdout %d bytes in direct mode <%s>", nread, mangle_string_for_debug_log((buf[nread]='\0', buf), MANGLE_LENGTH)); yield(); continue; } DPRINTF2(DEBUG_TERMIO, "read %d bytes from pty into buffer: %s", nread, mangle_string_for_debug_log((buf[nread]='\0', buf), MANGLE_LENGTH)); remove_padding_and_terminate(buf, nread); write_logfile(buf); if (within_line_edit) /* client output arrives while we're editing keyboard input: */ save_rl_state(); /* temporarily disable readline and restore the screen state before readline was called */ assert(saved_rl_state.raw_prompt != NULL); /* We *always* compute the printable part and the new raw prompt, and *always* print the printable part There are four possibilities: 1. impatient before cooking. The raw prompt has been printed, write the new output after it 2. patient before cooking No raw prompt has been printed yet, don't print anything 3. impatient after cooking 3a no current prompt print the new output 3b some current prompt erase it, replace by current raw prompt and print new output 4. patient after cooking don't print anything */ /* sometimes we want to leave the prompt standing, e.g. after accepting a line, or when a signal arrived */ leave_prompt_alone = *saved_rl_state.raw_prompt == '\0' /* saved_rl_state.raw_prompt = "" in two distinct cases: when there is actually no prompt, or just after accepting a line, when the cursor is at the end of the prompt. In both cases, we dont't want to move the cursor */ || prompt_is_still_uncooked /* in this case no prompt has been displayed yet */ || command_is_dead || (we_just_got_a_signal_or_EOF && strrchr(buf, '\n')); /* a signal followed by output with a newline in it: treat it as response to user input, so leave the prompt alone */ DPRINTF3(DEBUG_READLINE, "leave_prompt_alone: %s (raw prompt: %s, prompt_is_still_uncooked: %d)", (leave_prompt_alone? "yes" : "no"), mangle_string_for_debug_log(saved_rl_state.raw_prompt, MANGLE_LENGTH), prompt_is_still_uncooked); if (!leave_prompt_alone) /* && (!impatient_prompt || !saved_rl_state.cooked_prompt)) */ move_cursor_to_start_of_prompt(ERASE); else if (we_just_got_a_signal_or_EOF) { free (saved_rl_state.raw_prompt); saved_rl_state.raw_prompt = mysavestring(""); /* prevent reprinting the prompt */ } if (impatient_prompt && !leave_prompt_alone) old_raw_prompt = mysavestring(saved_rl_state.raw_prompt); new_output_minus_prompt = process_new_output(buf, &saved_rl_state); /* chop off the part after the last newline and put this in saved_rl_state.raw_prompt (or append buf if no newline found)*/ if (impatient_prompt) { /* in impatient mode, ALL command output is passed through the OUTPUT filter, including the prompt The prompt, however, is filtered separately at cooking time and then displayed */ char *filtered = pass_through_filter(TAG_OUTPUT, buf); if(!leave_prompt_alone) { my_putstr(old_raw_prompt); free(old_raw_prompt); } my_putstr(filtered); free (filtered); rlwrap_already_prompted = TRUE; } else { my_putstr(new_output_minus_prompt); rlwrap_already_prompted = FALSE; } free(new_output_minus_prompt); prompt_is_still_uncooked = TRUE; if (within_line_edit) restore_rl_state(); yield(); /* wait for what client has to say .... */ continue; /* ... and don't attempt to process keyboard input as long as it is talking , in order to avoid re-printing the current prompt (i.e. unfinished output line) */ } /* ----------------------------- key pressed: read stdin -------------------------*/ if (FD_ISSET(STDIN_FILENO, &readfds)) { /* key pressed */ unsigned char byte_read; /* the readline function names and documentation talk about "characters" and "keys", but we're reading bytes (i.e. unsigned chars) here, and those may very well be part of a multi-byte character. Example: hebrew "aleph" in utf-8 is 0xd790; pressing this key will make us read 2 bytes 0x90 and then 0xd7, (or maybe the other way round depending on endianness??) The readline library hides all this complexity and allows one to just "pass the bytes around" */ nread = read(STDIN_FILENO, &byte_read, 1); /* read next byte of input */ assert(sizeof(unsigned char) == 1); /* gets optimised away */ if (nread <= 0) DPRINTF1(DEBUG_TERMIO, "read from stdin returned %d", nread); if (nread < 0) if (errno == EINTR) continue; else myerror("Unexpected error"); else if (nread == 0) /* EOF on stdin */ cleanup_rlwrap_and_exit(EXIT_SUCCESS); else if (ignore_queued_input) continue; /* do nothing with it*/ assert(nread == 1); DPRINTF2(DEBUG_TERMIO, "read from stdin: byte 0x%02x (%s)", byte_read, mangle_char_for_debug_log(byte_read, TRUE)); if (skip_rlwrap()) { /* direct mode, just pass it on */ /* remote possibility of a race condition here: when the first half of a multi-byte char is read in direct mode and the second half in readline mode. Oh well... */ DPRINTF0(DEBUG_TERMIO, "passing it on (in transparent mode)"); completely_mirror_slaves_terminal_settings(); /* this is of course 1 keypress too late: we should mirror the terminal settings *before* the user presses a key. (maybe using rl_event_hook??) @@@FIXME @@@ HOW?*/ write_patiently(master_pty_fd, &byte_read, 1, "to master pty"); } else { /* hand it over to readline */ if (!within_line_edit) { /* start a new line edit */ DPRINTF0(DEBUG_READLINE, "Starting line edit"); within_line_edit = TRUE; restore_rl_state(); } if (term_eof && byte_read == term_eof && strlen(rl_line_buffer) == 0) { /* hand a term_eof (usually CTRL-D) directly to command */ char *sent_EOF = mysavestring("?"); *sent_EOF = term_eof; put_in_output_queue(sent_EOF); we_just_got_a_signal_or_EOF = TRUE; free(sent_EOF); } else { rl_stuff_char(byte_read); /* stuff it back in readline's input queue */ DPRINTF0(DEBUG_TERMIO, "passing it to readline"); DPRINTF2(DEBUG_READLINE, "rl_callback_read_char() (_rl_eof_char=%d, term_eof=%d)", _rl_eof_char, term_eof); rl_callback_read_char(); } } } /* -------------------------- write pty --------------------------------- */ if (FD_ISSET(master_pty_fd, &writefds)) { flush_output_queue(); yield(); /* give slave command time to respond. If we don't do this, nothing bad will happen, but the "dialogue" on screen will be out of order */ } } /* if (ndfs > 0) */ } /* while (1) */ } /* void main_loop() */
static void init_readline_intrinsic (char *appname) { (void) init_readline (appname); }
int main(int argc, char *argv[]) { int ret = 0; char *home = getenv("HOME"), *tmp; progname = argv[0]; #ifdef HAVE_SETLOCALE setlocale(LC_ALL, ""); #endif #ifdef ENABLE_NLS bindtextdomain(PACKAGE_NAME, LOCALEDIR); textdomain(PACKAGE_NAME); #endif /* ENABLE_NLS */ ne_debug_init(stderr, 0); if (!home) { /* Show me the way to go home... */ printf(_("Environment variable $HOME needs to be set!\n")); return -1; } ne_sock_init(); memset(&session, 0, sizeof session); /* Options before rcfile, so rcfile settings can * override defaults */ tmp = ne_concat(home, "/.cadaver-locks", NULL); set_option(opt_lockstore, tmp); init_options(); init_netrc(); init_signals(); init_locking(); parse_args(argc, argv); ret = init_rcfile(); init_readline(); while (ret == 0) { char *cmd; cmd = read_command(); if (cmd == NULL) { /* Is it safe to do this... they just closed stdin, so * is it bad to write to stdout? */ putchar('\n'); ret = 1; } else { #ifdef HAVE_ADD_HISTORY if (strcmp(cmd, "") != 0) add_history(cmd); #endif ret = execute_command(cmd); free(cmd); } } if (session.connected) { close_connection(); } finish_locking(); ne_sock_exit(); return 0; }
int main(int argc, char **argv) { int opt, count = 1; pthread_t thread; /* FIXME */ ip = dstr_new("127.0.0.1"); port = 33330; while ((opt = getopt(argc, argv, "h:p:xt?")) != -1) switch (opt) { case 'h': dstr_free(ip); ip = dstr_new(optarg); count += 2; break; case 'p': port = atoi(optarg); count += 2; break; case 'x': execute = 1; count += 1; break; case 't': timestamp = 1; count += 1; break; case '?': default: usage(); } if ((tcpsock = net_tcp_nonblock_connect(ip, port, neterr, sizeof neterr)) == -1) { fprintf(stderr, "Connecting %s:%d: %s\n", ip, port, neterr); exit(1); } if (errno == EINPROGRESS) { struct pollfd wfd[1]; int res, err = 0; socklen_t errlen = sizeof err; wfd[0].fd = tcpsock; wfd[0].events = POLLOUT; /* wait for 5 seconds */ if ((res = poll(wfd, 1, 5000)) == -1) { fprintf(stderr, "Connecting %s:%d: %s\n", ip, port, strerror(errno)); exit(1); } else if (res == 0) { errno = ETIMEDOUT; fprintf(stderr, "Connecting %s:%d: %s\n", ip, port, strerror(errno)); exit(1); } if (getsockopt(tcpsock, SOL_SOCKET, SO_ERROR, &err, &errlen) == -1) { fprintf(stderr, "Connecting %s:%d: %s\n", ip, port, strerror(errno)); exit(1); } if (err) { errno = err; fprintf(stderr, "Connecting %s:%d: %s\n", ip, port, strerror(errno)); exit(1); } } if (execute && pipe(proceed_pipe) != 0) { fprintf(stderr, "Error creating pipe: %s\n", strerror(errno)); exit(1); } if (execute) { argc -= count; argv += count; if (argc > 0) { dstr cmd; int i; struct pollfd rfd[1]; if (pthread_create(&thread, NULL, recv_thread, NULL) != 0) { fprintf(stderr, "Error initializing receiver thread\n"); exit(1); } cmd = dstr_new(argv[0]); for (i = 1; i < argc; ++i) { cmd = dstr_cat(cmd, " "); cmd = dstr_cat(cmd, argv[i]); } cmd = dstr_cat(cmd, "\r\n"); net_try_write(tcpsock, cmd, dstr_length(cmd), 100, NET_NONBLOCK); /* dstr_free(cmd); */ rfd[0].fd = proceed_pipe[0]; rfd[0].events = POLLIN; if (poll(rfd, 1, -1) == -1) { fprintf(stderr, "Error polling: %s\n", strerror(errno)); exit(1); } } } else { fprintf(stdout, "XCUBE CLI, Copyright (c) 2013-2015, " "Dalian Futures Information Technology Co., Ltd.\n"); fprintf(stdout, "Type 'help' or '?' for help.\n"); init_readline(); stifle_history(100); if (pthread_create(&thread, NULL, recv_thread, NULL) != 0) { fprintf(stderr, "Error initializing receiver thread\n"); exit(1); } while (loop) { char *line; line = readline(prompt); if (rl_inited == 0) rl_inited = 1; if (line == NULL) continue; LTRIM(line); RTRIM(line); if (*line) { add_history(line); if (tcpsock == -1) execute_line(line); else { net_try_write(tcpsock, line, strlen(line), 100, NET_NONBLOCK); net_try_write(tcpsock, "\r\n", 2, 100, NET_NONBLOCK); if (!strncasecmp(line, "quit", 4)) com_quit(NULL); } } FREE(line); } } return 0; }