Some stuff in my tree I'm shelving:

OutputJob.  It's useful, fixes the cls bug, and makes buffered outputting
trivial from any job, but it's still a bit overcomplicated and I havn't
had the interest in it recently to nail down the rest of the bugs.  (You
don't seem particularly interested in it, either.)

Some m4 patches that come closer to quieting the autoconf deprecation warning.
I sent these in, you only applied about half of them, not going to keep the
rest around if you won't apply them.

Unicode quotes.  This needs a clean way to switch back to non-Unicode
quotes, that seems to need help from gettext, and there doesn't seem to
be interest upstream to get that help right now.  I think they're nice,
and it's great to stop overloading ` and ' all over the place, so I
might revisit this.  (No files for this one, since it broke during the
gettext update and I never fixed it.)

Attached patches to get them archived; all source files correspond to
OutputJob.

-- 
Glenn Maynard
/* lftp and utils
 *
 * Copyright (c) 2002 by Alexander V. Lukyanov ([EMAIL PROTECTED])
 *
 * 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 2 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, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

/* Usage notes: 
 * 
 * Set AllowPostpone to true if sending large amounts of data.  Check the
 * result of each Put and Format call to see if a write was postponed.
 * If disabled, writes will always succeed.
 *
 * This is useful for jobs with a lot of output, like "cat". This can be
 * set selectively, where convenient.  For example, a job which outputs a
 * line of formatted text, followed by the contents of a file, can send
 * the first line with AllowPostpone off, then the file with it on.
 * 
 * Call PreFilter() to add a filter to the beginning of the chain; these
 * filters are initialized only once for all data.  For example,
 * PreFilter("wc -l")
 *
 */

/* 
 * Implementation notes:
 * Background things we can't get around: 
 * We must buffer (via FileCopy) output to a filter, since it might block.
 *
 * We must buffer the output from the filter to an output FileCopyPeer (ie.
 * a URL), for the same reason.
 *
 * So, we're stuck with having up to two FileCopy's.  (One to send, one to filter.)
 *
 * In some cases, we only need one: if the output is an FD, the filter can
 * hook up directly and we can forget about that stage.
 *
 * In the case where we're outputting to a URL, we set up a FileCopy from a
 * pipe to the URL, and then pretend we're just outputting to an FD (the
 * pipe.)
 * 
 * to it and pretend we're just outputting to a file; this simplifies things
 * significantly.  This means in the simple case of having no filters at
 * all, writing to a URL or file, we send the data an extra time through
 * a FileCopy and a pipe.  That's a bit inefficient, but that's
 * "cat file1 > file2"; that's normally done with "get file1 -o file2", so
 * this shouldn't happen often.
 *
 * It's very important that if the output is stdout, any filters point directly
 * at it, not through an extra copy: a pager, for example, will expect the output
 * to be a TTY.
 *
 */
#include <config.h>

#include "OutputJob.h"
#include "ArgV.h"
#include "FileCopy.h"
#include "CopyJob.h"
#include "url.h"
#include "misc.h"
#include "StatusLine.h"
#include "LocalAccess.h"

#include <assert.h>
#include <unistd.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <fcntl.h>

#define super Job

void OutputJob::InitCopy()
{
   if(error)
      return;
   
   if(initialized)
      return;

   initialized=true;
      
   if(filter)
   {
      /* Create the global filter: */
      OutputFilter *global = new OutputFilter(filter, output_fd);
      global->DeleteSecondaryStream();
      output_fd=global;
   }

   /* Use a FileCopy to buffer our output to the filter: */
   FileCopyPeerFDStream *out = new FileCopyPeerFDStream(output_fd, FileCopyPeer::PUT);
   out->DontDeleteStream();
   
   FileCopy *input_fc = FileCopy::New(new FileCopyPeer(FileCopyPeer::GET), out, false);

   if(!fail_if_broken)
      input_fc->DontFailIfBroken();

   char *buf = xasprintf(_("%s (filter)"), a0);
   input=new CopyJob(input_fc, buf, filter?filter:a0);
   xfree(buf);

   if(!output)
      output=input;

   input->SetParentFg(this);
   InputPeer()->SetDate(NO_DATE);
   InputPeer()->SetSize(NO_SIZE);
   input->GetCopy()->DontCopyDate();
   input->NoStatus();

   if(input != output)
   {
      output->SetParentFg(this);
      OutputPeer()->SetDate(NO_DATE);
      OutputPeer()->SetSize(NO_SIZE);
      output->GetCopy()->DontCopyDate();
      output->NoStatus();
   }

   if(is_stdout)
   {
      output->ClearStatusOnWrite();
      output->GetCopy()->LineBuffered();
   }

   Timeout(0);
}

void OutputJob::Init(const char *_a0)
{
   input=output=0;
   filter=0;
   initialized=false;
   error=false;
   no_status=false;
   eof=false;
   a0=xstrdup(_a0);
   last.Set(0,0);
   is_stdout=false;
   fail_if_broken=true;
   output_fd=0;
}

/* Local (fd) output. */
OutputJob::OutputJob(FDStream *output_, const char *a0):
   inter(1)
{
   Init(a0);

   output_fd=output_;

   if(!output_fd)
      output_fd=new FDStream(1,"<stdout>");
   else
      // some legitimate uses produce broken pipe condition (cat|head)
      // TODO: once actual piping uses OutputJob, set this only when
      // really doing a pipe, so cat>file can produce broken pipe
      fail_if_broken=false;

   is_stdout=output_fd->usesfd(1);

   /* We don't output status when outputting locally. */
   no_status=true;

   /* Make sure that if the output is going to fail, it fails early, so
    * the parent doesn't start anything expensive (like begin downloading
    * a file.) */
   if(output_fd->getfd() == -1)
   {
      eprintf("%s: %s\n", a0, output_fd->error_text);
      error=true;
   }
}

OutputJob::OutputJob(const char *path, const char *a0, FileAccess *fa):
   inter(1)
{
   Init(a0);

   /* Set up a pipe sending data at the peer, so we can act like the FDStream
    * constructor. */
   int filter_pipe[2];

   if(pipe(filter_pipe) == -1) {
      /* FIXME: This can be retryable. */
      eprintf("%s: %s\n", a0, strerror(errno));
      error=true;
      /* This won't actually be written to, since error is set, but we must set
       * it to something. */
      output_fd=new FDStream(1, "<stdout>");
      return;
   }

   bool reuse = false;
   if(!fa)
   {
      fa = new LocalAccess;
      reuse = true;
   }

   FileCopyPeerFA *dst_peer = FileCopyPeerFA::New(fa, path, FA::STORE, reuse);

   /* Status only for remote outputs. */
   if(!strcmp(dst_peer->GetProto(), "file"))
      no_status=true;

   fcntl(filter_pipe[0],F_SETFL,O_NONBLOCK);
   fcntl(filter_pipe[1],F_SETFL,O_NONBLOCK);

   /* The output of the pipe (0) goes to the output FileCopy. */ 
   FDStream *pipe_output = new FDStream(filter_pipe[0],"<filter-out>");

   FileCopy *output_fc=FileCopy::New(new FileCopyPeerFDStream(pipe_output, FileCopyPeer::GET), dst_peer,false);
   output=new CopyJob(output_fc, path, a0);

   output_fd=new FDStream(filter_pipe[1],"<filter-in>");
   
   pipe_output->CloseFD();
   output_fd->CloseFD();
}

OutputJob::~OutputJob()
{
   Bg();
   AcceptSig(SIGTERM);

   Delete(input);
   if(input != output)
      Delete(output);
   delete output_fd;

   xfree(a0);
   xfree(filter);
}

void OutputJob::Reconfig(const char *r)
{
   if(!r || !strcmp(r,"cmd:status-interval"))
   {
      inter=TimeInterval((const char*)ResMgr::Query("cmd:status-interval",0));
   }
}

bool OutputJob::ShowStatusLine()
{
   /* If our output file is gone, or isn't stdout, we don't care, */
   if(!output || !is_stdout)
      return true;

   /* If we're filtered, we never display at all.  (We don't know anything about
    * the filter's output; the only time we do is when we're outputting to a URL
    * or a file, and that doesn't apply here.) */
   if(IsFiltered())
      return false;

   /* If we're not line buffered, display only if the output CopyJob says to. */
   if(!output->GetCopy()->IsLineBuffered())
      return output->HasStatus();

   /* We're line buffered, so we can output a status line without stomping
    * on a partially output line.
    * 
    * Don't display the statusline if the we've output something within the
    * last status interval, so if we're currently bursting output we won't
    * flicker status for no reason.  (Actually, we should be concerned about
    * the last time the output peer has sent something...) */
   if(now - last < inter)
      return false;

   last = now;

   /* Stop the output again, so the FileCopy will clear the StatusLine
    * when there's more data. */
   output->GetCopy()->AllowWrite(false);

   return true;
}

const char *OutputJob::Status(const StatusLine *s)
{
   if(no_status)
      return "";

   /* Never show anything if we havn't even received any data yet; it won't
    * start connecting until then, so it's not interesting. */
   if(!initialized)
      return "";

   /* Use the status from the output CopyJob.  It'll be the one that's connecting
    * to a host, if applicable. */
   return output->Status(s,true);
}

void OutputJob::PutEOF()
{
   /* Make sure we've sent at least one (empty) block.  This ensures
    * that we always start the input->output code path. */
   Put("", 0);

   if(InputPeer())
      InputPeer()->PutEOF();
   eof=true;
}

/* add a filter to the beginning of the list */
void OutputJob::PreFilter(const char *newfilter)
{
   if(!filter)
   {
      SetFilter(newfilter);
      return;
   }

   char *newstr = xasprintf("%s | %s", newfilter, filter);
   SetFilter(newstr);
   printf("new: '%s'\n", newstr);
   xfree(newstr);
}

void OutputJob::SetFilter(const char *newfilter)
{
   xfree(filter);
   filter=xstrdup(newfilter);
}

int OutputJob::GetWidth() const
{
   if(IsFiltered() || output_fd->getfd() != 1)
      return -1;
   return fd_width(1);
}

bool OutputJob::IsTTY() const
{
   if(IsFiltered() || output_fd->getfd() != 1)
      return false;
   return isatty(1);
}

/* Get the input FileCopyPeer; this is the buffer we write to. */
FileCopyPeer *OutputJob::InputPeer() const
{
   return input? input->GetGet():0;
}

/* Get the output FileCopyPeer (the FileCopyPeer that's doing the final output). */
FileCopyPeer *OutputJob::OutputPeer() const
{
   return output? output->GetPut():0;
}

/* We're done if the output is finished, or on error. */
int OutputJob::Done()
{
   if(Error())
      return true;
   
   /* We're always done if the output breaks, regardless of whether
    * we treat it as an error or not. */
   if(output_fd->broken())
      return true;

   if(!initialized)
      return false;

   if(input && !input->Done())
     return false;
   if(output && !output->Done())
     return false;
   if(output_fd && !output_fd->Done())
     return false;
   
      return true;
   return false;
   if(eof && input && input->Done() && output && output->Done())
//   if(eof && output && output->Done())
   {
	   printf("xxxxxx\n");
      return true;
   }
   
   return false;
}

int OutputJob::Do()
{
   if(!fg_data && output_fd && output_fd->GetProcGroup())
   {
      fg_data=new FgData(output_fd->GetProcGroup(),fg);
      return MOVED;
   }
   
   return STALL;
}

/* Don't register errors until they're actually printed by
 * the sub-job (ie. it's also Done()). */
bool OutputJob::Error()
{
   if(error)
      return true;
   if(input && input->Error() && input->Done())
      error=true;
   if(output && input != output && output->Error() && output->Done())
      error=true;
   if(fail_if_broken && output_fd->broken())
      error=true;
   return error;
}

void OutputJob::Fg()
{
   super::Fg();
   if(input)
      input->Fg();
   if(output && input != output)
      output->Fg();
}

void OutputJob::Bg()
{
   if(output && input != output)
      output->Bg();
   if(input)
      input->Bg();
   super::Bg();
}

void OutputJob::Suspend()
{
   if(input)
      input->Suspend();
   if(output && input != output)
      output->Suspend();
   super::Suspend();
}

void OutputJob::Resume()
{
   if(input)
      input->Resume();
   if(output && input != output)
      output->Resume();
   super::Resume();
}

bool OutputJob::Full()
{
   if(input == 0)
      return false;

   /* It'd be nicer to just check copy->GetGet()->IsSuspended(), since
    * the FileCopy will suspend the Get end if the Put end gets filled.
    * However, it won't do that until it actually tries to send something. */
   int size = 0;
   if(input->GetPut())
      size += input->GetPut()->Buffered();
   if(input->GetGet())
      size += input->GetGet()->Buffered();
   if(input != output)
   {
      if(output->GetPut())
	 size += output->GetPut()->Buffered();
      if(output->GetGet())
	 size += output->GetGet()->Buffered();
   }

   return size >= 0x10000;
}

/* We'll actually go over the buffer limit here; that's OK; it's not a
 * strict value.  (It's not convenient to prevent that completely with
 * Format(), either.) */
void OutputJob::Put(const char *buf,int size)
{
   InitCopy();
   if(!InputPeer())
      return;

   last.SetToCurrentTime();

   int oldpos = InputPeer()->GetPos();
   InputPeer()->Put(buf, size);
   InputPeer()->SetPos(oldpos);
}

void OutputJob::Format(const char *f,...)
{
   InitCopy();
   if(!InputPeer())
      return;

   int oldpos = InputPeer()->GetPos();

   va_list v;
   va_start(v,f);
   InputPeer()->vFormat(f, v);
   va_end(v);

   InputPeer()->SetPos(oldpos);
}

/* Propagate signals down to our child processes. */
int OutputJob::AcceptSig(int sig)
{
   int m=MOVED;
   if(sig == SIGTERM || sig == SIGINT)
      m=WANTDIE;
   
   /* If we have an input copier right now, it'll contain the top filter
    * (which is linked to all other filters), so send it the signal. */
   if(input)
      m=input->AcceptSig(sig);
   /* Otherwise, the only filters we have running are in output_fd. */
   else
      output_fd->Kill(sig);
   if(sig!=SIGCONT)
      AcceptSig(SIGCONT);
   return m;
}

#ifndef OUTPUTJOB_H
#define OUTPUTJOB_H

#include "Job.h"
#include "FileCopy.h"
#include "CopyJob.h"
#include "TimeDate.h"

class StatusBar;

class OutputJob : public Job
{
   /* Main CopyJob: */
   CopyJob *input;

   /* CopyJob that sends to the output.  (output may be equal to input) */
   CopyJob *output;

   FDStream *output_fd;
   
   bool initialized;

   char *a0;
   char *filter;

   bool error;
   bool is_stdout;
   bool fail_if_broken;
   bool eof;

   /* if true, we never contribute to the parent job's status
    * (Status() == "") */
   bool no_status;

   Time last;
   TimeInterval inter;

   void Init(const char *a0);
   void InitCopy();

   void SetError(const char *e, ...) PRINTF_LIKE(2,3);

   /* Get the input FileCopyPeer */
   FileCopyPeer *InputPeer() const;

   /* Get the output FileCopyPeer (the FileCopyPeer that's doing the final output) */
   FileCopyPeer *OutputPeer() const;
   
public:
   OutputJob(FDStream *output, const char *a0);
   OutputJob(const char *path, const char *a0, FA *fa=0);
   ~OutputJob();

   /* Set the main filter: */
   void SetFilter(const char *filter);
   /* Prepend a filter before the main filter: */
   void PreFilter(const char *filter);

   void DontFailIfBroken(bool n=false) { fail_if_broken=n; }
   bool Error();

   int Done();
   int Do();

   void Put(const char *buf,int size);
   void Put(const char *buf) { return Put(buf,strlen(buf)); }
   void Format(const char *f,...) PRINTF_LIKE(2,3);
   void PutEOF();

   /* Return true if our buffers don't want any more input.  (They'll always
    * *accept* more input; this is optional.) */
   bool Full();

   /* Get properties of the output: */
   int GetWidth() const;
   bool IsTTY() const;
   /* Whether the ultimate destination is stdout: */
   bool IsStdout() const { return is_stdout; }
   /* Whether the output is filtered: */
   bool IsFiltered() const { return filter; }

   /* Call before showing a StatusLine on a job using this class.  If it
    * returns false, don't display it. */
   bool ShowStatusLine();

   const char *Status(const StatusLine *s);
   void Reconfig(const char *r);

   void Fg();
   void Bg();
   void Suspend();
   void Resume();
   int AcceptSig(int sig);
};

#endif
/*
 * lftp and utils
 *
 * Copyright (c) 2001 by Alexander V. Lukyanov ([EMAIL PROTECTED])
 *
 * 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 2 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, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

#include <config.h>

#include "echoJob.h"
#include "misc.h"

#define super Job

echoJob::echoJob(const char *buf, int len, OutputJob *_output)
{
   output=_output;
   AddWaiting(output);
   output->SetParentFg(this);
   output->Put(buf, len);
   output->PutEOF();
}

echoJob::echoJob(const char *buf, OutputJob *_output)
{
   output=_output;
   AddWaiting(output);
   output->SetParentFg(this);
   output->Put(buf);
   output->PutEOF();
}

echoJob::~echoJob()
{
   Delete(output);
}

int echoJob::Done()
{
   return output->Done();
}

int echoJob::ExitCode()
{
   /* if the output fails, we failed */
   return output->Error()? 1:0;
}

