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