Blame src/SysCmdJob.cc

Packit 8f70b4
/*
Packit 8f70b4
 * lftp - file transfer program
Packit 8f70b4
 *
Packit 8f70b4
 * Copyright (c) 1996-2012 by Alexander V. Lukyanov (lav@yars.free.net)
Packit 8f70b4
 *
Packit 8f70b4
 * This program is free software; you can redistribute it and/or modify
Packit 8f70b4
 * it under the terms of the GNU General Public License as published by
Packit 8f70b4
 * the Free Software Foundation; either version 3 of the License, or
Packit 8f70b4
 * (at your option) any later version.
Packit 8f70b4
 *
Packit 8f70b4
 * This program is distributed in the hope that it will be useful,
Packit 8f70b4
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 8f70b4
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit 8f70b4
 * GNU General Public License for more details.
Packit 8f70b4
 *
Packit 8f70b4
 * You should have received a copy of the GNU General Public License
Packit 8f70b4
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
Packit 8f70b4
 */
Packit 8f70b4
Packit 8f70b4
#include <config.h>
Packit 8f70b4
Packit 8f70b4
#include <sys/types.h>
Packit 8f70b4
#include <sys/wait.h>
Packit 8f70b4
#include <unistd.h>
Packit 8f70b4
#include <errno.h>
Packit 8f70b4
Packit 8f70b4
#include "SysCmdJob.h"
Packit 8f70b4
#include "SignalHook.h"
Packit 8f70b4
#include "misc.h"
Packit 8f70b4
Packit 8f70b4
#define super Job
Packit 8f70b4
Packit 8f70b4
SysCmdJob::SysCmdJob(const char *c)
Packit 8f70b4
   : cmd(c)
Packit 8f70b4
{
Packit 8f70b4
}
Packit 8f70b4
Packit 8f70b4
void SysCmdJob::PrepareToDie()
Packit 8f70b4
{
Packit 8f70b4
   Bg();
Packit 8f70b4
   AcceptSig(SIGTERM);
Packit 8f70b4
   if(w)
Packit 8f70b4
      w.borrow()->Auto();
Packit 8f70b4
   super::PrepareToDie();
Packit 8f70b4
}
Packit 8f70b4
SysCmdJob::~SysCmdJob() {}
Packit 8f70b4
Packit 8f70b4
int SysCmdJob::Do()
Packit 8f70b4
{
Packit 8f70b4
   int m=STALL;
Packit 8f70b4
Packit 8f70b4
   if(w)
Packit 8f70b4
      return m;
Packit 8f70b4
Packit 8f70b4
   const char *shell=getenv("SHELL");
Packit 8f70b4
   if(!shell)
Packit 8f70b4
      shell="/bin/sh";
Packit 8f70b4
Packit 8f70b4
   ProcWait::Signal(false);
Packit 8f70b4
Packit 8f70b4
   pid_t pid;
Packit 8f70b4
   fflush(stderr);
Packit 8f70b4
   switch(pid=fork())
Packit 8f70b4
   {
Packit 8f70b4
   case(0): /* child */
Packit 8f70b4
      setpgid(0,0);
Packit 8f70b4
      kill(getpid(),SIGSTOP);
Packit 8f70b4
      SignalHook::RestoreAll();
Packit 8f70b4
      if(cmd)
Packit 8f70b4
	 execlp(shell,basename_ptr(shell),"-c",cmd.get(),NULL);
Packit 8f70b4
      else
Packit 8f70b4
	 execlp(shell,basename_ptr(shell),NULL);
Packit 8f70b4
      fprintf(stderr,_("execlp(%s) failed: %s\n"),shell,strerror(errno));
Packit 8f70b4
      fflush(stderr);
Packit 8f70b4
      _exit(1);
Packit 8f70b4
   case(-1): /* error */
Packit 8f70b4
      TimeoutS(1);   // wait a second and retry
Packit 8f70b4
      goto out;
Packit 8f70b4
   }
Packit 8f70b4
   /* parent */
Packit 8f70b4
   int info;
Packit 8f70b4
   waitpid(pid,&info,WUNTRACED); // wait until the process stops
Packit 8f70b4
   w=new ProcWait(pid);
Packit 8f70b4
   fg_data=new FgData(pid,fg);
Packit 8f70b4
   m=MOVED;
Packit 8f70b4
out:
Packit 8f70b4
   ProcWait::Signal(true);
Packit 8f70b4
   return m;
Packit 8f70b4
}
Packit 8f70b4
Packit 8f70b4
int SysCmdJob::AcceptSig(int sig)
Packit 8f70b4
{
Packit 8f70b4
   if(!w)
Packit 8f70b4
   {
Packit 8f70b4
      if(sig==SIGINT)
Packit 8f70b4
	 return WANTDIE;
Packit 8f70b4
      return STALL;
Packit 8f70b4
   }
Packit 8f70b4
   w->Kill(sig);
Packit 8f70b4
   if(sig!=SIGCONT)
Packit 8f70b4
      AcceptSig(SIGCONT);  // for the case of stopped process
Packit 8f70b4
   return MOVED;
Packit 8f70b4
}