~ubuntu-branches/debian/squeeze/ghostscript/squeeze

« back to all changes in this revision

Viewing changes to debian/local/pdftoraster/pdftoraster.c

  • Committer: Bazaar Package Importer
  • Author(s): Masayuki Hatta (mhatta)
  • Date: 2009-01-04 12:09:59 UTC
  • mfrom: (16.1.1 sid)
  • Revision ID: james.westby@ubuntu.com-20090104120959-m9lbagj775ucg0h3
Tags: 8.63.dfsg.1-2
libgs-dev: put versioned dependency on libgs8 - closes: #510691

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
Copyright (c) 2008, Till Kamppeter
 
3
Copyright (c) 2008, BBR Inc.  All rights reserved.
 
4
 
 
5
Permission is hereby granted, free of charge, to any person obtaining
 
6
a copy of this software and associated documentation files (the
 
7
"Software"), to deal in the Software without restriction, including
 
8
without limitation the rights to use, copy, modify, merge, publish,
 
9
distribute, sublicense, and/or sell copies of the Software, and to
 
10
permit persons to whom the Software is furnished to do so, subject to
 
11
the following conditions:
 
12
 
 
13
The above copyright notice and this permission notice shall be included
 
14
in all copies or substantial portions of the Software.
 
15
 
 
16
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 
17
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 
18
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 
19
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
 
20
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 
21
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 
22
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
23
 
 
24
MIT Open Source License  -  http://www.opensource.org/
 
25
 
 
26
*/
 
27
 
 
28
/* $Id: pdftoraster.c 9171 2008-10-17 22:58:21Z giles $ */
 
29
 
 
30
/* PDF to CUPS Raster filter based on Ghostscript */
 
31
 
 
32
#include <stdio.h>
 
33
#include <stdlib.h>
 
34
#include <cups/cups.h>
 
35
#include <stdarg.h>
 
36
#include <fcntl.h>
 
37
#include <cups/raster.h>
 
38
 
 
39
#define MAX_CHECK_COMMENT_LINES 20
 
40
#ifndef GS
 
41
#define GS "gs"
 
42
#endif
 
43
#ifndef BINDIR
 
44
#define BINDIR "/usr/bin"
 
45
#endif
 
46
#ifndef CUPS_FONTPATH
 
47
#define CUPS_FONTPATH "/usr/share/cups/fonts"
 
48
#endif
 
49
 
 
50
int exitCode = 0;
 
51
int deviceCopies = 1;
 
52
cups_bool_t deviceCollate = CUPS_FALSE;
 
53
#ifdef CUPS_RASTER_SYNCv1
 
54
cups_page_header2_t h;
 
55
#else
 
56
cups_page_header_t h;
 
57
#endif /* CUPS_RASTER_SYNCv1 */
 
58
int num_options = 0;
 
59
cups_option_t *options = 0;
 
60
 
 
61
void parseOpts(int argc, char **argv)
 
62
{
 
63
  ppd_file_t *ppd = 0;
 
64
 
 
65
  if (argc < 6 || argc > 7) {
 
66
    fprintf(stderr, "ERROR: %s job-id user title copies options [file]",
 
67
      argv[0]);
 
68
    exit(1);
 
69
  }
 
70
 
 
71
  ppd = ppdOpenFile(getenv("PPD"));
 
72
  ppdMarkDefaults(ppd);
 
73
  options = NULL;
 
74
  num_options = cupsParseOptions(argv[5],0,&options);
 
75
  cupsMarkOptions(ppd,num_options,options);
 
76
  cupsRasterInterpretPPD(&h,ppd,num_options,options,0);
 
77
}
 
78
 
 
79
void parsePDFTOPDFComment(FILE *fp)
 
80
{
 
81
  char buf[4096];
 
82
  int i;
 
83
 
 
84
  /* skip until PDF start header */
 
85
  while (fgets(buf,sizeof(buf),fp) != 0) {
 
86
    if (strncmp(buf,"%PDF",4) == 0) {
 
87
      break;
 
88
    }
 
89
  }
 
90
  for (i = 0;i < MAX_CHECK_COMMENT_LINES;i++) {
 
91
    if (fgets(buf,sizeof(buf),fp) == 0) break;
 
92
    if (strncmp(buf,"%%PDFTOPDFNumCopies",19) == 0) {
 
93
      char *p;
 
94
 
 
95
      p = strchr(buf+19,':');
 
96
      deviceCopies = atoi(p+1);
 
97
    } else if (strncmp(buf,"%%PDFTOPDFCollate",17) == 0) {
 
98
      char *p;
 
99
 
 
100
      p = strchr(buf+17,':');
 
101
      while (*p == ' ' || *p == '\t') p++;
 
102
      if (strncasecmp(p,"true",4) == 0) {
 
103
        deviceCollate = CUPS_TRUE;
 
104
      } else {
 
105
        deviceCollate = CUPS_FALSE;
 
106
      }
 
107
    }
 
108
  }
 
109
}
 
