[Gs-code-review] new switch for stdout redirection -sstdout

Stefan Kemper stefan at artifex.com
Wed Mar 7 10:44:42 PST 2001


Don't know the Sourceforge bug number
Debian bug #9285


Problem:

Postscript language allows print commands to stdout.
gs allows redirection of driver output to stdout.
Intermixing text with driver output doesn't work for most drivers.
See attached notes for the ghost's email discussion on stdout. 

Solution:

Allow the redirection of all non-driver stdout output to a file, 
while still allowing driver stdout to go to the console,
via a new command line option:

    -sstdout=<filename>
	
This is option C) in the email discussion.

Recommend using -dNOPAUSE -dBATCH and possibly the -q options whenever
redirecting stdout.
Not seeing prompts for return keys is annoying.  

gs ... -sstdout=/tmp/gs_stdout.log -sOutputFile=- inputFile  2>>
/tmp/gs_stderr.log | driverFilter 

All text stdout output goes to /tmp/gs_stdout.log
Driver output goes to the console stdout "-" is then piped to
driverFilter
Note the sstdout redirect file is opened for append.  

gs ... -sstdout=- -sOutputFile=- ...
gs ... -sOutputFile=- ...

Works the same as before, driver output and stdout text are mixed on
stdout.


Design:

First a few obvious features of the existing code base:
An attempt to hide stdin, stdout, stderr is done early in the code, 
these are copied to gs_stdxxx variables, and to minst->fstdxxx
varriables.

There are "Special" gx_io_devices used to handle the console file
descripters in gsiodevs.c
differently from normal files that can be opened and closed.

Both the gx_io_devices and the gs_stdout FILE pointers are used.  Most
writing to stdout happens 
using the FILE* not a stream based on the io_device abstraction.

The gx_io_device abstration seems to be missing a get for the underlying
FILE*, this leads to code that compares the io_device.dname to "%stdout"
and then grabs the FILE*.

Added a new file descriptor:	  gs_realstdout 
Added a new io device:		  %realstdout%
Both of these are always associated to the real stdout or windows
stdout.

Added -sstdout command line options to pcl6 and gs.
Added redirect of gs_stdout to the -sstdout="specified file".

Note gs_stdout is opened for append.  Is this acceptable?  Should it be
an option?
perhaps -sstdout=file+ for append -sstdout=file for "w" construction?

Changed driver output -sOutputFile=- to open %realstdout /
gs_realstdout.

I didn't feel that stdin or stderr needed this kind of option, 
normal io redirection should work fine.

The io device %stdout% should be closed and replaced with a os file
device.  
This would ensure proper closure of the redirected stdout file, instead
of
relying on the OS the close the file on exit.  This wasn't done since
most
code uses the FILE pointer directly.

Currently (Mar 7 2001): Untested in the windows or vms environments. 
Missing -help text and any documentation changes.

Code Diffs are based on meerkat cvs :( and include pcl6 redirect changes


Index: files.h
===================================================================
RCS file: /home/henrys/cvsroot2/gs/src/files.h,v
retrieving revision 1.9
diff -C2 -r1.9 files.h
*** files.h	2000/12/12 19:04:09	1.9
--- files.h	2001/03/07 17:40:14
***************
*** 28,31 ****
--- 28,32 ----
  int zget_stdout(P2(i_ctx_t *, stream **));
  int zget_stderr(P2(i_ctx_t *, stream **));
+ int zget_realstdout(P2(i_ctx_t *, stream **));
  extern bool gs_stdin_is_interactive;
  /* Test whether a stream is stdin. */
***************
*** 37,40 ****
--- 38,42 ----
  #define ref_stdout ref_stdio[1]
  #define ref_stderr ref_stdio[2]
+ #define ref_realstdout ref_stdio[3]
  /* An invalid (closed) file. */
  #define avm_invalid_file_entry avm_foreign
Index: gp_msio.c
===================================================================
RCS file: /home/henrys/cvsroot2/gs/src/gp_msio.c,v
retrieving revision 1.8
diff -C2 -r1.8 gp_msio.c
*** gp_msio.c	2000/12/12 19:04:11	1.8
--- gp_msio.c	2001/03/07 17:40:21
***************
*** 111,114 ****
--- 111,130 ----
  }
  
+ extern const gx_io_device gs_iodev_realstdout;
+ private int
+ win_realstdout_open(gx_io_device * iodev, const char *access, stream
** ps,
+ 		gs_memory_t * mem)
+ {
+     int code = gs_iodev_realstdout.procs.open_device(iodev, access,
ps, mem);
+     stream *s = *ps;
+ 
+     if (code != 1)
+ 	return code;
+     s->procs.process = win_std_write_process;
+     s->procs.available = win_std_available;
+     s->file = NULL;
+     return 0;
+ }
+ 
  extern const gx_io_device gs_iodev_stderr;
  private int
***************
*** 145,148 ****
--- 161,168 ----
  	gs_findiodevice((const byte *)"%stderr", 7)->procs.open_device =
  	    win_stderr_open;
+ 
+     if (gp_file_is_console(gs_realstdout))
+ 	gs_findiodevice((const byte *)"%realstdout", 11)->procs.open_device =
+ 	    win_realstdout_open;
  }
  
