xref: /plan9/sys/src/cmd/gs/src/gp_mshdl.c (revision 593dc095aefb2a85c828727bbfa9da139a49bdf4)
1 /* Copyright (C) 1999 Aladdin Enterprises.  All rights reserved.
2 
3   This software is provided AS-IS with no warranty, either express or
4   implied.
5 
6   This software is distributed under license and may not be copied,
7   modified or distributed except as expressly authorized under the terms
8   of the license contained in the file LICENSE in this distribution.
9 
10   For more information about licensing, please refer to
11   http://www.ghostscript.com/licensing/. For information on
12   commercial licensing, go to http://www.artifex.com/licensing/ or
13   contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14   San Rafael, CA  94903, U.S.A., +1(415)492-9861.
15 */
16 
17 /* $Id: gp_mshdl.c,v 1.4 2002/02/21 22:24:52 giles Exp $ */
18 /* %handle% IODevice */
19 #include "errno_.h"
20 #include "stdio_.h"
21 #include "string_.h"
22 #include "ctype_.h"
23 #include <io.h>
24 #include "gserror.h"
25 #include "gstypes.h"
26 #include "gsmemory.h"		/* for gxiodev.h */
27 #include "gxiodev.h"
28 
29 /* The MS-Windows handle IODevice */
30 
31 /* This allows an MS-Windows file handle to be passed in to
32  * Ghostscript as %handle%NNNNNNNN where NNNNNNNN is the hexadecimal
33  * value of the handle.
34  * The typical use is for another program to create a pipe,
35  * pass the write end into Ghostscript using
36  *  -sOutputFile="%handle%NNNNNNNN"
37  * so that Ghostscript printer output can be captured by the
38  * other program.  The handle would be created with CreatePipe().
39  * If Ghostscript is not a DLL, the pipe will have to be inheritable
40  * by the Ghostscript process.
41  */
42 
43 private iodev_proc_fopen(mswin_handle_fopen);
44 private iodev_proc_fclose(mswin_handle_fclose);
45 const gx_io_device gs_iodev_handle = {
46     "%handle%", "FileSystem",
47     {iodev_no_init, iodev_no_open_device,
48      NULL /*iodev_os_open_file */ , mswin_handle_fopen, mswin_handle_fclose,
49      iodev_no_delete_file, iodev_no_rename_file, iodev_no_file_status,
50      iodev_no_enumerate_files, NULL, NULL,
51      iodev_no_get_params, iodev_no_put_params
52     }
53 };
54 
55 /* The file device procedures */
56 #ifndef INVALID_HANDLE_VALUE
57 #define INVALID_HANDLE_VALUE (-1)
58 #endif
59 
60 /* Allow printer filename specified by -sOutputFile="..."
61  * to contain a hexadecimal encoded OS file handle in the
62  * form -sOutputFile="\\handle\\000001c5"
63  *
64  * Returns:
65  *   The OS file handle on success.
66  *   INVALID_HANDLE_VALUE on failure.
67  *
68  * This allows the caller to create an OS pipe and give us a
69  * handle to the write end of the pipe.
70  * If we are called as an EXE, the OS file handle must be
71  * inherited by Ghostscript.
72  * Pipes aren't supported under Win32s.
73  */
74 private long
get_os_handle(const char * name)75 get_os_handle(const char *name)
76 {
77     ulong hfile;	/* This must be as long as the longest handle. */
78 			/* This is correct for Win32, maybe wrong for Win64. */
79     int i, ch;
80 
81     for (i = 0; (ch = name[i]) != 0; ++i)
82 	if (!isxdigit(ch))
83 	    return (long)INVALID_HANDLE_VALUE;
84     if (sscanf(name, "%lx", &hfile) != 1)
85 	return (long)INVALID_HANDLE_VALUE;
86     return (long)hfile;
87 }
88 
89 private int
mswin_handle_fopen(gx_io_device * iodev,const char * fname,const char * access,FILE ** pfile,char * rfname,uint rnamelen)90 mswin_handle_fopen(gx_io_device * iodev, const char *fname, const char *access,
91 	   FILE ** pfile, char *rfname, uint rnamelen)
92 {
93     int fd;
94     long hfile;	/* Correct for Win32, may be wrong for Win64 */
95     errno = 0;
96 
97     if ((hfile = get_os_handle(fname)) == (long)INVALID_HANDLE_VALUE)
98 	return_error(gs_fopen_errno_to_code(EBADF));
99 
100     /* associate a C file handle with an OS file handle */
101     fd = _open_osfhandle((long)hfile, 0);
102     if (fd == -1)
103 	return_error(gs_fopen_errno_to_code(EBADF));
104 
105     /* associate a C file stream with C file handle */
106     *pfile = fdopen(fd, (char *)access);
107     if (*pfile == NULL)
108 	return_error(gs_fopen_errno_to_code(errno));
109 
110     if (rfname != NULL)
111 	strcpy(rfname, fname);
112     return 0;
113 }
114 
115 private int
mswin_handle_fclose(gx_io_device * iodev,FILE * file)116 mswin_handle_fclose(gx_io_device * iodev, FILE * file)
117 {
118     fclose(file);
119     return 0;
120 }
121