void initedit() { editing = 1; if (!elc && histc) { elc = el_init(__progname, stdin, stdout, stderr); el_set(elc, EL_HIST, history, histc); /* use history */ el_set(elc, EL_EDITOR, "emacs"); /* default type */ el_set(elc, EL_PROMPT, cprompt); /* set the prompt * function */ el_set(elc, EL_ADDFN, "complt", "Command completion", complt_c); el_set(elc, EL_BIND, "\t", "complt", NULL); el_source(elc, NULL); /* read ~/.editrc */ el_set(elc, EL_SIGNAL, 1); } if (!eli && histi) { eli = el_init(__progname, stdin, stdout, stderr); /* again */ el_set(eli, EL_HIST, history, histi); el_set(eli, EL_EDITOR, "emacs"); el_set(eli, EL_PROMPT, iprompt); el_set(eli, EL_ADDFN, "complt", "Command completion", complt_i); el_set(eli, EL_BIND, "\t", "complt", NULL); #ifdef notyet el_set(eli, EL_ADDFN, "exit", "Exit", NULL); el_set(eli, EL_BIND, "\026", "exit", NULL); #endif el_source(eli, NULL); el_set(eli, EL_SIGNAL, 1); } }
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; }
/* * Command parser. */ static void cmdscanner(void) { struct cmd *c; static EditLine *el; static History *hist; static HistEvent he; size_t len; int num; const char *bp; num = 0; bp = NULL; el = NULL; hist = NULL; for (;;) { if (fromatty) { if (!el) { el = el_init("lpc", stdin, stdout, stderr); hist = history_init(); history(hist, &he, H_SETSIZE, 100); el_set(el, EL_HIST, history, hist); el_set(el, EL_EDITOR, "emacs"); el_set(el, EL_PROMPT, lpc_prompt); el_set(el, EL_SIGNAL, 1); el_source(el, NULL); /* * EditLine init may call 'cgetset()' to set a * capability-db meant for termcap (eg: to set * terminal type 'xterm'). Reset that now, or * that same db-information will be used for * printcap (giving us an "xterm" printer, with * all kinds of invalid capabilities...). */ cgetset(NULL); } if ((bp = el_gets(el, &num)) == NULL || num == 0) quit(0, NULL); len = (num > MAX_CMDLINE -1) ? MAX_CMDLINE -1 : num; memcpy(cmdline, bp, len); cmdline[len] = 0; history(hist, &he, H_ENTER, bp); } else { if (fgets(cmdline, MAX_CMDLINE, stdin) == 0) quit(0, NULL); if (cmdline[0] == 0 || cmdline[0] == '\n') break; } makeargv(); if (margc == 0) continue; if (el != NULL && el_parse(el, margc, (const char **)margv) != -1) continue; c = getcmd(margv[0]); if (c == (struct cmd *)-1) { printf("?Ambiguous command\n"); continue; } if (c == NULL) { printf("?Invalid command\n"); continue; } if ((c->c_opts & LPC_PRIVCMD) && getuid() && ingroup(LPR_OPER) == 0) { printf("?Privileged command\n"); continue; } /* * Two different commands might have the same generic rtn * (eg: "clean" and "tclean"), and just use different * handler routines for distinct command-setup. The handler * routine might also be set on a generic routine for * initial parameter processing. */ if (c->c_generic != 0) generic(c->c_generic, c->c_opts, c->c_handler, margc, margv); else (*c->c_handler)(margc, margv); } }
int main(int argc, char *argv[]) { EditLine *el; History *hist; chidb *db; int rc; HistEvent ev; if (argc != 2) { fprintf(stderr, "ERROR: Must specify a database file.\n"); return 1; } rc = chidb_open(argv[1], &db); if (rc != CHIDB_OK) { fprintf(stderr, "ERROR: Could not open file %s or file is not well formed.\n", argv[1]); return 1; } /* Initialize EditLine */ el = el_init(argv[0], stdin, stdout, stderr); el_set(el, EL_PROMPT, &prompt); el_set(el, EL_EDITOR, "emacs"); /* Initialize the history */ hist = history_init(); if (hist == 0) { fprintf(stderr, "ERROR: Could not initialize history.\n"); return 1; } history(hist, &ev, H_SETSIZE, 100); // 100 elements in history el_set(el, EL_HIST, history, hist); // history callback while (1) { int count; const char *sql; chidb_stmt *stmt; sql = el_gets(el, &count); if (count == 1) break; else { history(hist, &ev, H_ENTER, sql); // Add to history rc = chidb_prepare(db, sql, &stmt); if (rc == CHIDB_OK) { int numcol = chidb_column_count(stmt); for(int i = 0; i < numcol; i ++) { printf(i==0?"":COL_SEPARATOR); printf("%s", chidb_column_name(stmt,i)); } printf("\n"); while((rc = chidb_step(stmt)) == CHIDB_ROW) { for(int i = 0; i < numcol; i++) { printf(i==0?"":COL_SEPARATOR); switch(chidb_column_type(stmt,i)) { case SQL_NULL: break; case SQL_INTEGER_1BYTE: case SQL_INTEGER_2BYTE: case SQL_INTEGER_4BYTE: printf("%i", chidb_column_int(stmt,i)); break; case SQL_TEXT: printf("%s", chidb_column_text(stmt,i)); break; } } printf("\n"); } switch(rc) { case CHIDB_ECONSTRAINT: printf("ERROR: SQL statement failed because of a constraint violation.\n"); break; case CHIDB_EMISMATCH: printf("ERROR: Data type mismatch.\n"); break; case CHIDB_EMISUSE: printf("ERROR: API used incorrectly.\n"); break; case CHIDB_EIO: printf("ERROR: An I/O error has occurred when accessing the file.\n"); break; } rc = chidb_finalize(stmt); if(rc == CHIDB_EMISUSE) printf("API used incorrectly.\n"); } else if (rc == CHIDB_EINVALIDSQL) printf("SQL syntax error.\n"); else if (rc == CHIDB_ENOMEM) printf("ERROR: Could not allocate memory.\n"); } } history_end(hist); el_end(el); return 0; }
/* * Set history and editing status. Called whenever the status may * have changed (figures out what to do). */ void histedit() { #define editing (Eflag || Vflag) if (iflag) { if (!hist) { /* * turn history on */ INTOFF; hist = history_init(); INTON; if (hist != NULL) sethistsize(); else out2str("sh: can't initialize history\n"); } if (editing && !el && isatty(0)) { /* && isatty(2) ??? */ /* * turn editing on */ INTOFF; if (el_in == NULL) el_in = fdopen(0, "r"); if (el_out == NULL) el_out = fdopen(2, "w"); if (el_in == NULL || el_out == NULL) goto bad; el = el_init(arg0, el_in, el_out); if (el != NULL) { if (hist) el_set(el, EL_HIST, history, hist); el_set(el, EL_PROMPT, getprompt); } else { bad: out2str("sh: can't initialize editing\n"); } INTON; } else if (!editing && el) { INTOFF; el_end(el); el = NULL; INTON; } if (el) { if (Vflag) el_set(el, EL_EDITOR, "vi"); else if (Eflag) el_set(el, EL_EDITOR, "emacs"); } } else { INTOFF; if (el) { /* no editing if not interactive */ el_end(el); el = NULL; } if (hist) { history_end(hist); hist = NULL; } INTON; } }
int cmdloop(void) { char *line; const char *elline; int cmd_argc, rval = 0, known; #define scratch known char **cmd_argv; struct cmdtable *cmdp; History *hist; EditLine *elptr; HistEvent he; curinode = ginode(UFS_ROOTINO); curinum = UFS_ROOTINO; printactive(0); hist = history_init(); history(hist, &he, H_SETSIZE, 100); /* 100 elt history buffer */ elptr = el_init("fsdb", stdin, stdout, stderr); el_set(elptr, EL_EDITOR, "emacs"); el_set(elptr, EL_PROMPT, prompt); el_set(elptr, EL_HIST, history, hist); el_source(elptr, NULL); while ((elline = el_gets(elptr, &scratch)) != NULL && scratch != 0) { if (debug) printf("command `%s'\n", elline); history(hist, &he, H_ENTER, elline); line = strdup(elline); cmd_argv = crack(line, &cmd_argc); /* * el_parse returns -1 to signal that it's not been handled * internally. */ if (el_parse(elptr, cmd_argc, (const char **)cmd_argv) != -1) continue; if (cmd_argc) { known = 0; for (cmdp = cmds; cmdp->cmd; cmdp++) { if (!strcmp(cmdp->cmd, cmd_argv[0])) { if ((cmdp->flags & FL_WR) == FL_WR && nflag) warnx("`%s' requires write access", cmd_argv[0]), rval = 1; else if (cmd_argc >= cmdp->minargc && cmd_argc <= cmdp->maxargc) rval = (*cmdp->handler)(cmd_argc, cmd_argv); else if (cmd_argc >= cmdp->minargc && (cmdp->flags & FL_ST) == FL_ST) { strcpy(line, elline); cmd_argv = recrack(line, &cmd_argc, cmdp->maxargc); rval = (*cmdp->handler)(cmd_argc, cmd_argv); } else rval = argcount(cmdp, cmd_argc, cmd_argv); known = 1; break; } } if (!known) warnx("unknown command `%s'", cmd_argv[0]), rval = 1; } else rval = 0; free(line); if (rval < 0) /* user typed "quit" */ return 0; if (rval) warnx("rval was %d", rval); } el_end(elptr); history_end(hist); return rval; }
/* * Set history and editing status. Called whenever the status may * have changed (figures out what to do). */ void histedit(void) { #define editing (Eflag || Vflag) if (iflag) { if (!hist) { /* * turn history on */ INTOFF; hist = history_init(); INTON; if (hist != NULL) sethistsize(histsizeval()); else out2fmt_flush("sh: can't initialize history\n"); } if (editing && !el && isatty(0)) { /* && isatty(2) ??? */ /* * turn editing on */ char *term; INTOFF; if (el_in == NULL) el_in = fdopen(0, "r"); if (el_err == NULL) el_err = fdopen(1, "w"); if (el_out == NULL) el_out = fdopen(2, "w"); if (el_in == NULL || el_err == NULL || el_out == NULL) goto bad; term = lookupvar("TERM"); if (term) setenv("TERM", term, 1); else unsetenv("TERM"); el = el_init(arg0, el_in, el_out, el_err); if (el != NULL) { if (hist) el_set(el, EL_HIST, history, hist); el_set(el, EL_PROMPT, getprompt); // el_set(el, EL_ADDFN, "sh-complete", // "Filename completion", // _el_fn_sh_complete); el_set(el, EL_ADDFN, "sh-complete", "Filename completion", _el_fn_complete); } else { bad: out2fmt_flush("sh: can't initialize editing\n"); } INTON; } else if (!editing && el) { INTOFF; el_end(el); el = NULL; INTON; } if (el) { if (Vflag) el_set(el, EL_EDITOR, "vi"); else if (Eflag) el_set(el, EL_EDITOR, "emacs"); el_set(el, EL_BIND, "^I", "sh-complete", NULL); el_source(el, NULL); } } else { INTOFF; if (el) { /* no editing if not interactive */ el_end(el); el = NULL; } if (hist) { history_end(hist); hist = NULL; } INTON; } }
int main(int argc, char * const argv[]) { Boolean doDNS = FALSE; Boolean doNet = FALSE; Boolean doNWI = FALSE; Boolean doPrefs = FALSE; Boolean doProxy = FALSE; Boolean doReach = FALSE; Boolean doSnap = FALSE; char *get = NULL; char *log = NULL; extern int optind; int opt; int opti; const char *prog = argv[0]; char *renew = NULL; char *set = NULL; char *nc_cmd = NULL; InputRef src; int timeout = 15; /* default timeout (in seconds) */ char *wait = NULL; Boolean watch = FALSE; int xStore = 0; /* non dynamic store command line options */ /* process any arguments */ while ((opt = getopt_long(argc, argv, "dDvprt:w:W", longopts, &opti)) != -1) switch(opt) { case 'd': _sc_debug = TRUE; _sc_log = FALSE; /* enable framework logging */ break; case 'D': doDispatch = TRUE; break; case 'v': _sc_verbose = TRUE; _sc_log = FALSE; /* enable framework logging */ break; case 'p': enablePrivateAPI = TRUE; break; case 'r': doReach = TRUE; xStore++; break; case 't': timeout = atoi(optarg); break; case 'w': wait = optarg; xStore++; break; case 'W': watch = TRUE; break; case 0: if (strcmp(longopts[opti].name, "dns") == 0) { doDNS = TRUE; xStore++; } else if (strcmp(longopts[opti].name, "get") == 0) { get = optarg; xStore++; } else if (strcmp(longopts[opti].name, "nc") == 0) { nc_cmd = optarg; xStore++; } else if (strcmp(longopts[opti].name, "net") == 0) { doNet = TRUE; xStore++; } else if (strcmp(longopts[opti].name, "nwi") == 0) { doNWI = TRUE; xStore++; } else if (strcmp(longopts[opti].name, "prefs") == 0) { doPrefs = TRUE; xStore++; } else if (strcmp(longopts[opti].name, "proxy") == 0) { doProxy = TRUE; xStore++; } else if (strcmp(longopts[opti].name, "renew") == 0) { renew = optarg; xStore++; } else if (strcmp(longopts[opti].name, "set") == 0) { set = optarg; xStore++; } else if (strcmp(longopts[opti].name, "snapshot") == 0) { doSnap = TRUE; xStore++; } else if (strcmp(longopts[opti].name, "log") == 0) { log = optarg; xStore++; } else if (strcmp(longopts[opti].name, "user") == 0) { username = CFStringCreateWithCString(NULL, optarg, kCFStringEncodingUTF8); } else if (strcmp(longopts[opti].name, "password") == 0) { password = CFStringCreateWithCString(NULL, optarg, kCFStringEncodingUTF8); } else if (strcmp(longopts[opti].name, "secret") == 0) { sharedsecret = CFStringCreateWithCString(NULL, optarg, kCFStringEncodingUTF8); } break; case '?': default : usage(prog); } argc -= optind; argv += optind; if (xStore > 1) { // if we are attempting to process more than one type of request usage(prog); } /* are we checking (or watching) the reachability of a host/address */ if (doReach) { if (argc < 1) { usage(prog); } if (watch) { do_watchReachability(argc, (char **)argv); } else { do_checkReachability(argc, (char **)argv); } /* NOT REACHED */ } /* are we waiting on the presense of a dynamic store key */ if (wait) { do_wait(wait, timeout); /* NOT REACHED */ } /* are we looking up the DNS configuration */ if (doDNS) { do_showDNSConfiguration(argc, (char **)argv); /* NOT REACHED */ } if (doNWI) { do_nwi(argc, (char**)argv); /* NOT REACHED */ } if (doSnap) { if (!enablePrivateAPI #if !TARGET_IPHONE_SIMULATOR || (geteuid() != 0) #endif // !TARGET_IPHONE_SIMULATOR ) { usage(prog); } do_open(0, NULL); /* open the dynamic store */ do_snapshot(argc, (char**)argv); exit(0); } /* are we looking up a preference value */ if (get) { if (argc != 2) { if (findPref(get) < 0) { usage(prog); } } else { /* need to go back one argument * for the filename */ argc++; argv--; } do_getPref(get, argc, (char **)argv); /* NOT REACHED */ } /* are we looking up the proxy configuration */ if (doProxy) { do_showProxyConfiguration(argc, (char **)argv); /* NOT REACHED */ } /* are we changing a preference value */ if (set) { if (findPref(set) < 0) { usage(prog); } do_setPref(set, argc, (char **)argv); /* NOT REACHED */ } /* verbose log */ if (log != NULL) { if (strcasecmp(log, "IPMonitor")) { usage(prog); } do_log(log, argc, (char * *)argv); /* NOT REACHED */ } /* network connection commands */ if (nc_cmd) { if (find_nc_cmd(nc_cmd) < 0) { usage(prog); } do_nc_cmd(nc_cmd, argc, (char **)argv, watch); /* NOT REACHED */ } if (doNet) { /* if we are going to be managing the network configuration */ commands = (cmdInfo *)commands_net; nCommands = nCommands_net; if (!getenv("ENABLE_EXPERIMENTAL_SCUTIL_COMMANDS")) { usage(prog); } do_net_init(); /* initialization */ do_net_open(argc, (char **)argv); /* open prefs */ } else if (doPrefs) { /* if we are going to be managing the network configuration */ commands = (cmdInfo *)commands_prefs; nCommands = nCommands_prefs; do_dictInit(0, NULL); /* start with an empty dictionary */ do_prefs_init(); /* initialization */ do_prefs_open(argc, (char **)argv); /* open prefs */ } else { /* if we are going to be managing the dynamic store */ commands = (cmdInfo *)commands_store; nCommands = nCommands_store; do_dictInit(0, NULL); /* start with an empty dictionary */ do_open(0, NULL); /* open the dynamic store */ } /* are we trying to renew a DHCP lease */ if (renew != NULL) { do_renew(renew); /* NOT REACHED */ } /* allocate command input stream */ src = (InputRef)CFAllocatorAllocate(NULL, sizeof(Input), 0); src->fp = stdin; src->el = NULL; src->h = NULL; if (isatty(fileno(src->fp))) { int editmode = 1; HistEvent ev; struct termios t; if (tcgetattr(fileno(src->fp), &t) != -1) { if ((t.c_lflag & ECHO) == 0) { editmode = 0; } } src->el = el_init(prog, src->fp, stdout, stderr); src->h = history_init(); (void)history(src->h, &ev, H_SETSIZE, INT_MAX); el_set(src->el, EL_HIST, history, src->h); if (!editmode) { el_set(src->el, EL_EDITMODE, 0); } el_set(src->el, EL_EDITOR, "emacs"); el_set(src->el, EL_PROMPT, prompt); el_source(src->el, NULL); if ((el_get(src->el, EL_EDITMODE, &editmode) != -1) && editmode != 0) { el_set(src->el, EL_SIGNAL, 1); } else { history_end(src->h); src->h = NULL; el_end(src->el); src->el = NULL; } } while (TRUE) { Boolean ok; ok = process_line(src); if (!ok) { break; } } /* close the socket, free resources */ if (src->h) history_end(src->h); if (src->el) el_end(src->el); (void)fclose(src->fp); CFAllocatorDeallocate(NULL, src); exit (EX_OK); // insure the process exit status is 0 return 0; // ...and make main fit the ANSI spec. }
void EditLine::setPrompt(PromptF f) { mPromptCallback = f; el_set(el, EL_PROMPT, editLinePromptCallback); }
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; EditLine *el = NULL; #ifdef USE_LIBEDIT History *hl = NULL; HistEvent hev; extern char *__progname; if (!batchmode && isatty(STDIN_FILENO)) { if ((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); } #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("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); 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); 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 (el == 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"); } } else { #ifdef USE_LIBEDIT 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, "Error: input line too long\n"); continue; } #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; } xfree(pwd); #ifdef USE_LIBEDIT if (el != NULL) el_end(el); #endif /* USE_LIBEDIT */ /* err == 1 signifies normal "quit" exit */ return (err >= 0 ? 0 : -1); }
int main(int argc, char *argv[]) { esl_handle_t handle = {{0}}; int count = 0; const char *line = NULL; char cmd_str[1024] = ""; cli_profile_t *profile = NULL; #ifndef WIN32 char hfile[512] = "/tmp/fs_cli_history"; char cfile[512] = "/etc/fs_cli.conf"; char dft_cfile[512] = "/etc/fs_cli.conf"; #else char hfile[512] = "fs_cli_history"; char cfile[512] = "fs_cli.conf"; char dft_cfile[512] = "fs_cli.conf"; #endif char *home = getenv("HOME"); /* Vars for optargs */ int opt; static struct option options[] = { {"help", 0, 0, 'h'}, {"no-color", 0, 0, 'n'}, {"host", 1, 0, 'H'}, {"port", 1, 0, 'P'}, {"user", 1, 0, 'u'}, {"password", 1, 0, 'p'}, {"debug", 1, 0, 'd'}, {"execute", 1, 0, 'x'}, {"loglevel", 1, 0, 'l'}, {"log-uuid", 0, 0, 'U'}, {"quiet", 0, 0, 'q'}, {"batchmode", 0, 0, 'b'}, {"retry", 0, 0, 'r'}, {"interrupt", 0, 0, 'i'}, {"reconnect", 0, 0, 'R'}, {"timeout", 1, 0, 't'}, {"connect-timeout", 1, 0, 'T'}, {0, 0, 0, 0} }; char temp_host[128]; int argv_host = 0; char temp_user[256]; char temp_pass[128]; int argv_pass = 0 ; int argv_user = 0 ; int temp_port = 0; int argv_port = 0; int temp_log = -1; int argv_error = 0; int argv_exec = 0; char argv_command[1024] = ""; char argv_loglevel[128] = ""; int argv_log_uuid = 0; int argv_quiet = 0; int argv_batch = 0; int loops = 2, reconnect = 0; char *ccheck; #ifdef WIN32 feature_level = 0; #else feature_level = 1; #endif if ((ccheck = getenv("FS_CLI_COLOR"))) { is_color = esl_true(ccheck); } strncpy(internal_profile.host, "127.0.0.1", sizeof(internal_profile.host)); strncpy(internal_profile.pass, "ClueCon", sizeof(internal_profile.pass)); strncpy(internal_profile.name, "internal", sizeof(internal_profile.name)); internal_profile.port = 8021; set_fn_keys(&internal_profile); esl_set_string(internal_profile.prompt_color, prompt_color); esl_set_string(internal_profile.input_text_color, input_text_color); esl_set_string(internal_profile.output_text_color, output_text_color); if (home) { snprintf(hfile, sizeof(hfile), "%s/.fs_cli_history", home); snprintf(cfile, sizeof(cfile), "%s/.fs_cli_conf", home); } signal(SIGINT, handle_SIGINT); #ifdef SIGTSTP signal(SIGTSTP, handle_SIGINT); #endif #ifdef SIGQUIT signal(SIGQUIT, handle_SIGQUIT); #endif esl_global_set_default_logger(6); /* default debug level to 6 (info) */ for(;;) { int option_index = 0; opt = getopt_long(argc, argv, "H:P:S:u:p:d:x:l:Ut:T:qrRhib?n", options, &option_index); if (opt == -1) break; switch (opt) { case 'H': esl_set_string(temp_host, optarg); argv_host = 1; break; case 'P': temp_port= atoi(optarg); if (temp_port > 0 && temp_port < 65536) { argv_port = 1; } else { printf("ERROR: Port must be in range 1 - 65535\n"); argv_error = 1; } break; case 'n': is_color = 0; break; case 'u': esl_set_string(temp_user, optarg); argv_user = 1; break; case 'p': esl_set_string(temp_pass, optarg); argv_pass = 1; break; case 'd': temp_log=atoi(optarg); if (temp_log < 0 || temp_log > 7) { printf("ERROR: Debug level should be 0 - 7.\n"); argv_error = 1; } else { esl_global_set_default_logger(temp_log); } break; case 'x': argv_exec = 1; esl_set_string(argv_command, optarg); break; case 'l': esl_set_string(argv_loglevel, optarg); break; case 'U': argv_log_uuid = 1; break; case 'q': argv_quiet = 1; break; case 'b': argv_batch = 1; break; case 'i': allow_ctl_c = 1; break; case 'r': loops += 120; break; case 'R': reconnect = 1; break; case 't': timeout = atoi(optarg); break; case 'T': connect_timeout = atoi(optarg); break; case 'h': case '?': print_banner(stdout, is_color); usage(argv[0]); return 0; } } if (argv_error) { printf("\n"); return usage(argv[0]); } read_config(dft_cfile, cfile); if (optind < argc) { get_profile(argv[optind], &profile); } if (!profile) { if (get_profile("default", &profile)) { esl_log(ESL_LOG_DEBUG, "profile default does not exist using builtin profile\n"); profile = &internal_profile; } } if (temp_log < 0 ) { esl_global_set_default_logger(profile->debug); } if (argv_host) { esl_set_string(profile->host, temp_host); } if (argv_port) { profile->port = (esl_port_t)temp_port; } if (argv_user) { esl_set_string(profile->user, temp_user); } if (argv_pass) { esl_set_string(profile->pass, temp_pass); } if (argv_batch || profile->batch_mode) { profile->batch_mode = 1; feature_level=0; } if (*argv_loglevel) { esl_set_string(profile->loglevel, argv_loglevel); profile->quiet = 0; } if (argv_log_uuid) { profile->log_uuid = 1; } esl_log(ESL_LOG_DEBUG, "Using profile %s [%s]\n", profile->name, profile->host); esl_set_string(prompt_color, profile->prompt_color); esl_set_string(input_text_color, profile->input_text_color); esl_set_string(output_text_color, profile->output_text_color); if (argv_host) { if (argv_port && profile->port != 8021) { snprintf(bare_prompt_str, sizeof(bare_prompt_str), "freeswitch@%s:%u@%s> ", profile->host, profile->port, profile->name); } else { snprintf(bare_prompt_str, sizeof(bare_prompt_str), "freeswitch@%s@%s> ", profile->host, profile->name); } } else { snprintf(bare_prompt_str, sizeof(bare_prompt_str), "freeswitch@%s> ", profile->name); } bare_prompt_str_len = (int)strlen(bare_prompt_str); if (feature_level) { snprintf(prompt_str, sizeof(prompt_str), "%s%s%s", prompt_color, bare_prompt_str, input_text_color); } else { snprintf(prompt_str, sizeof(prompt_str), "%s", bare_prompt_str); } connect: connected = 0; while (--loops > 0) { memset(&handle, 0, sizeof(handle)); if (esl_connect_timeout(&handle, profile->host, profile->port, profile->user, profile->pass, connect_timeout)) { esl_global_set_default_logger(7); esl_log(ESL_LOG_ERROR, "Error Connecting [%s]\n", handle.err); if (loops == 1) { if (!argv_exec) usage(argv[0]); return -1; } else { sleep_s(1); esl_log(ESL_LOG_INFO, "Retrying\n"); } } else { connected = 1; if (temp_log < 0 ) { esl_global_set_default_logger(profile->debug); } else { esl_global_set_default_logger(temp_log); } break; } } if (argv_exec) { const char *err = NULL; snprintf(cmd_str, sizeof(cmd_str), "api %s\nconsole_execute: true\n\n", argv_command); if (timeout) { esl_status_t status = esl_send_recv_timed(&handle, cmd_str, timeout); if (status != ESL_SUCCESS) { printf("Request timed out.\n"); esl_disconnect(&handle); return -2; } } else { esl_send_recv(&handle, cmd_str); } if (handle.last_sr_event) { if (handle.last_sr_event->body) { printf("%s\n", handle.last_sr_event->body); } else if ((err = esl_event_get_header(handle.last_sr_event, "reply-text")) && !strncasecmp(err, "-err", 3)) { printf("Error: %s!\n", err + 4); } } esl_disconnect(&handle); return 0; } global_handle = &handle; global_profile = profile; if (esl_thread_create_detached(msg_thread_run, &handle) != ESL_SUCCESS) { printf("Error starting thread!\n"); esl_disconnect(&handle); return 0; } #ifdef HAVE_EDITLINE el = el_init(__FILE__, stdin, stdout, stderr); el_set(el, EL_PROMPT, &prompt); el_set(el, EL_EDITOR, "emacs"); el_set(el, EL_ADDFN, "f1-key", "F1 KEY PRESS", console_f1key); el_set(el, EL_ADDFN, "f2-key", "F2 KEY PRESS", console_f2key); el_set(el, EL_ADDFN, "f3-key", "F3 KEY PRESS", console_f3key); el_set(el, EL_ADDFN, "f4-key", "F4 KEY PRESS", console_f4key); el_set(el, EL_ADDFN, "f5-key", "F5 KEY PRESS", console_f5key); el_set(el, EL_ADDFN, "f6-key", "F6 KEY PRESS", console_f6key); el_set(el, EL_ADDFN, "f7-key", "F7 KEY PRESS", console_f7key); el_set(el, EL_ADDFN, "f8-key", "F8 KEY PRESS", console_f8key); el_set(el, EL_ADDFN, "f9-key", "F9 KEY PRESS", console_f9key); el_set(el, EL_ADDFN, "f10-key", "F10 KEY PRESS", console_f10key); el_set(el, EL_ADDFN, "f11-key", "F11 KEY PRESS", console_f11key); el_set(el, EL_ADDFN, "f12-key", "F12 KEY PRESS", console_f12key); el_set(el, EL_ADDFN, "EOF-key", "EOF (^D) KEY PRESS", console_eofkey); el_set(el, EL_BIND, "\033OP", "f1-key", NULL); el_set(el, EL_BIND, "\033OQ", "f2-key", NULL); el_set(el, EL_BIND, "\033OR", "f3-key", NULL); el_set(el, EL_BIND, "\033OS", "f4-key", NULL); el_set(el, EL_BIND, "\033OT", "f5-key", NULL); el_set(el, EL_BIND, "\033OU", "f6-key", NULL); el_set(el, EL_BIND, "\033OV", "f7-key", NULL); el_set(el, EL_BIND, "\033OW", "f8-key", NULL); el_set(el, EL_BIND, "\033OX", "f9-key", NULL); el_set(el, EL_BIND, "\033OY", "f10-key", NULL); el_set(el, EL_BIND, "\033OZ", "f11-key", NULL); el_set(el, EL_BIND, "\033O[", "f12-key", NULL); el_set(el, EL_BIND, "\033[11~", "f1-key", NULL); el_set(el, EL_BIND, "\033[12~", "f2-key", NULL); el_set(el, EL_BIND, "\033[13~", "f3-key", NULL); el_set(el, EL_BIND, "\033[14~", "f4-key", NULL); el_set(el, EL_BIND, "\033[15~", "f5-key", NULL); el_set(el, EL_BIND, "\033[17~", "f6-key", NULL); el_set(el, EL_BIND, "\033[18~", "f7-key", NULL); el_set(el, EL_BIND, "\033[19~", "f8-key", NULL); el_set(el, EL_BIND, "\033[20~", "f9-key", NULL); el_set(el, EL_BIND, "\033[21~", "f10-key", NULL); el_set(el, EL_BIND, "\033[23~", "f11-key", NULL); el_set(el, EL_BIND, "\033[24~", "f12-key", NULL); el_set(el, EL_BIND, "\004", "EOF-key", NULL); el_set(el, EL_ADDFN, "ed-complete", "Complete argument", complete); el_set(el, EL_BIND, "^I", "ed-complete", NULL); /* "Delete" key. */ el_set(el, EL_BIND, "\033[3~", "ed-delete-next-char", NULL); if (!(myhistory = history_init())) { esl_log(ESL_LOG_ERROR, "history could not be initialized\n"); goto done; } history(myhistory, &ev, H_SETSIZE, 800); el_set(el, EL_HIST, history, myhistory); history(myhistory, &ev, H_LOAD, hfile); el_source(el, NULL); #endif #ifdef WIN32 hStdout = GetStdHandle(STD_OUTPUT_HANDLE); if (hStdout != INVALID_HANDLE_VALUE && GetConsoleScreenBufferInfo(hStdout, &csbiInfo)) { wOldColorAttrs = csbiInfo.wAttributes; } #endif if (!argv_quiet && !profile->quiet) { snprintf(cmd_str, sizeof(cmd_str), "log %s\n\n", profile->loglevel); esl_send_recv(&handle, cmd_str); } if (global_profile->batch_mode) { setvbuf(stdout, (char*)NULL, _IONBF, 0); } print_banner(stdout, is_color); esl_log(ESL_LOG_INFO, "FS CLI Ready.\nenter /help for a list of commands.\n"); output_printf("%s\n", handle.last_sr_reply); while (running > 0) { int r; #ifdef HAVE_EDITLINE if (!(global_profile->batch_mode)) { line = el_gets(el, &count); } else { #endif line = basic_gets(&count); #ifdef HAVE_EDITLINE } #endif if (count > 1 && !esl_strlen_zero(line)) { char *p, *cmd = strdup(line); assert(cmd); if ((p = strrchr(cmd, '\r')) || (p = strrchr(cmd, '\n'))) { *p = '\0'; } #ifdef HAVE_EDITLINE history(myhistory, &ev, H_ENTER, line); #endif if ((r = process_command(&handle, cmd))) { running = r; } free(cmd); clear_el_buffer(); } sleep_ms(1); } if (running < 0 && reconnect) { running = 1; loops = 120; goto connect; } #ifdef HAVE_EDITLINE done: history(myhistory, &ev, H_SAVE, hfile); history_end(myhistory); el_end(el); #endif esl_disconnect(&handle); global_handle = NULL; thread_running = 0; return 0; }
static PyObject * redisplay(EditLineObject *self, PyObject *noarg) { el_set(self->el, EL_REFRESH); Py_RETURN_NONE; }
static int elObj_init(EditLineObject *self, PyObject *args, PyObject *kwds) { PyObject *pyfd; int fd_in, fd_out, fd_err, rv; char *name; if (!PyArg_ParseTuple(args, "sOOO", &name, &self->pyin, &self->pyout, &self->pyerr)) return -1; /* need to ensure I own the refs */ Py_INCREF(self->pyin); Py_INCREF(self->pyout); Py_INCREF(self->pyerr); /* check that there is fileno() on each stream */ pyfd = PyObject_CallMethod(self->pyin, "fileno", NULL); fd_in = (int) PyLong_AsLong(pyfd); self->fin = fdopen(fd_in, "r"); pyfd = PyObject_CallMethod(self->pyout, "fileno", NULL); fd_out = (int) PyLong_AsLong(pyfd); self->fout = fdopen(fd_out, "w"); pyfd = PyObject_CallMethod(self->pyerr, "fileno", NULL); fd_err = (int) PyLong_AsLong(pyfd); self->ferr = fdopen(fd_err, "w"); //printf("in: %d out:%d err:%d\n", fd_in, fd_out, fd_err); /* save the name */ self->name = PyMem_RawMalloc(strlen(name)+1); if (self->name == NULL) { PyErr_NoMemory(); goto error; } strcpy(self->name, name); /* prepare the default prompt */ #define MY_INIT_PROMPT "EL> " self->prompt = PyMem_RawMalloc(strlen(MY_INIT_PROMPT)+1); if (self->prompt == NULL) { PyErr_NoMemory(); goto error; } strcpy(self->prompt, MY_INIT_PROMPT); self->prompt_esc = '\1'; /* prepare the right-prompt to be empty */ self->rprompt = PyMem_RawMalloc(2); if (self->rprompt == NULL) { PyErr_NoMemory(); goto error; } self->rprompt[0] = '\0'; self->rprompt[1] = '\0'; self->rprompt_esc = '\1'; self->_debug = 0; self->signature = 0xDEADBEEFUL; /* prepare the scratch pad */ self->buffer_size = 2048; self->buffer = PyMem_RawMalloc(self->buffer_size); if (self->buffer == NULL) { PyErr_NoMemory(); goto error; } /* create the history manager */ self->hist = history_init(); if (self->hist == NULL) { PyErr_SetString(PyExc_ValueError, "history init failed"); goto error; } /* setup the history buffer */ rv = history(self->hist, &self->ev, H_SETSIZE, 100); if (rv < 0) { PyErr_SetString(PyExc_ValueError, "setting history size failed"); goto error; } rv = history(self->hist, &self->ev, H_SETUNIQUE, 0x1); if (rv < 0) { PyErr_SetString(PyExc_ValueError, "setting history uniqueness failed"); goto error; } /* create the tokenizer */ self->tok = tok_init(NULL); if (self->tok == NULL) { PyErr_SetString(PyExc_ValueError, "tokenizer init failed"); goto error; } /* create the libedit instance */ self->el = el_init(name,self->fin, self->fout, self->ferr); if (self->el == NULL) { PyErr_SetString(PyExc_ValueError, "libedit init failed"); goto error; } /* general init ... */ el_set(self->el, EL_EDITOR, "emacs"); el_set(self->el, EL_SIGNAL, 1); el_set(self->el, EL_PROMPT_ESC, _prompt, self->prompt_esc); el_set(self->el, EL_RPROMPT_ESC, _rprompt, self->rprompt_esc); el_set(self->el, EL_HIST, history, self->hist); el_set(self->el, EL_ADDFN, "ed-complete", "Complete argument", el_complete); el_set(self->el, EL_BIND, "^I", "ed-complete", NULL); el_source(self->el, NULL); self->begidx = PyLong_FromLong(0L); self->endidx = PyLong_FromLong(0L); /* leave myself a breadcrumb... */ el_set(self->el, EL_CLIENTDATA, self); return 0; error: _cleanup_editlineobject(self); return -1; }
char * input(int *cmd) { #define MAXLINE 80 static EditLine *el = NULL; #if __FreeBSD_version >= 500000 HistEvent he; #endif static History *hist = NULL; const char *bp = NULL; static char buf[MAXLINE]; char *p; int num = 0; int len; do { if (verbose) { if (!el) { el = el_init("ufmcontrol", stdin, stdout #if __FreeBSD_version >= 500000 , stderr #endif ); hist = history_init(); history(hist, #if __FreeBSD_version >= 500000 &he, #endif H_SETSIZE, 100); el_set(el, EL_HIST, history, hist); el_set(el, EL_EDITOR, "emacs"); el_set(el, EL_PROMPT, ufmcontrol_prompt); el_set(el, EL_SIGNAL, 1); el_source(el, NULL); } if ((bp = el_gets(el, &num)) == NULL || num == 0) { *cmd = CMD_QUIT; (void)fprintf(stderr, "\r\n"); return (0); } len = (num > MAXLINE) ? MAXLINE : num; memcpy(buf, bp, len); buf[len] = 0; history(hist, #if __FreeBSD_version >= 500000 &he, #endif H_ENTER, bp); #undef MAXLINE } else { if (! fgets (buf, sizeof (buf), stdin)) { *cmd = CMD_QUIT; (void)fprintf(stderr, "\r\n"); return (0); } } p = parse (buf, cmd); } while (! p); return (p); }
static void *editline_threadproc(void *arg) { HistEvent ev; EditLine *el; /* This holds all the state for our line editor */ History *myhistory; /* This holds the info for our history */ voglperf_data_t *data = (voglperf_data_t *)arg; /* Initialize the EditLine state to use our prompt function and emacs style editing. */ el = el_init("voglperfun", stdin, stdout, stderr); el_set(el, EL_PROMPT, &prompt); el_set(el, EL_EDITOR, "vi"); /* Initialize the history */ myhistory = history_init(); if (myhistory == 0) { fprintf(stderr, "history could not be initialized\n"); return (void *)-1; } /* Set the size of the history */ history(myhistory, &ev, H_SETSIZE, 800); /* This sets up the call back functions for history functionality */ el_set(el, EL_HIST, history, myhistory); pthread_cleanup_push(cleanup_handler, el); while (!(data->flags & F_QUIT)) { /* count is the number of characters read. line is a const char* of our command line with the tailing \n */ int count; const char *line = el_gets(el, &count); /* In order to use our history we have to explicitly add commands to the history */ if (count > 0) { size_t line_len = strlen(line); while ((line_len > 0) && isspace(line[line_len - 1])) line_len--; if (line_len) { std::string command(line, line_len); pthread_mutex_lock(&data->lock); data->thread_commands.push_back(command); pthread_mutex_unlock(&data->lock); history(myhistory, &ev, H_ENTER, line); } } } pthread_cleanup_pop(0); /* Clean up our memory */ history_end(myhistory); el_end(el); return NULL; }
void EditLine::setHistory(History& h) { el_set(el, EL_HIST, history, &h); }
int main(int argc, char **argv) { struct sockaddr *sock; struct sockaddr_un ifsun; int fd, len, display, save_errno; unsigned TimeoutVal; struct sigaction act, oact; char *sockname = HONEYD_SOCK; #ifdef HAVE_LIBEDIT EditLine *edit; History *hist; HistEvent hev = { 0, "" }; #endif const char *l; int ch; display = REC_SHOW; TimeoutVal = 2; while ((ch = getopt(argc, argv, "t:v")) != -1) { switch (ch) { case 't': TimeoutVal = (unsigned)atoi(optarg); break; case 'v': display += REC_VERBOSE; break; default: usage(); } } argc -= optind; argv += optind; if (argc > 0) sockname = argv[0]; sock = (struct sockaddr *)&ifsun; memset(&ifsun, '\0', sizeof (ifsun)); #ifdef HAVE_SUN_LEN ifsun.sun_len = strlen(sockname); if (ifsun.sun_len > sizeof (ifsun.sun_path) - 1) errx(1, "%s: path too long", sockname); #endif /* HAVE_SUN_LEN */ ifsun.sun_family = AF_UNIX; strlcpy(ifsun.sun_path, sockname, sizeof(ifsun.sun_path)); if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) errx(2, "cannot create local domain socket"); TimedOut = 0; if (TimeoutVal) { act.sa_handler = Timeout; sigemptyset(&act.sa_mask); act.sa_flags = 0; sigaction(SIGALRM, &act, &oact); alarm(TimeoutVal); } if (connect(fd, sock, sizeof (ifsun)) == -1) { if (TimeoutVal) { save_errno = errno; alarm(0); sigaction(SIGALRM, &oact, 0); errno = save_errno; } if (TimedOut) warnx("timeout: cannot connect to socket %s", sockname); else warn("cannot connect to socket %s", sockname); close(fd); return 3; } if (TimeoutVal) { alarm(0); sigaction(SIGALRM, &oact, 0); } /* Get Prompt ? */ receive(fd, display); #ifdef HAVE_LIBEDIT hist = history_init(); # ifdef H_SETSIZE history(hist, &hev, H_SETSIZE, 20); edit = el_init("honeydctl", stdin, stdout, stderr); # else /* !H_SETSIZE */ history(hist, H_EVENT, 20); edit = el_init("honeydctl", stdin, stdout); # endif el_source(edit, NULL); el_set(edit, EL_PROMPT, getprompt); el_set(edit, EL_EDITOR, "emacs"); el_set(edit, EL_SIGNAL, 1); el_set(edit, EL_HIST, history, (const char *)hist); #endif #ifdef HAVE_LIBEDIT while ((l = smartgets(edit, &len, fd))) { if (len > 1) # ifdef H_SETSIZE history(hist, &hev, H_ENTER, l); # else history(hist, H_ENTER, l); # endif /* H_SETSIZE */ #else /* !HAVE_LIBEDIT */ while ((l = smartgets(&len, fd))) { char line[128]; if (len > 0) { add_history((char *)l); snprintf(line, sizeof(line), "%s\n", l); l = line; len++; } #endif if(write(fd, l, len) == -1) { errx(EXIT_FAILURE, "Failed to write to file descriptor"); } if (receive(fd, display) != 0) break; } fprintf(stderr, "Connection closed\n"); #ifdef HAVE_LIBEDIT el_end(edit); history_end(hist); #endif close(fd); return 0; }
void interact( const char *const argv_0) { EditLine *const el = el_init(argv_0, stdin, stdout, stderr); el_set(el, EL_PROMPT, &prompt); el_set(el, EL_EDITOR, "emacs"); History *const hist = history_init(); if (!hist) { fprintf(stderr, "Could not initalize history\n"); exit(EXIT_FAILURE); } HistEvent ev; history(hist, &ev, H_SETSIZE, 100); el_set(el, EL_HIST, history, hist); const pid_t child_pid = _gen_child(); verbose_printf("child process is %d\n", child_pid); if (options.verbose) help(); char buf[PAGE_SIZE]; size_t buf_sz = 0; int end = 0, child_died = 0; struct proc_info_t info = {}; ARCH_INIT_PROC_INFO(info); ptrace_launch(child_pid); ptrace_cont(child_pid, &info); ptrace_reap(child_pid, &info); display(&info); for (;;) { int count; const char *const line = el_gets(el, &count); if (count == -1) { perror("el_gets"); exit(EXIT_FAILURE); } // count is 0 == ^d if (!count || strcasestr(line, ".quit") || strcasestr(line, ".exit")) break; // We have input, add it to the our history history(hist, &ev, H_ENTER, line); // If we start with a ., we have a command if (line[0] == '.') { if (strcasestr(line, "help")) { help(); continue; } if (strcasestr(line, "info")) { display(&info); continue; } if (strcasestr(line, "showmap")) { char cmd[PATH_MAX] = { 0 }; snprintf(cmd, sizeof(cmd), "cat /proc/%d/maps", child_pid); if (system(cmd)) fprintf(stderr, "sh: %s failed\n", cmd); continue; } if (strcasestr(line, "read")) { ui_read(child_pid, line); continue; } if (strcasestr(line, "write")) { continue; } if (strcasestr(line, "begin")) { in_block = 1; continue; } // Note the lack of continue. Need to fall through... if (strcasestr(line, "end")) { in_block = 0; end = 1; } } if (buf_sz + count > sizeof(buf)) { printf("Buffer full (max: 0x%lx), please use '.end'\n", sizeof(buf)); continue; } // Since we fell through, we want to avoid adding adding .end to our buffer if (!end) { memcpy(buf + buf_sz, line, count); buf_sz += count; } if (!in_block) { verbose_printf("Trying to assemble(%zu):\n%s", buf_sz, buf); uint8_t bytecode[PAGE_SIZE]; const size_t bytecode_sz = assemble(bytecode, sizeof(bytecode), buf, buf_sz); memset(buf, 0, sizeof(buf)); buf_sz = 0; end = 0; verbose_printf("Got asm(%zu):\n", bytecode_sz); verbose_dump(bytecode, bytecode_sz, -1); if (!bytecode_sz) { fprintf(stderr, "'%s' assembled to 0 length bytecode\n", buf); continue; } ptrace_write(child_pid, (void *)options.start, bytecode, bytecode_sz); ptrace_reset(child_pid, options.start); ptrace_cont(child_pid, &info); if (ptrace_reap(child_pid, &info)) { child_died = 1; break; } display(&info); } } if (!child_died) ptrace_detatch(child_pid, &info); printf("\n"); history_end(hist); el_end(el); }
void setterm(const char *term) { if (rootshell && el != NULL && term != NULL) el_set(el, EL_TERMINAL, term); }
void cmd_getnum(const unsigned long int idx, const unsigned long int spice) { xmlNodePtr db_node = NULL; xmlChar *key = NULL, *value = NULL, *value_nl = NULL, *line = NULL, *line_randomed = NULL, *tmp = NULL; unsigned long int lines = 0, line_req = 1, value_len = 0, line_len = 0, line_randomed_len = 0, erase_len = 0, i = 0; char rc = 0; char *rand_str = NULL; char **fork_argv = NULL; int child; int pipefd[2]; db_node = find_key(idx); if (db_node) { key = xmlGetProp(db_node, BAD_CAST "name"); value = xmlGetProp(db_node, BAD_CAST "value"); value_nl = parse_newlines(value, 0); xmlFree(value); value = NULL; value_len = xmlStrlen(value_nl); /* count how many (new)lines are in the string */ for (i=0; i < value_len; i++) if (value_nl[i] == '\n') lines++; lines++; #ifndef _READLINE /* clear the prompt temporarily */ if (el_set(e, EL_PROMPT, el_prompt_null) != 0) { perror("ERROR: el_set(EL_PROMPT)"); } if (el_set(e, EL_UNBUFFERED, 1) != 0) { perror("ERROR: el_set(EL_UNBUFFERED)"); xmlFree(key); key = NULL; xmlFree(value_nl); value_nl = NULL; return; } #else rl_prep_terminal(1); #endif while (rc != 'q' && rc != 4) { /* quit for 'q' or EOT */ if (batchmode) puts(""); printf("[%s] ", key); /* print the key */ /* if multiline, prefix the line with a line number */ if (lines > 1) printf("[%lu/%lu] ", line_req, lines); /* get a line out from the value */ line = get_line(value_nl, line_req); line_len = xmlStrlen(line); if (spice > 0) { /* if random padding is requested */ line_randomed_len = line_len + line_len * spice + spice + 1; line_randomed = calloc(1, line_randomed_len); malloc_check(line_randomed); /* begin with the random string */ rand_str = get_random_str(spice, 1); if (!rand_str) { xmlFree(key); key = NULL; xmlFree(value_nl); value_nl = NULL; xmlFree(line); line = NULL; free(line_randomed); line_randomed = NULL; return; } (void) strlcat((char *)line_randomed, rand_str, line_randomed_len); free(rand_str); rand_str = NULL; for (i = 0; i < line_len; i++) { /* append a character from the line */ tmp = xmlUTF8Strsub(line, i, 1); (void) strlcat((char *)line_randomed, (const char *)tmp, line_randomed_len); xmlFree(tmp); tmp = NULL; /* append a random string */ rand_str = get_random_str(spice, 1); if (!rand_str) { xmlFree(key); key = NULL; xmlFree(value_nl); value_nl = NULL; xmlFree(line); line = NULL; free(line_randomed); line_randomed = NULL; return; } (void) strlcat((char *)line_randomed, rand_str, line_randomed_len); free(rand_str); rand_str = NULL; } line_randomed[line_randomed_len - 1] = '\0'; xmlFree(line); line = NULL; line = line_randomed; } printf("%s", line); #ifdef _READLINE rl_redisplay(); #endif if (batchmode) { rc = 'q'; puts(""); } else { /* this is the prompt, after displaying the value */ #ifndef _READLINE el_getc(e, &rc); #else rc = rl_read_key(); #endif /* erase (overwrite) the previously written value with spaces */ printf("\r"); erase_len = ERASE_LEN; for (i = 0; i < erase_len; i++) putchar(' '); printf("\r"); /* process the keypress */ switch (rc) { /* line forward */ case 'f': case 'n': case 'j': case '+': case ' ': case '>': case ']': case '}': case 10: /* editline */ case 13: /* readline */ if (line_req < lines) line_req++; break; /* line backward */ case 'b': case 'p': case 'k': case '-': case '<': case '[': case '{': case 8: if (line_req - 1 > 0) line_req--; break; /* jump to the requested line */ case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': if ((unsigned char)(rc - 48) <= lines) line_req = rc - 48; break; case 't': /* This is duplicated in cmd_clipboard.c */ /* Copy value to tmux paste buffer */ switch (child = fork()) { case -1: perror("\nERROR: Couldn't fork(2) for tmux(1)"); break; case 0: /* Child */ close(0); /* This is also needed for Editline's UNBUFFERED mode to continue to work properly. */ close(1); if (bio_chain) BIO_free_all(bio_chain); if (db_params.db_file) { if (close(db_params.db_file) == -1) { perror("ERROR: child: close(database file)"); exit(EXIT_FAILURE); } else { db_params.db_file = -1; } } fork_argv = malloc(5 * sizeof(char *)); malloc_check(fork_argv); fork_argv[0] = "tmux"; fork_argv[1] = "set-buffer"; fork_argv[2] = "--"; fork_argv[3] = (char *) line; fork_argv[4] = NULL; if (execvp(fork_argv[0], fork_argv) == -1) dprintf(STDERR_FILENO, "ERROR: tmux: %s\n", strerror(errno)); quit(EXIT_FAILURE); break; default: /* Parent */ rc = 'q'; break; } break; case 'x': case 'X': /* This is duplicated in cmd_clipboard.c */ /* Copy value to X11 clipboard, using xclip(1) */ pipe(pipefd); switch (child = fork()) { case -1: perror("\nERROR: Couldn't fork(2) for xclip(1)"); break; case 0: /* Child */ close(0); /* This is also needed for Editline's UNBUFFERED mode to continue to work properly. */ close(1); close(pipefd[1]); if (bio_chain) BIO_free_all(bio_chain); if (db_params.db_file) { if (close(db_params.db_file) == -1) { perror("ERROR: child: close(database file)"); exit(EXIT_FAILURE); } else { db_params.db_file = -1; } } fork_argv = malloc(4 * sizeof(char *)); malloc_check(fork_argv); fork_argv[0] = "xclip"; fork_argv[1] = "-selection"; if (rc == 'x') { fork_argv[2] = "primary"; } else if (rc == 'X') { fork_argv[2] = "clipboard"; } fork_argv[3] = NULL; /* stdin becomes the read end of the pipe in the child, * and the exec'd process will have the same environment. */ dup2(pipefd[0], 0); if (execvp(fork_argv[0], fork_argv) == -1) dprintf(STDERR_FILENO, "ERROR: xclip: %s\n", strerror(errno)); quit(EXIT_FAILURE); break; default: /* Parent */ /* Write the value to the pipe's write end, which will * appear in the child's stdin (pipe's read end). */ close(pipefd[0]); write(pipefd[1], line, line_len); close(pipefd[1]); rc = 'q'; break; } break; default: break; } } xmlFree(line); line = NULL; } xmlFree(key); key = NULL; xmlFree(value_nl); value_nl = NULL; #ifndef _READLINE /* re-enable the default prompt */ if (el_set(e, EL_PROMPT, prompt_str) != 0) { perror("ERROR: el_set(EL_PROMPT)"); } el_set(e, EL_UNBUFFERED, 0); #else rl_deprep_terminal(); #endif } else puts("Invalid index!"); } /* cmd_getnum() */
int main(int argc, char *argv[]) { EditLine *el = NULL; int num; const char *buf; Tokenizer *tok; #if 0 int lastevent = 0; #endif int ncontinuation; History *hist; HistEvent ev; (void) setlocale(LC_CTYPE, ""); (void) signal(SIGINT, sig); (void) signal(SIGQUIT, sig); (void) signal(SIGHUP, sig); (void) signal(SIGTERM, sig); hist = history_init(); /* Init the builtin history */ /* Remember 100 events */ history(hist, &ev, H_SETSIZE, 100); tok = tok_init(NULL); /* Initialize the tokenizer */ /* Initialize editline */ el = el_init(*argv, stdin, stdout, stderr); el_set(el, EL_EDITOR, "vi"); /* Default editor is vi */ el_set(el, EL_SIGNAL, 1); /* Handle signals gracefully */ el_set(el, EL_PROMPT_ESC, prompt, '\1');/* Set the prompt function */ /* Tell editline to use this history interface */ el_set(el, EL_HIST, history, hist); /* Add a user-defined function */ el_set(el, EL_ADDFN, "ed-complete", "Complete argument", complete); /* Bind tab to it */ el_set(el, EL_BIND, "^I", "ed-complete", NULL); /* * Bind j, k in vi command mode to previous and next line, instead * of previous and next history. */ el_set(el, EL_BIND, "-a", "k", "ed-prev-line", NULL); el_set(el, EL_BIND, "-a", "j", "ed-next-line", NULL); /* * Source the user's defaults file. */ el_source(el, NULL); while ((buf = el_gets(el, &num)) != NULL && num != 0) { int ac, cc, co; #ifdef DEBUG int i; #endif const char **av; const LineInfo *li; li = el_line(el); #ifdef DEBUG (void) fprintf(stderr, "==> got %d %s", num, buf); (void) fprintf(stderr, " > li `%.*s_%.*s'\n", (li->cursor - li->buffer), li->buffer, (li->lastchar - 1 - li->cursor), (li->cursor >= li->lastchar) ? "" : li->cursor); #endif if (gotsig) { (void) fprintf(stderr, "Got signal %d.\n", gotsig); gotsig = 0; el_reset(el); } if (!continuation && num == 1) continue; ac = cc = co = 0; ncontinuation = tok_line(tok, li, &ac, &av, &cc, &co); if (ncontinuation < 0) { (void) fprintf(stderr, "Internal error\n"); continuation = 0; continue; } #ifdef DEBUG (void) fprintf(stderr, " > nc %d ac %d cc %d co %d\n", ncontinuation, ac, cc, co); #endif #if 0 if (continuation) { /* * Append to the right event in case the user * moved around in history. */ if (history(hist, &ev, H_SET, lastevent) == -1) err(1, "%d: %s", lastevent, ev.str); history(hist, &ev, H_ADD , buf); } else { history(hist, &ev, H_ENTER, buf); lastevent = ev.num; } #else /* Simpler */ history(hist, &ev, continuation ? H_APPEND : H_ENTER, buf); #endif continuation = ncontinuation; ncontinuation = 0; if (continuation) continue; #ifdef DEBUG for (i = 0; i < ac; i++) { (void) fprintf(stderr, " > arg# %2d ", i); if (i != cc) (void) fprintf(stderr, "`%s'\n", av[i]); else (void) fprintf(stderr, "`%.*s_%s'\n", co, av[i], av[i] + co); } #endif if (strcmp(av[0], "history") == 0) { int rv; switch (ac) { case 1: for (rv = history(hist, &ev, H_LAST); rv != -1; rv = history(hist, &ev, H_PREV)) (void) fprintf(stdout, "%4d %s", ev.num, ev.str); break; case 2: if (strcmp(av[1], "clear") == 0) history(hist, &ev, H_CLEAR); else goto badhist; break; case 3: if (strcmp(av[1], "load") == 0) history(hist, &ev, H_LOAD, av[2]); else if (strcmp(av[1], "save") == 0) history(hist, &ev, H_SAVE, av[2]); break; badhist: default: (void) fprintf(stderr, "Bad history arguments\n"); break; } } else if (el_parse(el, ac, av) == -1) { switch (fork()) { case 0: execvp(av[0], (char *const *)__UNCONST(av)); perror(av[0]); _exit(1); /*NOTREACHED*/ break; case -1: perror("fork"); break; default: if (wait(&num) == -1) perror("wait"); (void) fprintf(stderr, "Exit %x\n", num); break; } } tok_reset(tok); } el_end(el); tok_end(tok); history_end(hist); return (0); }
void cmd_cnew(const char *e_line, command *commands) { xmlNodePtr db_node = NULL; xmlChar *name = NULL, *description = NULL; char *created = NULL; char *line = NULL; unsigned long int idx = 0; #ifndef _READLINE int e_count = 0; #endif /* this is unused in this function */ commands = NULL; if ((idx = count_elements(keychain->parent->children)) >= ITEMS_MAX - 1) { dprintf(STDERR_FILENO, "ERROR: Can not create the keychain: maximum number of keychains reached, %lu.\n", ITEMS_MAX - 1); return; } line = strdup(e_line); malloc_check(line); strtok(line, " "); /* remove the command from the line */ name = BAD_CAST strtok(NULL, " "); /* assign the command's first parameter (name) */ if (name) { name = xmlStrdup(name); } else { /* if we didn't get a name as a parameter */ strlcpy(prompt_context, "NEW keychain name", sizeof(prompt_context)); #ifndef _READLINE /* disable history temporarily */ if (el_set(e, EL_HIST, history, NULL) != 0) { perror("ERROR: el_set(EL_HIST)"); } e_line = el_gets(e, &e_count); /* re-enable history */ if (el_set(e, EL_HIST, history, eh) != 0) { perror("ERROR: el_set(EL_HIST)"); } #else e_line = readline(prompt_str()); #endif if (e_line) { name = xmlStrdup(BAD_CAST e_line); malloc_check(name); #ifndef _READLINE name[xmlStrlen(name) - 1] = '\0'; /* remove the newline */ #else free((char *)e_line); e_line = NULL; #endif } else { #ifndef _READLINE el_reset(e); #endif strlcpy(prompt_context, "", sizeof(prompt_context)); return; } } free(line); line = NULL; strlcpy(prompt_context, "NEW keychain description", sizeof(prompt_context)); #ifndef _READLINE /* disable history temporarily */ if (el_set(e, EL_HIST, history, NULL) != 0) { perror("ERROR: el_set(EL_HIST)"); } e_line = el_gets(e, &e_count); /* re-enable history */ if (el_set(e, EL_HIST, history, eh) != 0) { perror("ERROR: el_set(EL_HIST)"); } #else e_line = readline(prompt_str()); #endif if (e_line) { description = xmlStrdup(BAD_CAST e_line); malloc_check(description); #ifndef _READLINE description[xmlStrlen(description) - 1] = '\0'; /* remove the newline */ #else free((char *)e_line); e_line = NULL; #endif } else { #ifndef _READLINE el_reset(e); #endif strlcpy(prompt_context, "", sizeof(prompt_context)); return; } strlcpy(prompt_context, "", sizeof(prompt_context)); db_node = find_keychain(name, 1); if (!db_node) { created = malloc(TIME_MAXLEN); malloc_check(created); snprintf(created, TIME_MAXLEN, "%d", (int)time(NULL)); /* XXX reloading a saved document inserts a 'text' element between each visible node (why?) * so we must reproduce this */ xmlAddChild(keychain->parent, xmlNewText(BAD_CAST "\t")); db_node = xmlNewChild(keychain->parent, NULL, BAD_CAST "keychain", NULL); xmlNewProp(db_node, BAD_CAST "name", name); xmlNewProp(db_node, BAD_CAST "created", BAD_CAST created); xmlNewProp(db_node, BAD_CAST "modified", BAD_CAST created); xmlNewProp(db_node, BAD_CAST "description", description); /* make the XML document prettttyyy */ xmlAddChild(db_node, xmlNewText(BAD_CAST "\n\t")); printf("Created keychain: %lu. %s\n", idx, name); /* XXX reloading a saved document inserts a 'text' element between each visible node (why?) * so we must reproduce this */ xmlAddChild(keychain->parent, xmlNewText(BAD_CAST "\n")); db_params.dirty = 1; } else { printf("Keychain '%s' already exists!\n", name); } xmlFree(name); name = NULL; xmlFree(description); description = NULL; free(created); created = NULL; } /* cmd_cnew() */
int noit_console_handler(eventer_t e, int mask, void *closure, struct timeval *now) { int newmask = EVENTER_READ | EVENTER_EXCEPTION; int keep_going; acceptor_closure_t *ac = closure; noit_console_closure_t ncct = ac->service_ctx; if(mask & EVENTER_EXCEPTION || (ncct && ncct->wants_shutdown)) { socket_error: /* Exceptions cause us to simply snip the connection */ /* This removes the log feed which is important to do before calling close */ eventer_remove_fd(e->fd); if(ncct) noit_console_closure_free(ncct); if(ac) acceptor_closure_free(ac); e->opset->close(e->fd, &newmask, e); return 0; } if(!ac->service_ctx) { ncct = ac->service_ctx = noit_console_closure_alloc(); } if(!ncct->initialized) { ncct->e = e; if(allocate_pty(&ncct->pty_master, &ncct->pty_slave)) { nc_printf(ncct, "Failed to open pty: %s\n", strerror(errno)); ncct->wants_shutdown = 1; goto socket_error; } else { int i; const char *line_protocol; HistEvent ev; ncct->hist = history_init(); history(ncct->hist, &ev, H_SETSIZE, 500); ncct->el = el_init("noitd", ncct->pty_master, NULL, e->fd, e, e->fd, e); if(!ncct->el) goto socket_error; if(el_set(ncct->el, EL_USERDATA, ncct)) { noitL(noit_error, "Cannot set userdata on noitedit session\n"); goto socket_error; } if(el_set(ncct->el, EL_EDITOR, "emacs")) noitL(noit_error, "Cannot set emacs mode on console\n"); if(el_set(ncct->el, EL_HIST, history, ncct->hist)) noitL(noit_error, "Cannot set history on console\n"); el_set(ncct->el, EL_ADDFN, "noit_complete", "auto completion functions for noit", noit_edit_complete); el_set(ncct->el, EL_BIND, "^I", "noit_complete", NULL); for(i=EL_NUM_FCNS; i < ncct->el->el_map.nfunc; i++) { if(ncct->el->el_map.func[i] == noit_edit_complete) { ncct->noit_edit_complete_cmdnum = i; break; } } if(!noit_hash_retr_str(ac->config, "line_protocol", strlen("line_protocol"), &line_protocol)) { line_protocol = NULL; } if(line_protocol && !strcasecmp(line_protocol, "telnet")) { ncct->telnet = noit_console_telnet_alloc(ncct); ncct->output_cooker = nc_telnet_cooker; } noit_console_state_init(ncct); } snprintf(ncct->feed_path, sizeof(ncct->feed_path), "console/%d", e->fd); noit_log_stream_new(ncct->feed_path, "noit_console", ncct->feed_path, ncct, NULL); noit_console_motd(e, ac, ncct); ncct->initialized = 1; } /* If we still have data to send back to the client, this will take * care of that */ if(noit_console_continue_sending(ncct, &newmask) < 0) { if(ncct->wants_shutdown || errno != EAGAIN) goto socket_error; return newmask | EVENTER_EXCEPTION; } for(keep_going=1 ; keep_going ; ) { int len, plen; char sbuf[4096]; const char *buffer; keep_going = 0; buffer = el_gets(ncct->el, &plen); if(!el_eagain(ncct->el)) { if(!buffer) { buffer = "exit"; plen = 4; nc_write(ncct, "\n", 1); } keep_going++; } len = e->opset->read(e->fd, sbuf, sizeof(sbuf)-1, &newmask, e); if(len == 0 || (len < 0 && errno != EAGAIN)) { eventer_remove_fd(e->fd); if(ncct) noit_console_closure_free(ncct); if(ac) acceptor_closure_free(ac); e->opset->close(e->fd, &newmask, e); return 0; } if(len > 0) { keep_going++; sbuf[len] = '\0'; if(ncct->telnet) { noit_console_telnet_telrcv(ncct, sbuf, len); ptyflush(ncct); } else { int written; written = write(ncct->pty_slave, sbuf, len); if(written <= 0) goto socket_error; assert(written == len); } } if(buffer) { char *cmd_buffer; cmd_buffer = malloc(plen+1); memcpy(cmd_buffer, buffer, plen); /* chomp */ cmd_buffer[plen] = '\0'; if(cmd_buffer[plen-1] == '\n') cmd_buffer[plen-1] = '\0'; noitL(noit_debug, "IN[%d]: '%s'\n", plen, cmd_buffer); noit_console_dispatch(e, cmd_buffer, ncct); free(cmd_buffer); } if(noit_console_continue_sending(ncct, &newmask) == -1) { if(ncct->wants_shutdown || errno != EAGAIN) goto socket_error; return newmask | EVENTER_EXCEPTION; } if(ncct->wants_shutdown) goto socket_error; } return newmask | EVENTER_EXCEPTION; }
int main(int argc, char *argv[]) { esl_handle_t handle = {{0}}; int count = 0; const char *line = NULL; char cmd_str[1024] = ""; esl_config_t cfg; cli_profile_t *profile = NULL; int rv = 0; #ifndef WIN32 char hfile[512] = "/etc/fs_cli_history"; char cfile[512] = "/etc/fs_cli.conf"; char dft_cfile[512] = "/etc/fs_cli.conf"; #else char hfile[512] = "fs_cli_history"; char cfile[512] = "fs_cli.conf"; char dft_cfile[512] = "fs_cli.conf"; #endif char *home = getenv("HOME"); /* Vars for optargs */ int opt; static struct option options[] = { {"help", 0, 0, 'h'}, {"host", 1, 0, 'H'}, {"port", 1, 0, 'P'}, {"user", 1, 0, 'u'}, {"password", 1, 0, 'p'}, {"debug", 1, 0, 'd'}, {"execute", 1, 0, 'x'}, {"loglevel", 1, 0, 'l'}, {"quiet", 0, 0, 'q'}, {0, 0, 0, 0} }; char temp_host[128]; int argv_host = 0; char temp_user[256]; char temp_pass[128]; int argv_pass = 0 ; int argv_user = 0 ; int temp_port = 0; int argv_port = 0; int temp_log = -1; int argv_error = 0; int argv_exec = 0; char argv_command[256] = ""; char argv_loglevel[128] = ""; int argv_quiet = 0; strncpy(internal_profile.host, "127.0.0.1", sizeof(internal_profile.host)); strncpy(internal_profile.pass, "ClueCon", sizeof(internal_profile.pass)); strncpy(internal_profile.name, "internal", sizeof(internal_profile.name)); internal_profile.port = 8021; set_fn_keys(&internal_profile); if (home) { snprintf(hfile, sizeof(hfile), "%s/.fs_cli_history", home); snprintf(cfile, sizeof(cfile), "%s/.fs_cli_conf", home); } signal(SIGINT, handle_SIGINT); #ifdef SIGQUIT signal(SIGQUIT, handle_SIGQUIT); #endif esl_global_set_default_logger(6); /* default debug level to 6 (info) */ for(;;) { int option_index = 0; opt = getopt_long(argc, argv, "H:U:P:S:u:p:d:x:l:qh?", options, &option_index); if (opt == -1) break; switch (opt) { case 'H': esl_set_string(temp_host, optarg); argv_host = 1; break; case 'P': temp_port= atoi(optarg); if (temp_port > 0 && temp_port < 65536){ argv_port = 1; } else { printf("ERROR: Port must be in range 1 - 65535\n"); argv_error = 1; } break; case 'u': esl_set_string(temp_user, optarg); argv_user = 1; break; case 'p': esl_set_string(temp_pass, optarg); argv_pass = 1; break; case 'd': temp_log=atoi(optarg); if (temp_log < 0 || temp_log > 7){ printf("ERROR: Debug level should be 0 - 7.\n"); argv_error = 1; } else { esl_global_set_default_logger(temp_log); } break; case 'x': argv_exec = 1; esl_set_string(argv_command, optarg); break; case 'l': esl_set_string(argv_loglevel, optarg); break; case 'q': argv_quiet = 1; break; case 'h': case '?': print_banner(stdout); usage(argv[0]); return 0; default: opt = 0; } } if (argv_error){ printf("\n"); return usage(argv[0]); } if (!(rv = esl_config_open_file(&cfg, cfile))) { rv = esl_config_open_file(&cfg, dft_cfile); } if (rv) { char *var, *val; char cur_cat[128] = ""; while (esl_config_next_pair(&cfg, &var, &val)) { if (strcmp(cur_cat, cfg.category)) { esl_set_string(cur_cat, cfg.category); esl_set_string(profiles[pcount].name, cur_cat); esl_set_string(profiles[pcount].host, "localhost"); esl_set_string(profiles[pcount].pass, "ClueCon"); profiles[pcount].port = 8021; set_fn_keys(&profiles[pcount]); esl_log(ESL_LOG_DEBUG, "Found Profile [%s]\n", profiles[pcount].name); pcount++; } if (!strcasecmp(var, "host")) { esl_set_string(profiles[pcount-1].host, val); } else if (!strcasecmp(var, "user")) { esl_set_string(profiles[pcount-1].user, val); } else if (!strcasecmp(var, "password")) { esl_set_string(profiles[pcount-1].pass, val); } else if (!strcasecmp(var, "port")) { int pt = atoi(val); if (pt > 0) { profiles[pcount-1].port = (esl_port_t)pt; } } else if (!strcasecmp(var, "debug")) { int dt = atoi(val); if (dt > -1 && dt < 8){ profiles[pcount-1].debug = dt; } } else if(!strcasecmp(var, "loglevel")) { esl_set_string(profiles[pcount-1].loglevel, val); } else if(!strcasecmp(var, "quiet")) { profiles[pcount-1].quiet = esl_true(val); } else if (!strncasecmp(var, "key_F", 5)) { char *key = var + 5; if (key) { int i = atoi(key); if (i > 0 && i < 13) { profiles[pcount-1].console_fnkeys[i - 1] = strdup(val); } } } } esl_config_close_file(&cfg); } if (optind < argc) { get_profile(argv[optind], &profile); } if (!profile) { if (get_profile("default", &profile)) { esl_log(ESL_LOG_DEBUG, "profile default does not exist using builtin profile\n"); profile = &internal_profile; } } if (temp_log < 0 ) { esl_global_set_default_logger(profile->debug); } if (argv_host) { esl_set_string(profile->host, temp_host); } if (argv_port) { profile->port = (esl_port_t)temp_port; } if (argv_user) { esl_set_string(profile->user, temp_user); } if (argv_pass) { esl_set_string(profile->pass, temp_pass); } if (*argv_loglevel) { esl_set_string(profile->loglevel, argv_loglevel); profile->quiet = 0; } esl_log(ESL_LOG_DEBUG, "Using profile %s [%s]\n", profile->name, profile->host); if (argv_host) { if (argv_port && profile->port != 8021) { snprintf(prompt_str, sizeof(prompt_str), "freeswitch@%s:%u@%s> ", profile->host, profile->port, profile->name); } else { snprintf(prompt_str, sizeof(prompt_str), "freeswitch@%s@%s> ", profile->host, profile->name); } } else { snprintf(prompt_str, sizeof(prompt_str), "freeswitch@%s> ", profile->name); } if (esl_connect(&handle, profile->host, profile->port, profile->user, profile->pass)) { esl_global_set_default_logger(7); esl_log(ESL_LOG_ERROR, "Error Connecting [%s]\n", handle.err); if (!argv_exec) usage(argv[0]); return -1; } if (argv_exec){ const char *err = NULL; snprintf(cmd_str, sizeof(cmd_str), "api %s\n\n", argv_command); esl_send_recv(&handle, cmd_str); if (handle.last_sr_event) { if (handle.last_sr_event->body) { printf("%s\n", handle.last_sr_event->body); } else if ((err = esl_event_get_header(handle.last_sr_event, "reply-text")) && !strncasecmp(err, "-err", 3)) { printf("Error: %s!\n", err + 4); } } esl_disconnect(&handle); return 0; } global_handle = &handle; global_profile = profile; esl_thread_create_detached(msg_thread_run, &handle); #ifdef HAVE_EDITLINE el = el_init(__FILE__, stdout, stdout, stdout); el_set(el, EL_PROMPT, &prompt); el_set(el, EL_EDITOR, "emacs"); myhistory = history_init(); el_set(el, EL_ADDFN, "f1-key", "F1 KEY PRESS", console_f1key); el_set(el, EL_ADDFN, "f2-key", "F2 KEY PRESS", console_f2key); el_set(el, EL_ADDFN, "f3-key", "F3 KEY PRESS", console_f3key); el_set(el, EL_ADDFN, "f4-key", "F4 KEY PRESS", console_f4key); el_set(el, EL_ADDFN, "f5-key", "F5 KEY PRESS", console_f5key); el_set(el, EL_ADDFN, "f6-key", "F6 KEY PRESS", console_f6key); el_set(el, EL_ADDFN, "f7-key", "F7 KEY PRESS", console_f7key); el_set(el, EL_ADDFN, "f8-key", "F8 KEY PRESS", console_f8key); el_set(el, EL_ADDFN, "f9-key", "F9 KEY PRESS", console_f9key); el_set(el, EL_ADDFN, "f10-key", "F10 KEY PRESS", console_f10key); el_set(el, EL_ADDFN, "f11-key", "F11 KEY PRESS", console_f11key); el_set(el, EL_ADDFN, "f12-key", "F12 KEY PRESS", console_f12key); el_set(el, EL_ADDFN, "EOF-key", "EOF (^D) KEY PRESS", console_eofkey); el_set(el, EL_BIND, "\033OP", "f1-key", NULL); el_set(el, EL_BIND, "\033OQ", "f2-key", NULL); el_set(el, EL_BIND, "\033OR", "f3-key", NULL); el_set(el, EL_BIND, "\033OS", "f4-key", NULL); el_set(el, EL_BIND, "\033[11~", "f1-key", NULL); el_set(el, EL_BIND, "\033[12~", "f2-key", NULL); el_set(el, EL_BIND, "\033[13~", "f3-key", NULL); el_set(el, EL_BIND, "\033[14~", "f4-key", NULL); el_set(el, EL_BIND, "\033[15~", "f5-key", NULL); el_set(el, EL_BIND, "\033[17~", "f6-key", NULL); el_set(el, EL_BIND, "\033[18~", "f7-key", NULL); el_set(el, EL_BIND, "\033[19~", "f8-key", NULL); el_set(el, EL_BIND, "\033[20~", "f9-key", NULL); el_set(el, EL_BIND, "\033[21~", "f10-key", NULL); el_set(el, EL_BIND, "\033[23~", "f11-key", NULL); el_set(el, EL_BIND, "\033[24~", "f12-key", NULL); el_set(el, EL_BIND, "\004", "EOF-key", NULL); el_set(el, EL_ADDFN, "ed-complete", "Complete argument", complete); el_set(el, EL_BIND, "^I", "ed-complete", NULL); if (myhistory == 0) { esl_log(ESL_LOG_ERROR, "history could not be initialized\n"); goto done; } history(myhistory, &ev, H_SETSIZE, 800); el_set(el, EL_HIST, history, myhistory); history(myhistory, &ev, H_LOAD, hfile); el_source(el, NULL); #endif #ifdef WIN32 hStdout = GetStdHandle(STD_OUTPUT_HANDLE); if (hStdout != INVALID_HANDLE_VALUE && GetConsoleScreenBufferInfo(hStdout, &csbiInfo)) { wOldColorAttrs = csbiInfo.wAttributes; } #endif if (!argv_quiet && !profile->quiet) { snprintf(cmd_str, sizeof(cmd_str), "log %s\n\n", profile->loglevel); esl_send_recv(&handle, cmd_str); } print_banner(stdout); esl_log(ESL_LOG_INFO, "FS CLI Ready.\nenter /help for a list of commands.\n"); printf("%s\n", handle.last_sr_reply); while (running) { #ifdef HAVE_EDITLINE line = el_gets(el, &count); #else line = basic_gets(&count); #endif if (count > 1) { if (!esl_strlen_zero(line)) { char *cmd = strdup(line); char *p; #ifdef HAVE_EDITLINE const LineInfo *lf = el_line(el); char *foo = (char *) lf->buffer; #endif if ((p = strrchr(cmd, '\r')) || (p = strrchr(cmd, '\n'))) { *p = '\0'; } assert(cmd != NULL); #ifdef HAVE_EDITLINE history(myhistory, &ev, H_ENTER, line); #endif if (process_command(&handle, cmd)) { running = 0; } #ifdef HAVE_EDITLINE el_deletestr(el, strlen(foo) + 1); memset(foo, 0, strlen(foo)); #endif free(cmd); } } usleep(1000); } #ifdef HAVE_EDITLINE done: history(myhistory, &ev, H_SAVE, hfile); /* Clean up our memory */ history_end(myhistory); el_end(el); #endif esl_disconnect(&handle); thread_running = 0; return 0; }
/* * Set history and editing status. Called whenever the status may * have changed (figures out what to do). */ void histedit(void) { FILE *el_err; #define editing (Eflag || Vflag) if (iflag == 1) { if (!hist) { /* * turn history on */ INTOFF; hist = history_init(); INTON; if (hist != NULL) sethistsize(histsizeval()); else out2str("sh: can't initialize history\n"); } if (editing && !el && isatty(0)) { /* && isatty(2) ??? */ /* * turn editing on */ char *term, *shname; INTOFF; if (el_in == NULL) el_in = fdopen(0, "r"); if (el_out == NULL) el_out = fdopen(2, "w"); if (el_in == NULL || el_out == NULL) goto bad; el_err = el_out; #if DEBUG if (tracefile) el_err = tracefile; #endif term = lookupvar("TERM"); if (term) setenv("TERM", term, 1); else unsetenv("TERM"); shname = arg0; if (shname[0] == '-') shname++; el = el_init(shname, el_in, el_out, el_err); if (el != NULL) { if (hist) el_set(el, EL_HIST, history, hist); el_set(el, EL_PROMPT, getprompt); el_set(el, EL_SIGNAL, 1); el_set(el, EL_ADDFN, "rl-complete", "ReadLine compatible completion function", _el_fn_complete); } else { bad: out2str("sh: can't initialize editing\n"); } INTON; } else if (!editing && el) { INTOFF; el_end(el); el = NULL; INTON; } if (el) { if (Vflag) el_set(el, EL_EDITOR, "vi"); else if (Eflag) el_set(el, EL_EDITOR, "emacs"); el_set(el, EL_BIND, "^I", tabcomplete ? "rl-complete" : "ed-insert", NULL); el_source(el, NULL); } } else { INTOFF; if (el) { /* no editing if not interactive */ el_end(el); el = NULL; } if (hist) { history_end(hist); hist = NULL; } INTON; } }
/* * Set history and editing status. Called whenever the status may * have changed (figures out what to do). */ void histedit(void) { #define editing (Eflag || Vflag) if (iflag) { if (!hist) { /* * turn history on */ INTOFF; hist = history_init(); INTON; if (hist != NULL) sethistsize(histsizeval()); else out2str("sh: can't initialize history\n"); } if (editing && !el && isatty(0)) { /* && isatty(2) ??? */ /* * turn editing on */ INTOFF; if (el_in == NULL) el_in = fdopen(0, "r"); if (el_err == NULL) el_err = fdopen(1, "w"); if (el_out == NULL) el_out = fdopen(2, "w"); if (el_in == NULL || el_err == NULL || el_out == NULL) goto bad; el = el_init(arg0, el_in, el_out, el_err); if (el != NULL) { if (hist) el_set(el, EL_HIST, history, hist); el_set(el, EL_PROMPT, getprompt); } else { bad: out2str("sh: can't initialize editing\n"); } INTON; } else if (!editing && el) { INTOFF; el_end(el); el = NULL; INTON; } if (el) { if (Vflag) el_set(el, EL_EDITOR, "vi"); else if (Eflag) el_set(el, EL_EDITOR, "emacs"); el_set(el, EL_ADDFN, "ed-do-complete", "Complete Argument", complete); el_set(el, EL_ADDFN, "ed-list-complete", "List Argument Completions", complete_list); el_set(el, EL_ADDFN, "ed-maybe-complete", "Complete Argument Or List Completions", complete_or_list); el_set(el, EL_ADDFN, "ed-expand", "Expand Completions", complete_expand); el_set(el, EL_BIND, "^I", "ed-maybe-complete", NULL); el_set(el, EL_BIND, "-a", "=", "ed-list-complete", NULL); el_set(el, EL_BIND, "-a", "\\\\", "ed-do-complete", NULL); el_set(el, EL_BIND, "-a", "*", "ed-expand", NULL); el_source(el, NULL); } } else { INTOFF; if (el) { /* no editing if not interactive */ el_end(el); el = NULL; } if (hist) { history_end(hist); hist = NULL; } INTON; } }