On Wed, Jul 10, 2002 at 03:15:02PM +0400, Alexander V. Lukyanov wrote:
> I have committed it to cvs, without commented out test code.

Normally I'd bash on this a bit more before sending it in, but since the
stuff in CVS right now is pretty buggy, I'll send this now. 

OutputJob.cc, OutputJob.h:
 Update comments.
 
 Let the input copier own output_fd, so it'll delete it when it's done
 with it as intended (fixing the delete->close fd->output finished code path).
 This also means we don't have to deal with fg_data in OutputJob (since
 the copier owns the fd, CopyJob will do it for us.)

 eof is gone.

 Store width/tty status so we don't need output_fd after initialization.
 (needed in order to let the copier own it)

 Reversed DontFailIfBroken parameter.

 Disable fail_if_broken correctly; leave incorrect one in place for now
 (see comments.)  Fixes broken pipe with zcat.

 Use Timer; fixes scheduler problems with updating the statusline.

 Clear the status line on init, since if we have a statusline and
 we start a filter we won't be able to clear it later (due to changed
 pgrp.)
 
StatusLine.cc, StatusLine.h, OutputJob.cc, all ShowStatusLine users:
 When we've output to stdout recently, instead of refusing to print a
 statusline, instead tell the statusline to only send the next update to
 the title.  This gives us a title status during "cat", etc.

CmdExec.cc, StatusLine.cc, StatusLine.h: Don't clear the title when
 we're clearing the statusline due to stdout.

CatJob.cc: Override ShowRunStatus to call output->ShowStatusLine.  (Any
job using an OutputJob should call ShowStatusLine() before it or a child
displays a statusline; CopyJob, CatJob's child, was displaying a
statusline without doing this.)

OutputJob.cc, OutputJob.h, CatJob.cc: Don't reenable the statusbar for
commands that stream data from the server, since that's annoying when
the server is rate-limited per-second.

The title isn't updated when there's a filter running, since we don't know
if the child process is using it.  We can fairly safely use it when the
only filter running is zcat/bzcat, though.  I'll think about this.

> Ok, it is good thing to do. I've noticed that it is acually partially
> applied. Could you check what is not applied and still needed?

Erm.  The iumacros stuff wasn't in that patch.  I thought it was, so I
reverted my tree, so now I don't have a copy at all.  Maybe I'll redo it
some time, but that particular m4 is a headache ...

Separate patch:

acconfig.h, m4/lftp.m4: HAVE_POLL acconfig (trivial).

lftp.conf: Fix cls/hostls aliases (hostls was calling the ls alias, which was
calling the cls alias; didn't notice this since I rarely use that alias.)

log.cc, log.h: Add a resource (debug:quiet-used-tty) to disable the behavior
of quieting debug while a subprocess is in the foreground.  Useful for
debugging OutputJob.

Try: 
repeat 0s !echo hi
A ^C gets eaten by the child job; you have to mash ^C to stop it.  I'm
not sure there's a clean way to fix this.  (Repeat shouldn't stop if its
command exits with an error; perhaps it should exit if the command exits
because of an interrupt?)

-- 
Glenn Maynard
Index: src/CatJob.cc
===================================================================
RCS file: /home/lav/cvsroot/lftp/src/CatJob.cc,v
retrieving revision 1.23
diff -u -r1.23 CatJob.cc
--- src/CatJob.cc       2002/07/10 08:48:50     1.23
+++ src/CatJob.cc       2002/07/11 02:02:17
@@ -95,6 +95,8 @@
    ascii=false;
    auto_ascii=true;
 
+   output->DontRedisplayStatusbar();
+
    if(!strcmp(op,"more") || !strcmp(op,"zmore") || !strcmp(op,"bzmore"))
    {
       const char *pager=getenv("PAGER");
@@ -114,3 +116,12 @@
       Binary();
    }
 }
+
+void CatJob::ShowRunStatus(StatusLine *s)
+{
+   if(cp && cp->HasStatus() && output->ShowStatusLine(s))
+   {
+      cp->ShowRunStatus(s);
+   }
+}
+   
Index: src/CatJob.h
===================================================================
RCS file: /home/lav/cvsroot/lftp/src/CatJob.h,v
retrieving revision 1.10
diff -u -r1.10 CatJob.h
--- src/CatJob.h        2002/07/10 08:48:50     1.10
+++ src/CatJob.h        2002/07/11 02:02:17
@@ -24,6 +24,7 @@
 #define CATJOB_H
 
 #include "CopyJob.h"
+#include "StatusLine.h"
 
 class ArgV;
 class OutputJob;
