|
Packit Service |
a2489d |
/*
|
|
Packit Service |
a2489d |
* lftp - file transfer program
|
|
Packit Service |
a2489d |
*
|
|
Packit Service |
a2489d |
* Copyright (c) 1996-2017 by Alexander V. Lukyanov (lav@yars.free.net)
|
|
Packit Service |
a2489d |
*
|
|
Packit Service |
a2489d |
* This program is free software; you can redistribute it and/or modify
|
|
Packit Service |
a2489d |
* it under the terms of the GNU General Public License as published by
|
|
Packit Service |
a2489d |
* the Free Software Foundation; either version 3 of the License, or
|
|
Packit Service |
a2489d |
* (at your option) any later version.
|
|
Packit Service |
a2489d |
*
|
|
Packit Service |
a2489d |
* This program is distributed in the hope that it will be useful,
|
|
Packit Service |
a2489d |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit Service |
a2489d |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
Packit Service |
a2489d |
* GNU General Public License for more details.
|
|
Packit Service |
a2489d |
*
|
|
Packit Service |
a2489d |
* You should have received a copy of the GNU General Public License
|
|
Packit Service |
a2489d |
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
Packit Service |
a2489d |
*/
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
#include <config.h>
|
|
Packit Service |
a2489d |
#include <stddef.h>
|
|
Packit Service |
a2489d |
#include <errno.h>
|
|
Packit Service |
a2489d |
#include <unistd.h>
|
|
Packit Service |
a2489d |
#include <ctype.h>
|
|
Packit Service |
a2489d |
#include <fcntl.h>
|
|
Packit Service |
a2489d |
#include "CmdExec.h"
|
|
Packit Service |
a2489d |
#include "xstring.h"
|
|
Packit Service |
a2489d |
#include "SignalHook.h"
|
|
Packit Service |
a2489d |
#include "alias.h"
|
|
Packit Service |
a2489d |
#include "misc.h"
|
|
Packit Service |
a2489d |
#include "ResMgr.h"
|
|
Packit Service |
a2489d |
#include "module.h"
|
|
Packit Service |
a2489d |
#include "url.h"
|
|
Packit Service |
a2489d |
#include "QueueFeeder.h"
|
|
Packit Service |
a2489d |
#include "LocalDir.h"
|
|
Packit Service |
a2489d |
#include "ConnectionSlot.h"
|
|
Packit Service |
a2489d |
#include "DummyProto.h"
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
#define RL_PROMPT_START_IGNORE '\001'
|
|
Packit Service |
a2489d |
#define RL_PROMPT_END_IGNORE '\002'
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
#define super SessionJob
|
|
Packit Service |
a2489d |
#define waiting_num waiting.count()
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
static ResType lftp_cmd_vars[] = {
|
|
Packit Service |
a2489d |
{"cmd:default-protocol", "ftp", 0,0},
|
|
Packit Service |
a2489d |
{"cmd:long-running", "30", ResMgr::UNumberValidate,0},
|
|
Packit Service |
a2489d |
{"cmd:remote-completion", "on", ResMgr::BoolValidate,0},
|
|
Packit Service |
a2489d |
{"cmd:prompt", "lftp \\S\\? \\u\\@\\h:\\w> ",0,0},
|
|
Packit Service |
a2489d |
{"cmd:default-title", "lftp \\h:\\w",0,0},
|
|
Packit Service |
a2489d |
{"cmd:ls-default", "", 0,0},
|
|
Packit Service |
a2489d |
{"cmd:csh-history", "off", ResMgr::BoolValidate,ResMgr::NoClosure},
|
|
Packit Service |
a2489d |
{"cmd:verify-path", "yes", ResMgr::BoolValidate,0},
|
|
Packit Service |
a2489d |
{"cmd:verify-path-cached", "no", ResMgr::BoolValidate,0},
|
|
Packit Service |
a2489d |
{"cmd:verify-host", "yes", ResMgr::BoolValidate,0},
|
|
Packit Service |
a2489d |
{"cmd:at-exit", "", 0,0},
|
|
Packit Service |
a2489d |
{"cmd:at-exit-bg", "", 0,0},
|
|
Packit Service |
a2489d |
{"cmd:at-exit-fg", "", 0,0},
|
|
Packit Service |
a2489d |
{"cmd:at-background", "", 0,0},
|
|
Packit Service |
a2489d |
{"cmd:at-terminate", "", 0,0},
|
|
Packit Service |
a2489d |
{"cmd:at-finish", "", 0,0},
|
|
Packit Service |
a2489d |
{"cmd:at-queue-finish", "", 0,0},
|
|
Packit Service |
a2489d |
{"cmd:fail-exit", "no", ResMgr::BoolValidate,ResMgr::NoClosure},
|
|
Packit Service |
a2489d |
{"cmd:verbose", "no", ResMgr::BoolValidate,ResMgr::NoClosure},
|
|
Packit Service |
a2489d |
{"cmd:interactive", "auto", ResMgr::TriBoolValidate,ResMgr::NoClosure},
|
|
Packit Service |
a2489d |
{"cmd:show-status", "yes", ResMgr::BoolValidate,ResMgr::NoClosure},
|
|
Packit Service |
a2489d |
{"cmd:move-background", "yes", ResMgr::BoolValidate,ResMgr::NoClosure},
|
|
Packit Service |
a2489d |
{"cmd:move-background-detach","yes", ResMgr::BoolValidate,ResMgr::NoClosure},
|
|
Packit Service |
a2489d |
{"cmd:set-term-status", "no", ResMgr::BoolValidate,0},
|
|
Packit Service |
a2489d |
{"cmd:term-status", "", 0, 0},
|
|
Packit Service |
a2489d |
{"cmd:trace", "no", ResMgr::BoolValidate,ResMgr::NoClosure},
|
|
Packit Service |
a2489d |
{"cmd:parallel", "1", ResMgr::UNumberValidate,0},
|
|
Packit Service |
a2489d |
{"cmd:queue-parallel", "1", ResMgr::UNumberValidate,0},
|
|
Packit Service |
a2489d |
{"cmd:cls-exact-time", "yes", ResMgr::BoolValidate,ResMgr::NoClosure},
|
|
Packit Service |
a2489d |
{0}
|
|
Packit Service |
a2489d |
};
|
|
Packit Service |
a2489d |
static ResDecls lftp_cmd_vars_register(lftp_cmd_vars);
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
CmdExec *CmdExec::cwd_owner;
|
|
Packit Service |
a2489d |
CmdExec *CmdExec::chain;
|
|
Packit Service |
a2489d |
JobRef<CmdExec> CmdExec::top;
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
void CmdExec::SaveCWD()
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
if(!cwd)
|
|
Packit Service |
a2489d |
cwd=new LocalDirectory;
|
|
Packit Service |
a2489d |
cwd->SetFromCWD();
|
|
Packit Service |
a2489d |
if(cwd_owner==0)
|
|
Packit Service |
a2489d |
cwd_owner=this;
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
int CmdExec::RestoreCWD()
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
if(cwd_owner==this)
|
|
Packit Service |
a2489d |
return 0;
|
|
Packit Service |
a2489d |
if(cwd==0)
|
|
Packit Service |
a2489d |
return -1;
|
|
Packit Service |
a2489d |
const char *err=cwd->Chdir();
|
|
Packit Service |
a2489d |
if(!err)
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
cwd_owner=this;
|
|
Packit Service |
a2489d |
return 0;
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
const char *name=cwd->GetName();
|
|
Packit Service |
a2489d |
eprintf(_("Warning: chdir(%s) failed: %s\n"),name?name:"?",err);
|
|
Packit Service |
a2489d |
return -1;
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
void CmdExec::FeedCmd(const char *c)
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
partial_cmd=false;
|
|
Packit Service |
a2489d |
start_time=now;
|
|
Packit Service |
a2489d |
cmd_buf.Put(c);
|
|
Packit Service |
a2489d |
};
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
void CmdExec::PrependCmd(const char *c)
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
start_time=now;
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
int len=strlen(c);
|
|
Packit Service |
a2489d |
int nl=(len>0 && c[len-1]!='\n');
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
if(nl)
|
|
Packit Service |
a2489d |
cmd_buf.Prepend("\n",1);
|
|
Packit Service |
a2489d |
cmd_buf.Prepend(c,len);
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
if(alias_field>0)
|
|
Packit Service |
a2489d |
alias_field+=len+nl;
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
int CmdExec::find_cmd(const char *cmd_name,const struct cmd_rec **ret)
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
int part=0;
|
|
Packit Service |
a2489d |
const cmd_rec *c=dyn_cmd_table?dyn_cmd_table.get():static_cmd_table;
|
|
Packit Service |
a2489d |
const int count=dyn_cmd_table?dyn_cmd_table.count():static_cmd_table_length;
|
|
Packit Service |
a2489d |
for(int i=0; i
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
if(!strcasecmp(c->name,cmd_name))
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
*ret=c;
|
|
Packit Service |
a2489d |
return 1;
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
if(!strncasecmp(c->name,cmd_name,strlen(cmd_name)))
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
part++;
|
|
Packit Service |
a2489d |
*ret=c;
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
if(part!=1)
|
|
Packit Service |
a2489d |
*ret=0;
|
|
Packit Service |
a2489d |
return part;
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
CMD(lcd);
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
void CmdExec::exec_parsed_command()
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
switch(condition)
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
case(COND_ANY):
|
|
Packit Service |
a2489d |
if(exit_code!=0 && ResMgr::QueryBool("cmd:fail-exit",0))
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
failed_exit_code=exit_code;
|
|
Packit Service |
a2489d |
while(feeder)
|
|
Packit Service |
a2489d |
RemoveFeeder();
|
|
Packit Service |
a2489d |
cmd_buf.Empty();
|
|
Packit Service |
a2489d |
return;
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
break;
|
|
Packit Service |
a2489d |
case(COND_AND):
|
|
Packit Service |
a2489d |
if(exit_code!=0)
|
|
Packit Service |
a2489d |
return;
|
|
Packit Service |
a2489d |
break;
|
|
Packit Service |
a2489d |
case(COND_OR):
|
|
Packit Service |
a2489d |
if(exit_code==0)
|
|
Packit Service |
a2489d |
return;
|
|
Packit Service |
a2489d |
break;
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
prev_exit_code=exit_code;
|
|
Packit Service |
a2489d |
exit_code=1;
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
if(interactive)
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
SignalHook::ResetCount(SIGINT);
|
|
Packit Service |
a2489d |
SignalHook::ResetCount(SIGHUP);
|
|
Packit Service |
a2489d |
SignalHook::ResetCount(SIGTSTP);
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
bool did_default=false;
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
if(ResMgr::QueryBool("cmd:trace",0))
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
xstring_ca c(args->CombineQuoted());
|
|
Packit Service |
a2489d |
printf("+ %s\n",c.get());
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
restart:
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
const struct cmd_rec *c;
|
|
Packit Service |
a2489d |
const char *cmd_name=args->getarg(0);
|
|
Packit Service |
a2489d |
if(!cmd_name)
|
|
Packit Service |
a2489d |
return;
|
|
Packit Service |
a2489d |
int part=find_cmd(cmd_name,&c);
|
|
Packit Service |
a2489d |
if(part<=0)
|
|
Packit Service |
a2489d |
eprintf(_("Unknown command `%s'.\n"),cmd_name);
|
|
Packit Service |
a2489d |
else if(part>1)
|
|
Packit Service |
a2489d |
eprintf(_("Ambiguous command `%s'.\n"),cmd_name);
|
|
Packit Service |
a2489d |
else
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
if(RestoreCWD()==-1)
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
if(c->creator!=cmd_lcd)
|
|
Packit Service |
a2489d |
return;
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
args->setarg(0,c->name); // in case it was abbreviated
|
|
Packit Service |
a2489d |
args->rewind();
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
xstring_ca cmdline(args->Combine()); // save the cmdline
|
|
Packit Service |
a2489d |
Job *new_job=0;
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
if(c->creator==0)
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
if(did_default)
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
eprintf(_("Module for command `%s' did not register the command.\n"),cmd_name);
|
|
Packit Service |
a2489d |
exit_code=1;
|
|
Packit Service |
a2489d |
return;
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
new_job=default_cmd();
|
|
Packit Service |
a2489d |
did_default=true;
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
else
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
new_job=c->creator(this);
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
if(new_job==this || builtin)
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
if(builtin==BUILTIN_EXEC_RESTART)
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
builtin=BUILTIN_NONE;
|
|
Packit Service |
a2489d |
goto restart;
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
return;
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
RevertToSavedSession();
|
|
Packit Service |
a2489d |
if(new_job) {
|
|
Packit Service |
a2489d |
if(!new_job->cmdline)
|
|
Packit Service |
a2489d |
new_job->cmdline.move_here(cmdline);
|
|
Packit Service |
a2489d |
AddNewJob(new_job);
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
void CmdExec::AddNewJob(Job *new_job)
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
if(new_job->jobno<0)
|
|
Packit Service |
a2489d |
new_job->AllocJobno();
|
|
Packit Service |
a2489d |
new_job->SetParentFg(this,!background);
|
|
Packit Service |
a2489d |
exit_code=0;
|
|
Packit Service |
a2489d |
AddWaiting(new_job);
|
|
Packit Service |
a2489d |
if(background) {
|
|
Packit Service |
a2489d |
Roll(new_job);
|
|
Packit Service |
a2489d |
if(!new_job->Done())
|
|
Packit Service |
a2489d |
SuspendJob(new_job);
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
void CmdExec::SuspendJob(Job *j)
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
j->Bg();
|
|
Packit Service |
a2489d |
if(interactive)
|
|
Packit Service |
a2489d |
j->ListOneJob(0,0,"&";;
|
|
Packit Service |
a2489d |
last_bg=j->jobno;
|
|
Packit Service |
a2489d |
exit_code=0;
|
|
Packit Service |
a2489d |
RemoveWaiting(j);
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
void CmdExec::ExecParsed(ArgV *a,FDStream *o,bool b)
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
Enter();
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
args=a;
|
|
Packit Service |
a2489d |
output=o;
|
|
Packit Service |
a2489d |
background=b;
|
|
Packit Service |
a2489d |
condition=COND_ANY;
|
|
Packit Service |
a2489d |
exec_parsed_command();
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
Leave();
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
bool CmdExec::Idle()
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
return(waiting_num==0 && builtin==BUILTIN_NONE && (cmd_buf.Size()==0 || partial_cmd));
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
int CmdExec::Done()
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
Enter();
|
|
Packit Service |
a2489d |
bool done = (feeder==0 && Idle())
|
|
Packit Service |
a2489d |
|| (auto_terminate_in_bg && NumberOfChildrenJobs()==0 && !in_foreground_pgrp());
|
|
Packit Service |
a2489d |
Leave();
|
|
Packit Service |
a2489d |
return done;
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
void CmdExec::RemoveFeeder()
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
free_used_aliases();
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
if(!feeder)
|
|
Packit Service |
a2489d |
return;
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
// save old cwd if necessary
|
|
Packit Service |
a2489d |
if(interactive && feeder->prev==0)
|
|
Packit Service |
a2489d |
cwd_history.Set(session);
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
cmd_buf.Empty();
|
|
Packit Service |
a2489d |
cmd_buf.Put(feeder->saved_buf);
|
|
Packit Service |
a2489d |
partial_cmd=false;
|
|
Packit Service |
a2489d |
if(feeder==queue_feeder)
|
|
Packit Service |
a2489d |
queue_feeder=0;
|
|
Packit Service |
a2489d |
delete replace_value(feeder,feeder->prev);
|
|
Packit Service |
a2489d |
Reconfig(0);
|
|
Packit Service |
a2489d |
SetInteractive();
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
void CmdExec::ReuseSavedSession()
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
saved_session=0;
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
void CmdExec::RevertToSavedSession()
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
if(saved_session==0)
|
|
Packit Service |
a2489d |
return;
|
|
Packit Service |
a2489d |
ChangeSession(saved_session.borrow());
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
void CmdExec::ChangeSlot(const char *n)
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
if(!n || !*n)
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
slot.set(0);
|
|
Packit Service |
a2489d |
return;
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
slot.set(n);
|
|
Packit Service |
a2489d |
const FileAccess *s=ConnectionSlot::FindSession(n);
|
|
Packit Service |
a2489d |
if(!s)
|
|
Packit Service |
a2489d |
ConnectionSlot::Set(n,session);
|
|
Packit Service |
a2489d |
else
|
|
Packit Service |
a2489d |
ChangeSession(s->Clone());
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
void CmdExec::AtFinish()
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
if(queue_feeder && queue_feeder->JobCount())
|
|
Packit Service |
a2489d |
return;
|
|
Packit Service |
a2489d |
if(!fed_at_finish && NumAwaitedJobs()==0 && cmd_buf.Size()==0) {
|
|
Packit Service |
a2489d |
FeedCmd(ResMgr::Query(queue_feeder?"cmd:at-queue-finish":"cmd:at-finish",0));
|
|
Packit Service |
a2489d |
FeedCmd("\n");
|
|
Packit Service |
a2489d |
fed_at_finish=true;
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
int CmdExec::Do()
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
int m=STALL;
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
if(builtin!=BUILTIN_NONE)
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
int res;
|
|
Packit Service |
a2489d |
switch(builtin)
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
case(BUILTIN_CD):
|
|
Packit Service |
a2489d |
res=session->Done();
|
|
Packit Service |
a2489d |
if(res==FA::OK)
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
// done
|
|
Packit Service |
a2489d |
if(status_line)
|
|
Packit Service |
a2489d |
status_line->Clear();
|
|
Packit Service |
a2489d |
if(interactive || verbose)
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
const char *cwd=session->GetCwd();
|
|
Packit Service |
a2489d |
eprintf(_("cd ok, cwd=%s\n"),cwd?cwd:"~");
|
|
Packit Service |
a2489d |
cwd_history.Set(session,old_cwd);
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
if(slot)
|
|
Packit Service |
a2489d |
ConnectionSlot::SetCwd(slot,session->GetCwd());
|
|
Packit Service |
a2489d |
session->Close();
|
|
Packit Service |
a2489d |
exit_code=0;
|
|
Packit Service |
a2489d |
builtin=BUILTIN_NONE;
|
|
Packit Service |
a2489d |
redirections=0;
|
|
Packit Service |
a2489d |
beep_if_long();
|
|
Packit Service |
a2489d |
return MOVED;
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
if(res<0)
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
if(res==FA::FILE_MOVED)
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
// cd to another url.
|
|
Packit Service |
a2489d |
const char *loc_c=session->GetNewLocation();
|
|
Packit Service |
a2489d |
int max_redirections=ResMgr::Query("xfer:max-redirections",0);
|
|
Packit Service |
a2489d |
if(loc_c && max_redirections>0)
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
eprintf(_("%s: received redirection to `%s'\n"),"cd",loc_c);
|
|
Packit Service |
a2489d |
if(++redirections>max_redirections)
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
eprintf("cd: %s\n",_("Too many redirections"));
|
|
Packit Service |
a2489d |
goto cd_err_done;
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
char *loc=alloca_strdup(loc_c);
|
|
Packit Service |
a2489d |
ParsedURL u(loc,true);
|
|
Packit Service |
a2489d |
if(!u.proto)
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
bool is_file=(last_char(loc)!='/');
|
|
Packit Service |
a2489d |
FileAccess::Path new_cwd(session->GetNewCwd());
|
|
Packit Service |
a2489d |
new_cwd.Change(0,is_file,loc);
|
|
Packit Service |
a2489d |
session->PathVerify(new_cwd);
|
|
Packit Service |
a2489d |
session->Roll();
|
|
Packit Service |
a2489d |
return MOVED;
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
session->Close();
|
|
Packit Service |
a2489d |
exit_code=0;
|
|
Packit Service |
a2489d |
builtin=BUILTIN_NONE;
|
|
Packit Service |
a2489d |
PrependCmd(xstring::get_tmp("open ").append_quoted(loc));
|
|
Packit Service |
a2489d |
return MOVED;
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
// error
|
|
Packit Service |
a2489d |
if(status_line)
|
|
Packit Service |
a2489d |
status_line->Clear();
|
|
Packit Service |
a2489d |
eprintf("%s: %s\n",args->getarg(0),session->StrError(res));
|
|
Packit Service |
a2489d |
cd_err_done:
|
|
Packit Service |
a2489d |
session->Close();
|
|
Packit Service |
a2489d |
builtin=BUILTIN_NONE;
|
|
Packit Service |
a2489d |
redirections=0;
|
|
Packit Service |
a2489d |
beep_if_long();
|
|
Packit Service |
a2489d |
exit_code=1;
|
|
Packit Service |
a2489d |
return MOVED;
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
break;
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
case(BUILTIN_OPEN):
|
|
Packit Service |
a2489d |
res=session->Done();
|
|
Packit Service |
a2489d |
if(res==FA::OK)
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
if(status_line)
|
|
Packit Service |
a2489d |
status_line->Clear();
|
|
Packit Service |
a2489d |
session->Close();
|
|
Packit Service |
a2489d |
ReuseSavedSession();
|
|
Packit Service |
a2489d |
builtin=BUILTIN_NONE;
|
|
Packit Service |
a2489d |
redirections=0;
|
|
Packit Service |
a2489d |
beep_if_long();
|
|
Packit Service |
a2489d |
exit_code=0;
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
return MOVED;
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
if(res<0)
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
if(status_line)
|
|
Packit Service |
a2489d |
status_line->Clear();
|
|
Packit Service |
a2489d |
eprintf("%s: %s\n",args->getarg(0),session->StrError(res));
|
|
Packit Service |
a2489d |
session->Close();
|
|
Packit Service |
a2489d |
RevertToSavedSession();
|
|
Packit Service |
a2489d |
builtin=BUILTIN_NONE;
|
|
Packit Service |
a2489d |
redirections=0;
|
|
Packit Service |
a2489d |
beep_if_long();
|
|
Packit Service |
a2489d |
exit_code=1;
|
|
Packit Service |
a2489d |
return MOVED;
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
break;
|
|
Packit Service |
a2489d |
case(BUILTIN_GLOB):
|
|
Packit Service |
a2489d |
if(glob->Error())
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
if(status_line)
|
|
Packit Service |
a2489d |
status_line->Clear();
|
|
Packit Service |
a2489d |
eprintf("%s: %s\n",args->getarg(0),glob->ErrorText());
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
else if(glob->Done())
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
FileSet &list=*glob->GetResult();
|
|
Packit Service |
a2489d |
for(int i=0; list[i]; i++)
|
|
Packit Service |
a2489d |
args_glob->Append(list[i]->name);
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
if(glob->Done() || glob->Error())
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
const char *pat=args->getnext();
|
|
Packit Service |
a2489d |
if(!pat)
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
glob=0;
|
|
Packit Service |
a2489d |
// it was last argument
|
|
Packit Service |
a2489d |
args=args_glob.borrow();
|
|
Packit Service |
a2489d |
builtin=BUILTIN_NONE;
|
|
Packit Service |
a2489d |
redirections=0;
|
|
Packit Service |
a2489d |
if(status_line)
|
|
Packit Service |
a2489d |
status_line->Clear();
|
|
Packit Service |
a2489d |
exit_code=prev_exit_code;
|
|
Packit Service |
a2489d |
RevertToSavedSession();
|
|
Packit Service |
a2489d |
exec_parsed_command();
|
|
Packit Service |
a2489d |
return MOVED;
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
glob->NewGlob(pat);
|
|
Packit Service |
a2489d |
m=MOVED;
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
break;
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
case(BUILTIN_NONE):
|
|
Packit Service |
a2489d |
case(BUILTIN_EXEC_RESTART):
|
|
Packit Service |
a2489d |
abort(); // can't happen
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
if(interactive)
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
if(SignalHook::GetCount(SIGINT))
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
if(status_line)
|
|
Packit Service |
a2489d |
status_line->WriteLine(_("Interrupt"));
|
|
Packit Service |
a2489d |
return AcceptSig(SIGINT);
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
if(SignalHook::GetCount(SIGTSTP))
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
if(builtin==BUILTIN_CD || builtin==BUILTIN_OPEN)
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
if(status_line)
|
|
Packit Service |
a2489d |
status_line->Clear();
|
|
Packit Service |
a2489d |
if(builtin==BUILTIN_CD)
|
|
Packit Service |
a2489d |
session->ChdirAccept();
|
|
Packit Service |
a2489d |
session->Close();
|
|
Packit Service |
a2489d |
exit_code=0;
|
|
Packit Service |
a2489d |
builtin=BUILTIN_NONE;
|
|
Packit Service |
a2489d |
redirections=0;
|
|
Packit Service |
a2489d |
return MOVED;
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
else
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
SignalHook::ResetCount(SIGTSTP);
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
if(SignalHook::GetCount(SIGHUP))
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
SetInteractive(false);
|
|
Packit Service |
a2489d |
return MOVED;
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
if(status_line && show_status && status_line->CanShowNow())
|
|
Packit Service |
a2489d |
ShowRunStatus(status_line); // this is only for top level CmdExec.
|
|
Packit Service |
a2489d |
return m;
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
if(waiting_num>0)
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
Job *j;
|
|
Packit Service |
a2489d |
while((j=FindDoneAwaitedJob())!=0)
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
j->Bg();
|
|
Packit Service |
a2489d |
if(status_line)
|
|
Packit Service |
a2489d |
status_line->Clear();
|
|
Packit Service |
a2489d |
if(interactive || verbose)
|
|
Packit Service |
a2489d |
j->SayFinal(); // final phrase like 'rm succeed'
|
|
Packit Service |
a2489d |
exit_code=j->ExitCode();
|
|
Packit Service |
a2489d |
RemoveWaiting(j);
|
|
Packit Service |
a2489d |
Delete(j);
|
|
Packit Service |
a2489d |
beep_if_long();
|
|
Packit Service |
a2489d |
return MOVED;
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
if(interactive)
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
if(SignalHook::GetCount(SIGINT))
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
for(int i=0; i
|
|
Packit Service |
a2489d |
waiting[i]->Bg();
|
|
Packit Service |
a2489d |
SignalHook::ResetCount(SIGINT);
|
|
Packit Service |
a2489d |
if(status_line)
|
|
Packit Service |
a2489d |
status_line->WriteLine(_("Interrupt"));
|
|
Packit Service |
a2489d |
return AcceptSig(SIGINT);
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
if(SignalHook::GetCount(SIGTSTP))
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
while(waiting_num>0)
|
|
Packit Service |
a2489d |
SuspendJob(waiting[0]);
|
|
Packit Service |
a2489d |
return MOVED;
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
if(SignalHook::GetCount(SIGHUP))
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
SetInteractive(false);
|
|
Packit Service |
a2489d |
return MOVED;
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
if(status_line && show_status && status_line->CanShowNow())
|
|
Packit Service |
a2489d |
ShowRunStatus(status_line); // this is only for top level CmdExec.
|
|
Packit Service |
a2489d |
if(m != STALL || interactive || waiting_num >= max_waiting)
|
|
Packit Service |
a2489d |
return m;
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
if(!interactive)
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
BuryDoneJobs();
|
|
Packit Service |
a2489d |
if(FindJob(last_bg)==0)
|
|
Packit Service |
a2489d |
last_bg=-1;
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
try_get_cmd:
|
|
Packit Service |
a2489d |
if(cmd_buf.Size()==0 || partial_cmd)
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
if(feeder)
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
if(interactive && !partial_cmd)
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
ListDoneJobs();
|
|
Packit Service |
a2489d |
BuryDoneJobs();
|
|
Packit Service |
a2489d |
if(FindJob(last_bg)==0)
|
|
Packit Service |
a2489d |
last_bg=-1;
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
if(status_line && show_status)
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
const char *def_title = FormatPrompt(ResMgr::Query("cmd:default-title",getenv("TERM")));
|
|
Packit Service |
a2489d |
status_line->DefaultTitle(def_title);
|
|
Packit Service |
a2489d |
status_line->Clear();
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
const char *prompt=MakePrompt();
|
|
Packit Service |
a2489d |
feeder_called=true;
|
|
Packit Service |
a2489d |
if(fg)
|
|
Packit Service |
a2489d |
feeder->Fg();
|
|
Packit Service |
a2489d |
const char *cmd=feeder->NextCmd(this,prompt);
|
|
Packit Service |
a2489d |
feeder_called=false;
|
|
Packit Service |
a2489d |
if(!cmd)
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
if(cmd_buf.Size()>0 && partial_cmd)
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
const char *next_cmd=cmd_buf.Get();
|
|
Packit Service |
a2489d |
if(last_char(next_cmd)!='\n')
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
// missing EOL on last line, add it
|
|
Packit Service |
a2489d |
FeedCmd("\n");
|
|
Packit Service |
a2489d |
goto try_get_cmd;
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
fprintf(stderr,_("Warning: discarding incomplete command\n"));
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
if(!feeder->RealEOF() && top_level)
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
cmd_buf.Empty();
|
|
Packit Service |
a2489d |
FeedCmd("exit;");
|
|
Packit Service |
a2489d |
return MOVED;
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
if(waiting_num > 0)
|
|
Packit Service |
a2489d |
return m;
|
|
Packit Service |
a2489d |
RemoveFeeder();
|
|
Packit Service |
a2489d |
m=MOVED;
|
|
Packit Service |
a2489d |
goto try_get_cmd;
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
if(cmd[0])
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
auto_terminate_in_bg=false;
|
|
Packit Service |
a2489d |
FeedCmd(cmd);
|
|
Packit Service |
a2489d |
Roll();
|
|
Packit Service |
a2489d |
if(!Idle())
|
|
Packit Service |
a2489d |
fed_at_finish=false;
|
|
Packit Service |
a2489d |
return MOVED;
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
else
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
if(SignalHook::GetCount(SIGINT)>0)
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
SignalHook::ResetCount(SIGINT);
|
|
Packit Service |
a2489d |
cmd_buf.Empty(); // flush unparsed command
|
|
Packit Service |
a2489d |
return MOVED;
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
return m;
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
parse_result res = parse_one_cmd();
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
if(alias_field<=0)
|
|
Packit Service |
a2489d |
free_used_aliases();
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
switch(res)
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
case(PARSE_ERR):
|
|
Packit Service |
a2489d |
return MOVED;
|
|
Packit Service |
a2489d |
case(PARSE_AGAIN):
|
|
Packit Service |
a2489d |
partial_cmd=true;
|
|
Packit Service |
a2489d |
goto try_get_cmd;
|
|
Packit Service |
a2489d |
case(PARSE_OK):
|
|
Packit Service |
a2489d |
if(feeder)
|
|
Packit Service |
a2489d |
feeder->Bg();
|
|
Packit Service |
a2489d |
break;
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
if(args==0 || args->count()==0) {
|
|
Packit Service |
a2489d |
AtFinish();
|
|
Packit Service |
a2489d |
return MOVED; // empty command
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
if(interactive)
|
|
Packit Service |
a2489d |
session->DontSleep(); // We don't want to get a delay just after user
|
|
Packit Service |
a2489d |
// entered a command.
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
exec_parsed_command();
|
|
Packit Service |
a2489d |
return MOVED;
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
void CmdExec::ShowRunStatus(const SMTaskRef<StatusLine>& s)
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
switch(builtin)
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
case(BUILTIN_CD):
|
|
Packit Service |
a2489d |
if(session->IsOpen())
|
|
Packit Service |
a2489d |
s->Show("cd `%s' [%s]",squeeze_file_name(args->getarg(1),s->GetWidthDelayed()-40),session->CurrentStatus());
|
|
Packit Service |
a2489d |
break;
|
|
Packit Service |
a2489d |
case(BUILTIN_OPEN):
|
|
Packit Service |
a2489d |
if(session->IsOpen())
|
|
Packit Service |
a2489d |
s->Show("open `%s' [%s]",session->GetHostName(),session->CurrentStatus());
|
|
Packit Service |
a2489d |
break;
|
|
Packit Service |
a2489d |
case(BUILTIN_GLOB):
|
|
Packit Service |
a2489d |
s->Show("%s",glob->Status());
|
|
Packit Service |
a2489d |
break;
|
|
Packit Service |
a2489d |
case(BUILTIN_EXEC_RESTART):
|
|
Packit Service |
a2489d |
abort(); // can't happen
|
|
Packit Service |
a2489d |
case(BUILTIN_NONE):
|
|
Packit Service |
a2489d |
if(waiting_num>0)
|
|
Packit Service |
a2489d |
Job::ShowRunStatus(s);
|
|
Packit Service |
a2489d |
else
|
|
Packit Service |
a2489d |
s->Clear();
|
|
Packit Service |
a2489d |
break;
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
xstring& CmdExec::FormatStatus(xstring& s,int v,const char *prefix)
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
SessionJob::FormatStatus(s,v,prefix);
|
|
Packit Service |
a2489d |
if(builtin)
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
xstring_ca ac(args->Combine());
|
|
Packit Service |
a2489d |
return s.appendf(_("\tExecuting builtin `%s' [%s]\n"),ac.get(),session->CurrentStatus());
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
if(queue_feeder)
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
if(IsSuspended())
|
|
Packit Service |
a2489d |
s.appendf("%s%s\n",prefix,_("Queue is stopped."));
|
|
Packit Service |
a2489d |
BuryDoneJobs();
|
|
Packit Service |
a2489d |
for(int i=0; i
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
if(i==0)
|
|
Packit Service |
a2489d |
s.appendf("%s%s ",prefix,_("Now executing:"));
|
|
Packit Service |
a2489d |
if(v==0)
|
|
Packit Service |
a2489d |
waiting[i]->FormatOneJob(s,v);
|
|
Packit Service |
a2489d |
else
|
|
Packit Service |
a2489d |
waiting[i]->FormatJobTitle(s);
|
|
Packit Service |
a2489d |
if(i+1
|
|
Packit Service |
a2489d |
s.appendf("%s\t-",prefix);
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
return queue_feeder->FormatStatus(s,v,prefix);
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
if(waiting_num==1)
|
|
Packit Service |
a2489d |
return s.appendf(_("\tWaiting for job [%d] to terminate\n"),waiting[0]->jobno);
|
|
Packit Service |
a2489d |
else if(waiting_num>1)
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
s.appendf(_("\tWaiting for termination of jobs: "));
|
|
Packit Service |
a2489d |
for(int i=0; i
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
s.appendf("[%d]",waiting[i]->jobno);
|
|
Packit Service |
a2489d |
s.append(i+1
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
return s;
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
if(cmd_buf.Size()>0)
|
|
Packit Service |
a2489d |
s.append(_("\tRunning\n"));
|
|
Packit Service |
a2489d |
else if(feeder)
|
|
Packit Service |
a2489d |
s.append(_("\tWaiting for command\n"));
|
|
Packit Service |
a2489d |
return s;
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
void CmdExec::init(LocalDirectory *c)
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
// add this to chain
|
|
Packit Service |
a2489d |
next=chain;
|
|
Packit Service |
a2489d |
chain=this;
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
background=false;
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
interactive=false;
|
|
Packit Service |
a2489d |
show_status=true;
|
|
Packit Service |
a2489d |
top_level=false;
|
|
Packit Service |
a2489d |
auto_terminate_in_bg=false;
|
|
Packit Service |
a2489d |
feeder=0;
|
|
Packit Service |
a2489d |
feeder_called=false;
|
|
Packit Service |
a2489d |
used_aliases=0;
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
partial_cmd=false;
|
|
Packit Service |
a2489d |
alias_field=0;
|
|
Packit Service |
a2489d |
default_output=0;
|
|
Packit Service |
a2489d |
condition=COND_ANY;
|
|
Packit Service |
a2489d |
prev_exit_code=0;
|
|
Packit Service |
a2489d |
exit_code=0;
|
|
Packit Service |
a2489d |
failed_exit_code=0;
|
|
Packit Service |
a2489d |
last_bg=-1;
|
|
Packit Service |
a2489d |
fed_at_finish=true;
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
cwd=c;
|
|
Packit Service |
a2489d |
if(!cwd)
|
|
Packit Service |
a2489d |
SaveCWD();
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
remote_completion=false;
|
|
Packit Service |
a2489d |
long_running=0;
|
|
Packit Service |
a2489d |
csh_history=false;
|
|
Packit Service |
a2489d |
verify_host=verify_path=true;
|
|
Packit Service |
a2489d |
verify_path_cached=false;
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
start_time=0;
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
redirections=0;
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
queue_feeder=0;
|
|
Packit Service |
a2489d |
max_waiting=1;
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
saved_session=0;
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
builtin=BUILTIN_NONE;
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
Reconfig();
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
CmdExec::CmdExec(FileAccess *s,LocalDirectory *c)
|
|
Packit Service |
a2489d |
: SessionJob(s?s:new DummyProto), parent_exec(0)
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
init(c);
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
CmdExec::CmdExec(CmdExec *parent)
|
|
Packit Service |
a2489d |
: SessionJob(parent->session->Clone()), parent_exec(parent)
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
init(parent->cwd->Clone());
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
CmdExec::~CmdExec()
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
// remove this from chain.
|
|
Packit Service |
a2489d |
for(CmdExec **scan=&chain; *scan; scan=&(*scan)->next)
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
if(this==*scan)
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
*scan=(*scan)->next;
|
|
Packit Service |
a2489d |
break;
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
free_used_aliases();
|
|
Packit Service |
a2489d |
if(cwd_owner==this)
|
|
Packit Service |
a2489d |
cwd_owner=0;
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
const char *CmdExec::FormatPrompt(const char *scan)
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
const char *cwd=session->GetCwd();
|
|
Packit Service |
a2489d |
if(cwd==0 || cwd[0]==0)
|
|
Packit Service |
a2489d |
cwd="~";
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
const char *home=session->GetHome();
|
|
Packit Service |
a2489d |
int home_len=xstrlen(home);
|
|
Packit Service |
a2489d |
if(home_len>1 && !strncmp(cwd,home,home_len)
|
|
Packit Service |
a2489d |
&& (cwd[home_len]=='/' || cwd[home_len]==0))
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
cwd=xstring::format("~%s",cwd+home_len);
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
const char *cwdb=session->GetCwd();
|
|
Packit Service |
a2489d |
if(cwdb==0 || cwdb[0]==0)
|
|
Packit Service |
a2489d |
cwdb="~";
|
|
Packit Service |
a2489d |
const char *p=strrchr(cwdb,'/');
|
|
Packit Service |
a2489d |
if(p && p>cwdb)
|
|
Packit Service |
a2489d |
cwdb=p+1;
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
const char *lcwd=this->cwd->GetName();
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
const char *home=get_home();
|
|
Packit Service |
a2489d |
int home_len=xstrlen(home);
|
|
Packit Service |
a2489d |
if(home_len>1 && !strncmp(lcwd,home,home_len)
|
|
Packit Service |
a2489d |
&& (lcwd[home_len]=='/' || lcwd[home_len]==0))
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
lcwd=xstring::format("~%s",lcwd+home_len);
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
const char *lcwdb=this->cwd->GetName();
|
|
Packit Service |
a2489d |
p=strrchr(lcwdb,'/');
|
|
Packit Service |
a2489d |
if(p && p>lcwdb)
|
|
Packit Service |
a2489d |
lcwdb=p+1;
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
static const char StartIgn[]={RL_PROMPT_START_IGNORE,0};
|
|
Packit Service |
a2489d |
static const char EndIgn[]={RL_PROMPT_END_IGNORE,0};
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
subst_t subst[] = {
|
|
Packit Service |
a2489d |
{ 'a', "\007" },
|
|
Packit Service |
a2489d |
{ 'e', "\033" },
|
|
Packit Service |
a2489d |
{ 'n', "\n" },
|
|
Packit Service |
a2489d |
{ 's', "lftp" },
|
|
Packit Service |
a2489d |
{ 'v', VERSION },
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
{ 'h', session->GetHostName() },
|
|
Packit Service |
a2489d |
{ 'u', session->GetUser() },
|
|
Packit Service |
a2489d |
// @ if non-default user
|
|
Packit Service |
a2489d |
{ '@', session->GetUser()?"@":"" },
|
|
Packit Service |
a2489d |
{ 'U', session->GetConnectURL() },
|
|
Packit Service |
a2489d |
{ 'S', slot?slot.get():"" },
|
|
Packit Service |
a2489d |
{ 'w', cwd },
|
|
Packit Service |
a2489d |
{ 'W', cwdb },
|
|
Packit Service |
a2489d |
{ 'l', lcwd },
|
|
Packit Service |
a2489d |
{ 'L', lcwdb },
|
|
Packit Service |
a2489d |
{ '[', StartIgn },
|
|
Packit Service |
a2489d |
{ ']', EndIgn },
|
|
Packit Service |
a2489d |
{ 0, "" }
|
|
Packit Service |
a2489d |
};
|
|
Packit Service |
a2489d |
static xstring prompt;
|
|
Packit Service |
a2489d |
SubstTo(prompt, scan, subst);
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
return(prompt);
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
const char *CmdExec::MakePrompt()
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
if(partial_cmd)
|
|
Packit Service |
a2489d |
return "> ";
|
|
Packit Service |
a2489d |
return FormatPrompt(ResMgr::Query("cmd:prompt",getenv("TERM")));
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
void CmdExec::beep_if_long()
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
if(start_time!=0 && long_running!=0
|
|
Packit Service |
a2489d |
&& now.UnixTime()>start_time+long_running
|
|
Packit Service |
a2489d |
&& interactive && Idle() && isatty(1))
|
|
Packit Service |
a2489d |
write(1,"\007",1);
|
|
Packit Service |
a2489d |
AtFinish();
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
void CmdExec::Reconfig(const char *name)
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
const char *c=0;
|
|
Packit Service |
a2489d |
if(session)
|
|
Packit Service |
a2489d |
c = session->GetConnectURL(FA::NO_PATH);
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
long_running=ResMgr::Query("cmd:long-running",c);
|
|
Packit Service |
a2489d |
remote_completion=ResMgr::QueryBool("cmd:remote-completion",c);
|
|
Packit Service |
a2489d |
csh_history=ResMgr::QueryBool("cmd:csh-history",0);
|
|
Packit Service |
a2489d |
verify_path=ResMgr::QueryBool("cmd:verify-path",c);
|
|
Packit Service |
a2489d |
verify_path_cached=ResMgr::QueryBool("cmd:verify-path-cached",c);
|
|
Packit Service |
a2489d |
verify_host=ResMgr::QueryBool("cmd:verify-host",c);
|
|
Packit Service |
a2489d |
verbose=ResMgr::QueryBool("cmd:verbose",0);
|
|
Packit Service |
a2489d |
if(top_level || queue_feeder)
|
|
Packit Service |
a2489d |
max_waiting=ResMgr::Query(queue_feeder?"cmd:queue-parallel":"cmd:parallel",c);
|
|
Packit Service |
a2489d |
if(name && !strcmp(name,"cmd:interactive"))
|
|
Packit Service |
a2489d |
SetInteractive();
|
|
Packit Service |
a2489d |
show_status=ResMgr::QueryBool("cmd:show-status",0);
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
void CmdExec::pre_stdout()
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
if(status_line)
|
|
Packit Service |
a2489d |
status_line->Clear(false);
|
|
Packit Service |
a2489d |
if(feeder_called)
|
|
Packit Service |
a2489d |
feeder->clear();
|
|
Packit Service |
a2489d |
current->TimeoutS(1);
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
void CmdExec::top_vfprintf(FILE *file,const char *f,va_list v)
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
pre_stdout();
|
|
Packit Service |
a2489d |
::vfprintf(file,f,v);
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
void CmdExec::SetCmdFeeder(CmdFeeder *new_feeder)
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
new_feeder->prev=feeder;
|
|
Packit Service |
a2489d |
new_feeder->saved_buf.set(cmd_buf.Get());
|
|
Packit Service |
a2489d |
feeder=new_feeder;
|
|
Packit Service |
a2489d |
cmd_buf.Empty();
|
|
Packit Service |
a2489d |
SetInteractive();
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
int CmdExec::AcceptSig(int sig)
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
if(sig!=SIGINT && sig!=SIGTERM)
|
|
Packit Service |
a2489d |
return STALL;
|
|
Packit Service |
a2489d |
if(builtin)
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
switch(builtin)
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
case(BUILTIN_CD):
|
|
Packit Service |
a2489d |
session->Close();
|
|
Packit Service |
a2489d |
break;
|
|
Packit Service |
a2489d |
case(BUILTIN_OPEN):
|
|
Packit Service |
a2489d |
session->Close();
|
|
Packit Service |
a2489d |
RevertToSavedSession();
|
|
Packit Service |
a2489d |
break;
|
|
Packit Service |
a2489d |
case(BUILTIN_GLOB):
|
|
Packit Service |
a2489d |
glob=0;
|
|
Packit Service |
a2489d |
args_glob=0;
|
|
Packit Service |
a2489d |
break;
|
|
Packit Service |
a2489d |
case(BUILTIN_NONE):
|
|
Packit Service |
a2489d |
case(BUILTIN_EXEC_RESTART):
|
|
Packit Service |
a2489d |
abort(); // should not happen
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
builtin=BUILTIN_NONE;
|
|
Packit Service |
a2489d |
redirections=0;
|
|
Packit Service |
a2489d |
exit_code=1;
|
|
Packit Service |
a2489d |
return MOVED;
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
if(waiting_num>0)
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
int limit=waiting_num;
|
|
Packit Service |
a2489d |
for(int i=0; i
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
Job *r=waiting[i];
|
|
Packit Service |
a2489d |
int res=r->AcceptSig(sig);
|
|
Packit Service |
a2489d |
if(res==WANTDIE)
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
exit_code=1;
|
|
Packit Service |
a2489d |
RemoveWaiting(r);
|
|
Packit Service |
a2489d |
Delete(r);
|
|
Packit Service |
a2489d |
i--;
|
|
Packit Service |
a2489d |
limit--;
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
if(waiting_num==0 && parent!=0)
|
|
Packit Service |
a2489d |
return WANTDIE;
|
|
Packit Service |
a2489d |
return MOVED;
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
if(parent!=0)
|
|
Packit Service |
a2489d |
return WANTDIE;
|
|
Packit Service |
a2489d |
return STALL;
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
void CmdExec::SetInteractive(bool i)
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
if(interactive==i)
|
|
Packit Service |
a2489d |
return;
|
|
Packit Service |
a2489d |
if(i)
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
SignalHook::DoCount(SIGINT);
|
|
Packit Service |
a2489d |
SignalHook::DoCount(SIGTSTP);
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
else
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
SignalHook::Restore(SIGINT);
|
|
Packit Service |
a2489d |
SignalHook::Restore(SIGTSTP);
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
interactive=i;
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
void CmdExec::SetInteractive()
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
if(!top_level)
|
|
Packit Service |
a2489d |
return;
|
|
Packit Service |
a2489d |
bool def=feeder?feeder->IsInteractive():false;
|
|
Packit Service |
a2489d |
SetInteractive(ResMgr::QueryTriBool("cmd:interactive",0,def));
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
xstring& xstring::append_quoted(const char *str,int len)
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
if(!CmdExec::needs_quotation(str,len))
|
|
Packit Service |
a2489d |
return append(str);
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
append('"');
|
|
Packit Service |
a2489d |
while(len>0)
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
if(*str=='"' || *str=='\\')
|
|
Packit Service |
a2489d |
append('\\');
|
|
Packit Service |
a2489d |
append(*str++);
|
|
Packit Service |
a2489d |
len--;
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
return append('"');
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
bool CmdExec::needs_quotation(const char *buf,int len)
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
while(len>0)
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
if(*buf==' ' || *buf=='\t')
|
|
Packit Service |
a2489d |
return true;
|
|
Packit Service |
a2489d |
if(strchr("\"'\\&|;;",*buf))
|
|
Packit Service |
a2489d |
return true;
|
|
Packit Service |
a2489d |
buf++;
|
|
Packit Service |
a2489d |
len--;
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
return false;
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
void CmdExec::FeedQuoted(const char *c)
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
FeedCmd(xstring::get_tmp("").append_quoted(c));
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
// implementation is here because it depends on CmdExec.
|
|
Packit Service |
a2489d |
xstring& ArgV::CombineQuotedTo(xstring& res,int start) const
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
res.nset("",0);
|
|
Packit Service |
a2489d |
if(start>=Count())
|
|
Packit Service |
a2489d |
return res;
|
|
Packit Service |
a2489d |
for(;;)
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
const char *arg=String(start++);
|
|
Packit Service |
a2489d |
res.append_quoted(arg);
|
|
Packit Service |
a2489d |
if(start>=Count())
|
|
Packit Service |
a2489d |
return(res);
|
|
Packit Service |
a2489d |
res.append(' ');
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
xstring& ArgV::CombineCmdTo(xstring& res,int i) const
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
return i>=count()-1 ? CombineTo(res,i) : CombineQuotedTo(res,i);
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
const char *CmdExec::GetFullCommandName(const char *cmd)
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
const CmdExec::cmd_rec *c;
|
|
Packit Service |
a2489d |
int part=CmdExec::find_cmd(cmd,&c);
|
|
Packit Service |
a2489d |
if(part==1)
|
|
Packit Service |
a2489d |
return c->name;
|
|
Packit Service |
a2489d |
return cmd;
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
void CmdExec::AtExit()
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
FeedCmd(ResMgr::Query("cmd:at-exit",0));
|
|
Packit Service |
a2489d |
FeedCmd("\n");
|
|
Packit Service |
a2489d |
/* Clear the title, and ensure we don't write anything else
|
|
Packit Service |
a2489d |
* to it in case we're being backgrounded. */
|
|
Packit Service |
a2489d |
status_line=0;
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
void CmdExec::AtExitBg()
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
FeedCmd(ResMgr::Query("cmd:at-exit-bg",0));
|
|
Packit Service |
a2489d |
FeedCmd("\n");
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
void CmdExec::AtExitFg()
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
FeedCmd(ResMgr::Query("cmd:at-exit-fg",0));
|
|
Packit Service |
a2489d |
FeedCmd("\n");
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
void CmdExec::AtBackground()
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
FeedCmd(ResMgr::Query("cmd:at-background",0));
|
|
Packit Service |
a2489d |
FeedCmd("\n");
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
void CmdExec::AtTerminate()
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
FeedCmd(ResMgr::Query("cmd:at-terminate",0));
|
|
Packit Service |
a2489d |
FeedCmd("\n");
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
void CmdExec::EmptyCmds()
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
cmd_buf.Empty();
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
bool CmdExec::WriteCmds(int fd) const
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
const char *buf;
|
|
Packit Service |
a2489d |
int len;
|
|
Packit Service |
a2489d |
cmd_buf.Get(&buf,&len;;
|
|
Packit Service |
a2489d |
for(;;)
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
if(len==0)
|
|
Packit Service |
a2489d |
return true;
|
|
Packit Service |
a2489d |
int res=write(fd,buf,len);
|
|
Packit Service |
a2489d |
if(res<=0)
|
|
Packit Service |
a2489d |
return false;
|
|
Packit Service |
a2489d |
buf+=res;
|
|
Packit Service |
a2489d |
len-=res;
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
bool CmdExec::ReadCmds(int fd)
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
for(;;)
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
int size=0x1000;
|
|
Packit Service |
a2489d |
size=read(fd,cmd_buf.GetSpace(size),size);
|
|
Packit Service |
a2489d |
if(size==-1)
|
|
Packit Service |
a2489d |
return false;
|
|
Packit Service |
a2489d |
if(size==0)
|
|
Packit Service |
a2489d |
return true;
|
|
Packit Service |
a2489d |
cmd_buf.SpaceAdd(size);
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
void CmdExec::free_used_aliases()
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
if(used_aliases)
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
TouchedAlias::FreeChain(used_aliases);
|
|
Packit Service |
a2489d |
used_aliases=0;
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
alias_field=0;
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
void CmdExec::skip_cmd(int len)
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
cmd_buf.Skip(len);
|
|
Packit Service |
a2489d |
alias_field-=len;
|
|
Packit Service |
a2489d |
if(alias_field<=0)
|
|
Packit Service |
a2489d |
free_used_aliases();
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
int CmdExec::cmd_rec::cmp(const CmdExec::cmd_rec *a,const CmdExec::cmd_rec *b)
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
return strcmp(a->name,b->name);
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
xarray<CmdExec::cmd_rec> CmdExec::dyn_cmd_table;
|
|
Packit Service |
a2489d |
void CmdExec::RegisterCommand(const char *name,cmd_creator_t creator,const char *short_desc,const char *long_desc)
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
if(dyn_cmd_table==0)
|
|
Packit Service |
a2489d |
dyn_cmd_table.nset(static_cmd_table,static_cmd_table_length);
|
|
Packit Service |
a2489d |
cmd_rec new_entry={name,creator,short_desc,long_desc};
|
|
Packit Service |
a2489d |
int i;
|
|
Packit Service |
a2489d |
if(dyn_cmd_table.bsearch(new_entry,cmd_rec::cmp,&i))
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
cmd_rec *const c=&dyn_cmd_table[i];
|
|
Packit Service |
a2489d |
c->creator=creator;
|
|
Packit Service |
a2489d |
if(short_desc)
|
|
Packit Service |
a2489d |
c->short_desc=short_desc;
|
|
Packit Service |
a2489d |
if(long_desc || strlen(c->long_desc)<2)
|
|
Packit Service |
a2489d |
c->long_desc=long_desc;
|
|
Packit Service |
a2489d |
return;
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
dyn_cmd_table.insert(new_entry,i);
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
void CmdExec::ChangeSession(FileAccess *new_session)
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
session=new_session;
|
|
Packit Service |
a2489d |
session->SetPriority(fg?1:0);
|
|
Packit Service |
a2489d |
Reconfig(0);
|
|
Packit Service |
a2489d |
if(slot)
|
|
Packit Service |
a2489d |
ConnectionSlot::Set(slot,session);
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
const char *CmdExec::CmdByIndex(int i)
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
if(dyn_cmd_table)
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
if(i
|
|
Packit Service |
a2489d |
return dyn_cmd_table[i].name;
|
|
Packit Service |
a2489d |
return 0;
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
return static_cmd_table[i].name;
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
bool CmdExec::load_cmd_module(const char *op)
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
const char *modname=xstring::cat("cmd-",op,NULL);
|
|
Packit Service |
a2489d |
if(module_init_preloaded(modname))
|
|
Packit Service |
a2489d |
return true;
|
|
Packit Service |
a2489d |
#ifdef WITH_MODULES
|
|
Packit Service |
a2489d |
if(module_load(modname,0,0)==0)
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
eprintf("%s\n",module_error_message());
|
|
Packit Service |
a2489d |
return false;
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
return true;
|
|
Packit Service |
a2489d |
#else
|
|
Packit Service |
a2489d |
eprintf(_("%s: command `%s' is not compiled in.\n"),op,op);
|
|
Packit Service |
a2489d |
return false;
|
|
Packit Service |
a2489d |
#endif
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
Job *CmdExec::default_cmd()
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
const char *op=args->a0();
|
|
Packit Service |
a2489d |
if(load_cmd_module(op)) {
|
|
Packit Service |
a2489d |
builtin=BUILTIN_EXEC_RESTART;
|
|
Packit Service |
a2489d |
return this;
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
return 0;
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
Job *CmdExec::builtin_local()
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
if(args->count()<2) {
|
|
Packit Service |
a2489d |
eprintf(_("Usage: %s cmd [args...]\n"),args->a0());
|
|
Packit Service |
a2489d |
return 0;
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
saved_session=session.borrow();
|
|
Packit Service |
a2489d |
session=FileAccess::New("file");
|
|
Packit Service |
a2489d |
if(!session) {
|
|
Packit Service |
a2489d |
eprintf(_("%s: cannot create local session\n"),args->a0());
|
|
Packit Service |
a2489d |
RevertToSavedSession();
|
|
Packit Service |
a2489d |
return 0;
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
session->SetCwd(cwd->GetName());
|
|
Packit Service |
a2489d |
args->delarg(0);
|
|
Packit Service |
a2489d |
builtin=BUILTIN_EXEC_RESTART;
|
|
Packit Service |
a2489d |
return this;
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
void CmdExec::FeedArgV(const ArgV *args,int start)
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
xstring cmd;
|
|
Packit Service |
a2489d |
args->CombineCmdTo(cmd,start);
|
|
Packit Service |
a2489d |
FeedCmd(cmd);
|
|
Packit Service |
a2489d |
FeedCmd("\n");
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
bool CmdExec::SameQueueParameters(CmdExec *scan,const char *this_url)
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
return !strcmp(this_url,scan->session->GetConnectURL(FA::NO_PATH))
|
|
Packit Service |
a2489d |
&& this->slot.eq(scan->slot);
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
/* return the CmdExec containing a queue feeder; create if necessary */
|
|
Packit Service |
a2489d |
CmdExec *CmdExec::GetQueue(bool create)
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
const char *this_url=session->GetConnectURL(FA::NO_PATH);
|
|
Packit Service |
a2489d |
// future GetConnectURL overwrite the static buffer, save it.
|
|
Packit Service |
a2489d |
this_url=alloca_strdup(this_url);
|
|
Packit Service |
a2489d |
for(CmdExec *scan=chain; scan; scan=scan->next)
|
|
Packit Service |
a2489d |
{
|
|
Packit Service |
a2489d |
if(scan->queue_feeder && SameQueueParameters(scan,this_url))
|
|
Packit Service |
a2489d |
return scan;
|
|
Packit Service |
a2489d |
}
|
|
Packit Service |
a2489d |
if(!create)
|
|
Packit Service |
a2489d |
return NULL;
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
CmdExec *queue=new CmdExec(session->Clone(),cwd->Clone());
|
|
Packit Service |
a2489d |
queue->slot.set(slot);
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
queue->SetParentFg(this,false);
|
|
Packit Service |
a2489d |
queue->AllocJobno();
|
|
Packit Service |
a2489d |
const char *url=session->GetConnectURL(FA::NO_PATH);
|
|
Packit Service |
a2489d |
queue->cmdline.vset("queue (",url,slot?"; ":"",slot?slot.get():"",")",NULL);
|
|
Packit Service |
a2489d |
queue->queue_feeder=new QueueFeeder(session->GetCwd(), cwd->GetName());
|
|
Packit Service |
a2489d |
queue->SetCmdFeeder(queue->queue_feeder);
|
|
Packit Service |
a2489d |
queue->Reconfig(0);
|
|
Packit Service |
a2489d |
|
|
Packit Service |
a2489d |
return queue;
|
|
Packit Service |
a2489d |
}
|