Index: gsdevice.c
===================================================================
RCS file: /home/henrys/cvsroot2/gs/src/gsdevice.c,v
retrieving revision 1.17
diff -C2 -r1.17 gsdevice.c
*** gsdevice.c	2000/12/12 19:04:12	1.17
--- gsdevice.c	2001/03/07 17:40:28
***************
*** 674,679 ****
      }
      if (!pfn->iodev) {
! 	if (!strcmp(pfn->fname, "-")) {
! 	    pfn->iodev = gs_findiodevice((const byte *)"%stdout", 7);
  	    pfn->fname = NULL;
  	} else if (pfn->fname[0] == '|') {
--- 674,679 ----
      }
      if (!pfn->iodev) {
! 	if (!strcmp(pfn->fname, "-")) { 
! 	    pfn->iodev = gs_findiodevice((const byte *)"%realstdout", 11);
  	    pfn->fname = NULL;
  	} else if (pfn->fname[0] == '|') {
***************
*** 742,749 ****
      if (code < 0)
  	return code;
!     if (parsed.iodev && !strcmp(parsed.iodev->dname, "%stdout%")) {
  	if (parsed.fname)
  	    return_error(gs_error_undefinedfilename);
! 	*pfile = gs_stdout;
  	/* Force stdout to binary. */
  	return gp_setmode_binary(*pfile, true);
--- 742,753 ----
      if (code < 0)
  	return code;
!     /* realstdout is stdout without the effect of -sstdout redirection
!      * -sOutputFile=- always gets realstdout, everone else gets stdout 
!      * iodev interface to get the FILE* is missing 
!      */
!     if (parsed.iodev && !strcmp(parsed.iodev->dname, "%realstdout%"))
{
  	if (parsed.fname)
  	    return_error(gs_error_undefinedfilename);
! 	*pfile = gs_realstdout;
  	/* Force stdout to binary. */
  	return gp_setmode_binary(*pfile, true);
Index: gsio.h
===================================================================
RCS file: /home/henrys/cvsroot2/gs/src/gsio.h,v
retrieving revision 1.7
diff -C2 -r1.7 gsio.h
*** gsio.h	2000/12/12 19:04:12	1.7
--- gsio.h	2001/03/07 17:40:29
***************
*** 15,22 ****
   * referenced through an instance structure.
   */
! extern FILE *gs_stdio[3];
  #define gs_stdin (gs_stdio[0])
  #define gs_stdout (gs_stdio[1])
  #define gs_stderr (gs_stdio[2])
  
  /*
--- 15,23 ----
   * referenced through an instance structure.
   */
! extern FILE *gs_stdio[4];
  #define gs_stdin (gs_stdio[0])
  #define gs_stdout (gs_stdio[1])
  #define gs_stderr (gs_stdio[2])
+ #define gs_realstdout (gs_stdio[3])
  
  /*
Index: gsiodevs.c
===================================================================
RCS file: /home/henrys/cvsroot2/gs/src/gsiodevs.c,v
retrieving revision 1.1
diff -C2 -r1.1 gsiodevs.c
*** gsiodevs.c	2000/12/12 18:02:34	1.1
--- gsiodevs.c	2001/03/07 17:40:31
***************
*** 75,78 ****
--- 75,86 ----
  
  private int
+ realstdout_open(gx_io_device * iodev, const char *access, stream **
ps,
+ 	    gs_memory_t * mem)
+ {
+     return stdio_open(iodev, access, ps, mem, 'w', gs_realstdout,
swrite_file);
+ }
+ const gx_io_device gs_iodev_realstdout = iodev_stdio("%realstdout%",
realstdout_open);
+ 
+ private int
  stderr_open(gx_io_device * iodev, const char *access, stream ** ps,
  	    gs_memory_t * mem)
***************
*** 81,82 ****
--- 89,91 ----
  }
  const gx_io_device gs_iodev_stderr = iodev_stdio("%stderr%",
stderr_open);
+ 
Index: gsmisc.c
===================================================================
RCS file: /home/henrys/cvsroot2/gs/src/gsmisc.c,v
retrieving revision 1.9
diff -C2 -r1.9 gsmisc.c
*** gsmisc.c	2000/12/12 19:04:13	1.9
--- gsmisc.c	2001/03/07 17:40:42
***************
*** 41,45 ****
  
  /* Define private replacements for stdin, stdout, and stderr. */
! FILE *gs_stdio[3];
  
  /* ------ Debugging ------ */
--- 41,45 ----
  
  /* Define private replacements for stdin, stdout, and stderr. */
! FILE *gs_stdio[4];
  
  /* ------ Debugging ------ */
Index: imain.c
===================================================================
RCS file: /home/henrys/cvsroot2/gs/src/imain.c,v
retrieving revision 1.8
diff -C2 -r1.8 imain.c
*** imain.c	2000/12/12 19:04:15	1.8
--- imain.c	2001/03/07 17:40:52
***************
*** 12,20 ****
  #include <stdio.h>
  private void
! set_stdfiles(FILE * stdfiles[3])
  {
      stdfiles[0] = stdin;
      stdfiles[1] = stdout;
      stdfiles[2] = stderr;
  }
  #include "ghost.h"
--- 12,21 ----
  #include <stdio.h>
  private void
! set_stdfiles(FILE * stdfiles[4])
  {
      stdfiles[0] = stdin;
      stdfiles[1] = stdout;
      stdfiles[2] = stderr;
+     stdfiles[3] = stdout;
  }
  #include "ghost.h"
***************
*** 82,86 ****
  /* Save the real stdio files. */
  void
! gs_get_real_stdio(FILE * stdfiles[3])
  {
      set_stdfiles(stdfiles);
--- 83,87 ----
  /* Save the real stdio files. */
  void
! gs_get_real_stdio(FILE * stdfiles[4])
  {
      set_stdfiles(stdfiles);
***************
*** 99,102 ****
--- 100,104 ----
      gs_stdout = minst->fstdout = out;
      gs_stderr = minst->fstderr = err;
+     gs_realstdout = out;
      /* Do platform-dependent initialization. */
      /* We have to do this as the very first thing, */
Index: imainarg.c
===================================================================
RCS file: /home/henrys/cvsroot2/gs/src/imainarg.c,v
retrieving revision 1.9
diff -C2 -r1.9 imainarg.c
*** imainarg.c	2000/12/12 19:04:20	1.9
--- imainarg.c	2001/03/07 17:41:00
***************
*** 84,87 ****
--- 84,88 ----
  private int run_string(P3(gs_main_instance *, const char *, int));
  private int run_finish(P4(gs_main_instance *, int, int, ref *));
+ private int try_stdout_redirect(P3(gs_main_instance *, const char *,
const char *));
  
  /* Forward references for help printout */
***************
*** 110,114 ****
      const char *arg;
      arg_list args;
!     FILE *stdfiles[3];
      int code;
  
--- 111,115 ----
      const char *arg;
      arg_list args;
!     FILE *stdfiles[4];
      int code;
  
***************
*** 508,511 ****
--- 509,514 ----
  #undef name_is_string
  			}
+ 		    } else if ( 0 == try_stdout_redirect(minst, adef, eqp) ) {
+ 			/* stdout has been redirected to a file */
  		    } else {
  			int len = strlen(eqp);
***************
*** 893,895 ****
--- 896,921 ----
  				       "Use.htm", 7),
  	    GS_BUG_MAILBOX);
+ }
+ 
+ /* Redirect stdout to a file -sstdout='filename'
+  * -sOutputFile=- is not affected; uses gs_realstdout
+  * file close policy is: mulitple calls closes previous files,
+  * otherwise the end of program exit is relyed upon.
+  */
+ private int 
+ try_stdout_redirect(gs_main_instance * minst, const char *command,
const char *filename)
+ {
+     if ( !strcmp(command, "stdout") ) {
+ 	FILE *fp = 0;
+ 
+ 	if ( (filename != 0 &&  filename[0] != '-' && filename[1] != 0) &&
+ 	     ( 0 != (fp = fopen(filename, "a"))) ) {
+ 	    if ( fileno(gs_stdout) != fileno(gs_realstdout) ) 
+ 		fclose(gs_stdout);
+ 	    /* keep the two stdout variables in sync */
+ 	    gs_stdout = minst->fstdout = fp;
+ 	}
+ 	return 0;
+     }
+     return 1;
  }
Index: int.mak
===================================================================
RCS file: /home/henrys/cvsroot2/gs/src/int.mak,v
retrieving revision 1.14
diff -C2 -r1.14 int.mak
*** int.mak	2000/12/12 19:04:20	1.14
--- int.mak	2001/03/07 17:41:21
***************
*** 532,536 ****
  	$(ADDMOD) $(PSD)psbase -oper $(Z10OPS)
  	$(ADDMOD) $(PSD)psbase -oper $(Z11OPS)
! 	$(ADDMOD) $(PSD)psbase -iodev stdin stdout stderr lineedit
statementedit
  	$(ADDMOD) $(PSD)psbase -include $(PSD)isupport $(PSD)nobtoken
$(PSD)nousparm
  	$(ADDMOD) $(PSD)psbase -include $(GLD)rld $(GLD)rle $(GLD)sfile
--- 532,536 ----
  	$(ADDMOD) $(PSD)psbase -oper $(Z10OPS)
  	$(ADDMOD) $(PSD)psbase -oper $(Z11OPS)
! 	$(ADDMOD) $(PSD)psbase -iodev stdin stdout stderr realstdout lineedit
statementedit
  	$(ADDMOD) $(PSD)psbase -include $(PSD)isupport $(PSD)nobtoken
$(PSD)nousparm
  	$(ADDMOD) $(PSD)psbase -include $(GLD)rld $(GLD)rle $(GLD)sfile
Index: lib.mak
===================================================================
RCS file: /home/henrys/cvsroot2/gs/src/lib.mak,v
retrieving revision 1.23
diff -C2 -r1.23 lib.mak
*** lib.mak	2000/12/12 19:04:21	1.23
--- lib.mak	2001/03/07 17:41:51
***************
*** 772,776 ****
  	$(SETMOD) $(GLD)gsiodevs $(GLOBJ)gsiodevs.$(OBJ)
  	$(ADDMOD) $(GLD)gsiodevs -include $(GLD)sfile
! 	$(ADDMOD) $(GLD)gsiodevs -iodev stdin stdout stderr
  
  $(GLOBJ)gsiodevs.$(OBJ) : $(GLSRC)gsiodevs.c $(GXERR)\
--- 772,776 ----
  	$(SETMOD) $(GLD)gsiodevs $(GLOBJ)gsiodevs.$(OBJ)
  	$(ADDMOD) $(GLD)gsiodevs -include $(GLD)sfile
! 	$(ADDMOD) $(GLD)gsiodevs -iodev stdin stdout stderr realstdout
  
  $(GLOBJ)gsiodevs.$(OBJ) : $(GLSRC)gsiodevs.c $(GXERR)\
Index: unix-gcc.mak
===================================================================
RCS file: /home/henrys/cvsroot2/gs/src/unix-gcc.mak,v
retrieving revision 1.19
diff -C2 -r1.19 unix-gcc.mak
*** unix-gcc.mak	2000/12/12 19:04:22	1.19
--- unix-gcc.mak	2001/03/07 17:41:57
***************
*** 94,98 ****
  # Define the name of the executable file.
  
! GS=gs
  
  # Define the name of a pre-built executable that can be invoked at
build
--- 94,98 ----
  # Define the name of the executable file.
  
! GS=ngs
  
  # Define the name of a pre-built executable that can be invoked at
build
Index: ziodevs.c
===================================================================
RCS file: /home/henrys/cvsroot2/gs/src/ziodevs.c,v
retrieving revision 1.1
diff -C2 -r1.1 ziodevs.c
*** ziodevs.c	2000/12/12 18:02:34	1.1
--- ziodevs.c	2001/03/07 17:42:01
***************
*** 56,59 ****
--- 56,65 ----
      iodev_special("%stderr%", iodev_no_init, stderr_open);
  
+ #define REALSTDOUT_BUF_SIZE 128
+ /*#define ref_realstdout ref_stdio[3] *//* in files.h */
+ private iodev_proc_open_device(realstdout_open);
+ const gx_io_device gs_iodev_realstdout =
+     iodev_special("%realstdout%", iodev_no_init, realstdout_open);
+ 
  /* ------- %stdin, %stdout, and %stderr ------ */
  
***************
*** 197,200 ****
--- 203,252 ----
      }
      iodev = gs_findiodevice((const byte *)"%stdout", 7);
+     iodev->state = i_ctx_p;
+     code = (*iodev->procs.open_device)(iodev, "w", ps,
imemory_system);
+     iodev->state = NULL;
+     return min(code, 0);
+ }
+ private int
+ realstdout_open(gx_io_device * iodev, const char *access, stream **
ps,
+ 	    gs_memory_t * mem)
+ {
+     i_ctx_t *i_ctx_p = (i_ctx_t *)iodev->state;	/* see above */
+     stream *s;
+ 
+     if (!streq1(access, 'w'))
+ 	return_error(e_invalidfileaccess);
+     if (file_is_invalid(s, &ref_realstdout)) {
+ 	gs_memory_t *mem = imemory_system;
+ 	byte *buf;
+ 
+ 	s = file_alloc_stream(mem, "realstdout_open(stream)");
+ 	buf = gs_alloc_bytes(mem, REALSTDOUT_BUF_SIZE,
"realstdout_open(buffer)");
+ 	if (s == 0 || buf == 0)
+ 	    return_error(e_VMerror);
+ 	swrite_file(s, gs_realstdout, buf, REALSTDOUT_BUF_SIZE);
+ 	s->save_close = s->procs.flush;
+ 	s->procs.close = file_close_file;
+ 	make_file(&ref_stdout, a_write | avm_system, s->write_id, s);
+ 	*ps = s;
+ 	return 1;
+     }
+     *ps = s;
+     return 0;
+ }
+ 
+ /* This is the public routine for getting the stdout stream. */
+ int
+ zget_realstdout(i_ctx_t *i_ctx_p, stream ** ps)
+ {
+     stream *s;
+     gx_io_device *iodev;
+     int code;
+ 
+     if (file_is_valid(s, &ref_realstdout)) {
+ 	*ps = s;
+ 	return 0;
+     }
+     iodev = gs_findiodevice((const byte *)"%realstdout", 7);
      iodev->state = i_ctx_p;
      code = (*iodev->procs.open_device)(iodev, "w", ps,
imemory_system);






===================================================================
RCS file: /home/henrys/cvsroot2/pl/plmain.c,v
retrieving revision 1.30
diff -C2 -r1.30 plmain.c
*** plmain.c    2001/02/06 08:36:18     1.30
--- plmain.c    2001/02/28 17:25:18
***************
*** 4,12 ****
  /* get stdio values before they get redefined */
   private void
! pl_get_real_stdio(FILE **in, FILE **out, FILE **err)
  {
      *in = stdin;
      *out = stdout;
      *err = stderr;
  }
  #include "string_.h"
--- 4,13 ----
  /* get stdio values before they get redefined */
   private void
!  pl_get_real_stdio(FILE **in, FILE **out, FILE **err, FILE **rout)
  {
      *in = stdin;
      *out = stdout;
      *err = stderr;
+     *rout = stdout;
  }
  #include "string_.h"
***************
*** 163,167 ****
--- 164,171 ----
  void pl_main_cursor_close(P1(pl_top_cursor_t *cursor));

+ /* Redirect stdout */
+ private void pl_main_stdout_redirect(const char *out);

+
  /* ----------- Command-line driver for pl_interp's  ------ */
  /*
***************
*** 187,191 ****

      /* Init std io: set up in, our err - not much we can do here if
this fails */
!     pl_get_real_stdio(&gs_stdin, &gs_stdout, &gs_stderr);

      /* Initialize the platform. */
--- 191,195 ----

      /* Init std io: set up in, our err - not much we can do here if
this fails */
!     pl_get_real_stdio(&gs_stdin, &gs_stdout, &gs_stderr,
&gs_realstdout);

      /* Initialize the platform. */
***************
*** 799,803 ****
                    pl_top_create_device(pmi, di, false);
                  }
!                 else
                    { param_string_from_string(str, value);
                      code = param_write_string(plist,
arg_heap_copy(arg),
--- 803,811 ----
                    pl_top_create_device(pmi, di, false);
                  }
!                 else if ( !strcmp(arg, "stdout") )
!                   {
!                       pl_main_stdout_redirect(value);
!                   }
!                 else
                    { param_string_from_string(str, value);
                      code = param_write_string(plist,
arg_heap_copy(arg),
***************
*** 1025,1028 ****
--- 1033,1055 ----
        pl_top_cursor_dnit(cursor);
        fclose(cursor->strm);
+ }
+
+
+ /* Redirect stdout to a file -sstdout='filename'
+  * -sOutputFile=- is not affected; uses gs_realstdout
+  * file close policy is: mulitple calls closes previous files,
+  * otherwise the end of program exit is relyed upon.
+  */
+ private void
+ pl_main_stdout_redirect( const char *out /* file to redirect stdout */
+                       )
+ {
+     FILE *fp = 0;
+     if ( ( out != 0 &&  out[0] != '-' && out[1] != 0 ) &&
+        ( 0 != (fp = fopen(out, "a"))) )  {
+       if ( fileno(gs_stdout) != fileno(gs_realstdout) )
+           fclose(gs_stdout);
+       gs_stdout = fp;
+     }
  }
-------------- next part --------------
From: Dan Coby [dan at artifex.com]
Sent: Tuesday, January 30, 2001 9:54 PM
To: Stefan Kemper
Cc: Ray J Johnston; Miles Jones; Igor V. Melichev; Henry Stiles; Alex
Cherepanov
Subject: Redirection of stdout.


Stefan,

Here is an old problem for which you can try to come up with a
solution.

The basic problem is that a Postscript interpreter produces several
different outputs.  These are:
1.  The output image data.
2.  Text that gets sent to stdout.  This includes warning messages
    generated by Ghostscript (this can be disabled via a switch) and
    various responses generated by the Postscript program itself.
3.  Error messages (these generally go to stdout).

The problem is that many unix users like to use Ghostscript as a
typical unix filter.  Thus they specify that the image data be
sent to stdout.  They then are unhappy when the image data is
mixed with the stdout text.

Various solutions have been proposed.  These generally consist of
either the simple solution (simply providing a switch to disable
the text output to stdout - this only works for about 80 to 90%
of the users) or some more complex scheme for specifying redirection
of stdout text data.

We would like you to take a look at this problem and come up with
a proposed solution (and probably then to implement it).

If you have any questions, please feel free to contact me.

The remainder of this email includes information from two sources.
The first group is an email discussion on the topic which was
started by L. Peter Deutsch.  The second group is from a Discussion
Group topic on the Ghostscript page on Source Forge.  (The two
topic groups are started with a line of XXXXXXXXXXXs.


Dan

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Email discussion on stdout

From:  L. Peter Deutsch [ghost at aladdin.com]


Dear friends of Ghostscript.

As you know, Ghostscript can generate output to stdout and stderr.  Output
to stderr is not a problem.  However, output to stdout has been an ongoing
problem, because there are 3 conceptually different entities that generate
it, and they interfere with each other:

	1) Ghostscript itself can generate warning, error, or debugging
	messages.

	2) PostScript files can explicitly write to %stdout using the
	operators print, =, ==, stack, and pstack; for example, quite a few
	PostScript files print comments like
		%%[Page: <page#>]%%
	for each page.

	3) Driver output can be directed to stdout with
		-sOutputFile=-
	or
		-sOutputFile=%stdout
	or by executing the equivalent setpagedevice or .putdeviceparams
	in PostScript code.

#1 and #2 can be interleaved with no problem, because in both cases it is a
person that is reading the output.  However, mixing #1 or #2 with #3
produces corrupted driver output.

In a production (non-debugging) configuration, the -q switch currently
suppresses all non-fatal messages of type #1.  (In the future, it may divert
some or all of them to stderr instead.)  However, #2 still interferes with
#3.

Note that this problem is specific to the PostScript interpreter.  PDF
doesn't have constructs of type #2, and the graphics library never prints
anything on stdout in a production configuration.

I've considered the following ways to deal with this problem, and I'm not
completely happy with any of them.

	A) Disallow setting OutputFile to stdout: allow output only to a
	real file or to a pipe.  (Output to a pipe is no problem.)  This
	would be simplest, but it would annoy Unix users, who feel they get
	a lot of value from being able to construct pipelines of programs in
	which each program's stdout feeds the next program's stdin.

	B) If OutputFile is set to stdout, automatically redirect the
	PostScript %stdout to stderr.  This is the only alternative that
	doesn't require users to do something different than what they do
	now, but I think it is likely to create some ugly design coupling
	between different parts of the Ghostscript code.

	C) Add a command line switch that says explicitly where to send the
	PostScript %stdout output.  One possibility that occurred to me is
		-sstdout=<filename>
	Or one could couple this to setting OutputFile, e.g.,
		-sOutputFile=-<filename>
	which would send the driver output to stdout and the PostScript
	%stdout to <filename>.

	D) Other ideas?

