/* * lftp - file transfer program * * Copyright (c) 1996-2016 by Alexander V. Lukyanov (lav@yars.free.net) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef CMDEXEC_H #define CMDEXEC_H #include #include "Job.h" #include "ArgV.h" #include "Filter.h" #include "alias.h" #include "History.h" #include "bookmark.h" #include "FileGlob.h" class QueueFeeder; class LocalDirectory; extern History cwd_history; #define CMD(name) Job *cmd_##name(CmdExec *parent) typedef Job * (*cmd_creator_t)(class CmdExec *parent); class CmdFeeder { public: xstring_c saved_buf; CmdFeeder *prev; virtual const char *NextCmd(class CmdExec *exec,const char *prompt) = 0; virtual ~CmdFeeder() {} virtual void clear() {} virtual bool RealEOF() { return true; } virtual void Fg() {} virtual void Bg() {} virtual bool IsInteractive() const { return false; } }; extern CmdFeeder *lftp_feeder; // feeder to use after 'lftp' command class CmdExec : public SessionJob, public ResClient { public: // current command data Ref args; Ref output; bool background; int exit_code; int prev_exit_code; private: CmdExec *parent_exec; Buffer cmd_buf; bool partial_cmd; int alias_field; // length of expanded alias (and ttl for used_aliases) int failed_exit_code; TouchedAlias *used_aliases; void free_used_aliases(); void skip_cmd(int len); enum { COND_ANY, COND_AND, COND_OR } condition; struct cmd_rec { const char *name; cmd_creator_t creator; const char *short_desc; const char *long_desc; static int cmp(const CmdExec::cmd_rec *a,const CmdExec::cmd_rec *b); }; static const cmd_rec static_cmd_table[]; static const int static_cmd_table_length; static xarray dyn_cmd_table; static int find_cmd(const char *cmd_name,const cmd_rec **ret); void exec_parsed_command(); enum parse_result { PARSE_OK, PARSE_ERR, PARSE_AGAIN }; parse_result parse_one_cmd(); CmdFeeder *feeder; bool feeder_called; bool fed_at_finish; void AtFinish(); enum builtins { BUILTIN_NONE=0, BUILTIN_OPEN, BUILTIN_CD, BUILTIN_EXEC_RESTART, BUILTIN_GLOB } builtin; FileAccess::Path old_cwd; xstring_c old_lcwd; xstring_c slot; Ref glob; Ref args_glob; int redirections; static CmdExec *chain; CmdExec *next; QueueFeeder *queue_feeder; CmdExec *GetQueue(bool create = true); bool SameQueueParameters(CmdExec *,const char *); int max_waiting; FileAccessRef saved_session; void ReuseSavedSession(); void RevertToSavedSession(); void init(LocalDirectory *c); public: void FeedCmd(const char *c); void FeedArgV(const ArgV *,int start=0); void PrependCmd(const char *c); void ExecParsed(ArgV *a,FDStream *o=0,bool b=false); static bool needs_quotation(const char *buf,int len); static bool needs_quotation(const char *buf) { return needs_quotation(buf,strlen(buf)); } static bool quotable(char c,char in_quotes); static bool is_space(char c) { return c==' ' || c=='\t'; } static bool is_quote(char c) { return c=='"' || c=='\''; } void FeedQuoted(const char *c); void Exit(int); void AtExit(); void AtExitBg(); void AtExitFg(); void AtBackground(); void AtTerminate(); void EmptyCmds(); bool WriteCmds(int fd) const; bool ReadCmds(int fd); // does not clear queue before reading (appends) void AddNewJob(Job *new_job); void SuspendJob(Job *j); CmdExec(FileAccess *s,LocalDirectory *c); CmdExec(CmdExec *parent); ~CmdExec(); bool Idle(); // when we have no command running and command buffer is empty int Done(); int ExitCode() { return failed_exit_code ? failed_exit_code : exit_code; } int Do(); xstring& FormatStatus(xstring&,int,const char *prefix="\t"); void ShowRunStatus(const SMTaskRef& s); int AcceptSig(int sig); const char *FormatPrompt(const char *scan); const char *MakePrompt(); bool interactive; bool show_status; bool top_level; bool verbose; bool auto_terminate_in_bg; SMTaskRef status_line; void SetCmdFeeder(CmdFeeder *new_feeder); void RemoveFeeder(); friend char *command_generator(char *,int); // readline completor static const char *GetFullCommandName(const char *); bool remote_completion; int long_running; bool csh_history; bool verify_host; bool verify_path; bool verify_path_cached; void Reconfig(const char *name=0); void beep_if_long(); time_t start_time; static CmdExec *cwd_owner; Ref cwd; void SaveCWD(); int RestoreCWD(); FDStream *default_output; void top_vfprintf(FILE *file,const char *f,va_list v); void SetInteractive(bool i); void SetInteractive(); void SetTopLevel() { top_level=true; Reconfig(0); SetInteractive(); } void SetStatusLine(StatusLine *s) { status_line=s; } void SetAutoTerminateInBackground(bool b) { auto_terminate_in_bg=b; } static void RegisterCommand(const char *name,cmd_creator_t creator, const char *short_name=0,const char *long_name=0); Job *builtin_lcd(); Job *builtin_cd(); Job *builtin_open(); Job *builtin_exit(); Job *builtin_lftp(); Job *builtin_restart(); Job *builtin_glob(); Job *builtin_queue(); Job *builtin_queue_edit(); Job *builtin_local(); bool load_cmd_module(const char *op); Job *default_cmd(); void ChangeSession(FileAccess *new_session); bool print_cmd_help(const char *cmd); void print_cmd_index(); static const char *CmdByIndex(int i); void enable_debug(const char *opt=0); int last_bg; bool wait_all; void pre_stdout(); void ChangeSlot(const char *n); static JobRef top; }; extern const char * const bookmark_subcmd[]; extern const char * const cache_subcmd[]; #endif//CMDEXEC_H