/* We have no interesting status for "jobs", so we have no PrintStatus
 * override.  (The output job will print the output status, if relevant.) */

void  echoJob::ShowRunStatus(StatusLine *s)
{
   if(Done())
      return;

   /* Never call output->ShowStatusLine unless we're really going
    * to display something. */
   const char *stat = output->Status(s);
   if(*stat && output->ShowStatusLine())
      s->Show("echo: %s", stat);
}

void echoJob::Fg()
{
   super::Fg();
   if(output)
      output->Fg();
}
void echoJob::Bg()
{
   if(output)
      output->Bg();
   super::Bg();
}

/*
 * lftp and utils
 *
 * Copyright (c) 1996-1997 by Alexander V. Lukyanov ([EMAIL PROTECTED])
 *
 * 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 2 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, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

#ifndef ECHOJOB_H
#define ECHOJOB_H

#include "Job.h"
#include "StatusLine.h"
#include "OutputJob.h"
#include <stdio.h>

class echoJob : public Job
{
   OutputJob *output;

public:
   int	 Do() { return STALL; }
   int	 Done();
   int	 ExitCode();

   void	 ShowRunStatus(StatusLine *);

   echoJob(const char *buf, OutputJob *output);
   echoJob(const char *buf, int len, OutputJob *output);
   ~echoJob();

   void Fg();
   void Bg();
};

#endif // ECHOJOB_H
? .lftp.outputjob.patch.swp
? autom4te.cache
? backup.tgz
? gettext.diff.merge
? gettext.diff2
? gettext.diff3
? lftp.outputjob.patch
? lftp.patch
? macro.patch
? set.txt
? stamp-h2.in
? stamp-h3.in
? stamp-h4.in
? trans_quotes.pl
? include/stamp-h1.in
? m4/codeset.m4
? m4/gettext.m4
? m4/glibc21.m4
? m4/iconv.m4
? m4/isc-posix.m4
? m4/lcmessage.m4
? m4/lib-ld.m4
? m4/lib-link.m4
? m4/lib-prefix.m4
? m4/progtest.m4
? po/Makevars.template
? po/Rules-quot
? po/boldquot.sed
? [EMAIL PROTECTED]
? [EMAIL PROTECTED]
? po/insert-header.sin
? po/quot.sed
? po/remove-potcdate.sin
? readline-4.2/autom4te.cache
? readline-4.2/config.h.in
? src/.NetAccess.cc.swp
? src/.NetAccess.h.swp
? src/OutputJob.cc
? src/OutputJob.h
? src/bk
? src/echoJob.cc
? src/echoJob.h
? src/find
? src/globbed
? src/lftp-mirror.patch
? src/lftp.patch
? src/x
Index: BUGS
===================================================================
RCS file: /home/lav/cvsroot/lftp/BUGS,v
retrieving revision 1.3
diff -u -r1.3 BUGS
--- BUGS        2001/12/05 17:08:23     1.3
+++ BUGS        2002/07/08 23:25:46
@@ -1,3 +1,3 @@
 This file describes some limitations or misfeatures lftp has.
 
-* cls status bar does not show progress of the list download.
+(none known)
Index: Makefile.am
===================================================================
RCS file: /home/lav/cvsroot/lftp/Makefile.am,v
retrieving revision 1.23
diff -u -r1.23 Makefile.am
--- Makefile.am 2002/05/17 07:52:44     1.23
+++ Makefile.am 2002/07/08 23:25:46
@@ -1,4 +1,4 @@
-EXTRA_DIST = config.rpath lftp.conf lftp.lsm FAQ acconfig.h README 
README.debug-levels\
+EXTRA_DIST = config.rpath  config.rpath lftp.conf lftp.lsm FAQ acconfig.h README 
+README.debug-levels\
  README.modules MIRRORS BUGS FEATURES
 SUBDIRS = include readline-4.2 lib doc src po m4
 AUTOMAKE_OPTIONS = foreign
Index: src/CatJob.cc
===================================================================
RCS file: /home/lav/cvsroot/lftp/src/CatJob.cc,v
retrieving revision 1.22
diff -u -r1.22 CatJob.cc
--- src/CatJob.cc       2002/01/21 16:25:14     1.22
+++ src/CatJob.cc       2002/07/08 23:25:47
@@ -25,44 +25,32 @@
 #include <errno.h>
 #include <unistd.h>
 
-#include "xmalloc.h"
-
 #include "CatJob.h"
 #include "ArgV.h"
-#include "Filter.h"
-#include "url.h"
+#include "OutputJob.h"
 
 #define super CopyJobEnv
 
+int CatJob::ExitCode()
+{
+   return errors!=0 || output->Error();
+}
+   
 int CatJob::Done()
 {
-   return super::Done() && global==0;
+   return super::Done() && output->Done();
 }
 
 int   CatJob::Do()
 {
    int m=STALL;
-   if(Done())
-      return m;
-   if(!fg_data && global && global->GetProcGroup())
-   {
-      if(fg)
-      {
-        // clear status line.
-        const char *empty="";
-        eprintf(empty);
-      }
-      fg_data=new FgData(global->GetProcGroup(),fg);
-   }
-   if(super::Done())
-   {
-      if(global->Done())
-      {
-        delete global;
-        global=0;
-        return MOVED;
-      }
+
+   if(!done && output->Done())
+   {
+      done=true;
+      m=MOVED;
    }
+
    return m||super::Do();
 }
 
@@ -73,120 +61,56 @@
    if(src==0)
    {
       SetCopier(0,0);
+      output->PutEOF();
       return;
    }
 
    FileCopyPeerFA *src_peer=FileCopyPeerFA::New(session,src,FA::RETRIEVE,false);
+   FileCopyPeer *dst_peer=new FileCopyPeerOutputJob(output);
 
-   FileCopyPeerFDStream *dst_peer=0;
-   if(for_each)
-   {
-      OutputFilter *out=new OutputFilter(new ArgV(for_each),global);
-      out->SetCwd(cwd);
-      dst_peer=new FileCopyPeerFDStream(out,FileCopyPeer::PUT);
-      dst_peer->DontCreateFgData();
-   }
-   else
-   {
-      dst_peer=new FileCopyPeerFDStream(global,FileCopyPeer::PUT);
-      dst_peer->DontDeleteStream();
-   }
-
    FileCopy *copier=FileCopy::New(src_peer,dst_peer,false);
    copier->DontCopyDate();
-   if(!fail_if_broken)
-      copier->DontFailIfBroken();
-   if(ascii || (auto_ascii && !for_each && global->usesfd(1)))
+
+   if(ascii || (auto_ascii && !output->IsFiltered() && output->IsStdout()))
    {
-      if(!for_each && global->usesfd(1))
+      if(output->IsStdout())
         copier->LineBuffered();
+
       copier->Ascii();
    }
-   SetCopier(copier,src);
 
-   if(no_status)
-      cp->NoStatus();
+   SetCopier(copier,src);
 }
 
 CatJob::~CatJob()
 {
-   Bg();
-
-   AcceptSig(SIGTERM);
-
-   delete global;
-   delete for_each;
-};
-
-int CatJob::AcceptSig(int sig)
-{
-   pid_t grp=0;
-   if(cp)
-      grp=cp->GetProcGroup();
-   if(global && grp==0)
-      grp=global->GetProcGroup();
-   if(grp==0)
-   {
-      if(sig==SIGINT || sig==SIGTERM)
-        return WANTDIE;
-      return STALL;
-   }
-   if(cp)
-      cp->AcceptSig(sig);
-   if(global && !cp)
-      global->Kill(sig);
-   if(sig!=SIGCONT)
-      AcceptSig(SIGCONT);
-   return MOVED;
+   delete output;
 }
 
-CatJob::CatJob(FileAccess *new_session,FDStream *new_global,ArgV *new_args)
+CatJob::CatJob(FileAccess *new_session,OutputJob *_output,ArgV *new_args)
    : CopyJobEnv(new_session,new_args)
 {
-   global=new_global;
-   for_each=0;
+   output=_output;
+   output->SetParentFg(this);
    ascii=false;
    auto_ascii=true;
-   fail_if_broken=true;
 
    if(!strcmp(op,"more") || !strcmp(op,"zmore") || !strcmp(op,"bzmore"))
    {
-      if(!global)
-      {
-        const char *pager=getenv("PAGER");
-        if(pager==NULL)
-           pager="exec more";
-        delete global;
-        global=new OutputFilter(pager);
-        fail_if_broken=false;
-      }
+      const char *pager=getenv("PAGER");
+      if(pager==NULL)
+        pager="exec more";
+      output->PreFilter(pager);
    }
    if(!strcmp(op,"zcat") || !strcmp(op,"zmore"))
    {
-      for_each=new ArgV("zcat");
+      output->PreFilter("zcat");
       Binary();
    }
 
    if(!strcmp(op,"bzcat") || !strcmp(op,"bzmore"))
    {
-      for_each=new ArgV("bzcat");
+      output->PreFilter("bzcat");
       Binary();
    }
-
-   // some legitimate uses produce broken pipe condition (cat|head)
-   if(global)
-      fail_if_broken=false;
-
-   if(!global)
-      global=new FDStream(1,"<stdout>");
-
-   if(for_each)
-   {
-      // we need a single process group for all for_each filters.
-      OutputFilter *new_global=new OutputFilter(new ArgV("cat"),global);
-      new_global->DeleteSecondaryStream();
-      global=new_global;
-   }
-
-   no_status=global->usesfd(1);
 }
Index: src/CatJob.h
===================================================================
RCS file: /home/lav/cvsroot/lftp/src/CatJob.h,v
retrieving revision 1.9
diff -u -r1.9 CatJob.h
--- src/CatJob.h        2002/01/10 15:30:58     1.9
+++ src/CatJob.h        2002/07/08 23:25:47
@@ -26,25 +26,24 @@
 #include "CopyJob.h"
 
 class ArgV;
-class FDStream;
+class OutputJob;
 
 class CatJob : public CopyJobEnv
 {
 protected:
-   FDStream *global;
-   ArgV *for_each;
+   OutputJob *output;
    bool ascii;
    bool auto_ascii;
-   bool fail_if_broken;
 
    void        NextFile();
 
 public:
    int Do();
    int Done();
-   int AcceptSig(int sig);
+   int ExitCode();
 
-   CatJob(FileAccess *s,FDStream *global,ArgV *args);
+   CatJob(FileAccess *s,OutputJob *output,ArgV *args);
+
    ~CatJob();
 
    void Ascii() { ascii=true; }
Index: src/ColumnOutput.cc
===================================================================
RCS file: /home/lav/cvsroot/lftp/src/ColumnOutput.cc,v
retrieving revision 1.9
diff -u -r1.9 ColumnOutput.cc
--- src/ColumnOutput.cc 2001/11/13 16:26:41     1.9
+++ src/ColumnOutput.cc 2002/07/08 23:25:47
@@ -85,7 +85,7 @@
 /* Assuming cursor is at position FROM, indent up to position TO.
  * Use a TAB character instead of two or more spaces whenever possible.  */
 static void