Please let me know your thoughts about this, since I would like to finally
deal with it soon.

				Thanks -

L. Peter Deutsch        |               Aladdin Enterprises
ghost at aladdin.com       | http://www.aladdin.com | 203 Santa Margarita Ave.
                        | fax +1-650-322-1734    | Menlo Park, CA 94025
	The future of software is at http://www.opensource.org

----------------------------------------------------------------------------

From: Graham Stoney [greyham at research.canon.com.au]


This problem has caused us some grief, so here's my suggestions:

L. Peter Deutsch writes:
> 	B) If OutputFile is set to stdout, automatically redirect the
> 	PostScript %stdout to stderr.  This is the only alternative that
> 	doesn't require users to do something different than what they do
> 	now, but I think it is likely to create some ugly design coupling
> 	between different parts of the Ghostscript code.

I can't comment on Ghostscript internals with regards to this, but I think
this is the best solution for users.  For one thing, it's the same one GNU
tar
uses to solve the same problem with "tar cvf -", so there's a precedent.

> 	C) Add a command line switch that says explicitly where to send the
> 	PostScript %stdout output.  One possibility that occurred to me is
> 		-sstdout=<filename>

It may still be useful to provide this option too, and I much prefer it over
coupling interpreter output with device output in OutputFile.  Users that
_really_ want intermingled output could still get the current (arguably
broken) functionality with:
		-sOutputFile=- -sstdout=-