@@ -48,6 +49,7 @@
 
    void Ascii() { ascii=true; }
    void Binary() { ascii=auto_ascii=false; }
+   void ShowRunStatus(StatusLine *s);
 };
 
 #endif /* CATJOB_H */
Index: src/CmdExec.cc
===================================================================
RCS file: /home/lav/cvsroot/lftp/src/CmdExec.cc,v
retrieving revision 1.91
diff -u -r1.91 CmdExec.cc
--- src/CmdExec.cc      2002/07/10 13:08:04     1.91
+++ src/CmdExec.cc      2002/07/11 02:02:18
@@ -949,7 +949,7 @@
 void CmdExec::pre_stdout()
 {
    if(status_line)
-      status_line->Clear();
+      status_line->Clear(false);
    if(feeder_called)
       feeder->clear();
    current->TimeoutS(1);
Index: src/FileSetOutput.cc
===================================================================
RCS file: /home/lav/cvsroot/lftp/src/FileSetOutput.cc,v
retrieving revision 1.25
diff -u -r1.25 FileSetOutput.cc
--- src/FileSetOutput.cc        2002/07/10 08:48:51     1.25
+++ src/FileSetOutput.cc        2002/07/11 02:02:18
@@ -422,7 +422,7 @@
    if(fso.quiet)
       return;
 
-   if(!output->ShowStatusLine())
+   if(!output->ShowStatusLine(s))
       return;
 
    if(list_info && !list_info->Done())
Index: src/OutputJob.cc
===================================================================
RCS file: /home/lav/cvsroot/lftp/src/OutputJob.cc,v
retrieving revision 1.1
diff -u -r1.1 OutputJob.cc
--- src/OutputJob.cc    2002/07/10 08:48:52     1.1
+++ src/OutputJob.cc    2002/07/11 02:02:18
@@ -20,15 +20,6 @@
 
 /* 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")
@@ -37,7 +28,8 @@
 
 /*
  * Implementation notes:
- * Background things we can't get around:
+ *
+ * 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.
@@ -50,15 +42,11 @@
  *
  * 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.)
+ * pipe.) 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.
  *
- * 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.
@@ -93,6 +81,18 @@
 
    initialized=true;
 
+   if(Error())
+      return;
+
+   /* Clear the statusline, since we might change the pgrp if we create filters. */
+   printf("%s", ""); /* (and avoid gcc warning) */
+
+   /* Some legitimate uses produce broken pipe condition (cat|head).
+    * We still want to produce broken pipe if we're not piping, eg
+    * cat > pipe. */
+   if(IsFiltered())
+      fail_if_broken=false;
+
    if(filter)
    {
       /* Create the global filter: */
@@ -103,10 +103,16 @@
 
    /* 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);
 
+   /* out now owns output_fd, and will delete it when it's finished, so
+    * we can't keep it around. */
+   output_fd=0;
+
+   // I don't think we need to do this; the CopyJob picks up the output_fd's
+   // FgData now, since we're not telling it not to delete it.
+   // fg_data=new FgData(output_fd->GetProcGroup(),fg);
+
    if(!fail_if_broken)
       input_fc->DontFailIfBroken();
 
@@ -148,17 +154,17 @@
    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;
+   is_a_tty=false;
+   width=-1;
+   statusbar_redisplay=true;
 }
 
 /* Local (fd) output. */
-OutputJob::OutputJob(FDStream *output_, const char *a0):
-   inter(1)
+OutputJob::OutputJob(FDStream *output_, const char *a0)
 {
    Init(a0);
 
@@ -167,12 +173,20 @@
    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
+      /* We don't want to produce broken pipe when we're actually
+       * piping, since some legitimate uses produce broken pipe, eg
+       * cat|head.  However, that's actually handled in InitCopy().
+       * User pipes aren't handled by us yet: instead of being set with
+       * SetFilter, they're being set up ahead of time and passed to
+       * us as an FDStream, so we don't really know if we're being filtered.
+       * 
+       * So, until we handle pipes directly, disable broken pipe whenever
+       * we're being sent anywhere but stdout. */
       fail_if_broken=false;
 
    is_stdout=output_fd->usesfd(1);
+   is_a_tty=isatty(output_fd->fd);
+   width=fd_width(output_fd->fd);
 
    /* We don't output status when outputting locally. */
    no_status=true;
@@ -187,8 +201,7 @@
    }
 }
 
