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