Regards,
Graham
--
Graham Stoney
Principal Hardware/Software Engineer
Canon Information Systems Research Australia
Ph: +61 2 9805 2909  Fax: +61 2 9805 2929

----------------------------------------------------------------------------
---

From:  Stephen J. Turnbull [turnbull at sk.tsukuba.ac.jp]

>>>>> "Peter" == L Peter Deutsch <ghost at aladdin.com> writes:

	C) Add a command line switch that says explicitly where to send the
	PostScript %stdout output.  One possibility that occurred to me is
		-sstdout=<filename>
	Or one could couple this to setting OutputFile, e.g.,
		-sOutputFile=-<filename>
	which would send the driver output to stdout and the PostScript
	%stdout to <filename>.

	D) Other ideas?

Rather than a command line option (or additionally) would it be
possible to create a third output stream specifically for the
Postscript stdout?  This stream would normally be directed to the same
console as stderr and stdout, but if you redirect stderr, to get the
Postscript stdout to follow it you would do "gs 2>somefile 3>&2" or
the like.

This would mean that pipelines would automatically have the Postscript
stdout stripped, but you could flexibly (at the shell script level)
redirect this.

I would argue that Postscript programs that do what you describe are
badly designed, but I'm sure there are enough of them that they should
be accomodated, and there are probably good reasons for doing it, too.