-indent (int from, int to, Buffer *o)
+indent (int from, int to, OutputJob *o)
 {
    // TODO
 #define tabsize 8
@@ -154,7 +154,7 @@
 
 }
 
-void ColumnOutput::print(Buffer *o, unsigned width, bool color) const
+void ColumnOutput::print(OutputJob *o, unsigned width, bool color) const
 {
    if(!lst_cnt) return; /* we have nothing to display */
 
@@ -231,7 +231,7 @@
    curwidth += mbswidth(name, MBSW_ACCEPT_INVALID|MBSW_ACCEPT_UNPRINTABLE);
 }
 
-void datum::print(Buffer *o, bool color, int skip,
+void datum::print(OutputJob *o, bool color, int skip,
                const char *color_pref, const char *color_suf, const char 
*color_reset) const
 {
    const char *cur_color = 0;
Index: src/ColumnOutput.h
===================================================================
RCS file: /home/lav/cvsroot/lftp/src/ColumnOutput.h,v
retrieving revision 1.2
diff -u -r1.2 ColumnOutput.h
--- src/ColumnOutput.h  2001/10/15 11:58:38     1.2
+++ src/ColumnOutput.h  2002/07/08 23:25:47
@@ -21,7 +21,7 @@
 #ifndef DISPCOLUMNS_H
 #define DISPCOLUMNS_H
 
-#include "FileCopy.h"
+#include "OutputJob.h"
 
 struct datum {
    /* Each entry has a series of strings; each string has a color. */
@@ -36,7 +36,7 @@
    int width() const;
 
    // print with or without color
-   void print(Buffer *o, bool color, int skip,
+   void print(OutputJob *o, bool color, int skip,
           const char *color_pref, const char *color_suf, const char *color_reset) 
const;
 
    /* count leading whitespace in the first name only. */
@@ -61,7 +61,7 @@
    void SetWidth(unsigned width);
    void SetColor(bool color);
 
-   void print(Buffer *o, unsigned width, bool color) const;
+   void print(OutputJob *o, unsigned width, bool color) const;
    void set_mode(mode_t m) { mode = m; }
 
 private:
Index: src/CopyJob.cc
===================================================================
RCS file: /home/lav/cvsroot/lftp/src/CopyJob.cc,v
retrieving revision 1.25
diff -u -r1.25 CopyJob.cc
--- src/CopyJob.cc      2001/12/26 14:45:02     1.25
+++ src/CopyJob.cc      2002/07/08 23:25:47
@@ -45,14 +45,15 @@
    }
    if(!c->WriteAllowed() && c->WritePending())
    {
-      if(no_status_on_write)
+      if(no_status_on_write || clear_status_on_write)
       {
         // clear status.
         const char *empty="";
         eprintf(empty);
-        // disable status.
-        NoStatus();
       }
+      if(no_status_on_write)
+        NoStatus(); // disable status.
+
       c->AllowWrite();
       return MOVED;
    }
@@ -69,8 +70,10 @@
    return 0;
 }
 
-const char *CopyJob::SqueezeName(int w)
+const char *CopyJob::SqueezeName(int w, bool base)
 {
+   if(base)
+      return squeeze_file_name(basename_ptr(name),w);
    return squeeze_file_name(name,w);
 }
 
@@ -80,20 +83,39 @@
       (long long)c->GetPos(),c->GetPercentDoneStr(),c->GetRateStr(),\
       c->GetETAStr(),c->GetStatus()
 
+const char *CopyJob::Status(const StatusLine *s, bool base)
+{
+   if(c->Done() || c->Error())
+      return "";
+
+   static char *buf = 0;
+   xfree(buf);
+
+   const char *name=SqueezeName(s->GetWidthDelayed()-50, base);
+   buf = xasprintf(COPY_STATUS);
+
+   return buf;
+}
+
 void CopyJob::ShowRunStatus(StatusLine *s)
 {
    if(no_status)
       return;
-   if(c->Done() || c->Error())
-      return;
 
-   const char *name=SqueezeName(s->GetWidthDelayed()-50);
-   s->Show(COPY_STATUS);
+   s->Show(Status(s, false));
 }
 void CopyJob::PrintStatus(int v)
 {
    if(c->Done() || c->Error())
       return;
+   /* If neither of our FileCopyPeers have a status, we're something
+    * dumb like buffer->fd and have no meaningful status to print.
+    * (If that's the case, we're probably a child job, so our parent
+    * will be printing something anyway.)  If an OutputJob actually
+    * attaches to a real output peer, we *do* want to print status.
+    */ 
+   if(!*c->GetStatus())
+      return;
 
    printf("\t");
    const char *name=GetName();
@@ -123,26 +145,14 @@
    done=false;
    no_status=false;
    no_status_on_write=false;
+   clear_status_on_write=false;
 }
+
 CopyJob::~CopyJob()
 {
    Delete(c);
    xfree(name);
    xfree(op);
-}
-
-CopyJob *CopyJob::NewEcho(const char *str,int len,FDStream *o,const char *op)
-{
-   if(o==0)
-      o=new FDStream(1,"<stdout>");
-   CopyJob *j=new CopyJob(FileCopy::New(
-        new FileCopyPeerString(str,len),
-        new FileCopyPeerFDStream(o,FileCopyPeer::PUT),
-        false
-      ),o->name,op);
-   if(o->usesfd(1))
-      j->NoStatus();
-   return j;
 }
 
 // CopyJobEnv
Index: src/CopyJob.h
===================================================================
RCS file: /home/lav/cvsroot/lftp/src/CopyJob.h,v
retrieving revision 1.15
diff -u -r1.15 CopyJob.h
--- src/CopyJob.h       2001/11/06 13:15:32     1.15
+++ src/CopyJob.h       2002/07/08 23:25:47
@@ -35,6 +35,7 @@
    char *op;   // command name
    bool no_status;
    bool no_status_on_write;
+   bool clear_status_on_write;
 
 public:
    CopyJob(FileCopy *c1,const char *n,const char *op1);
@@ -42,6 +43,8 @@
 
    void NoStatus() { no_status=true; }
    void NoStatusOnWrite() { no_status_on_write=true; }
+   void ClearStatusOnWrite() { clear_status_on_write=true; }
+   bool HasStatus() const { return !no_status; }
 
    int Do();
    int Done();
@@ -68,19 +71,19 @@
    void SetRange(off_t s,off_t lim) { c->SetRange(s,lim); }
    void SetDate(time_t d) { c->SetDate(d); }
    void SetSize(off_t s)   { c->SetSize(s); }
+   FileCopy *GetCopy() { return c; }
    FileCopyPeer *GetPut() { return c->put; }
+   FileCopyPeer *GetGet() { return c->get; }
 
+   const char *Status(const StatusLine *s,bool base=false);
    void ShowRunStatus(StatusLine *s);
    void        PrintStatus(int);
 
    const char *GetName() { return name; }
-   const char *SqueezeName(int w);
+   const char *SqueezeName(int w, bool base=false);
 
    static CopyJob *NewGet(FileAccess *f,const char *src,const char *dst);
    static CopyJob *NewPut(FileAccess *f,const char *src,const char *dst);
-   static CopyJob *NewEcho(const char *str,int len,FDStream *o,const char *op);
-   static CopyJob *NewEcho(const char *str,FDStream *o,const char *op)
-      { return NewEcho(str,strlen(str),o,op); }
 };
 
 class ArgV;
@@ -108,7 +111,7 @@
 public:
    int Do();
    int Done();
-   int ExitCode() { return errors!=0; }
+   virtual int ExitCode() { return errors!=0; }
 
    int AcceptSig(int sig);
 
Index: src/FileCopy.cc
===================================================================
RCS file: /home/lav/cvsroot/lftp/src/FileCopy.cc,v
retrieving revision 1.86
diff -u -r1.86 FileCopy.cc
--- src/FileCopy.cc     2002/06/05 09:29:51     1.86
+++ src/FileCopy.cc     2002/07/08 23:25:48
@@ -46,6 +46,7 @@
 #include "misc.h"
 #include "LsCache.h"
 #include "plural.h"
+#include "OutputJob.h"
 
 #define skip_threshold 0x1000
 #define debug(a) Log::global->Format a
@@ -1553,31 +1554,6 @@
 }
 
 