-OutputJob::OutputJob(const char *path, const char *a0, FileAccess *fa):
-   inter(1)
+OutputJob::OutputJob(const char *path, const char *a0, FileAccess *fa)
 {
    Init(a0);
 
@@ -200,9 +213,6 @@
       /* 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;
    }
 
@@ -248,17 +258,10 @@
    xfree(filter);
 }
 
-void OutputJob::Reconfig(const char *r)
+/* This is called to ask us "permission" to display a status line. */
+bool OutputJob::ShowStatusLine(StatusLine *s)
 {
-   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 our output file is gone, or isn't stdout, we don't care. */
    if(!output || !is_stdout)
       return true;
 
@@ -275,22 +278,32 @@
    /* 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;
+    * If we've output something recently, only send the output to the title,
+    * to avoid flickering status for no reason.
+    */
+   if(!update_timer.Stopped()) {
+      s->NextUpdateTitleOnly();
+      return true;
+   }
 
-   last = now;
+   /* If we're not reenabling the status bar, and the statusbar has
+    * been turned off (due to output being reenabled), only send to
+    * the title. */
+   if(!statusbar_redisplay && output->GetCopy()->WriteAllowed())
+   {
+      s->NextUpdateTitleOnly();
+      return true;
+   }
 
-   /* Stop the output again, so the FileCopy will clear the StatusLine
-    * when there's more data. */
+   /* There hasn't been output in a while.  Stop the output again,
+    * so the FileCopy will clear the StatusLine when there's more data. */
    output->GetCopy()->AllowWrite(false);
 
    return true;
 }
 
+/* Get our contribution to the status line, which is just the output
+ * status, if any.  Input status is the job of the user object. */
 const char *OutputJob::Status(const StatusLine *s)
 {
    if(no_status)
@@ -312,9 +325,10 @@
     * that we always start the input->output code path. */
    Put("", 0);
 
+   /* Send an EOF to the input peer; it'll send an EOF to the output peer
+    * when all of its data is actually sent. */
    if(InputPeer())
       InputPeer()->PutEOF();
-   eof=true;
 }
 
 /* add a filter to the beginning of the list */
@@ -338,18 +352,23 @@
    filter=xstrdup(newfilter);
 }
 
+/* Return the width of the output.  If there's a filter, we can either
+ * return -1 (we might be piping through "sed", changing the width),
+ * or the width we know (which is sane for most pagers.)  I'm not sure
+ * which is better. */
 int OutputJob::GetWidth() const
 {
-   if(IsFiltered() || output_fd->getfd() != 1)
+   if(IsFiltered())
       return -1;
-   return fd_width(1);
+   return width;
 }
 
+/* Return true if the output is going directly to a TTY. */
 bool OutputJob::IsTTY() const
 {
-   if(IsFiltered() || output_fd->getfd() != 1)
+   if(IsFiltered())
       return false;
-   return isatty(1);
+   return is_a_tty;
 }
 
 /* Get the input FileCopyPeer; this is the buffer we write to. */
@@ -368,43 +387,21 @@
 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;
+   
+   return true;
 }
 
 int OutputJob::Do()
 {
-   if(!fg_data && output_fd && output_fd->GetProcGroup())
-   {
-      fg_data=new FgData(output_fd->GetProcGroup(),fg);
-      return MOVED;
-   }
-
    return STALL;
 }
 
@@ -418,8 +415,6 @@
       error=true;
    if(output && input != output && output->Error() && output->Done())
       error=true;
-   if(fail_if_broken && output_fd->broken())
-      error=true;
    return error;
 }
 
@@ -492,7 +487,7 @@
    if(!InputPeer())
       return;
 
-   last.SetToCurrentTime();
+   update_timer.SetResource("cmd:status-interval",0);
 
    int oldpos = InputPeer()->GetPos();
    InputPeer()->Put(buf, size);
@@ -505,6 +500,8 @@
    if(!InputPeer())
       return;
 
+   update_timer.SetResource("cmd:status-interval",0);
+
    int oldpos = InputPeer()->GetPos();
 
    va_list v;
@@ -525,11 +522,12 @@
    /* 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);
+      input->AcceptSig(sig);
    /* Otherwise, the only filters we have running are in output_fd. */
-   else
+   else if(output_fd)
       output_fd->Kill(sig);
    if(sig!=SIGCONT)
       AcceptSig(SIGCONT);
    return m;
 }
+
Index: src/OutputJob.h
===================================================================
RCS file: /home/lav/cvsroot/lftp/src/OutputJob.h,v
retrieving revision 1.1
diff -u -r1.1 OutputJob.h
--- src/OutputJob.h     2002/07/10 08:48:52     1.1
+++ src/OutputJob.h     2002/07/11 02:02:18
@@ -24,7 +24,7 @@
 #include "Job.h"
 #include "FileCopy.h"
 #include "CopyJob.h"