--
University of Tsukuba                Tennodai 1-1-1 Tsukuba 305-8573 JAPAN
Institute of Policy and Planning Sciences       Tel/fax: +81 (298) 53-5091
_________________  _________________  _________________  _________________
What are those straight lines for?  "XEmacs rules."


---------------------------------------------------------------------------

From:  gherteg at csc.com

As you know, Ghostscript can generate output to stdout and stderr.  Output
to stderr is not a problem.  However, output to stdout has been an ongoing
problem, because there are 3 conceptually different entities that generate
it, and they interfere with each other:

        1) Ghostscript itself can generate warning, error, or debugging
        messages.

        2) PostScript files can explicitly write to %stdout using the
        operators print, =, ==, stack, and pstack; for example, quite a
few
        PostScript files print comments like
                %%[Page: <page#>]%%
        for each page.

#1 and #2 can be interleaved with no problem, because in both cases it is
a
person that is reading the output.

I don't know that you can completely discount the possibility of a
PostScript program
using the output operators in a production mode where the output stream
would be
read by another program.  The bbox device is a good example of how this
might
happen, although that particular driver appears to write on stderr rather
than stdout
(just to make life even more interesting!).

Glenn Herteg

----------------------------------------------------------------------------
---

From:  Ray Johnston [ray at artifex.com]

Peter (and the Artifex Tech group),

"L. Peter Deutsch" wrote:
> As you know, Ghostscript can generate output to stdout and stderr.  Output
> to stderr is not a problem.  However, output to stdout has been an ongoing
> problem, because there are 3 conceptually different entities that generate
> it, and they interfere with each other:

For sure!

There are another couple of related issues that you don't mention:

i)  Some drivers expect/require random access to their output file, or is
    this disallowed in the driver design?

ii) Some systems wish to capture stdout in ways other than the connection
    to a file handle/stream pointer. Windows DLL use does this and others
    have requested the facility to redirect stdout to a callback for other
    than Windows. The current method that Windows uses to 'hook' stdout
    is rather messy and poorly documented.

Any design changes should address these two points. As long as we're making
changes, let's see if we can make these better as well.

> I've considered the following ways to deal with this problem, and I'm not
> completely happy with any of them.

>         C) Add a command line switch that says explicitly where to send
the
>         PostScript %stdout output.  One possibility that occurred to me is
>                 -sstdout=<filename>

I favor this approach as intuitive and unambguous I assume that <filename>
in this case can be a named pipe as well.

>         Or one could couple this to setting OutputFile, e.g.,
>                 -sOutputFile=-<filename>

Yuk!

Regards,
Ray

----------------------------------------------------------------------------

From:  Thomas Henlich [henlich at mmers1.mw.tu-dresden.de]

On Wed, Sep 13, 2000 at 06:34:59PM -0700, L. Peter Deutsch wrote:

> 	A) Disallow setting OutputFile to stdout: allow output only to a
> 	real file or to a pipe.  (Output to a pipe is no problem.)  This
> 	would be simplest, but it would annoy Unix users, who feel they get
> 	a lot of value from being able to construct pipelines of programs in
> 	which each program's stdout feeds the next program's stdin.

Not an option.

>
> 	B) If OutputFile is set to stdout, automatically redirect the
> 	PostScript %stdout to stderr.  This is the only alternative that
> 	doesn't require users to do something different than what they do
> 	now, but I think it is likely to create some ugly design coupling
> 	between different parts of the Ghostscript code.

Not an option. If the code gets ugly, this solution is ugly.