-// FileCopyPeerString
-#undef super
-#define super FileCopyPeer
-FileCopyPeerString::FileCopyPeerString(const char *s, int len)
-   : super(GET)
-{
-   if(len==-1)
-      len=strlen(s);
-   Put(s,len);
-   eof=true;
-   pos=0;
-   can_seek=true;
-   can_seek0=true;
-}
-FileCopyPeerString::~FileCopyPeerString()
-{
-}
-void FileCopyPeerString::Seek(off_t new_pos)
-{
-   assert(new_pos!=FILE_END);
-   UnSkip(pos-new_pos);
-   super::Seek(new_pos);
-   pos=new_pos;
-}
-
 // FileCopyPeerDirList
 FileCopyPeerDirList::FileCopyPeerDirList(FA *s,ArgV *v)
    : FileCopyPeer(GET)
@@ -1621,6 +1597,78 @@
    in_buffer+=s;
    dl->Skip(s);
    return MOVED;
+}
+
+FileCopyPeerOutputJob::FileCopyPeerOutputJob(OutputJob *new_o)
+   : FileCopyPeer(PUT)
+{
+   o=new_o;
+   DontCopyDate();
+}
+       
+int FileCopyPeerOutputJob::Put_LL(const char *buf,int len)
+{
+   off_t io_at=pos;
+   if(GetRealPos()!=io_at) // GetRealPos can alter pos.
+      return 0;
+
+   if(len==0 && eof)
+      return 0;
+
+   if(o->Full())
+      return 0;
+
+   o->Put(buf,len);
+
+   seek_pos+=len; // mainly to indicate that there was some output.
+   return len;
+}
+          
+int FileCopyPeerOutputJob::Do()
+{
+   if(o->Error())
+   {
+      broken=true;
+      return MOVED;
+   }
+
+   if(eof && !in_buffer)
+   {
+      done=true;
+      return MOVED;
+   }
+
+   int m=STALL;
+
+   if(!write_allowed)
+      return m;
+
+   while(in_buffer>0)
+   {
+      int res=Put_LL(buffer+buffer_ptr,in_buffer);
+      if(res>0)
+      {
+        in_buffer-=res;
+        buffer_ptr+=res;
+        m=MOVED;
+      }
+      if(res<0)
+        return MOVED;
+      if(res==0)
+        break;
+   }
+   return m;
+}
+
+void FileCopyPeerOutputJob::Fg()
+{
+   o->Fg();
+   FileCopyPeer::Fg();
+}
+void FileCopyPeerOutputJob::Bg()
+{
+   o->Bg();
+   FileCopyPeer::Bg();
 }
 
 // special pointer to creator of ftp/ftp copier. It is init'ed in Ftp class.