-#include "TimeDate.h"
+#include "Timer.h"
 
 class StatusBar;
 
@@ -46,14 +46,16 @@
    bool error;
    bool is_stdout;
    bool fail_if_broken;
-   bool eof;
+   bool statusbar_redisplay;
 
+   int width;
+   bool is_a_tty;
+
    /* if true, we never contribute to the parent job's status
     * (Status() == "") */
    bool no_status;
 
-   Time last;
-   TimeInterval inter;
+   Timer update_timer;
 
    void Init(const char *a0);
    void InitCopy();
@@ -76,7 +78,7 @@
    /* Prepend a filter before the main filter: */
    void PreFilter(const char *filter);
 
-   void DontFailIfBroken(bool n=false) { fail_if_broken=n; }
+   void DontFailIfBroken(bool y=true) { fail_if_broken=!y; }
    bool Error();
 
    int Done();
@@ -87,8 +89,9 @@
    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.) */
+   /* If sending large amounts of data, call this function and stop
+    * sending if it returns true.  (This always accept more input;
+    * this is optional.) */
    bool Full();
 
    /* Get properties of the output: */
@@ -101,10 +104,14 @@
 
    /* Call before showing a StatusLine on a job using this class.  If it
     * returns false, don't display it. */
-   bool ShowStatusLine();
+   bool ShowStatusLine(StatusLine *s);
+
+   /* For commands that stream output from servers, redisplaying the
+    * statusbar when output becomes idle can be annoying, especially
+    * if the line is rate-limited. */
+   void DontRedisplayStatusbar() { statusbar_redisplay=false; }
 
    const char *Status(const StatusLine *s);
-   void Reconfig(const char *r);
 
    void Fg();
    void Bg();
Index: src/StatusLine.cc
===================================================================
RCS file: /home/lav/cvsroot/lftp/src/StatusLine.cc,v
retrieving revision 1.20
diff -u -r1.20 StatusLine.cc
--- src/StatusLine.cc   2002/05/14 11:55:23     1.20
+++ src/StatusLine.cc   2002/07/11 02:02:19
@@ -58,6 +58,7 @@
 {
    fd=new_fd;
    update_delayed=false;
+   next_update_title_only=false;
    strcpy(shown,"");
    strcpy(def_title,"");
    not_term=!isatty(fd);
@@ -69,7 +70,7 @@
 {
 }
 
-void StatusLine::Clear()
+void StatusLine::Clear(bool title_also)
 {
    char newstr[sizeof(shown)];
 
@@ -78,7 +79,8 @@
    update_delayed=false;
    update_timer.SetMilliSeconds(20);
 
-   WriteTitle(def_title, fd);
+   if(title_also)
+      WriteTitle(def_title, fd);
 }
 
 void StatusLine::DefaultTitle(const char *s)
@@ -147,6 +149,12 @@
 
    /* Don't write blank titles into the title; let Clear() do that. */
    if(newstr[0]) WriteTitle(newstr, fd);
+
+   if(next_update_title_only)
+   {
+      next_update_title_only=false;
+      return;
+   }
 
    char *end=newstr+strlen(newstr);
 
Index: src/StatusLine.h
===================================================================
RCS file: /home/lav/cvsroot/lftp/src/StatusLine.h,v
retrieving revision 1.11
diff -u -r1.11 StatusLine.h
--- src/StatusLine.h    2001/12/24 07:31:48     1.11
+++ src/StatusLine.h    2002/07/11 02:02:19
@@ -37,6 +37,7 @@
    bool update_delayed;
    void update(char *);
    int LastWidth;
+   bool next_update_title_only;
 
 protected:
    ~StatusLine();
@@ -45,10 +46,11 @@
 public:
    int GetWidth();
    int GetWidthDelayed() const { return LastWidth; }
+   void NextUpdateTitleOnly() { next_update_title_only=true; }
    void DefaultTitle(const char *s);
    void Show(const char *f,...) PRINTF_LIKE(2,3);
    void WriteLine(const char *f,...) PRINTF_LIKE(2,3);
-   void Clear();
+   void Clear(bool title_also=true);
 
    int getfd() const { return fd; }
 
Index: src/echoJob.cc
===================================================================
RCS file: /home/lav/cvsroot/lftp/src/echoJob.cc,v
retrieving revision 1.1
diff -u -r1.1 echoJob.cc
--- src/echoJob.cc      2002/07/10 08:48:53     1.1
+++ src/echoJob.cc      2002/07/11 02:02:19
@@ -70,7 +70,7 @@
    /* Never call output->ShowStatusLine unless we're really going
     * to display something. */
    const char *stat = output->Status(s);
-   if(*stat && output->ShowStatusLine())
+   if(*stat && output->ShowStatusLine(s))
       s->Show("echo: %s", stat);
 }
 