110
 
 
111
int main(int argc, char *argv[], char *envp[]) {
 
112
  int i;
 
113
  FILE *fp;
 
114
  cups_array_t *gs_args;
 
115
  char tmpstr[1024];
 
116
  const char *t = NULL;
 
117
  int fd;
 
118
  char buf[BUFSIZ];
 
119
  int n;
 
120
  int numargs;
 
121
  char *argument;
 
122
  char **gsargv;
 
123
  const char* apos;
 
124
  int fds[2];
 
125
  int pid;
 
126
 
 
127
  parseOpts(argc, argv);
 
128
 
 
129
  if (argc == 6) {
 
130
    /* stdin */
 
131
 
 
132
    fd = cupsTempFd(buf,BUFSIZ);
 
133
    if (fd < 0) {
 
134
      fprintf(stderr, "ERROR: Can't create temporary file");
 
135
      exit(1);
 
136
    }
 
137
    /* remove name */
 
138
    unlink(buf);
 
139
 
 
140
    /* copy stdin to the tmp file */
 
141
    while ((n = read(0,buf,BUFSIZ)) > 0) {
 
142
      if (write(fd,buf,n) != n) {
 
143
        fprintf(stderr, "ERROR: Can't copy stdin to temporary file");
 
144
        close(fd);
 
145
        exit(1);
 
146
      }
 
147
    }
 
148
    if (lseek(fd,0,SEEK_SET) < 0) {
 
149
        fprintf(stderr, "ERROR: Can't rewind temporary file");
 
150
        close(fd);
 
151
        exit(1);
 
152
    }
 
153
 
 
154
    if ((fp = fdopen(fd,"rb")) == 0) {
 
155
        fprintf(stderr, "ERROR: Can't fdopen temporary file");
 
156
        close(fd);
 
157
        exit(1);
 
158
    }
 
159
  } else {
 
160
    /* argc == 7 filenmae is specified */
 
161
 
 
162
    if ((fp = fopen(argv[6],"rb")) == 0) {
 
163
        fprintf(stderr, "ERROR: Can't open input file %s",argv[6]);
 
164
        exit(1);
 
165
    }
 
166
  }
 
167
  parsePDFTOPDFComment(fp);
 
168
  rewind(fp);
 
169
 
 
170
  /* Fix NumCopies and Collate according to PDFTOPDFComments */
 
171
  h.NumCopies = deviceCopies;
 
172
  h.Collate = deviceCollate;
 
173
  /* fixed other values that pdftopdf handles */
 
174
  h.MirrorPrint = CUPS_FALSE;
 
175
  h.Orientation = CUPS_ORIENT_0;
 
176
 
 
177
  /* Ghostscript parameters */
 
178
  gs_args = cupsArrayNew(NULL, NULL);
 
179
  if (!gs_args)
 
180
  {
 
181
    fprintf(stderr, "ERROR: Unable to allocate memory for Ghostscript arguments array\n");
 
182
    exit(1);
 
183
  }
 
184
 
 
185
  /* Part of Ghostscript command line which is not dependent on the job and/or
 
186
     the driver */
 
187
  snprintf(tmpstr, sizeof(tmpstr), "%s/%s", BINDIR, GS);
 
188
  cupsArrayAdd(gs_args, strdup(tmpstr));
 
189
  cupsArrayAdd(gs_args, strdup("-dQUIET"));
 
190
  /*cupsArrayAdd(gs_args, strdup("-dDEBUG"));*/
 
191
  cupsArrayAdd(gs_args, strdup("-dPARANOIDSAFER"));
 
192
  cupsArrayAdd(gs_args, strdup("-dNOPAUSE"));
 
193
  cupsArrayAdd(gs_args, strdup("-dBATCH"));
 
194
  /* cupsArrayAdd(gs_args, strdup("-dNOMEDIAATTRS")); */
 
195
  cupsArrayAdd(gs_args, strdup("-sDEVICE=cups"));
 
196
  cupsArrayAdd(gs_args, strdup("-sstdout=%stderr"));
 
197
  cupsArrayAdd(gs_args, strdup("-sOutputFile=%stdout"));
 
198
 
 
199
  /* CUPS font path */
 
200
  if ((t = getenv("CUPS_FONTPATH")) == NULL)
 
201
    t = CUPS_FONTPATH;
 
202
  snprintf(tmpstr, sizeof(tmpstr), "-I%s", t);
 
203
  cupsArrayAdd(gs_args, strdup(tmpstr));
 
204
 
 
205
  /* Simple boolean, enumerated choice, numerical, and string parameters */
 
206
  if (h.MediaClass[0] |= '\0') {
 
207
    snprintf(tmpstr, sizeof(tmpstr), "-sMediaClass=%s", h.MediaClass);
 
208
    cupsArrayAdd(gs_args, strdup(tmpstr));
 
209
  }
 
210
  if (h.MediaColor[0] |= '\0') {
 
211
    snprintf(tmpstr, sizeof(tmpstr), "-sMediaColor=%s", h.MediaColor);
 
212
    cupsArrayAdd(gs_args, strdup(tmpstr));
 
213
  }
 
214
  if (h.MediaType[0] |= '\0') {
 
215
    snprintf(tmpstr, sizeof(tmpstr), "-sMediaType=%s", h.MediaType);
 
216
    cupsArrayAdd(gs_args, strdup(tmpstr));
 
217
  }
 
218
  if (h.OutputType[0] |= '\0') {
 
219
    snprintf(tmpstr, sizeof(tmpstr), "-sOutputType=%s", h.OutputType);
 
220
    cupsArrayAdd(gs_args, strdup(tmpstr));
 
221
  }
 
222
  if (h.AdvanceDistance) {
 
223
    snprintf(tmpstr, sizeof(tmpstr), "-dAdvanceDistance=%d", 
 
224
             (unsigned)(h.AdvanceDistance));
 
225
    cupsArrayAdd(gs_args, strdup(tmpstr));
 
226
  }
 
227
  if (h.AdvanceMedia) {
 
228
    snprintf(tmpstr, sizeof(tmpstr), "-dAdvanceMedia=%d", 
 
229
             (unsigned)(h.AdvanceMedia));
 
230
    cupsArrayAdd(gs_args, strdup(tmpstr));
 
231
  }
 
232
  if (h.Collate) {
 
233
    cupsArrayAdd(gs_args, strdup("-dCollate"));
 
234
  }
 
235
  if (h.CutMedia) {
 
236
    snprintf(tmpstr, sizeof(tmpstr), "-dCutMedia=%d", 
 
237
             (unsigned)(h.CutMedia));
 
238
    cupsArrayAdd(gs_args, strdup(tmpstr));
 
239
  }
 
240
  if (h.Duplex) {
 
241
    cupsArrayAdd(gs_args, strdup("-dDuplex"));
 
242
  }
 
243
  if ((h.HWResolution[0] != 100) || (h.HWResolution[1] != 100))
 
244
    snprintf(tmpstr, sizeof(tmpstr), "-r%dx%d", 
 
245
             (unsigned)(h.HWResolution[0]), (unsigned)(h.HWResolution[1]));
 
246
  else
 
247
    snprintf(tmpstr, sizeof(tmpstr), "-r100x100");
 
248
  cupsArrayAdd(gs_args, strdup(tmpstr));
 
249
  if (h.InsertSheet) {
 
250
    cupsArrayAdd(gs_args, strdup("-dInsertSheet"));
 
251
  }
 
252
  if (h.Jog) {
 
253
    snprintf(tmpstr, sizeof(tmpstr), "-dJog=%d", 
 
254
             (unsigned)(h.Jog));
 
255
    cupsArrayAdd(gs_args, strdup(tmpstr));
 
256
  }
 
257
  if (h.LeadingEdge) {
 
258
    snprintf(tmpstr, sizeof(tmpstr), "-dLeadingEdge=%d", 
 
259
             (unsigned)(h.LeadingEdge));
 
260
    cupsArrayAdd(gs_args, strdup(tmpstr));
 
261
  }
 
262
  if (h.ManualFeed) {
 
263
    cupsArrayAdd(gs_args, strdup("-dManualFeed"));
 
264
  }
 
265
  if (h.MediaPosition) {
 
266
    snprintf(tmpstr, sizeof(tmpstr), "-dMediaPosition=%d", 
 
267
             (unsigned)(h.MediaPosition));
 
268
    cupsArrayAdd(gs_args, strdup(tmpstr));
 
269
  }
 
270
  if (h.MediaWeight) {
 
271
    snprintf(tmpstr, sizeof(tmpstr), "-dMediaWeight=%d", 
 
272
             (unsigned)(h.MediaWeight));
 
273
    cupsArrayAdd(gs_args, strdup(tmpstr));
 
274
  }
 
275
  if (h.MirrorPrint) {
 
276
    cupsArrayAdd(gs_args, strdup("-dMirrorPrint"));
 
277
  }
 
278
  if (h.NegativePrint) {
 
279
    cupsArrayAdd(gs_args, strdup("-dNegativePrint"));
 
280
  }
 
281
  if (h.NumCopies != 1) {
 
282
    snprintf(tmpstr, sizeof(tmpstr), "-dNumCopies=%d", 
 
283
             (unsigned)(h.NumCopies));
 
284
    cupsArrayAdd(gs_args, strdup(tmpstr));
 
285
  }
 
286
  if (h.Orientation) {
 
287
    snprintf(tmpstr, sizeof(tmpstr), "-dOrientation=%d", 
 
288
             (unsigned)(h.Orientation));
 
289
    cupsArrayAdd(gs_args, strdup(tmpstr));
 
290
  }
 
291
  if (h.OutputFaceUp) {
 
292
    cupsArrayAdd(gs_args, strdup("-dOutputFaceUp"));
 
293
  }
 
294
  if (h.PageSize[0] != 612)
 
295
    snprintf(tmpstr, sizeof(tmpstr), "-dDEVICEWIDTHPOINTS=%d", 
 
296
             (unsigned)(h.PageSize[0]));
 
297
  else
 
298
    snprintf(tmpstr, sizeof(tmpstr), "-dDEVICEWIDTHPOINTS=612");
 
299
  cupsArrayAdd(gs_args, strdup(tmpstr));
 
300
  if (h.PageSize[1] != 792)
 
301
    snprintf(tmpstr, sizeof(tmpstr), "-dDEVICEHEIGHTPOINTS=%d", 
 
302
             (unsigned)(h.PageSize[1]));
 
303
  else
 
304
    snprintf(tmpstr, sizeof(tmpstr), "-dDEVICEHEIGHTPOINTS=792");
 
305
  cupsArrayAdd(gs_args, strdup(tmpstr));
 
306
  if (h.Separations) {
 
307
    cupsArrayAdd(gs_args, strdup("-dSeparations"));
 
308
  }
 
309
  if (h.TraySwitch) {
 
310
    cupsArrayAdd(gs_args, strdup("-dTraySwitch"));
 
311
  }
 
312
  if (h.Tumble) {
 
313
    cupsArrayAdd(gs_args, strdup("-dTumble"));
 
314
  }
 
315
  if (h.cupsMediaType) {
 
316
    snprintf(tmpstr, sizeof(tmpstr), "-dcupsMediaType=%d", 
 
317
             (unsigned)(h.cupsMediaType));
 
318
    cupsArrayAdd(gs_args, strdup(tmpstr));
 
319
  }
 
320
  if (h.cupsBitsPerColor != 1)
 
321
    snprintf(tmpstr, sizeof(tmpstr), "-dcupsBitsPerColor=%d", 
 
322
             (unsigned)(h.cupsBitsPerColor));
 
323
  else
 
324
    snprintf(tmpstr, sizeof(tmpstr), "-dcupsBitsPerColor=1");
 
325
  cupsArrayAdd(gs_args, strdup(tmpstr));
 
326
  if (h.cupsColorOrder != CUPS_ORDER_CHUNKED)
 
327
    snprintf(tmpstr, sizeof(tmpstr), "-dcupsColorOrder=%d", 
 
328
             (unsigned)(h.cupsColorOrder));
 
329
  else
 
330
    snprintf(tmpstr, sizeof(tmpstr), "-dcupsColorOrder=%d", 
 
331
             CUPS_ORDER_CHUNKED);
 
332
  cupsArrayAdd(gs_args, strdup(tmpstr));
 
333
  if (h.cupsColorSpace != CUPS_CSPACE_K)
 
334
    snprintf(tmpstr, sizeof(tmpstr), "-dcupsColorSpace=%d", 
 
335
             (unsigned)(h.cupsColorSpace));
 
336
  else
 
337
    snprintf(tmpstr, sizeof(tmpstr), "-dcupsColorSpace=%d", 
 
338
             CUPS_CSPACE_K);
 
339
  cupsArrayAdd(gs_args, strdup(tmpstr));
 
340
  if (h.cupsCompression) {
 
341
    snprintf(tmpstr, sizeof(tmpstr), "-dcupsCompression=%d", 
 
342
             (unsigned)(h.cupsCompression));
 
343
    cupsArrayAdd(gs_args, strdup(tmpstr));
 
344
  }
 
345
  if (h.cupsRowCount) {
 
346
    snprintf(tmpstr, sizeof(tmpstr), "-dcupsRowCount=%d", 
 
347
             (unsigned)(h.cupsRowCount));
 
348
    cupsArrayAdd(gs_args, strdup(tmpstr));
 
349
  }
 
350
  if (h.cupsRowFeed) {
 
351
    snprintf(tmpstr, sizeof(tmpstr), "-dcupsRowFeed=%d", 
 
352
             (unsigned)(h.cupsRowFeed));
 
353
    cupsArrayAdd(gs_args, strdup(tmpstr));
 
354
  }
 
355
  if (h.cupsRowStep) {
 
356
    snprintf(tmpstr, sizeof(tmpstr), "-dcupsRowStep=%d", 
 
357
             (unsigned)(h.cupsRowStep));
 
358
    cupsArrayAdd(gs_args, strdup(tmpstr));
 
359
  }
 
360
#ifdef CUPS_RASTER_SYNCv1
 
361
  if (h.cupsBorderlessScalingFactor != 1.0f) {
 
362
    snprintf(tmpstr, sizeof(tmpstr), "-dcupsBorderlessScalingFactor=%.4f", 
 
363
             h.cupsBorderlessScalingFactor);
 
364
    cupsArrayAdd(gs_args, strdup(tmpstr));
 
365
  }
 
366
  for (i=0; i <= 15; i ++)
 
367
    if (h.cupsInteger[i]) {
 
368
      snprintf(tmpstr, sizeof(tmpstr), "-dcupsInteger%d=%d", 
 
369
               i, (unsigned)(h.cupsInteger[i]));
 
370
      cupsArrayAdd(gs_args, strdup(tmpstr));
 
371
    }
 
372
  for (i=0; i <= 15; i ++)
 
373
    if (h.cupsReal[i]) {
 
374
      snprintf(tmpstr, sizeof(tmpstr), "-dcupsReal%d=%.4f", 
 
375
               i, h.cupsReal[i]);
 
376
      cupsArrayAdd(gs_args, strdup(tmpstr));
 
377
    }
 
378
  for (i=0; i <= 15; i ++)
 
379
    if (h.cupsString[i][0] != '\0') {
 
380
      snprintf(tmpstr, sizeof(tmpstr), "-scupsString%d=%s", 
 
381
               i, h.cupsString[i]);
 
382
      cupsArrayAdd(gs_args, strdup(tmpstr));
 
383
    }
 
384
  if (h.cupsMarkerType[0] != '\0') {
 
385
    snprintf(tmpstr, sizeof(tmpstr), "-scupsMarkerType=%s", 
 
386
             h.cupsMarkerType);
 
387
    cupsArrayAdd(gs_args, strdup(tmpstr));
 
388
  }
 
389
  if (h.cupsRenderingIntent[0] != '\0') {
 
390
    snprintf(tmpstr, sizeof(tmpstr), "-scupsRenderingIntent=%s", 
 
391
             h.cupsRenderingIntent);
 
392
    cupsArrayAdd(gs_args, strdup(tmpstr));
 
393
  }
 
394
  if (h.cupsPageSizeName[0] != '\0') {
 
395
    snprintf(tmpstr, sizeof(tmpstr), "-scupsPageSizeName=%s", 
 
396
             h.cupsPageSizeName);
 
397
    cupsArrayAdd(gs_args, strdup(tmpstr));
 
398
  }
 
399
#endif /* CUPS_RASTER_SYNCv1 */
 
400
 
 
401
  /* Parameters of array type. They cannot be supplied as "-d" or "-s"
 
402
     command line options. We use "-c" here to supply them as
 
403
     PostScript commands */
 
404
 
 
405
  /* Switch to taking PostScript commands on the Ghostscript command line */
 
406
  cupsArrayAdd(gs_args, "-c");
 
407
 
 
408
  if ((t = cupsGetOption("profile", num_options, options)) != NULL) {
 
409
    snprintf(tmpstr, sizeof(tmpstr), "<</cupsProfile(%s)>>setpagedevice", t);
 
410
    cupsArrayAdd(gs_args, strdup(tmpstr));
 
411
  }
 
412
 
 
413
  /* Mark the end of PostScript commands supplied on the Ghostscript command
 
414
     line (with the "-c" option), so that we can supply the input file name */
 
415
  cupsArrayAdd(gs_args, strdup("-f"));
 
416
 
 
417
  /* Let Ghostscript read from STDIN */
 
418
  cupsArrayAdd(gs_args, strdup("-_"));
 
419
 
 
420
  /* Put Ghostscript command line argument into an array for the "exec()"
 
421
     call */
 
422
  numargs = cupsArrayCount(gs_args);
 
423
  gsargv = calloc(numargs + 1, sizeof(char *));
 
424
  for (argument = (char *)cupsArrayFirst(gs_args), i = 0; argument;
 
425
       argument = (char *)cupsArrayNext(gs_args), i++) {
 
426
    gsargv[i] = argument;
 
427
  }
 
428
  gsargv[i] = NULL;
 
429
 
 
430
  /* Debug output: Full Ghostscript command line and environment variables */
 
431
  fprintf(stderr, "DEBUG: Ghostscript command line:");
 
432
  for (i = 0; gsargv[i]; i ++) {
 
433
    if ((strchr(gsargv[i],' ')) || (strchr(gsargv[i],'\t')))
 
434
      apos = "'";
 
435
    else
 
436
      apos = "";
 
437
    fprintf(stderr, " %s%s%s", apos, gsargv[i], apos);
 
438
  }
 
439
  fprintf(stderr, "\n");
 
440
 
 
441
  for (i = 0; envp[i]; i ++)
 
442
    fprintf(stderr, "DEBUG: envp[%d]=\"%s\"\n", i, envp[i]);
 
443
 
 
444
  /* Create a pipe for feeding the job into Ghostscript */
 
445
  if (pipe(fds))
 
446
  {
 
447
    fds[0] = -1;
 
448
    fds[1] = -1;
 
449
    fprintf(stderr, "ERROR: Unable to establish pipe for Ghostscript call");
 
450
    exit(1);
 
451
  }
 
452
 
 
453
  /* Set the "close on exec" flag on each end of the pipe... */
 
454
  if (fcntl(fds[0], F_SETFD, fcntl(fds[0], F_GETFD) | FD_CLOEXEC))
 
455
  {
 
456
    close(fds[0]);
 
457
    close(fds[1]);
 
458
    fds[0] = -1;
 
459
    fds[1] = -1;
 
460
    fprintf(stderr, "ERROR: Unable to set \"close on exec\" flag on read end of the pipe for Ghostscript call");
 
461
    exit(1);
 
462
  }
 
463
  if (fcntl(fds[1], F_SETFD, fcntl(fds[1], F_GETFD) | FD_CLOEXEC))
 
464
  {
 
465
    close(fds[0]);
 
466
    close(fds[1]);
 
467
    fprintf(stderr, "ERROR: Unable to set \"close on exec\" flag on write end of the pipe for Ghostscript call");
 
468
    exit(1);
 
469
  }
 
470
 
 
471
  if ((pid = fork()) == 0)
 
472
  {
 
473
    /* Ghostscript child process */
 
474
 
 
475
    /* Couple pipe with STDIN of Ghostscript process */
 
476
    if (fds[0] != 0) {
 
477
      close(0);
 
478
      if (fds[0] > 0)
 
479
        dup(fds[0]);
 
480
      else {
 
481
        fprintf(stderr, "ERROR: Unable to couple pipe with STDIN of Ghostscript process");
 
482
        exit(1);
 
483
      }
 
484
    }
 
485
 
 
486
    /* Execute Ghostscript command line ... */
 
487
    snprintf(tmpstr, sizeof(tmpstr), "%s/%s", BINDIR, GS);
 
488
    execve(tmpstr, gsargv, envp);
 
489
 
 
490
    perror(tmpstr);
 
491
 
 
492
    exit(1);
 
493
  } else {
 
494
    /* Main process */
 
495
 
 
496
    /* Feed job data into Ghostscript */
 
497
    while ((n = fread(buf, 1, BUFSIZ, fp)) > 0) {
 
498
      if (write(fds[1], buf, n) != n) {
 
499
        fprintf(stderr, "ERROR: Can't feed job data into Ghostscript");
 
500
        fclose(fp);
 
501
        exit(1);
 
502
      }
 
503
    }
 
504
    fclose(fp);
 
505
  }
 
506
 
 
507
  exit(0);
 
508
}
 
509