> 	C) Add a command line switch that says explicitly where to send the
> 	PostScript %stdout output.  One possibility that occurred to me is
> 		-sstdout=<filename>
> 	Or one could couple this to setting OutputFile, e.g.,
> 		-sOutputFile=-<filename>

This seems the best way to deal with this problem, as it offers the highest
amount of flexibility.

> 	D) Other ideas?

Nope, sorry.

Regards,
--
Thomas Henlich

----------------------------------------------------------------------------
---

From:  Torsten Landschoff [torsten at pclab.ifg.uni-kiel.de]

Hi Peter,

On Wed, Sep 13, 2000 at 06:34:59PM -0700, L. Peter Deutsch wrote:
> As you know, Ghostscript can generate output to stdout and stderr.  Output
> to stderr is not a problem.  However, output to stdout has been an ongoing
> problem, because there are 3 conceptually different entities that generate
> it, and they interfere with each other:

Thanks for acting on this problem, Peter. This would close the oldest bug
on the Ghostscript packages in Debian which would make me very happy :)

> 	2) PostScript files can explicitly write to %stdout using the
> 	operators print, =, ==, stack, and pstack; for example, quite a few
> 	PostScript files print comments like
> 		%%[Page: <page#>]%%
> 	for each page.

I would like to add that those files are typically generated using Word. I
am not sure if Microsoft Word writes this or if it is Adobes Postscript
driver in Windows. Whoever it is the behaviour of that driver really sucks
- the result is not even DSC compliant so that pstops etc. don't work :(

> 	3) Driver output can be directed to stdout with
> 		-sOutputFile=-
> 	or
> 		-sOutputFile=%stdout
> 	or by executing the equivalent setpagedevice or .putdeviceparams
> 	in PostScript code.

Hmm, isn't that even the default?

> Note that this problem is specific to the PostScript interpreter.  PDF
> doesn't have constructs of type #2, and the graphics library never prints

Interesting. So converting the file to PDF and printing it should work? ;-)

> I've considered the following ways to deal with this problem, and I'm not
> completely happy with any of them.

Same here.

> 	A) Disallow setting OutputFile to stdout: allow output only to a
> 	real file or to a pipe.  (Output to a pipe is no problem.)  This
> 	would be simplest, but it would annoy Unix users, who feel they get
> 	a lot of value from being able to construct pipelines of programs in
> 	which each program's stdout feeds the next program's stdin.

Right, I would oppose to this. Also there are a lot of scripts who use that
feature. All of them would have to be changed.

> 	B) If OutputFile is set to stdout, automatically redirect the
> 	PostScript %stdout to stderr.  This is the only alternative that
> 	doesn't require users to do something different than what they do
> 	now, but I think it is likely to create some ugly design coupling
> 	between different parts of the Ghostscript code.
>
> 	C) Add a command line switch that says explicitly where to send the
> 	PostScript %stdout output.  One possibility that occurred to me is
> 		-sstdout=<filename>
> 	Or one could couple this to setting OutputFile, e.g.,
> 		-sOutputFile=-<filename>
> 	which would send the driver output to stdout and the PostScript
> 	%stdout to <filename>.

I would mix B and C so that %stdout points to stderr by default if driver
output goes to stdout and you can overwrite it with -sstdout=<file> or
whatever.

> Please let me know your thoughts about this, since I would like to finally
> deal with it soon.

Thanks!

	Torsten

PS: Can you please include me on the rest of this discussion? Sounds quite
interesting to me. Also I am wondering if there will be mailing lists for
discussion of stuff like this on SourceForge in the future!?

----------------------------------------------------------------------------
--

From:  Jan Stoeckenius [jan at orimp.com]

> From ghost at aladdin.com  Wed Sep 13 18:50:04 2000
> Date: Wed, 13 Sep 2000 18:34:59 -0700
> Subject: Ghostscript piped output problem: design opinions solicited
>
> ...
> I've considered the following ways to deal with this problem, and I'm not
> completely happy with any of them.
>
> 	A) Disallow setting OutputFile to stdout: allow output only to a
> 	real file or to a pipe.  (Output to a pipe is no problem.)  This
> 	would be simplest, but it would annoy Unix users, who feel they get
> 	a lot of value from being able to construct pipelines of programs in
> 	which each program's stdout feeds the next program's stdin.
>
> 	B) If OutputFile is set to stdout, automatically redirect the
> 	PostScript %stdout to stderr.  This is the only alternative that
> 	doesn't require users to do something different than what they do
> 	now, but I think it is likely to create some ugly design coupling
> 	between different parts of the Ghostscript code.
>
> 	C) Add a command line switch that says explicitly where to send the
> 	PostScript %stdout output.  One possibility that occurred to me is
> 		-sstdout=<filename>
> 	Or one could couple this to setting OutputFile, e.g.,
> 		-sOutputFile=-<filename>
> 	which would send the driver output to stdout and the PostScript
> 	%stdout to <filename>.
>
> 	D) Other ideas?
>
> Please let me know your thoughts about this, since I would like to finally
> deal with it soon.

Options (B) and (C) are actually very much the same, as both break the
association between %stdout and Unix standard output. Other than as a
default setting, there is no particular reason to make this association.
On most printing device %stdout and %stderr map to the same pipe,
and some argue that this pipe be mapped to Unix standard error by default.
This is not my favorite approach, but it is workable.

I have had reasonable results with a variation of (B) that works well on
Unix, and can probably be used on other operating systems as well. Normally,
%stdout maps to Unix standard output. If, however, standard output has
been preempted for graphic ouput, %stdout is mapped to /dev/tty.

In the case of ghostscript, I would probably combine this behavior with
the command-line options you have given in (C). Specifically:

    -sstdout=<filename>     determines the mapping for %stdout

    -sstderr=<filename>     determines the mapping for %stderr

Where <filename> can be - (for Unix standard output) or a file descriptor
number (e.g.: -sstdout=2 would map %stdout to Unix standard error, which
would also be the default mapping). If the command line option for stdout
is used, that sets the mapping for %stdout, even if the same pipe is
receiving graphical output. Otherwise, the behavior would be as described
above: %stdout is Unix standard output if that is not being used for
graphical output, other it is /dev/tty.

I would also eliminate the use of -sOutputFile=%stdout as a synonym for
-sOutputFile=-. The former seems to say "map graphical output to the same
location as %stdout", which is not a useful selection.

                                                       Jan

----------------------------------------------------------------------------
-

From:  Pierre Arnaud [Pierre.Arnaud at opac.ch]

Dear Peter,

I prefer option (C). I don't like the magic of (B) and feel that (A)
would indeed cause Unix-people to complain heavily.

