1/*
2 * "$Id: bcp.c 11093 2013-07-03 20:48:42Z msweet $"
3 *
4 *   TBCP port monitor for CUPS.
5 *
6 *   Copyright 2007-2010 by Apple Inc.
7 *   Copyright 1993-2006 by Easy Software Products.
8 *
9 *   These coded instructions, statements, and computer programs are the
10 *   property of Apple Inc. and are protected by Federal copyright
11 *   law.  Distribution and use rights are outlined in the file "LICENSE.txt"
12 *   which should have been included with this file.  If this file is
13 *   file is missing or damaged, see the license at "http://www.cups.org/".
14 *
15 *   This file is subject to the Apple OS-Developed Software exception.
16 *
17 * Contents:
18 *
19 *   main()    - Main entry...
20 *   psgets()  - Get a line from a file.
21 *   pswrite() - Write data from a file.
22 */
23
24/*
25 * Include necessary headers...
26 */
27
28#include <cups/cups-private.h>
29#include <cups/ppd.h>
30
31
32/*
33 * Local functions...
34 */
35
36static char		*psgets(char *buf, size_t *bytes, FILE *fp);
37static size_t		pswrite(const char *buf, size_t bytes, FILE *fp);
38
39
40/*
41 * 'main()' - Main entry...
42 */
43
44int					/* O - Exit status */
45main(int  argc,				/* I - Number of command-line args */
46     char *argv[])			/* I - Command-line arguments */
47{
48  FILE		*fp;			/* File to print */
49  int		copies;			/* Number of copies left */
50  char		line[1024];		/* Line/buffer from stream/file */
51  size_t	linelen;		/* Length of line */
52  ppd_file_t	*ppd;			/* PPD file */
53
54
55 /*
56  * Check command-line...
57  */
58
59  if (argc < 6 || argc > 7)
60  {
61    _cupsLangPrintf(stderr,
62                    _("Usage: %s job-id user title copies options [file]"),
63		    argv[0]);
64    return (1);
65  }
66
67  if (argc == 6)
68  {
69    copies = 1;
70    fp     = stdin;
71  }
72  else
73  {
74    copies = atoi(argv[4]);
75    fp     = fopen(argv[6], "rb");
76
77    if (!fp)
78    {
79      perror(argv[6]);
80      return (1);
81    }
82  }
83
84 /*
85  * Open the PPD file as needed...
86  */
87
88  ppd = ppdOpenFile(getenv("PPD"));
89
90 /*
91  * Copy the print file to stdout...
92  */
93
94  while (copies > 0)
95  {
96    copies --;
97
98    if (ppd && ppd->jcl_begin)
99      fputs(ppd->jcl_begin, stdout);
100    if (ppd && ppd->jcl_ps)
101      fputs(ppd->jcl_ps, stdout);
102
103    if (!ppd || ppd->language_level == 1)
104    {
105     /*
106      * Use setsoftwareiomode for BCP mode...
107      */
108
109      puts("%!PS-Adobe-3.0 ExitServer");
110      puts("%%Title: (BCP - Level 1)");
111      puts("%%EndComments");
112      puts("%%BeginExitServer: 0");
113      puts("serverdict begin 0 exitserver");
114      puts("%%EndExitServer");
115      puts("statusdict begin");
116      puts("/setsoftwareiomode known {100 setsoftwareiomode}");
117      puts("end");
118      puts("%EOF");
119    }
120    else
121    {
122     /*
123      * Use setdevparams for BCP mode...
124      */
125
126      puts("%!PS-Adobe-3.0");
127      puts("%%Title: (BCP - Level 2)");
128      puts("%%EndComments");
129      puts("currentsysparams");
130      puts("/CurInputDevice 2 copy known {");
131      puts("get");
132      puts("<</Protocol /Binary>> setdevparams");
133      puts("}{");
134      puts("pop pop");
135      puts("} ifelse");
136      puts("%EOF");
137    }
138
139    if (ppd && ppd->jcl_end)
140      fputs(ppd->jcl_end, stdout);
141    else if (!ppd || ppd->num_filters == 0)
142      putchar(0x04);
143
144   /*
145    * Loop until we see end-of-file...
146    */
147
148    do
149    {
150      linelen = sizeof(line);
151      if (psgets(line, &linelen, fp) == NULL)
152	break;
153    }
154    while (pswrite(line, linelen, stdout) > 0);
155
156    fflush(stdout);
157  }
158
159  return (0);
160}
161
162
163/*
164 * 'psgets()' - Get a line from a file.
165 *
166 * Note:
167 *
168 *   This function differs from the gets() function in that it
169 *   handles any combination of CR, LF, or CR LF to end input
170 *   lines.
171 */
172
173static char *				/* O  - String or NULL if EOF */
174psgets(char   *buf,			/* I  - Buffer to read into */
175       size_t *bytes,			/* IO - Length of buffer */
176       FILE   *fp)			/* I  - File to read from */
177{
178  char		*bufptr;		/* Pointer into buffer */
179  int		ch;			/* Character from file */
180  size_t	len;			/* Max length of string */
181
182
183  len    = *bytes - 1;
184  bufptr = buf;
185  ch     = EOF;
186
187  while ((bufptr - buf) < len)
188  {
189    if ((ch = getc(fp)) == EOF)
190      break;
191
192    if (ch == '\r')
193    {
194     /*
195      * Got a CR; see if there is a LF as well...
196      */
197
198      ch = getc(fp);
199
200      if (ch != EOF && ch != '\n')
201      {
202        ungetc(ch, fp);	/* Nope, save it for later... */
203        ch = '\r';
204      }
205      else
206        *bufptr++ = '\r';
207      break;
208    }
209    else if (ch == '\n')
210      break;
211    else
212      *bufptr++ = ch;
213  }
214
215 /*
216  * Add a trailing newline if it is there...
217  */
218
219  if (ch == '\n' || ch == '\r')
220  {
221    if ((bufptr - buf) < len)
222      *bufptr++ = ch;
223    else
224      ungetc(ch, fp);
225  }
226
227 /*
228  * Nul-terminate the string and return it (or NULL for EOF).
229  */
230
231  *bufptr = '\0';
232  *bytes  = bufptr - buf;
233
234  if (ch == EOF && bufptr == buf)
235    return (NULL);
236  else
237    return (buf);
238}
239
240
241/*
242 * 'pswrite()' - Write data from a file.
243 */
244
245static size_t				/* O - Number of bytes written */
246pswrite(const char *buf,		/* I - Buffer to write */
247        size_t     bytes,		/* I - Bytes to write */
248	FILE       *fp)			/* I - File to write to */
249{
250  size_t	count;			/* Remaining bytes */
251
252
253  for (count = bytes; count > 0; count --, buf ++)
254    switch (*buf)
255    {
256      case 0x04 : /* CTRL-D */
257          if (bytes == 1)
258	  {
259	   /*
260	    * Don't quote the last CTRL-D...
261	    */
262
263	    putchar(0x04);
264	    break;
265	  }
266
267      case 0x01 : /* CTRL-A */
268      case 0x03 : /* CTRL-C */
269      case 0x05 : /* CTRL-E */
270      case 0x11 : /* CTRL-Q */
271      case 0x13 : /* CTRL-S */
272      case 0x14 : /* CTRL-T */
273      case 0x1c : /* CTRL-\ */
274	  if (putchar(0x01) < 0)
275	    return (-1);
276	  if (putchar(*buf ^ 0x40) < 0)
277	    return (-1);
278	  break;
279
280      default :
281	  if (putchar(*buf) < 0)
282	    return (-1);
283	  break;
284    }
285
286  return (bytes);
287}
288
289
290/*
291 * End of "$Id: bcp.c 11093 2013-07-03 20:48:42Z msweet $".
292 */
293