Index: src/FileCopy.h
===================================================================
RCS file: /home/lav/cvsroot/lftp/src/FileCopy.h,v
retrieving revision 1.49
diff -u -r1.49 FileCopy.h
--- src/FileCopy.h      2002/01/10 09:52:25     1.49
+++ src/FileCopy.h      2002/07/08 23:25:48
@@ -26,8 +26,8 @@
    FileCopyPeer
    +FileCopyPeerFA
    +FileCopyPeerFDStream
-   +FileCopyPeerString
    \FileCopyPeerList
+   +FileCopyPeerOutputJob
 */
 
 #ifndef FILECOPY_H
@@ -285,6 +285,7 @@
    void DontReuseSession() { reuse_later=false; }
 
    const char *GetStatus();
+   const char *GetProto() { return session->GetProto(); }
 
    bool NeedSizeDateBeforehand() { return session->NeedSizeDateBeforehand(); }
    void RemoveFile();
@@ -337,16 +338,6 @@
    static FileCopyPeerFDStream *NewGet(const char *file);
 };
 
-class FileCopyPeerString : public FileCopyPeer
-{
-protected:
-   ~FileCopyPeerString();
-
-public:
-   FileCopyPeerString(const char *s,int len=-1);
-   void Seek(off_t new_pos);
-};
-
 class FileCopyPeerDirList : public FileCopyPeer
 {
 private:
@@ -365,6 +356,21 @@
    void Bg() { session->SetPriority(0); }
    const char *GetStatus() { return session->CurrentStatus(); }
    void UseColor(bool c=true) { if(dl) dl->UseColor(c); }
+};
+
+class OutputJob;
+
+class FileCopyPeerOutputJob : public FileCopyPeer
+{
+   OutputJob *o;
+   int Put_LL(const char *buf,int len);
+
+public:
+   FileCopyPeerOutputJob(OutputJob *o);
+
+   int Do();
+   void Fg();
+   void Bg();
 };
 
 #endif
Index: src/FileSetOutput.cc
===================================================================
RCS file: /home/lav/cvsroot/lftp/src/FileSetOutput.cc,v
retrieving revision 1.24
diff -u -r1.24 FileSetOutput.cc
--- src/FileSetOutput.cc        2002/04/18 10:37:21     1.24
+++ src/FileSetOutput.cc        2002/07/08 23:25:48
@@ -45,13 +45,14 @@
 #include "ColumnOutput.h"
 #include "DirColors.h"
 #include "FileGlob.h"
+#include "CopyJob.h"
 
 
 ResDecl        res_default_cls         ("cmd:cls-default",  "-F", 
FileSetOutput::ValidateArgv,0),
        res_default_comp_cls    ("cmd:cls-completion-default", 
"-FB",FileSetOutput::ValidateArgv,0);
 
 /* note: this sorts (add a nosort if necessary) */
-void FileSetOutput::print(FileSet &fs, Buffer *o) const
+void FileSetOutput::print(FileSet &fs, OutputJob *o) const
 {
    fs.Sort(sort, sort_casefold);
    if(sort_dirs_first) fs.Sort(FileSet::DIRSFIRST, false);
@@ -217,13 +218,13 @@
    return *this;
 }
 
-void FileSetOutput::config(FDStream *fd)
+void FileSetOutput::config(const OutputJob *o)
 {
-   width = fd_width(fd->getfd());
+   width = o->GetWidth();
    if(width == -1)
       width = 80;
 
-   if(!strcasecmp(ResMgr::Query("color:use-color", 0), "auto")) color = 
isatty(fd->getfd());
+   if(!strcasecmp(ResMgr::Query("color:use-color", 0), "auto")) color = o->IsTTY();
    else color = ResMgr::QueryBool("color:use-color", 0);
 }
 
@@ -252,115 +253,203 @@
    return NULL;
 }
 
-/* Peer interface: */
-
-#define super FileCopyPeer
-FileCopyPeerCLS::FileCopyPeerCLS(FA *_session, ArgV *a, const FileSetOutput &_fso):
-   super(GET),
-   session(_session),
-   fso(_fso), f(0),
+int FileSetOutput::Need() const
+{
+   int need=FileInfo::NAME;
+   if(mode & PERMS)
+      need|=FileInfo::MODE;
+//   if(mode & SIZE) /* this must be optional */
+//      need|=FileInfo::SIZE;
+//   if(mode & DATE) /* this too */
+//      need|=FileInfo::DATE;
+   if(mode & LINKS)
+      need|=FileInfo::SYMLINK_DEF;
+   if(mode & USER)
+      need|=FileInfo::USER;
+   if(mode & GROUP)
+      need|=FileInfo::GROUP;
+
+   return need;
+}
+
+#undef super
+#define super SessionJob
+
+clsJob::clsJob(FA *s, ArgV *a, const FileSetOutput &_opts, OutputJob *_output):
+   SessionJob(s),
+   fso(_opts),
    args(a),
-   quiet(false),
-   num(1), dir(0), mask(0)
+   num(1)
 {
+   use_cache=true;
+   done=0;
+   dir=0;
+   mask=0;
+   state=INIT;
+   list_info=0;
+
    if(args->count() == 1)
       args->Add("");
-   list_info=0;
-   can_seek=false;
-   can_seek0=false;
+
+   output=_output;
+   output->SetParentFg(this);
 }
 
-FileCopyPeerCLS::~FileCopyPeerCLS()
+clsJob::~clsJob()
 {
-   delete f;
    delete args;
-   Delete(list_info);
-   SessionPool::Reuse(session);
    xfree(dir);
+   Delete(list_info);
+   Delete(output);
+}
+
+int clsJob::Done()
+{
+   return done && output->Done();
 }
 
