int main(int argc, char **argv) { s7_scheme *s7; char *buffer; char response[1024]; GetLine *gl; /* The tecla line editor */ gl = new_GetLine(500, 5000); s7 = s7_init(); if (argc == 2) { fprintf(stderr, "load %s\n", argv[1]); s7_load(s7, argv[1]); } else { while (1) { buffer = gl_get_line(gl, "> ", NULL, 0); if ((buffer[0] != '\n') || (strlen(buffer) > 1)) { sprintf(response, "(write %s)", buffer); s7_eval_c_string(s7, response); fprintf(stdout, "\n"); } } gl = del_GetLine(gl); } return EXIT_SUCCESS; }
static char *readline_r(char *prompt, GetLine *gl) { char *rval=0; char *l; int len; if ((l=gl_get_line(gl,prompt,NULL,0)) && (len=strlen(l)) > 0) { rval=strdup(l); } return rval; }
void CmdManager::interact() { bool isend = false; while (!isend) { std::string cmd = gl_get_line(mgl, "> ", 0, 0); if(cmd == "exit") isend = true; else execute(cmd); } }
/*....................................................................... * Read input from the controlling terminal of the program, using * gl_get_line(), and feed it to the user's program running in a child * process, via the controller side of the pseudo-terminal. Also pass * data received from the user's program via the conroller end of * the pseudo-terminal, to stdout. * * Input: * prog const char * The name of this program. * cntrl int The file descriptor of the controller end of the * pseudo-terminal. * Output: * return int 0 - OK. * 1 - Error. */ static int pty_parent(const char *prog, int cntrl) { GetLine *gl = NULL; /* The gl_get_line() resource object */ char *line; /* An input line read from the user */ char *rbuff=NULL; /* A buffer for reading from the pseudo terminal */ /* * Allocate the gl_get_line() resource object. */ gl = new_GetLine(PTY_MAX_LINE, PTY_HIST_SIZE); if(!gl) return pty_stop_parent(1, cntrl, gl, rbuff); /* * Allocate a buffer to use to accumulate bytes read from the * pseudo-terminal. */ rbuff = (char *) malloc(PTY_MAX_READ+1); if(!rbuff) return pty_stop_parent(1, cntrl, gl, rbuff); rbuff[0] = '\0'; /* * Register an event handler to watch for data appearing from the * user's program on the controller end of the pseudo terminal. */ if(gl_watch_fd(gl, cntrl, GLFD_READ, pty_read_from_program, rbuff)) return pty_stop_parent(1, cntrl, gl, rbuff); /* * Read input lines from the user and pass them on to the user's program, * by writing to the controller end of the pseudo-terminal. */ while((line=gl_get_line(gl, rbuff, NULL, 0))) { if(pty_write_to_fd(cntrl, line, strlen(line))) return pty_stop_parent(1, cntrl, gl, rbuff); rbuff[0] = '\0'; }; return pty_stop_parent(0, cntrl, gl, rbuff); }
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 */ /* * 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; /* * 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("Welcome to the demo program of libtecla version %d.%d.%d\n", major, minor, micro); /* * Load history. */ (void) gl_load_history(gl, "~/.demo_history", "#"); /* * 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); }; } while(1); /* * Save historical command lines. */ (void) gl_save_history(gl, "~/.demo_history", "#", -1); /* * Clean up. */ gl = del_GetLine(gl); return 0; }
char * interactive_get_line(const char *prompt) { return gl_get_line(gl, prompt, NULL, 0); }
/*....................................................................... * This demo takes no arguments. It reads lines of input until the * word 'exit' is entered, or C-d is pressed. It replaces the default * tab-completion callback with one which when invoked at the start of * a line, looks up completions of commands in the user's execution * path, and when invoked in other parts of the line, reverts to * normal filename completion. Whenever a new line is entered, it * extracts the first word on the line, looks it up in the user's * execution path to see if it corresponds to a known executable file, * and if so, displays the full pathname of the file, along with the * remaining arguments. */ int main(int argc, char *argv[]) { char *line; /* A line of input */ DemoRes *res; /* The resources of the demo */ int wa,wb; /* The delimiting indexes of a word in line[] */ int major,minor,micro; /* The version number of the library */ /* * Allocate the resources needed by this demo. */ res = new_DemoRes(); if(!res) 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 path-search demo of libtecla version %d.%d.%d\n", major, minor, micro); /* * Display some introductory text, left-justifying it within the current * width of the terminal and enclosing it in a box of asterixes. */ show_demo_introduction(res->gl); /* * Read lines of input from the user and print them to stdout. */ do { /* * Get a new line from the user. */ line = gl_get_line(res->gl, "$ ", NULL, 0); if(!line) break; /* * Work out the extent of the first word in the input line, and * try to identify this as a command in the path, displaying the * full pathname of the match if found. */ if(get_word_limits(line, &wa, &wb) == 0) { char *cmd = pca_lookup_file(res->pc, line + wa, wb-wa, 0); if(cmd) { printf("Command=%s\n", cmd); printf("Arguments=%s", line+wb); } else { printf("Command not found\n"); }; }; /* * If the user types "exit", quit the program. */ if(strcmp(line, "exit\n")==0) break; } while(1); /* * Clean up. */ res = del_DemoRes(res); return 0; }
rtems_task Init( rtems_task_argument ignored ) { GetLine *gl = 0; char *symf = 0, *sysscr=0, *user_script=0, *bufp; int argc = 0; int result = 0; int no_net = 0; char *dfltSrv = 0; char *pathspec = 0; #ifdef NFS_SUPPORT MntDescRec bootmnt = { "/boot", 0, 0 }; MntDescRec homemnt = { "/home", 0, 0 }; #endif char *argv[7]={ "Cexp", /* program name */ 0, 0, 0, 0 }; rtems_libio_set_private_env(); #ifdef HAVE_PCIBIOS #if RTEMS_VERSION_ATLEAST(4,6,99) pci_initialize(); #else pcib_init(); #endif #endif #ifdef STACK_CHECKER_ON { extern void Stack_check_Initialize(); Stack_check_Initialize(); } #endif #ifdef HAVE_LIBBSPEXT bspExtInit(); #endif /* make /tmp directory */ mkTmpDir(); printf("Welcome to RTEMS GeSys\n"); printf("This system $Name: GeSys_2_4 $ was built on %s\n",system_build_date); printf("$Id: init.c,v 1.43 2008/03/22 20:36:13 guest Exp $\n"); #ifdef EARLY_CMDLINE_GET { char *cmdlinetmp; EARLY_CMDLINE_GET(&cmdlinetmp); #ifdef HAVE_LIBNETBOOT /* Let libnetboot process the command line string; all * special name=value pairs recognized by libnetboot will * be removed... */ nvramFixupBsdnetConfig(1, cmdlinetmp); #endif cmdlinePairExtract(cmdlinetmp, putenv, 1); } #endif #if defined(USE_TECLA) /* * Install our special line discipline which implements * TIOCGWINSZ */ printf("Installing TIOCGWINSZ line discipline: %s.\n", ansiTiocGwinszInstall(7) ? "failed" : "ok"); #endif /* * Make sure the time-of-day clock is at least initialized. * The dummy routine just sets the date to 1/1/2000 */ dummy_clock_init(); cexpInit(cexpExcHandlerInstall); printf("To skip initialization, press a key now..."); fflush(stdout); if ( getchar_timeout(fileno(stdin),10) > 0 ) { printf("OK; skipping to shell"); no_net = 1; argc = 1; } printf("\n"); #ifndef CDROM_IMAGE #ifndef SKIP_NETINI #define SKIP_NETINI getenv("SKIP_NETINI") #endif /* check if we have a real ifconfig (first is loopback) */ if ( !no_net && (! (SKIP_NETINI) || !BUILTIN_SYMTAB) && rtems_bsdnet_config.ifconfig ) { gesys_network_start(); } else { fprintf(stderr,"Skipping network initialization - you can do it manually\n"); fprintf(stderr,"by invoking 'gesys_network_start()' (needs BOOTP/DHCP server)\n"); argc = 1; no_net = 1; } #endif #ifndef CDROM_IMAGE if ( BOOTPFN ) { char *slash,*dot; pathspec = malloc(strlen(BOOTPFN) + (BUILTIN_SYMTAB ? strlen(SYSSCRIPT) : strlen(SYMEXT)) + 1); strcpy(pathspec, BOOTPFN); slash = strrchr(pathspec,'/'); if ( BUILTIN_SYMTAB ) { if ( slash ) strcpy(slash+1,SYSSCRIPT); else strcpy(pathspec,SYSSCRIPT); } else { dot = strrchr(pathspec,'.'); if (slash>dot) dot=0; /* substitute suffix */ if (dot) { strcpy(dot,SYMEXT); } else { strcat(pathspec,SYMEXT); } } } { char *tarvar; void *addr; int len; if ( (tarvar=getenv("TARFS")) && 2 == sscanf(tarvar,"%p:%i",&addr,&len) && len > 0 ) { mkdir("/tar",0777); rtems_tarfs_load("/tar",addr,len); } } #else { extern void *gesys_tarfs_image_start; extern unsigned long gesys_tarfs_image_size; printf("Loading TARFS... %s\n", rtems_tarfs_load("/tmp", gesys_tarfs_image_start, gesys_tarfs_image_size) ? "FAILED" : "OK"); pathspec=strdup(BUILTIN_SYMTAB ? "/tmp/"SYSSCRIPT : "/tmp/rtems.sym"); } #endif dflt_fname = "rtems.sym"; #ifdef TFTP_SUPPORT path_prefix = strdup("/TFTP/BOOTP_HOST/"); #elif defined(NFS_SUPPORT) path_prefix = strdup(":/remote/rtems:"); #elif defined(RSH_SUPPORT) path_prefix = strdup("~rtems/"); #endif getDfltSrv(&dfltSrv); #ifdef PSIM { extern int loadTarImg(int verbose, int lun); if ( !pathspec ) { loadTarImg(1, 0); pathspec = strdup("/bin/"SYSSCRIPT); } else { fprintf(stderr,"PSIM: root tarfs not loaded (pathspec was '%s')\n",pathspec); } } #endif if ( no_net && ( !pathspec || LOCAL_PATH != pathType(pathspec) ) ) goto shell_entry; /* omit prompting for the symbol file */ if ( pathspec ) goto firstTimeEntry; /* no pathspec but a builtin symtab -> * skip reading symtab / system script */ if ( BUILTIN_SYMTAB ) goto bare_entry; do { chdir("/"); #ifdef NFS_SUPPORT if ( releaseMount( &bootmnt ) ) { fprintf(stderr,"Unable to unmount /boot NFS - don't know what to do, sorry\n"); break; } #endif freeps(&symf); freeps(&user_script); if (!gl) { assert( gl = new_GetLine(LINE_LENGTH, 10*LINE_LENGTH) ); /* silence warnings about missing .teclarc */ gl_configure_getline(gl,0,0,0); } do { printf("Symbol file can be loaded by:\n"); #ifdef NFS_SUPPORT printf(" NFS: [<uid>.<gid>@][<host>]:<export_path>:<symfile_path>\n"); #endif #ifdef TFTP_SUPPORT printf(" TFTP: [/TFTP/<host_ip>]<symfile_path>\n"); #endif #ifdef RSH_SUPPORT printf(" RSH: [<host>:]~<user>/<symfile_path>\n"); #endif #ifdef USE_TECLA bufp = gl_get_line(gl, "Enter Symbol File Name: ", pathspec, ( pathspec && *pathspec ) ? strlen(pathspec) : 0 ); #else bufp = my_getline(gl, "Enter Symbol File Name: ", LINE_LENGTH); #endif } while (!bufp || !*bufp); pathspec = realloc(pathspec, strlen(bufp) + 1); strcpy(pathspec, bufp); bufp = pathspec + strlen(bufp) - 1; while ( bufp >= pathspec && ('\n' == *bufp || '\r' == *bufp) ) *bufp-- = 0; firstTimeEntry: { int fd = -1, ed = -1; char *slash; getDfltSrv( &dfltSrv ); #ifdef TFTP_SUPPORT chdir("/TFTP/BOOTP_HOST/"); #endif switch ( pathType(pathspec) ) { case LOCAL_PATH: fd = open(pathspec,O_RDONLY); if ( fd >= 0 ) symf = strdup(pathspec); break; #ifdef TFTP_SUPPORT case TFTP_PATH: fd = isTftpPath( &dfltSrv, pathspec, &ed, &symf ); break; #endif #ifdef NFS_SUPPORT case NFS_PATH: fd = isNfsPath( &dfltSrv, pathspec, &ed, &symf, &bootmnt ); break; #endif #ifdef RSH_SUPPORT case RSH_PATH: fd = rshCopy( &dfltSrv, pathspec, &symf ); break; #endif default: fprintf(stderr,"Unrecognized pathspec; maybe remote FS support is not compiled in ?\n"); break; } if ( 0==result && dfltSrv ) { /* allow the default server to be overridden by the pathspec * during the first pass (original pathspec from boot) */ theSrv = strdup(dfltSrv); } if ( (fd < 0) && !BUILTIN_SYMTAB ) { fprintf(stderr,"Unable to open symbol file (%s)\n", -11 == fd ? "not a valid pathspec" : strerror(errno)); continue; } if ( fd >= 0 ) close(fd); if ( ed >= 0 ) close(ed); freeps( &sysscr ); sysscr = strdup(SYSSCRIPT); #if defined(RSH_SUPPORT) && !defined(CDROM_IMAGE) if ( !ISONTMP(symf) ) { #endif if ( (slash = strrchr(symf,'/')) ) { int ch=*(slash+1); *(slash+1)=0; printf("Change Dir to '%s'",symf); if ( chdir(symf) ) printf(" FAILED: %s",strerror(errno)); fputc('\n',stdout); *(slash+1)=ch; } #if defined(RSH_SUPPORT) && !defined(CDROM_IMAGE) } else { char *scrspec = malloc( strlen(pathspec) + strlen(SYSSCRIPT) + 1); strcpy(scrspec, pathspec); if ( (slash = strrchr(scrspec, '/')) ) strcpy( slash+1, SYSSCRIPT ); else strcpy( scrspec, SYSSCRIPT ); getDfltSrv( &dfltSrv ); freeps( &sysscr ); if ( (fd = rshCopy( &dfltSrv, scrspec, &sysscr )) >= 0 ) { close( fd ); } else { freeps( &sysscr ); } freeps(&scrspec); } #endif bare_entry: printf("Trying symfile '%s', system script '%s'\n", BUILTIN_SYMTAB ? "BUILTIN" : symf, sysscr ? sysscr :"(NONE)"); argc = 1; #ifdef DEFAULT_CPU_ARCH_FOR_CEXP if ( DEFAULT_CPU_ARCH_FOR_CEXP && *DEFAULT_CPU_ARCH_FOR_CEXP ) { argv[argc++] = "-a"; argv[argc++] = DEFAULT_CPU_ARCH_FOR_CEXP; } #endif if ( !BUILTIN_SYMTAB ) { argv[argc++] = "-s"; argv[argc++] = symf; } if ( sysscr ) { argv[argc++] = sysscr; } shell_entry: result = argc > 1 ? cexp_main(argc, argv) : 0; if ( ISONTMP( symf ) ) unlink( symf ); if ( sysscr && ISONTMP( sysscr ) ) unlink( sysscr ); freeps(&symf); freeps(&sysscr); if (!result || CEXP_MAIN_NO_SCRIPT==result) { int rc; if (gl) { del_GetLine(gl); gl = 0; } freeps(&pathspec); /* try a user script */ if ((user_script=getenv("INIT"))) { printf("Trying user script '%s':\n",user_script); pathspec = strdup(user_script); user_script = 0; getDfltSrv(&dfltSrv); switch ( pathType( pathspec ) ) { #ifdef NFS_SUPPORT case NFS_PATH: if ( 0 == (rc = isNfsPath( &dfltSrv, pathspec, 0, &user_script, &homemnt ) ) ) { /* valid NFS path; try to mount; */ if ( !bootmnt.uidhost || strcmp( homemnt.uidhost, bootmnt.uidhost ) || !bootmnt.rpath || strcmp( homemnt.rpath , bootmnt.rpath ) ) rc = nfsMount(homemnt.uidhost, homemnt.rpath, homemnt.mntpt); } break; #endif case RSH_PATH: fprintf(stderr,"RSH download of user scripts is not supported\n"); rc = -1; break; #ifdef TFTP_SUPPORT case TFTP_PATH: rc = isTftpPath( &dfltSrv, pathspec, 0, &user_script ); break; #endif case LOCAL_PATH: /* they might refer to a path on the local FS (already mounted NFS) */ user_script = pathspec; pathspec = 0; rc = 0; break; default: fprintf(stderr,"Invalid path specifier; support for remote FS not compiled in?\n"); rc = -1; break; } freeps(&pathspec); argc = 2; if ( rc ) { fprintf(stderr,"Unable to determine filesystem for user script\n"); freeps(&user_script); argc = 1; } else { if ((slash = strrchr(user_script,'/'))) { /* chdir to where the user script resides */ int ch=*(++slash); *(slash)=0; printf("Change Dir to '%s'\n",user_script); chdir(user_script); *(slash)=ch; argv[1]=slash; } else { argv[1]=user_script; } } argc=2; } else { argc=1; } do { result=cexp_main(argc,argv); argc=1; freeps(&user_script); } while (!result || CEXP_MAIN_NO_SCRIPT==result); chdir("/"); #ifdef NFS_SUPPORT releaseMount( &homemnt ); #endif } } switch (result) { case CEXP_MAIN_NO_SYMS : fprintf(stderr,"CEXP_MAIN_NO_SYMS\n"); result = 0; break; case CEXP_MAIN_INVAL_ARG: fprintf(stderr,"CEXP_MAIN_INVAL_ARG\n"); break; case CEXP_MAIN_NO_SCRIPT: fprintf(stderr,"CEXP_MAIN_NO_SCRIPT\n"); break; case CEXP_MAIN_KILLED : fprintf(stderr,"CEXP_MAIN_KILLED\n"); break; case CEXP_MAIN_NO_MEM : fprintf(stderr,"CEXP_MAIN_NO_MEM\n"); break; default: if (result) fprintf(stderr,"unknown error\n"); } } while ( !result ); /* retry asking for a sym-filename */ if (gl) { del_GetLine(gl); gl = 0; } fprintf(stderr,"Unable to execute CEXP - suspending initialization...\n"); rtems_task_suspend(RTEMS_SELF); exit( 1 ); }
/* * Replacement lex(1) character retrieval routines. */ int engine_cmd_getc(engine_state_t *E) { if (E->sc_cmd_file != NULL) return (getc(E->sc_cmd_file)); if (E->sc_cmd_flags & SC_CMD_EOF) return (EOF); if (E->sc_cmd_bufoff < E->sc_cmd_bufsz) return (*(E->sc_cmd_buf + E->sc_cmd_bufoff++)); if (!(E->sc_cmd_flags & SC_CMD_IACTIVE)) { E->sc_cmd_flags |= SC_CMD_EOF; return (EOF); } else { #ifdef NATIVE_BUILD return (EOF); #else extern int parens; if (parens <= 0) { E->sc_cmd_flags |= SC_CMD_EOF; return (EOF); } for (;;) { E->sc_cmd_buf = gl_get_line(E->sc_gl, "> ", NULL, -1); if (E->sc_cmd_buf != NULL) break; switch (gl_return_status(E->sc_gl)) { case GLR_SIGNAL: gl_abandon_line(E->sc_gl); continue; case GLR_EOF: E->sc_cmd_flags |= SC_CMD_EOF; return (EOF); case GLR_ERROR: uu_die(gettext("Error reading terminal: %s.\n"), gl_error_message(E->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(E->sc_gl)); #endif abort(); } } E->sc_cmd_bufsz = strlen(E->sc_cmd_buf); E->sc_cmd_bufoff = 1; return (E->sc_cmd_buf[0]); #endif /* NATIVE_BUILD */ } }
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); }
char * input_get_line(const char *prompt) { return gl_get_line(gl, prompt, NULL, 0); }
/*....................................................................... * 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; }