The -sstdout=<filename> seems a good solution. I would not couple it
with -sOutputFile, since this would (from my point of view) only
complicate matters. A separate option is clean and simple to use.

By the way, are there any other PostScript streams which would benefit
from this kind of command-line option ? Why not allow %stderr and %stdin
to be redirected in the same way ?

Warm regards.

    Pierre

----------------------------------------------------------------------------
---

From:  Vasu Raman [vasur at plp.com]

Dear Peter,

     I like the C) option the best.

Vasu Raman
VP Engineering
PLP Digital Systems
6060 E. Thomas Rd.
Scottsdale, AZ 85251
http://www.plp.com
Tel: 480-949-7568
Fax: 480-949-7321
E-mail: vasur at plp.com

----------------------------------------------------------------------------
---

From:  George White [aa056 at chebucto.ns.ca]

On Wed, 13 Sep 2000, L. Peter Deutsch wrote:

> Dear friends of Ghostscript.
>
> As you know, Ghostscript can generate output to stdout and stderr.  Output
> to stderr is not a problem.  However, output to stdout has been an ongoing
> problem, because there are 3 conceptually different entities that generate
> it, and they interfere with each other:
>
> 	1) Ghostscript itself can generate warning, error, or debugging
> 	messages.
>
> 	2) PostScript files can explicitly write to %stdout using the
> 	operators print, =, ==, stack, and pstack; for example, quite a few
> 	PostScript files print comments like
> 		%%[Page: <page#>]%%
> 	for each page.
>
> 	3) Driver output can be directed to stdout with
> 		-sOutputFile=-
> 	or
> 		-sOutputFile=%stdout
> 	or by executing the equivalent setpagedevice or .putdeviceparams
> 	in PostScript code.
>
> #1 and #2 can be interleaved with no problem, because in both cases it is
a
> person that is reading the output.  However, mixing #1 or #2 with #3
> produces corrupted driver output.

I have been bitten by mixing #1 and #3, so it is nice to think that this
situation can be improved.

There are programs that attempt to parse the messages from the interpreter
(e.g., to log the number of pages printed for accounting purposes).
The ones I have seen looked for the %%[...]%% structure, so probably
would not be fooled by GS output, but it is certainly more robust if
interpreter messages can be kept separate (is it possible to
ensure that debugging messages can't appear in the middle of
type #2 messages?).

> In a production (non-debugging) configuration, the -q switch currently
> suppresses all non-fatal messages of type #1.  (In the future, it may
divert
> some or all of them to stderr instead.)  However, #2 still interferes with
> #3.
>
> Note that this problem is specific to the PostScript interpreter.  PDF
> doesn't have constructs of type #2, and the graphics library never prints
> anything on stdout in a production configuration.
>
> I've considered the following ways to deal with this problem, and I'm not
> completely happy with any of them.
>
> 	A) Disallow setting OutputFile to stdout: allow output only to a
> 	real file or to a pipe.  (Output to a pipe is no problem.)  This
> 	would be simplest, but it would annoy Unix users, who feel they get
> 	a lot of value from being able to construct pipelines of programs in
> 	which each program's stdout feeds the next program's stdin.

The unix users have a valid point.  Pipelines are easy to understand
and tend to be relatively secure and efficient for system level tasks.
The gs pipe mechanism makes it a bit harder for someone to follow the
flow of data in a script written by someone else.

> 	B) If OutputFile is set to stdout, automatically redirect the
> 	PostScript %stdout to stderr.  This is the only alternative that
> 	doesn't require users to do something different than what they do
> 	now, but I think it is likely to create some ugly design coupling
> 	between different parts of the Ghostscript code.

The ugly design may be a hint that this is being a bit _too_ helpful.
Other programs don't do this, so it is a potential source of confusion.
Is there any reason that PostScript %stdout isn't set to stderr by
default?

> 	C) Add a command line switch that says explicitly where to send the
> 	PostScript %stdout output.  One possibility that occurred to me is
> 		-sstdout=<filename>
> 	Or one could couple this to setting OutputFile, e.g.,
> 		-sOutputFile=-<filename>
> 	which would send the driver output to stdout and the PostScript
> 	%stdout to <filename>.

The first (-sstdout=<filename>) mechanism is reasonable.  The second
is probably a bit too tricky.

> 	D) Other ideas?

The other common unixy mechanism for dealing with messages is the log
daemon (syslogd, which is also available on OS/2 if anybody still cares).
It might be worth thinking about organizing things so that the syslog
facility could be used in production (unix?)  environments.  I suppose
the ideal would be if all type #1 and #2 messages were handled in a
queue with type and priority attributes.  There would be a dispatcher
with a configurable policy to ensure that messages where sent to the
right place and that critical error notifications don't get lost.

> Please let me know your thoughts about this, since I would like to finally
> deal with it soon.
>
> 				Thanks -
>
> L. Peter Deutsch        |               Aladdin Enterprises
> ghost at aladdin.com       | http://www.aladdin.com | 203 Santa Margarita
Ave.
>                         | fax +1-650-322-1734    | Menlo Park, CA 94025

There must be some interaction with -dSAFER to be considered here.

--
George White <aa056 at chebucto.ns.ca> Halifax, Nova Scotia

----------------------------------------------------------------------------
-

From:  hkrug at Netz-Werker.COM; on behalf of; Holger Krug
[hkrug at rationalizer.com]


>         A) Disallow setting OutputFile to stdout: allow output only to a
>         real file or to a pipe.  (Output to a pipe is no problem.)  This
>         would be simplest, but it would annoy Unix users, who feel they
get
>         a lot of value from being able to construct pipelines of programs
in
>         which each program's stdout feeds the next program's stdin.

Really annoying !
If the output is PostScript code you could let them both interweave if
you could assure, that the %stdout generated output would be commented
out. (Add '%' before the %stdout generated output.) Admittedly, I don't
no what to do with other output formats.


>         B) If OutputFile is set to stdout, automatically redirect the
>         PostScript %stdout to stderr.  This is the only alternative that
>         doesn't require users to do something different than what they do
>         now, but I think it is likely to create some ugly design coupling
>         between different parts of the Ghostscript code.

For us, the users, this should be by far the best approach.

>         C) Add a command line switch that says explicitly where to send
the
>         PostScript %stdout output.  One possibility that occurred to me is
>                 -sstdout=<filename>
>         Or one could couple this to setting OutputFile, e.g.,
>                 -sOutputFile=-<filename>
>         which would send the driver output to stdout and the PostScript
>         %stdout to <filename>.

To complicated. Maybe additionally to variant B.

>         D) Other ideas?

No good ones.

----------------------------------------------------------------------------
-----

