int input_init() { int status = CLI_RET_UNKNOWN; if (gl) { input_deinit(); } gl = new_GetLine(CLI_MAX_LINE_LEN, CLI_MAX_HIST_LEN); if (gl) { /* Try to set up a clean exit on these signals. If it fails, we'll * trudge along with a warning */ if (gl_trap_signal(gl, SIGINT, GLS_DONT_FORWARD, GLS_ABORT, EINTR) || gl_trap_signal(gl, SIGQUIT, GLS_DONT_FORWARD, GLS_ABORT, EINTR)) { fprintf(stderr, SIGHANLDER_FAILED); } tab_complete = new_WordCompletion(); if (tab_complete != NULL) { gl_customize_completion(gl, NULL, tab_completion); } else { /* Non-fatal - complain and carry on */ fprintf(stderr, "Failed to initialize tab-completion.\n"); } status = 0; } return status; }
/*....................................................................... * Create a new DemoRes object containing the resources needed by the * demo. * * Output: * return DemoRes * The new object, or NULL on error. */ static DemoRes *new_DemoRes(void) { DemoRes *res; /* The object to be returned */ /* * Allocate the container. */ res = (DemoRes *)malloc(sizeof(DemoRes)); if(!res) { fprintf(stderr, "new_DemoRes: Insufficient memory.\n"); return NULL; }; /* * Before attempting any operation that might fail, initialize the * container at least up to the point at which it can safely be passed * to del_DemoRes(). */ res->gl = NULL; res->pc = NULL; res->ppc = NULL; /* * Create the line editor, specifying a max line length of 500 bytes, * and 10000 bytes to allocate to storage of historical input lines. */ res->gl = new_GetLine(500, 10000); if(!res->gl) return del_DemoRes(res); /* * Enable text attribute formatting directives in prompt strings. */ gl_prompt_style(res->gl, GL_FORMAT_PROMPT); /* * Allocate a cache of the executable files found in the user's path. */ res->pc = new_PathCache(); if(!res->pc) return del_DemoRes(res); /* * Populate the cache with the contents of the user's path. */ if(pca_scan_path(res->pc, getenv("PATH"))) return del_DemoRes(res); /* * Arrange for susequent calls to pca_lookup_file() and pca_path_completions() * to only report files that are executable by the user. */ pca_set_check_fn(res->pc, cpl_check_exe, NULL); /* * Allocate a configuration object for use with pca_path_completions(). */ res->ppc = new_PcaPathConf(res->pc); if(!res->ppc) return del_DemoRes(res); /* * Replace the builtin filename completion callback with one which * searches for completions of executables in the user's path when * invoked on a word at the start of the path, and completes files * elsewhere. */ if(gl_customize_completion(res->gl, res, demo_cpl_fn)) return del_DemoRes(res); return res; }
int engine_interp() { #ifdef NATIVE_BUILD uu_die("native build does not support interactive mode."); #else char *selfmri; size_t sfsz; int r; extern int parens; (void) sigset(SIGINT, SIG_IGN); est->sc_gl = new_GetLine(512, 8000); if (est->sc_gl == NULL) uu_die(gettext("Out of memory.\n")); /* The longest string is "[snapname]fmri[:instname]> ". */ sfsz = 1 + max_scf_name_len + 1 + max_scf_fmri_len + 2 + max_scf_name_len + 1 + 2 + 1; selfmri = safe_malloc(sfsz); r = gl_customize_completion(est->sc_gl, NULL, complete); assert(r == 0); for (;;) { lscf_get_selection_str(selfmri, sfsz - 2); (void) strcat(selfmri, "> "); est->sc_cmd_buf = gl_get_line(est->sc_gl, selfmri, NULL, -1); if (est->sc_cmd_buf == NULL) { switch (gl_return_status(est->sc_gl)) { case GLR_SIGNAL: gl_abandon_line(est->sc_gl); continue; case GLR_EOF: break; case GLR_ERROR: uu_die(gettext("Error reading terminal: %s.\n"), gl_error_message(est->sc_gl, NULL, 0)); /* NOTREACHED */ default: #ifndef NDEBUG (void) fprintf(stderr, "%s:%d: gl_get_line() " "returned unexpected value %d.\n", __FILE__, __LINE__, gl_return_status(est->sc_gl)); #endif abort(); } break; } parens = 0; est->sc_cmd_bufsz = strlen(est->sc_cmd_buf); est->sc_cmd_bufoff = 0; est->sc_cmd_flags = SC_CMD_IACTIVE; (void) yyparse(); } free(selfmri); est->sc_gl = del_GetLine(est->sc_gl); /* returns NULL */ #endif /* NATIVE_BUILD */ return (0); }
int cexp_main1(int argc, char **argv, void (*callback)(int argc, char **argv, CexpContext ctx)) { CexpContextRec context; /* the public parts of this instance's context */ CexpContext myContext; char *line=0, *prompt=0, *tmp; char *symfile=0, *script=0; int rval=CEXP_MAIN_INVAL_ARG, quiet=0; MyGetOptCtxtRec oc={0}; /* must be initialized */ int opt; #ifdef HAVE_TECLA #define rl_context context.gl #else #define rl_context 0 #endif char optstr[]={ 'h', 'v', 's',':', 'a',':', 'p',':', #ifdef YYDEBUG 'd', #endif 'q', '\0' }; context.prompt = 0; context.parser = 0; while ((opt=mygetopt_r(argc, argv, optstr,&oc))>=0) { switch (opt) { default: fprintf(stderr,"Unknown Option %c\n",opt); case 'h': usage(argv[0]); case 'v': version(argv[0]); return 0; #ifdef YYDEBUG case 'd': cexpdebug=1; break; #endif case 'q': quiet=1; break; case 's': symfile=oc.optarg; break; case 'a': cexpBuiltinCpuArch = oc.optarg; break; case 'p': free(context.prompt); context.prompt = strdup(oc.optarg); break; } } if (argc>oc.optind) script=argv[oc.optind]; /* make sure vital code is initialized */ { static int initialized=0; cexpContextRunOnce(&initialized, cexpInit); } if (!cexpSystemModule) { if (!symfile) { /* try to find a builtin table */ if ( !cexpModuleLoad(0,0) ) fprintf(stderr,"No builtin symbol table -- need a symbol file argument\n"); } else if (!cexpModuleLoad(symfile,"SYSTEM")) fprintf(stderr,"Unable to load system symbol table\n"); if (!cexpSystemModule) { usage(argv[0]); return CEXP_MAIN_NO_SYMS; } } #ifdef USE_MDBG mdbgInit(); #endif /* initialize the public context */ context.next=0; #ifdef HAVE_BFD_DISASSEMBLER { extern void cexpDisassemblerInit(); cexpDisassemblerInit(&context.dinfo, stdout); } #endif cexpContextGetCurrent(&myContext); if (!myContext) { /* topmost frame */ #ifdef HAVE_TECLA context.gl = new_GetLine(200,2000); if (!context.gl) { fprintf(stderr,"Unable to create line editor\n"); return CEXP_MAIN_NO_MEM; } /* mute warnings about being unable to * read ~/.teclarc */ gl_configure_getline(context.gl,0,0,0); #endif /* register first instance running in this thread's context; */ cexpContextRegister(); if (!quiet) hello(); } else { #ifdef HAVE_TECLA /* re-use caller's line editor */ context.gl = myContext->gl; #endif } /* push our frame to the top */ context.next = myContext; myContext = &context; cexpContextSetCurrent(myContext); /* See if there is an ancestor with a local prompt * and inherit */ if ( !context.prompt && context.next && context.next->prompt ) context.prompt = strdup(context.next->prompt); do { if (!(context.parser=cexpCreateParserCtx(quiet ? 0 : stdout))) { fprintf(stderr,"Unable to create parser context\n"); usage(argv[0]); rval = CEXP_MAIN_NO_MEM; goto cleanup; } #ifdef HAVE_TECLA { CPL_MATCH_FN(cexpSymComplete); gl_customize_completion(context.gl, context.parser, cexpSymComplete); } #endif if (cexpSigHandlerInstaller) cexpSigHandlerInstaller(sighandler); if (!(rval=setjmp(context.jbuf))) { /* call them back to pass the jmpbuf */ if (callback) callback(argc, argv, &context); if (script) { if ( (rval = process_script(context.parser, script, quiet)) ) goto cleanup; } else { while ( (line=readline_r( checkPrompt( &context, &prompt, argc > 0 ? argv[0] : "Cexp" ), rl_context)) ) { /* skip empty lines */ if (*line) { if ( '<' == *(tmp=skipsp(line)) ) { process_script(context.parser,tmp+1,quiet); } else { /* interactively process this line */ cexpResetParserCtx(context.parser,line); cexpparse((void*)context.parser); add_history(line); } } free(line); line=0; } } } else { fprintf(stderr,"\nOops, exception caught\n"); /* setjmp passes 0: first time * 1: longjmp(buf,0) or longjmp(buf,1) * other: longjmp(buf,other) */ rval = (rval<2 ? -1 : CEXP_MAIN_KILLED); } cleanup: script=0; /* become interactive if script is killed */ free(line); line=0; free(prompt); prompt=0; cexpFreeParserCtx(context.parser); context.parser=0; } while (-1==rval); free(context.prompt); /* pop our stack context from the chained list anchored * at the running thread */ myContext = myContext->next; cexpContextSetCurrent(myContext); if ( ! myContext ) { /* we'll exit the topmost instance */ #ifdef HAVE_TECLA del_GetLine(context.gl); #endif cexpContextUnregister(); } return rval; }
/*....................................................................... * This program demonstrates how to use gl_get_line() as a line editor to * to enable users to enter input. It takes no arguments. */ int main(int argc, char *argv[]) { char *line; /* A line of input */ GetLine *gl; /* The line editor */ int major,minor,micro; /* The version number of the library */ int retval; /* * Create the line editor, specifying a max line length of 500 bytes, * and 10000 bytes to allocate to storage of historical input lines. */ gl = new_GetLine(500, 5000); if(!gl) return 1; /* setup CLI tab line completion */ retval = gl_customize_completion(gl, my_tab_context_string_array, my_tab_callback); if (retval != 0) { printf("\nError: cannot set GL tab completion"); return 1; } /* * If the user has the LC_CTYPE or LC_ALL environment variables set, * enable display of characters corresponding to the specified locale. */ (void) setlocale(LC_CTYPE, ""); /* * Lookup and display the version number of the library. */ libtecla_version(&major, &minor, µ); printf("\n Welcome to the main demo program of libtecla version %d.%d.%d\n", major, minor, micro); /* * Display an introductory banner. */ show_demo_introduction(gl); /* * Load history. */ #ifndef WITHOUT_FILE_SYSTEM (void) gl_load_history(gl, "~/.demo_history", "#"); #endif /* * Read lines of input from the user and print them to stdout. */ do { /* * Get a new line from the user. */ line = gl_get_line(gl, "$ ", NULL, 0); if(!line) break; /* * Display what was entered. */ if(printf("You entered: %s", line) < 0 || fflush(stdout)) break; /* * If the user types "exit", quit the program. */ if(strcmp(line, "exit\n")==0) break; else if(strcmp(line, "history\n")==0) gl_show_history(gl, stdout, "%N %T %H\n", 0, -1); else if(strcmp(line, "size\n")==0) { GlTerminalSize size = gl_terminal_size(gl, 80, 24); printf("Terminal size = %d columns x %d lines.\n", size.ncolumn, size.nline); } else if(strcmp(line, "clear\n")==0) { if(gl_erase_terminal(gl)) return 1; }; } while(1); /* * Save historical command lines. */ #ifndef WITHOUT_FILE_SYSTEM (void) gl_save_history(gl, "~/.demo_history", "#", -1); #endif /* * Clean up. */ gl = del_GetLine(gl); return 0; }
int interactive_loop(int fd_in, int fd_out, char *file1, char *file2) { char *pwd; char *dir = NULL; char cmd[2048]; struct sftp_conn *conn; int err, interactive; void *il = NULL; #ifdef USE_LIBEDIT EditLine *el = NULL; History *hl = NULL; HistEvent hev; if (!batchmode && isatty(STDIN_FILENO)) { if ((il = el = el_init(__progname, stdin, stdout, stderr)) == NULL) fatal("Couldn't initialise editline"); if ((hl = history_init()) == NULL) fatal("Couldn't initialise editline history"); history(hl, &hev, H_SETSIZE, 100); el_set(el, EL_HIST, history, hl); el_set(el, EL_PROMPT, prompt); el_set(el, EL_EDITOR, "emacs"); el_set(el, EL_TERMINAL, NULL); el_set(el, EL_SIGNAL, 1); el_source(el, NULL); } #else #ifdef USE_LIBTECLA GetLine *gl = NULL; if (!batchmode && isatty(STDIN_FILENO)) { if ((il = gl = new_GetLine(MAX_LINE_LEN, MAX_CMD_HIST)) == NULL) fatal("Couldn't initialize GetLine"); if (gl_customize_completion(gl, NULL, nomatch) != 0) { (void) del_GetLine(gl); fatal("Couldn't register completion function"); } } #endif /* USE_LIBTECLA */ #endif /* USE_LIBEDIT */ conn = do_init(fd_in, fd_out, copy_buffer_len, num_requests); if (conn == NULL) fatal("Couldn't initialise connection to server"); pwd = do_realpath(conn, "."); if (pwd == NULL) fatal("Need cwd"); if (file1 != NULL) { dir = xstrdup(file1); dir = make_absolute(dir, pwd); if (remote_is_dir(conn, dir) && file2 == NULL) { printf(gettext("Changing to: %s\n"), dir); snprintf(cmd, sizeof cmd, "cd \"%s\"", dir); if (parse_dispatch_command(conn, cmd, &pwd, 1) != 0) { xfree(dir); xfree(pwd); xfree(conn); return (-1); } } else { if (file2 == NULL) snprintf(cmd, sizeof cmd, "get %s", dir); else snprintf(cmd, sizeof cmd, "get %s %s", dir, file2); err = parse_dispatch_command(conn, cmd, &pwd, 1); xfree(dir); xfree(pwd); xfree(conn); return (err); } xfree(dir); } #if defined(HAVE_SETVBUF) && !defined(BROKEN_SETVBUF) setvbuf(stdout, NULL, _IOLBF, 0); setvbuf(infile, NULL, _IOLBF, 0); #else setlinebuf(stdout); setlinebuf(infile); #endif interactive = !batchmode && isatty(STDIN_FILENO); err = 0; for (;;) { char *cp; signal(SIGINT, SIG_IGN); if (il == NULL) { if (interactive) printf("sftp> "); if (fgets(cmd, sizeof(cmd), infile) == NULL) { if (interactive) printf("\n"); break; } if (!interactive) { /* Echo command */ printf("sftp> %s", cmd); if (strlen(cmd) > 0 && cmd[strlen(cmd) - 1] != '\n') printf("\n"); } } #ifdef USE_LIBEDIT else { const char *line; int count = 0; if ((line = el_gets(el, &count)) == NULL || count <= 0) { printf("\n"); break; } history(hl, &hev, H_ENTER, line); if (strlcpy(cmd, line, sizeof(cmd)) >= sizeof(cmd)) { fprintf(stderr, gettext("Error: input line too long\n")); continue; } } #else #ifdef USE_LIBTECLA else { const char *line; line = gl_get_line(gl, "sftp> ", NULL, -1); if (line != NULL) { if (strlcpy(cmd, line, sizeof(cmd)) >= sizeof(cmd)) { fprintf(stderr, gettext( "Error: input line too long\n")); continue; } } else { GlReturnStatus rtn; rtn = gl_return_status(gl); if (rtn == GLR_SIGNAL) { gl_abandon_line(gl); continue; } else if (rtn == GLR_ERROR) { fprintf(stderr, gettext( "Error reading terminal: %s/\n"), gl_error_message(gl, NULL, 0)); } break; } } #endif /* USE_LIBTECLA */ #endif /* USE_LIBEDIT */ cp = strrchr(cmd, '\n'); if (cp) *cp = '\0'; /* Handle user interrupts gracefully during commands */ interrupted = 0; signal(SIGINT, cmd_interrupt); err = parse_dispatch_command(conn, cmd, &pwd, batchmode); if (err != 0) break; }