Blame src/SysCmdJob.cc

Packit Service a2489d
/*
Packit Service a2489d
 * lftp - file transfer program
Packit Service a2489d
 *
Packit Service a2489d
 * Copyright (c) 1996-2012 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
Packit Service a2489d
#include <sys/types.h>
Packit Service a2489d
#include <sys/wait.h>
Packit Service a2489d
#include <unistd.h>
Packit Service a2489d
#include <errno.h>
Packit Service a2489d
Packit Service a2489d
#include "SysCmdJob.h"
Packit Service a2489d
#include "SignalHook.h"
Packit Service a2489d
#include "misc.h"
Packit Service a2489d
Packit Service a2489d
#define super Job
Packit Service a2489d
Packit Service a2489d
SysCmdJob::SysCmdJob(const char *c)
Packit Service a2489d
   : cmd(c)
Packit Service a2489d
{
Packit Service a2489d
}
Packit Service a2489d
Packit Service a2489d
void SysCmdJob::PrepareToDie()
Packit Service a2489d
{
Packit Service a2489d
   Bg();
Packit Service a2489d
   AcceptSig(SIGTERM);
Packit Service a2489d
   if(w)
Packit Service a2489d
      w.borrow()->Auto();
Packit Service a2489d
   super::PrepareToDie();
Packit Service a2489d
}
Packit Service a2489d
SysCmdJob::~SysCmdJob() {}
Packit Service a2489d
Packit Service a2489d
int SysCmdJob::Do()
Packit Service a2489d
{
Packit Service a2489d
   int m=STALL;
Packit Service a2489d
Packit Service a2489d
   if(w)
Packit Service a2489d
      return m;
Packit Service a2489d
Packit Service a2489d
   const char *shell=getenv("SHELL");
Packit Service a2489d
   if(!shell)
Packit Service a2489d
      shell="/bin/sh";
Packit Service a2489d
Packit Service a2489d
   ProcWait::Signal(false);
Packit Service a2489d
Packit Service a2489d
   pid_t pid;
Packit Service a2489d
   fflush(stderr);
Packit Service a2489d
   switch(pid=fork())
Packit Service a2489d
   {
Packit Service a2489d
   case(0): /* child */
Packit Service a2489d
      setpgid(0,0);
Packit Service a2489d
      kill(getpid(),SIGSTOP);
Packit Service a2489d
      SignalHook::RestoreAll();
Packit Service a2489d
      if(cmd)
Packit Service a2489d
	 execlp(shell,basename_ptr(shell),"-c",cmd.get(),NULL);
Packit Service a2489d
      else
Packit Service a2489d
	 execlp(shell,basename_ptr(shell),NULL);
Packit Service a2489d
      fprintf(stderr,_("execlp(%s) failed: %s\n"),shell,strerror(errno));
Packit Service a2489d
      fflush(stderr);
Packit Service a2489d
      _exit(1);
Packit Service a2489d
   case(-1): /* error */
Packit Service a2489d
      TimeoutS(1);   // wait a second and retry
Packit Service a2489d
      goto out;
Packit Service a2489d
   }
Packit Service a2489d
   /* parent */
Packit Service a2489d
   int info;
Packit Service a2489d
   waitpid(pid,&info,WUNTRACED); // wait until the process stops
Packit Service a2489d
   w=new ProcWait(pid);
Packit Service a2489d
   fg_data=new FgData(pid,fg);
Packit Service a2489d
   m=MOVED;
Packit Service a2489d
out:
Packit Service a2489d
   ProcWait::Signal(true);
Packit Service a2489d
   return m;
Packit Service a2489d
}
Packit Service a2489d
Packit Service a2489d
int SysCmdJob::AcceptSig(int sig)
Packit Service a2489d
{
Packit Service a2489d
   if(!w)
Packit Service a2489d
   {
Packit Service a2489d
      if(sig==SIGINT)
Packit Service a2489d
	 return WANTDIE;
Packit Service a2489d
      return STALL;
Packit Service a2489d
   }
Packit Service a2489d
   w->Kill(sig);
Packit Service a2489d
   if(sig!=SIGCONT)
Packit Service a2489d
      AcceptSig(SIGCONT);  // for the case of stopped process
Packit Service a2489d
   return MOVED;
Packit Service a2489d
}