From:  Peter Kaiser [kaiser at acm.org]

No other ideas, but (C) looks best to me because it's quite clear and
because it permits best control.  Some other points, though: provide a
construct that directs PS stdout to the "terminal"; when so directed,
flush every line; and don't use "stdout" as the keyword of the switch
(i.e., not "-sstdout" but possibly "-sPSstdout" or something that clearly
maintains the distinction between image stdout and PostScript %stdout.

___Pete

----------------------------------------------------------------------------
----

From:  ghess at pandora.elmos.de; on behalf of; Gunther Hess [ghess at elmos.de]

Hi Peter,
         alternative B) is nice, but i share the bad feeling about the
coding.

Alternative A) would be nice too, but in fact quite a lot of
popular filter-scripts on Unix will fail (apsfilter is a candidate).
This can be done externally too, as the lp-unix distributed with
ghostscript shows.

Im am using this style of setup in my filters:

  exec 3>&1 1>gs.msg.$$
  gs ... -sOutputFile="|cat 1>&3"
  cat gs.msg.$$ 1>&2
  rm  gs.msg.$$

This has the additional advantage, that no buffering-problems
occur. I have observed interesting effects with mixed stdout
and stderr output on some unixes.

Well the snippet above would be somehow more readable with
Alternative C:

  gs -sstdout=gs.msg.$$ -sOutputFile=-
  cat gs.msg.$$ 1>&2
  rm  gs.msg.$$

Thus C) would be my favourite. It saves me an unnecessary pipe.

Regards
Gunther
--
Dr. Gunther Hess           Elmos Semiconductor AG
Tel.: ++49 +231 7549-520   Heinrich Hertz Str. 1
Fax:  ++49 +231 7549-109   D-44227 Dortmund
WWW: http://www.elmos.de   Opinions are strictly of my own

----------------------------------------------------------------------------
--
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
X

>From the Ghostscript discussion group on SourceForge
Topic:  Output from Postscript Programs


By: torsten ( Torsten Landschoff )
Output from Postscript Programs [ reply ]
2000-Jul-12 13:36
Hi,

Just want to check if I can close Debian bug #9285...

There is still a bug open on the gs package because sometimes informational
text is output to stdout which mixes up with printer commands if you have
-sOutputFile=- (which is used by magicfilter for example).

I plan to close that bug because it is correct by gs to write that
information
on stdout as it is requested in the Postscript source. An example of this
is the lclint postscript documentation which contains lines like this:

(%%[Page: 1]%%) =

which of course outputs "%%[Page: 1]%%" to stdout.

Further info:
- Debian bugreport: http://bugs.debian.org/9285
- LC-Lint documentation (Word output):
http://lclint.cs.virginia.edu/guide/guide.ps

Thanks

Torsten



By: lpd ( L. Peter Deutsch )
RE: Output from Postscript Programs [ reply ]
2000-Jul-12 17:33
Sigh. This problem keeps re-surfacing, but I don't really see what we can do
about it. Sending the rendered output to stdout (-sOutputFile=-) is
appropriate for a filter; the PostScript specification requires that
PostScript files be allowed to write to stdout. Do you have any good ideas
about how to resolve this -- in a way that isn't Unix-specific?



By: torsten ( Torsten Landschoff )
RE: Output from Postscript Programs [ reply ]
2000-Jul-13 00:48
Good question. The only solution I can think of is to allow the user to
redirect
the %std* filehandles to somewhere else. On Unix you could do something like

gs -sStdoutHandle=/dev/null

then to get rid of the text written to stdout. Not perfect but currently I
lack better
ideas how to deal with this.


By: chappell ( David S. Chappell )
RE: Output from Postscript Programs [ reply ]
2000-Sep-20 20:02
I have been having this problem too. I agree that it is not a bug that
Ghostscript writes the PostScript program's stdout to its own stdout. It is
a bug in a print filter if it asks Ghostscript to send the printer output to
stdout.

Unfortunately, the only way I know of for a filter can deal with this is to
put the next stage of the pipeline in a command line specified with
the -sOutputFile="| command" option. This has problems, including the fact
that Ghostscript truncates long command lines and that it can be difficult
to learn the command's exit code. Also, a new instance of the command must
be started for each instance of Ghostscript. This can be troublesome if the
purpose of the command is to connect to the printer.

For my purposes it would help a lot if the OutputFile syntax could be
extended to allow the output to be directed to pre-opened file descriptors
in addition to 1 (stdout). One way to do this would be to use a "filename"
in the form ">&3" to direct the rasterized output to file descriptor 3.

That would be enough to allow me to improve the Ghostscript support in my
spooler (PPR). Other people might like to be able to specify the external
file descriptors to which the PostScript stdout and stderr should be sent.

It would not be acceptable to simply provide a way to discard PostScript
stdout.



By: lpd ( L. Peter Deutsch )
RE: Output from Postscript Programs [ reply ]
2000-Sep-20 20:14
We've recently polled the active developers of Ghostscript about this issue.
As a result, in the near future (probably soon after the forthcoming 6.50
maintenance release) we're planning to add switches for redirecting the
PostScript %stdin/%stdout/%stderr files, -sstd{in,out,err}=<filename>.
<filename> can include %-prefixes; we suggest that if you want to redirect
to a pre-opened FD, you implement a new %fd%<number> IODevice, similar to
the %handle%<handle> IODevice currently implemented for MS Windows. We'd be
happy to include such an IODevice (as a build-time option, because of
security implications) in our distribution.



By: chappell ( David S. Chappell )
RE: Output from Postscript Programs [ reply ]
2000-Sep-22 11:47
That sounds like a slick way to do it. Being able to redirect the PostScript
file descriptors would add a lot of flexibility. I would be happy to write a
%fd% driver if I really thought it would help. However, I don't think it is
useful if it can't be included in the standard build configuration.

You see, what I and probably some of the others are trying to do is write
spoolers that use the copy of Ghostscript which is already a part of Linux
or BSD distributions. A solution which requires our users to get the
Ghostscript source code, set an option and then compile it and put it in a
private directory isn't really practical. If it then introduces security
problems, that is worse.

I assume that by "security implications" you mean the fact that the
PostScript program would have access to all pre-opened file descriptors.

What I would like to see is a solution which provided -sOutputFile="| cat -
>&3" but without the extra process and without opening the file descriptors
to the depredations of the PostScript code being interpreted.

I have looked at the Ghostscript 5.50 source code. This feature would
involve a tiny patch which would sit alongside the "|" code. Are the
Ghostscript maintainers against incorporating special-case code like this?








More information about the gs-code-review mailing list