Index: lftp.conf
===================================================================
RCS file: /home/lav/cvsroot/lftp/lftp.conf,v
retrieving revision 1.18
diff -u -r1.18 lftp.conf
--- lftp.conf   2002/07/10 07:58:51     1.18
+++ lftp.conf   2002/07/11 02:01:55
@@ -11,8 +11,8 @@
 #set prompt "\[\e[1;30m\][\[\e[0;34m\]f\[\e[1m\]t\[\e[37m\]p\[\e[30m\]] 
\[\e[34m\]\u\[\e[0;34m\]\@\[\e[1m\]\h\[\e[1;30m\]:\[\e[1;34m\]\w\[\e[1;30m\]>\[\e[0m\] 
"
 ## Uncomment the following two lines to make switch cls and ls, making
 ## cls the default.
-#alias ls cls
-#alias hostls ls
+#alias ls command cls
+#alias hostls command ls
 
 ## default protocol selection
 #set default-protocol/ftp.*    ftp
Index: acconfig.h
===================================================================
RCS file: /home/lav/cvsroot/lftp/acconfig.h,v
retrieving revision 1.34
diff -u -r1.34 acconfig.h
--- acconfig.h  2002/06/03 08:57:47     1.34
+++ acconfig.h  2002/07/11 02:01:55
@@ -26,7 +26,6 @@
 #undef HAVE_H_ERRLIST_DECL
 #undef HAVE_H_ERRNO_DECL
 #undef HAVE_INET_ATON_DECL
-#undef HAVE_POLL
 #undef HAVE_RANDOM_DECL
 #undef HAVE_RES_SEARCH_DECL
 #undef HAVE_STRCASECMP_DECL
Index: m4/lftp.m4
===================================================================
RCS file: /home/lav/cvsroot/lftp/m4/lftp.m4,v
retrieving revision 1.7
diff -u -r1.7 lftp.m4
--- m4/lftp.m4  2002/06/02 10:21:44     1.7
+++ m4/lftp.m4  2002/07/11 02:01:56
@@ -23,7 +23,7 @@
    ])
    AC_MSG_RESULT($lftp_cv_func_poll_works)
    if test $lftp_cv_func_poll_works = yes; then
-      AC_DEFINE(HAVE_POLL)
+      AC_DEFINE(HAVE_POLL, 1, [have poll()])
    fi
 ])
 
Index: src/log.cc
===================================================================
RCS file: /home/lav/cvsroot/lftp/src/log.cc,v
retrieving revision 1.13
diff -u -r1.13 log.cc
--- src/log.cc  2002/01/21 16:25:17     1.13
+++ src/log.cc  2002/07/11 02:01:56
@@ -28,6 +28,7 @@
 #include "xstring.h"
 #include "log.h"
 #include "SMTask.h"
+#include "ResMgr.h"
 
 Log *Log::global=new Log;
 
@@ -39,8 +40,16 @@
    enabled=false;
    level=0;
    tty=false;
+   quiet_used_tty=true;
 }
 
+ResDecl res_quiet_used_tty ("debug:quiet-used-tty",  "yes", ResMgr::BoolValidate,0);
+
+void Log::Reconfig(const char *n)
+{
+   quiet_used_tty = res_quiet_used_tty.QueryBool(0);
+}
+
 void Log::Write(int l,const char *s)
 {
    if(!enabled || l>level)
@@ -52,7 +61,7 @@
       pid_t pg=tcgetpgrp(output);
       if(pg==(pid_t)-1)
         tty=false;
-      else if(pg!=getpgrp())
+      else if(quiet_used_tty && pg!=getpgrp())
         return;
    }
    if(tty_cb && tty)
Index: src/log.h
===================================================================
RCS file: /home/lav/cvsroot/lftp/src/log.h,v
retrieving revision 1.6
diff -u -r1.6 log.h
--- src/log.h   2001/11/08 09:25:49     1.6
+++ src/log.h   2002/07/11 02:01:56
@@ -32,6 +32,7 @@
    int output;
    bool need_close_output;
    bool tty;
+   bool quiet_used_tty;
    typedef void (*tty_cb_t)();
    tty_cb_t tty_cb;
 
@@ -71,6 +72,7 @@
    void SetCB(tty_cb_t cb) { tty_cb=cb; }
 
    bool IsTTY() { return tty; }
+   void Reconfig(const char *r);
 
    void Init();
    Log() { Init(); }

Reply via email to