-int FileCopyPeerCLS::Do()
+int clsJob::Do()
 {
-   if(Done()) return STALL;
+   int m=STALL;
 
-   /* one currently processing? */
-   if(list_info) {
-      if(list_info->Error()) {
-        SetError(list_info->ErrorText());
+   if(output->Done())
+      state=DONE;
+
+   switch(state)
+   {
+   case INIT:
+      state=START_LISTING;
+      m=MOVED;
+
+   case START_LISTING:
+   {
+      Delete(list_info);
+      list_info=0;
+
+      /* next: */
+      xfree(dir); dir = 0;
+      xfree(mask); mask = 0;
+
+      dir = args->getnext();
+      if(!dir) {
+        /* done */
+        state=DONE;
         return MOVED;
       }
+      dir = xstrdup(dir);
 
+      /* If the basename contains wildcards, set up the mask. */
+      mask = strrchr(dir, '/');
+      if(!mask) mask=dir;
+      if(Glob::HasWildcards(mask)) {
+        if(mask == dir)
+           dir = xstrdup("");
+        else {
+           /* The mask is the whole argument, not just the basename; this is
+            * because the whole relative paths will end up in the FileSet, and
+            * that's what this pattern will be matched against. */
+           char *newmask = xstrdup(dir);
+
+           // leave the final / on the path, to prevent the dirname of
+           // "file/*" from being treated as a file
+           mask[1] = 0;
+           mask = newmask;
+        }
+      } else mask=0;
+
+      list_info=new GetFileInfo(session, dir, fso.list_directories);
+      list_info->UseCache(use_cache);
+      list_info->Need(fso.Need());
+
+      state=GETTING_LIST_INFO;
+      m=MOVED;
+   }
+   case GETTING_LIST_INFO:
+   {
       if(!list_info->Done())
-        return STALL;
+        return m;
 
+      if(list_info->Error()) {
+        eprintf("%s\n", list_info->ErrorText());
+        state=START_LISTING;
+        return MOVED;
+      }
+
       /* one just finished */
-      int oldpos = pos;
       fso.pat = mask;
       FileSet *res = list_info->GetResult();
-      Delete(list_info);
-      list_info=0;
+
       if(res)
-        fso.print(*res, this);
+        fso.print(*res, output);
+
       fso.pat = 0;
       delete res;
-      pos = oldpos;
-   }
 
-   /* next: */
-   xfree(dir); dir = 0;
-   xfree(mask); mask = 0;
-
-   dir = args->getnext();
-   if(!dir) {
-      /* done */
-      PutEOF();
+      state=START_LISTING;
       return MOVED;
    }
-   dir = xstrdup(dir);
 
-   /* If the basename contains wildcards, move the basename into mask. */
-   mask = strrchr(dir, '/');
-   if(!mask) mask=dir;
-   if(Glob::HasWildcards(mask)) {
-      if(mask == dir)
-        dir = xstrdup("");
-      else {
-        /* The mask is the whole argument, not just the basename; this is
-         * because the whole relative paths will end up in the FileSet, and
-         * that's what this pattern will be matched against. */
-        char *newmask = xstrdup(dir);
-
-        // leave the final / on the path, to prevent the dirname of
-        // "file/*" from being treated as a file
-        mask[1] = 0;
-        mask = newmask;
+   case DONE:
+      if(!done) 
+      {
+        output->PutEOF();
+        done=true;
+        m=MOVED;
       }
-   } else mask=0;
-
-   list_info=new GetFileInfo(session, dir, fso.list_directories);
-   if(!list_info) {
-      PutEOF();
-      return MOVED;
+      break;
    }
-   list_info->UseCache(use_cache);
+   return m;
+}
 
-   return MOVED;
+void clsJob::Suspend()
+{
+   if(list_info)
+      list_info->Suspend();
+   session->Suspend();
+   super::Suspend();
 }
 
-const char *FileCopyPeerCLS::GetStatus()
+void clsJob::Resume()
 {
-   return session->CurrentStatus();
+   if(list_info)
+      list_info->Resume();
+   session->Resume();
+   super::Resume();
 }
 
-void FileCopyPeerCLS::Suspend()
+void clsJob::ShowRunStatus(StatusLine *s)
 {
-   if(session)
-      session->Suspend();
-   super::Suspend();
+   if(fso.quiet)
+      return;
+
+   if(!output->ShowStatusLine())
+      return;
+
+   if(list_info && !list_info->Done())
+   {
+      const char *curr = args->getcurr();
+      if(!*curr)
+        curr = ".";
+      const char *stat = list_info->Status();
+      if(*stat)
+        s->Show("`%s' %s %s", curr, stat, output->Status(s));
+   }
+   else
+        s->Show("%s", output->Status(s));
 }
-void FileCopyPeerCLS::Resume()
+
+void clsJob::PrintStatus(int v)
 {
-   super::Resume();
-   if(session)
-      session->Resume();
+   Job::PrintStatus(v);
+
+   if(list_info)
+   {
+      const char *curr = args->getcurr();
+      if(!*curr)
+        curr = ".";
+      const char *stat = list_info->Status();
+      if(*stat)
+        printf("\t`%s' %s\n", curr, stat);
+   }
 }
+
Index: src/FileSetOutput.h
===================================================================
RCS file: /home/lav/cvsroot/lftp/src/FileSetOutput.h,v
retrieving revision 1.9
diff -u -r1.9 FileSetOutput.h
--- src/FileSetOutput.h 2001/12/05 17:12:51     1.9
+++ src/FileSetOutput.h 2002/07/08 23:25:49
@@ -6,7 +6,12 @@
 #include "keyvalue.h"
 #include "FileCopy.h"
 #include "GetFileInfo.h"
+#include "CopyJob.h"
+#include "OutputJob.h"
+#include "Job.h"
 
+class StatusLine;
+
 class FileSetOutput {
    const char *FileInfoSuffix(const FileInfo &fi) const;
 
@@ -48,45 +53,46 @@
    const FileSetOutput &operator = (const FileSetOutput &cp);
 
    void long_list();
-   void config(FDStream *fd);
+   void config(const OutputJob *fd);
    const char *parse_argv(ArgV *a);
    static const char *ValidateArgv(char **s);
-
-   void print(FileSet &fs, Buffer *o) const;
+   int Need() const;
+          
+   void print(FileSet &fs, OutputJob *o) const;
 };
 
 /* Job interface to FileSetOutput */
-class FileCopyPeerCLS : public FileCopyPeer
+class clsJob : public SessionJob
 {
-   FileAccess *session;
-
+   OutputJob *output;
    FileSetOutput fso;
-   FileSet *f;
-   ListInfo *list_info;
-
    ArgV *args;
-
-   bool quiet;
+   ListInfo *list_info;
+   char *dir, *mask;
+   bool done;
+   bool use_cache;
 
    /* element in args we're currently processing */
    int num;
-
-   char *dir;
-   char *mask;
 
-protected:
-   ~FileCopyPeerCLS();
+   enum { INIT, START_LISTING, GETTING_LIST_INFO, DONE } state;
 
 public:
-   FileCopyPeerCLS(FA *s, ArgV *a, const FileSetOutput &_opts);
+   clsJob(FA *s, ArgV *a, const FileSetOutput &_opts, OutputJob *output);
+   ~clsJob();
+   int Done();
    int Do();
-   const char *GetStatus();
-   void Quiet() { quiet = true; }
 
-   void Fg() { session->SetPriority(1); }
-   void Bg() { session->SetPriority(0); }
+   void UseCache(bool y=true) { use_cache=y; }
+
+   void Fg() { session->SetPriority(1); output->Fg(); }
+   void Bg() { session->SetPriority(0); output->Bg(); }
    void Suspend();
    void Resume();
+   int ExitCode() { return output->Error()? 1:0; }
+
+   void ShowRunStatus(StatusLine *s);
+   void PrintStatus(int v);
 };
 
 #endif
Index: src/Filter.cc
===================================================================
RCS file: /home/lav/cvsroot/lftp/src/Filter.cc,v
retrieving revision 1.25
diff -u -r1.25 Filter.cc
--- src/Filter.cc       2002/05/29 07:51:44     1.25
+++ src/Filter.cc       2002/07/08 23:25:49
@@ -48,6 +48,7 @@
       name=0;
    error_text=0;
    status=0;
+   close_fd=false;
 }
 FDStream::FDStream()
 {
@@ -55,6 +56,7 @@
    name=0;
    error_text=0;
    status=0;
+   close_fd=false;
 }
 void FDStream::MakeErrorText()
 {
@@ -66,7 +68,8 @@
 }
 FDStream::~FDStream()
 {
-   // don't close fd
+   if(close_fd)
+      close(fd);
    xfree(name);
    xfree(error_text);
 };
Index: src/Filter.h
===================================================================
RCS file: /home/lav/cvsroot/lftp/src/Filter.h,v
retrieving revision 1.16
diff -u -r1.16 Filter.h
--- src/Filter.h        2001/12/26 14:46:34     1.16
+++ src/Filter.h        2002/07/08 23:25:49
@@ -29,6 +29,8 @@
 
 class FDStream
 {
+   bool close_fd;
+
 public:
    int fd;
    char *name;
@@ -47,6 +49,7 @@
    bool NonFatalError(int err);
    void set_status(const char *str) { status=str; }
    void clear_status() { status=0; }
+   void CloseFD() { close_fd=true; }
 
    virtual off_t get_size() { return -1; }
    virtual void setmtime(time_t) {}
Index: src/Job.h
===================================================================
RCS file: /home/lav/cvsroot/lftp/src/Job.h,v
retrieving revision 1.17
diff -u -r1.17 Job.h
--- src/Job.h   2002/01/21 16:25:15     1.17
+++ src/Job.h   2002/07/08 23:25:49
@@ -61,8 +61,10 @@
    void SetParentFg(Job *j, bool f=true)
       {
         SetParent(j);
-        if(j->fg && f)
+        if(f && j->fg)
            Fg();
+//      else if(f && !j->fg)
+//         Bg();
       }
 
    void         AllocJobno();
Index: src/Makefile.am
===================================================================
RCS file: /home/lav/cvsroot/lftp/src/Makefile.am,v
retrieving revision 1.59
diff -u -r1.59 Makefile.am
--- src/Makefile.am     2002/06/18 13:29:20     1.59
+++ src/Makefile.am     2002/07/08 23:25:49
@@ -67,9 +67,10 @@
  bookmark.cc bookmark.h CatJob.cc CatJob.h GetJob.cc GetJob.h\
  mkdirJob.cc mkdirJob.h pgetJob.cc pgetJob.h FileFeeder.cc FileFeeder.h\
  QueueFeeder.cc QueueFeeder.h keyvalue.cc keyvalue.h history.cc history.h\
- FindJob.cc FindJob.h\
+ FindJob.cc FindJob.h \
  FindJobDu.cc FindJobDu.h ChmodJob.cc ChmodJob.h\
- TreatFileJob.cc TreatFileJob.h CopyJob.cc CopyJob.h
+ TreatFileJob.cc TreatFileJob.h CopyJob.cc CopyJob.h echoJob.cc echoJob.h \
+ OutputJob.cc OutputJob.h 
 
 lftp_LDFLAGS = -export-dynamic $(LFTP_SSL_LDFLAGS)
 lftp_LDADD = libjobs.a libtasks.a $(READLINE) $(READLINE_SUPPLIB) \
Index: src/commands.cc
===================================================================
RCS file: /home/lav/cvsroot/lftp/src/commands.cc,v
retrieving revision 1.177
diff -u -r1.177 commands.cc
--- src/commands.cc     2002/05/05 14:22:55     1.177
+++ src/commands.cc     2002/07/08 23:25:52
@@ -49,6 +49,8 @@
 #include "FindJobDu.h"
 #include "ChmodJob.h"
 #include "CopyJob.h"
+#include "OutputJob.h"
+#include "echoJob.h"
 
 #include "misc.h"
 #include "alias.h"
@@ -1195,7 +1197,47 @@
 
 CMD(ls)
 {
-   bool nlist=false;
+
+  /* 
+   decompress *d = new decompress_gunzip;
+
+   int fd = open("test.gz", O_RDONLY);
+   assert(fd != -1);
+   IOBufferFDStream *b = new IOBufferFDStream(new FDStream(1, "stdout"), 
+IOBuffer::PUT);
+
+   while(1)
+   {
+      char buf[1024];
+      int sz = read(fd, buf, sizeof(buf));
+      if(sz <= 0) break;
+      d->Put(buf, sz, *b);
+
+      
+
+   }
+
+
+   b->PutEOF();
+
+   while(!b->Done())
+   {
+      SMTask::Schedule();
+      if(SignalHook::GetCount(SIGINT))
+      {
+        SignalHook::ResetCount(SIGINT);
+        break;
+      }
+   }
+
+   SMTask::Delete(b);
+
+
+   close(fd);
+   delete d;
+
+       return 0;
+*/
+       bool nlist=false;
    bool re=false;
    int mode=FA::LIST;
    const char *op=args->a0();
@@ -1383,11 +1425,15 @@
    const char *op=args->a0();
    bool re=false;
 
-   if(!output)
-      output=new FDStream(1,"<stdout>");
+   OutputJob *out=new OutputJob(output, args->a0());
+//   OutputJob *out=new OutputJob("testfile", args->a0());
+//   OutputJob *out=new OutputJob("file:testfile", args->a0());
+//   OutputJob *out=new OutputJob("ftp://localhost/incoming/testing";, args->a0());
 
+   output=0;
+
    FileSetOutput fso;
-   fso.config(output);
+   fso.config(out);
 
    if(!strncmp(op,"re",2))
       re=true;
@@ -1398,34 +1444,15 @@
    if(const char *err = fso.parse_argv(args)) {
       eprintf("%s: %s.\n", op, err);
       eprintf(_("Try `help %s' for more information.\n"),op);
+      delete out;
       return 0;
    }
-
-   char *a=args->Combine(0);
 
-   FileCopyPeer *src_peer=0;
-   src_peer=new FileCopyPeerCLS(session->Clone(),args,fso);
-   args=0;
-
+   clsJob *j = new clsJob(session->Clone(), args, fso, out);
    if(re)
-      src_peer->NoCache();
-   src_peer->SetDate(NO_DATE);
-   src_peer->SetSize(NO_SIZE);
-   FileCopyPeer *dst_peer=new FileCopyPeerFDStream(output,FileCopyPeer::PUT);
+      j->UseCache(false);
 
-   FileCopy *c=FileCopy::New(src_peer,dst_peer,false);
-   c->DontCopyDate();
-   c->LineBuffered();
-   c->Ascii();
-
-   CopyJob *j=new CopyJob(c,a,op);
-   if(fso.quiet)
-      j->NoStatus();
-   else if(output->usesfd(1))
-      j->NoStatusOnWrite();
-
-   xfree(a);
-   output=0;
+   args=0;
 
    return j;
 }
@@ -1462,7 +1489,8 @@
       eprintf(_("Usage: %s [OPTS] files...\n"),op);
       return 0;
    }
-   CatJob *j=new CatJob(session->Clone(),output,args);
+   OutputJob *out=new OutputJob(output, args->a0());
+   CatJob *j=new CatJob(session->Clone(),out,args);
    if(!auto_ascii)
    {
       if(ascii)
@@ -1765,8 +1793,11 @@
    char *url=alloca_strdup(url_c);
    int len=strlen(url_c);
    url[len++]='\n';  // replaces \0
-   Job *j=CopyJob::NewEcho(url,len,output,args->a0());
+
+   OutputJob *out=new OutputJob(output, args->a0());
+   Job *j=new echoJob(url,len,out);
    output=0;
+
    return j;
 }
 
@@ -2006,7 +2037,8 @@
    if(a==0)
    {
       char *s=ResMgr::Format(with_defaults,only_defaults);
-      Job *j=CopyJob::NewEcho(s,output,args->a0());
+      OutputJob *out=new OutputJob(output, args->a0());
+      Job *j=new echoJob(s,out);
       xfree(s);
       output=0;
       return j;
@@ -2050,7 +2082,8 @@
    if(args->count()<2)
    {
       char *list=Alias::Format();
-      Job *j=CopyJob::NewEcho(list,output,args->a0());
+      OutputJob *out=new OutputJob(output, args->a0());
+      Job *j=new echoJob(list,out);
       xfree(list);
       output=0;
       return j;
@@ -2399,7 +2432,8 @@
    if(!strcasecmp(op,"list"))
    {
       char *list=lftp_bookmarks.FormatHidePasswords();
-      Job *j=CopyJob::NewEcho(list,output,args->a0());
+      OutputJob *out=new OutputJob(output, args->a0());
+      Job *j=new echoJob(list,out);
       xfree(list);
       output=0;
       return j;
@@ -2488,7 +2522,16 @@
    {
       s[len++]='\n'; // replaces \0 char
    }
-   Job *j=CopyJob::NewEcho(s,len,output,args->a0());
+      
+//   OutputJob *out=new OutputJob(outf, args->a0());
+//   OutputJob *out=new OutputJob("ftp://localhost/incoming/testing";, args->a0());
+   OutputJob *out=new OutputJob(output, args->a0());
+        
+//   out->SetFilter("cat > testing");
+//   out->SetFilter("cat");
+  // out->SetForEach("cat");
+   Job *j=new echoJob(s,len,out);
+
    xfree(s);
    output=0;
    return j;
@@ -2737,7 +2780,7 @@
    const char *name=parent->cwd->GetName();
    char *buf=alloca_strdup2(name,2);
    sprintf(buf,"%s\n",name?name:"?");
-   Job *j=CopyJob::NewEcho(buf,strlen(buf),output,args->a0());
+   Job *j=new echoJob(buf,new OutputJob(output, args->a0()));
    output=0;
    return j;
 }
Index: src/complete.cc
===================================================================
RCS file: /home/lav/cvsroot/lftp/src/complete.cc,v
retrieving revision 1.59
diff -u -r1.59 complete.cc
--- src/complete.cc     2002/06/11 07:36:56     1.59
+++ src/complete.cc     2002/07/08 23:25:54
@@ -44,6 +44,7 @@
 #include "ResMgr.h"
 #include "ColumnOutput.h"
 #include "FileSetOutput.h"
+#include "OutputJob.h"
 #include "misc.h"
 
 CDECL_BEGIN
@@ -391,6 +392,11 @@
         was_N=true;
         break;
       }
+      if(i-14 >= 0 && !strncmp(rl_line_buffer+i-13, "--newer-than",12) && 
+isspace(rl_line_buffer[i-14]))
+      {
+        was_N=true;
+        break;
+      }
       if(!strncmp(rl_line_buffer+i-3,"-O",2) && isspace(rl_line_buffer[i-4]))
       {
         was_O=true;
@@ -1197,8 +1203,7 @@
 
 extern "C" void completion_display_list (char **matches, int len)
 {
-   FDStream o(1,"<stdout>");
-   Buffer *b = new Buffer;
+   OutputJob *b=new OutputJob((FDStream *) NULL, "completion");
 
    if(glob_res) {
       /* Our last completion action was of files, and we kept that
@@ -1214,7 +1219,7 @@
       }
 
       FileSetOutput fso;
-      fso.config(&o);
+      fso.config(b);
 
       ArgV arg("", ResMgr::Query("cmd:cls-completion-default", 0));
       fso.parse_argv(&arg);
@@ -1227,19 +1232,19 @@
         c.append();
         c.add(matches[i], "");
       }
-      c.print(b, fd_width(o.getfd()), isatty(o.getfd()));
+      c.print(b, b->GetWidth(), b->IsTTY());
    }
+
+   b->PutEOF();
 
-   const char *buf;
-   int sz;
-   b->Get(&buf, &sz);
-
-   while(sz) {
-      int ret = write(1, buf, sz);
-      if(ret <= 0)
-        break; /* oops */
-      sz -= ret;
-      buf += ret;
+   while(!b->Done())
+   {
+      SMTask::Schedule();
+      if(SignalHook::GetCount(SIGINT))
+      {
+        SignalHook::ResetCount(SIGINT);
+        break;
+      }
    }
 
    SMTask::Delete(b);
Index: configure.in
===================================================================
RCS file: /home/lav/cvsroot/lftp/configure.in,v
retrieving revision 1.124
diff -u -r1.124 configure.in
--- configure.in        2002/05/17 07:52:45     1.124
+++ configure.in        2002/06/03 00:40:56
@@ -8,10 +8,6 @@
 # they're there.
 AC__GNU_SOURCE
 
-dnl Default AC_C_INLINE does not know about C++
-m4_undefine([AC_C_INLINE])
-AC_DEFUN([AC_C_INLINE],[LFTP_C_INLINE])
-
 test -z "$CXX"      && DEFAULT_CXX=yes
 test -z "$CFLAGS"    && DEFAULT_CFLAGS=yes
 test -z "$CXXFLAGS"  && DEFAULT_CXXFLAGS=yes
@@ -117,7 +113,7 @@
 AC_PROG_YACC
 
 if test x$ac_cv_lib_fl_yywrap = xno; then
-   AC_DEFINE(NEED_YYWRAP)
+   AC_DEFINE(NEED_YYWRAP, 1, [need yywrap]) dnl ?
 fi
 
 
@@ -152,7 +148,7 @@
 [  with_socks=$withval;        ],
 [  with_socks=no;      ])
 if test x$with_socks = xyes; then
-   AC_DEFINE(SOCKS4)
+   AC_DEFINE(SOCKS4, 1, [define if you are building with SOCKS support])
    SOCKSLIBS=-lsocks
 fi
 
@@ -161,7 +157,7 @@
 [  with_socks5=$withval;],
 [  with_socks5=no;     ])
 if test x$with_socks5 = xyes; then
-   AC_DEFINE(SOCKS5)
+   AC_DEFINE(SOCKS5, 1, [define if you are building with SOCKSv5 support])
    SOCKSLIBS=-lsocks5
 fi
 
@@ -170,7 +166,7 @@
 [  with_socksdante=$withval;],
 [  with_socksdante=no; ])
 if test x$with_socksdante = xyes; then
-   AC_DEFINE(SOCKS_DANTE)
+   AC_DEFINE(SOCKS_DANTE, 1, [define if you are building with SOCKS-Dante support])
    SOCKSLIBS=-lsocks
 fi
 AC_SUBST(SOCKSLIBS)
@@ -183,7 +179,7 @@
 if test "$with_modules" = yes; then
    enable_static=no
    enable_shared=yes
-   AC_DEFINE(WITH_MODULES)
+   AC_DEFINE(WITH_MODULES, 1, [build modular lftp])
    MODULES_LA="libnetwork.la proto-ftp.la proto-http.la proto-file.la proto-fish.la 
cmd-mirror.la cmd-sleep.la"
    LFTP_SSL_LDFLAGS=
    LFTP_SSL_LIBS=
@@ -206,11 +202,11 @@
 dnl Checks for libraries.
 LFTP_CHECK_LIBM
 dnl This won't work for glibc2
-dnl AC_SEARCH_LIBS(md5_process_bytes,crypt,[AC_DEFINE(HAVE_MD5)])
+dnl AC_SEARCH_LIBS(md5_process_bytes,crypt,[AC_DEFINE(HAVE_MD5, 1, [md5 support is 
+present in libc or libcrypt])])
 AC_SEARCH_LIBS(socket,socket)
 AC_SEARCH_LIBS(gethostbyname,nsl)
-AC_SEARCH_LIBS(dlopen,dl,[AC_DEFINE(HAVE_DLOPEN)])
-AC_SEARCH_LIBS(res_search,resolv bind,[AC_DEFINE(HAVE_RES_SEARCH)])
+AC_SEARCH_LIBS(dlopen,dl,[AC_DEFINE(HAVE_DLOPEN, 1, [have dlopen])])
+AC_SEARCH_LIBS(res_search,resolv bind,[AC_DEFINE(HAVE_RES_SEARCH, 1, [have 
+res_search])])
 IU_CHECK_DECL(res_search, [
      #include <stdio.h>
      #include <sys/types.h>
@@ -263,10 +270,10 @@
 AC_CHECK_HEADERS(fcntl.h sys/time.h errno.h stdlib.h varargs.h dirent.h\
  termios.h termio.h sys/select.h sys/poll.h sys/stropts.h string.h memory.h\
  strings.h sys/ioctl.h dlfcn.h resolv.h arpa/nameser.h netinet/tcp.h\
- langinfo.h endian.h regex.h)
+ langinfo.h endian.h regex.h locale.h)
 
 # See if the system has strerror and replace if not
-AC_CHECK_FUNC(strerror, AC_DEFINE(HAVE_STRERROR),[
+AC_CHECK_FUNC(strerror, AC_DEFINE(HAVE_STRERROR, 1, [System has usable strerror]),[
   AC_LIBOBJ(strerror)
   # No strerror, so see if the SYS_ERRLIST variable can be used by ours
   AC_CHECK_FUNC(sys_errlist,
@@ -287,7 +294,7 @@
       int iu_x = h_errno; ],
     inetutils_cv_var_h_errno=yes, inetutils_cv_var_h_errno=no))
 if test "$inetutils_cv_var_h_errno" = yes; then
-  AC_DEFINE(HAVE_H_ERRNO)
+  AC_DEFINE(HAVE_H_ERRNO, 1, [system has h_errno])
   IU_CHECK_DECL(h_errno, [#include <netdb.h>])
 fi
 
@@ -305,18 +312,17 @@
   # We still provide some definition, regardless, but this allows people to use
   # a reasonable alternative if the situation allows, rather than using a
   # degenerate version that only says `Host lookup error N'.
-  AC_DEFINE(HAVE_HSTRERROR)
+  AC_DEFINE(HAVE_HSTRERROR, 1, [System has usable hstrerror])
 fi
 
 dnl Checks for typedefs, structures, and compiler characteristics.
 AC_TYPE_PID_T
 AC_STRUCT_TM
 
-# these are checked by AM_GNU_GETTEXT
-dnl AC_C_CONST
-dnl AC_C_INLINE
-dnl AC_TYPE_OFF_T
-dnl AC_TYPE_SIZE_T
+AC_C_CONST
+AC_C_INLINE
+AC_TYPE_OFF_T
+AC_TYPE_SIZE_T
 if test x$ac_cv_header_endian_h = xno; then
    AC_C_BIGENDIAN
 fi
Index: acconfig.h
===================================================================
RCS file: /home/lav/cvsroot/lftp/acconfig.h,v
retrieving revision 1.33
diff -u -r1.33 acconfig.h
--- acconfig.h  2002/02/27 09:16:07     1.33
+++ acconfig.h  2002/06/03 00:40:56
@@ -20,125 +20,11 @@
 
 #ifndef CONFIG_H
 #define CONFIG_H
-@TOP@
-
-/* the name of package */
-#undef PACKAGE
-
-/* the version of package */
-#undef VERSION
-
-/* Define if inline functions a la GCC are available.  */
-#undef HAVE_INLINE
-
-/* Define as __inline if that's what the C compiler calls it.  */
-#undef c_inline
+@BOTTOM@
 
-#ifndef __cplusplus
-# ifdef c_inline
-#  define inline c_inline
-# endif
+#if defined(__cplusplus) && defined(inline)
+# undef inline
 #endif
-
-/* Define if sysinfo is available.  */
-#undef HAVE_SYSINFO
-
-/* Define if __NR_sysinfo is available.  */
-#undef HAVE_NRSYSINFO
-
-/* Define if ???.  */
-#undef HAVE_ALPHASORT_DECLARATION
-
-/* Define if function attributes a la GCC 2.5 and higher are available.  */
-#undef HAVE_GNUC25_ATTRIB
-
-/* Define if constant functions a la GCC 2.5 and higher are available.  */
-#undef HAVE_GNUC25_CONST
-
-/* Define if nonreturning functions a la GCC 2.5 and higher are available.  */
-#undef HAVE_GNUC25_NORETURN
-
-/* Define if printf-format argument lists a la GCC are available.  */
-#undef HAVE_GNUC25_PRINTFFORMAT
-
-/* Set this to the canonical Debian architecture string for this CPU type. */
-#undef ARCHITECTURE
-
-/* Set this to 1 to build new archives by default. */
-#define BUILDOLDPKGFORMAT 0
-
-/* Set this string to append something to the version number. */
-#define ARCHBINFMT ""
-
-/* Define to 1 if NLS is requested.  */
-#undef ENABLE_NLS
-
-/* Define as 1 if you have catgets and don't want to use GNU gettext.  */
-#undef HAVE_CATGETS
-
-/* Define as 1 if you have gettext and don't want to use GNU gettext.  */
-#undef HAVE_GETTEXT
-
-/* Define if your locale.h file contains LC_MESSAGES.  */
-#undef HAVE_LC_MESSAGES
-
-/* Define as 1 if you have the stpcpy function.  */
-#undef HAVE_STPCPY
-
-#undef HAVE_SYS_ERRLIST_DECL
-
-#undef HAVE_HSTRERROR_DECL
-
-#undef HAVE_H_ERRLIST_DECL
-
-#undef HAVE_H_ERRNO
-
-#undef HAVE_H_ERRNO_DECL
-
-#undef HAVE_UNSETENV_DECL
-
-#undef NEED_YYWRAP
-
-#undef HAVE_POLL
-
-#undef HAVE_STRERROR
-
-#undef HAVE_HSTRERROR
-
-#undef HAVE_DLOPEN
-
-#undef HAVE_RES_SEARCH
-
-#undef HAVE_RES_SEARCH_DECL
-
-#undef HAVE_RES_GETHOSTBYNAME2_DECL
-
-#undef HAVE_VSNPRINTF_DECL
-
-#undef HAVE_STRCASECMP_DECL
-
-#undef HAVE_STRPTIME_DECL
-
-#undef HAVE_RANDOM_DECL
-
-#undef HAVE_INET_ATON_DECL
-
-/* define if you are building with SOCKS support */
-#undef SOCKS4
-
-/* define if you are building with SOCKSv5 support */
-#undef SOCKS5
-
-/* define if you are building with SOCKS-Dante support */
-#undef SOCKS_DANTE
-
-/* build modular lftp */
-#undef WITH_MODULES
-
-/* md5 support is present in libc or libcrypt */
-#undef HAVE_MD5
-
-@BOTTOM@
 
 #if !defined(HAVE_LSTAT)
 # define lstat(file,stp)     stat((file),(stp))
Index: src/Makefile.am
===================================================================
RCS file: /home/lav/cvsroot/lftp/src/Makefile.am,v
retrieving revision 1.58
diff -u -r1.58 Makefile.am
--- src/Makefile.am     2002/05/16 14:04:03     1.58
+++ src/Makefile.am     2002/06/03 00:40:56
@@ -67,9 +67,10 @@
  bookmark.cc bookmark.h CatJob.cc CatJob.h GetJob.cc GetJob.h\
  mkdirJob.cc mkdirJob.h pgetJob.cc pgetJob.h FileFeeder.cc FileFeeder.h\
  QueueFeeder.cc QueueFeeder.h keyvalue.cc keyvalue.h history.cc history.h\
- FindJob.cc FindJob.h\
+ FindJob.cc FindJob.h \
  FindJobDu.cc FindJobDu.h ChmodJob.cc ChmodJob.h\
- TreatFileJob.cc TreatFileJob.h CopyJob.cc CopyJob.h
+ TreatFileJob.cc TreatFileJob.h CopyJob.cc CopyJob.h echoJob.cc echoJob.h \
+ OutputJob.cc OutputJob.h 
 
 lftp_LDFLAGS = -export-dynamic $(LFTP_SSL_LDFLAGS)
 lftp_LDADD = libjobs.a libtasks.a $(READLINE) $(READLINE_SUPPLIB) \
Index: src/Resolver.cc
===================================================================
RCS file: /home/lav/cvsroot/lftp/src/Resolver.cc,v
retrieving revision 1.56
diff -u -r1.56 Resolver.cc
--- src/Resolver.cc     2002/05/16 14:04:03     1.56
+++ src/Resolver.cc     2002/06/03 00:40:57
@@ -742,14 +742,12 @@
         break;
 
       struct hostent *ha;
-      bool free_ha=false;
 # if defined(HAVE_GETIPNODEBYNAME)
 #  ifndef HAVE_H_ERRNO
 #   define HAVE_H_ERRNO 1
 #  endif
       int h_errno=0;
       ha=getipnodebyname(name,af,0,&h_errno);
-      free_ha=true;
 # elif defined(HAVE_GETHOSTBYNAME2)
       ha=gethostbyname2(name,af);
 # else
@@ -769,8 +767,7 @@
            AddAddress(ha->h_addrtype, *a, ha->h_length);
         af_index++;
 # if defined(HAVE_GETIPNODEBYNAME)
-        if(free_ha)
-           freehostent(ha);
+        freehostent(ha);
 # endif
         continue;
       }

Reply via email to