• 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 
40 
41  /*
42   * Check command-line...
43   */
44 
45   if (argc != 6 && argc != 7)
46   {
47     _cupsLangPrintf(stderr,
48                     _("Usage: %s job-id user title copies options [file]"),
49 		    argv[0]);
50     return (1);
51   }
52 
53   if (argc == 6)
54   {
55     copies = 1;
56     fp     = stdin;
57   }
58   else
59   {
60     copies = atoi(argv[4]);
61     fp     = fopen(argv[6], "rb");
62 
63     if (!fp)
64     {
65       perror(argv[6]);
66       return (1);
67     }
68   }
69 
70  /*
71   * Copy the print file to stdout...
72   */
73 
74   while (copies > 0)
75   {
76     copies --;
77 
78    /*
79     * Read the first line...
80     */
81 
82     linelen = sizeof(line);
83     if (!psgets(line, &linelen, fp))
84       break;
85 
86    /*
87     * Handle leading PJL fun...
88     */
89 
90     if (!strncmp(line, "\033%-12345X", 9) || !strncmp(line, "@PJL ", 5))
91     {
92      /*
93       * Yup, we have leading PJL fun, so copy it until we hit a line
94       * with "ENTER LANGUAGE"...
95       */
96 
97       while (strstr(line, "ENTER LANGUAGE") == NULL)
98       {
99         fwrite(line, 1, linelen, stdout);
100 
101 	linelen = sizeof(line);
102 	if (psgets(line, &linelen, fp) == NULL)
103           break;
104       }
105     }
106     else
107     {
108      /*
109       * No PJL stuff, just add the UEL...
110       */
111 
112       fputs("\033%-12345X", stdout);
113     }
114 
115    /*
116     * Switch to TBCP mode...
117     */
118 
119     fputs("\001M", stdout);
120 
121    /*
122     * Loop until we see end-of-file...
123     */
124 
125     while (pswrite(line, linelen) > 0)
126     {
127       linelen = sizeof(line);
128       if (psgets(line, &linelen, fp) == NULL)
129 	break;
130     }
131 
132     fflush(stdout);
133   }
134 
135   return (0);
136 }
137 
138 
139 /*
140  * 'psgets()' - Get a line from a file.
141  *
142  * Note:
143  *
144  *   This function differs from the gets() function in that it
145  *   handles any combination of CR, LF, or CR LF to end input
146  *   lines.
147  */
148 
149 static char *				/* O  - String or NULL if EOF */
psgets(char * buf,size_t * bytes,FILE * fp)150 psgets(char   *buf,			/* I  - Buffer to read into */
151        size_t *bytes,			/* IO - Length of buffer */
152        FILE   *fp)			/* I  - File to read from */
153 {
154   char		*bufptr;		/* Pointer into buffer */
155   int		ch;			/* Character from file */
156   size_t	len;			/* Max length of string */
157 
158 
159   len    = *bytes - 1;
160   bufptr = buf;
161   ch     = EOF;
162 
163   while ((size_t)(bufptr - buf) < len)
164   {
165     if ((ch = getc(fp)) == EOF)
166       break;
167 
168     if (ch == '\r')
169     {
170      /*
171       * Got a CR; see if there is a LF as well...
172       */
173 
174       ch = getc(fp);
175 
176       if (ch != EOF && ch != '\n')
177       {
178         ungetc(ch, fp);	/* Nope, save it for later... */
179         ch = '\r';
180       }
181       else
182         *bufptr++ = '\r';
183       break;
184     }
185     else if (ch == '\n')
186       break;
187     else
188       *bufptr++ = (char)ch;
189   }
190 
191  /*
192   * Add a trailing newline if it is there...
193   */
194 
195   if (ch == '\n' || ch == '\r')
196   {
197     if ((size_t)(bufptr - buf) < len)
198       *bufptr++ = (char)ch;
199     else
200       ungetc(ch, fp);
201   }
202 
203  /*
204   * Nul-terminate the string and return it (or NULL for EOF).
205   */
206 
207   *bufptr = '\0';
208   *bytes  = (size_t)(bufptr - buf);
209 
210   if (ch == EOF && bufptr == buf)
211     return (NULL);
212   else
213     return (buf);
214 }
215 
216 
217 /*
218  * 'pswrite()' - Write data from a file.
219  */
220 
221 static ssize_t				/* O - Number of bytes written */
pswrite(const char * buf,size_t bytes)222 pswrite(const char *buf,		/* I - Buffer to write */
223         size_t     bytes)		/* I - Bytes to write */
224 {
225   size_t	count;			/* Remaining bytes */
226 
227 
228   for (count = bytes; count > 0; count --, buf ++)
229     switch (*buf)
230     {
231       case 0x04 : /* CTRL-D */
232           if (bytes == 1)
233 	  {
234 	   /*
235 	    * Don't quote the last CTRL-D...
236 	    */
237 
238 	    putchar(0x04);
239 	    break;
240 	  }
241 
242       case 0x01 : /* CTRL-A */
243       case 0x03 : /* CTRL-C */
244       case 0x05 : /* CTRL-E */
245       case 0x11 : /* CTRL-Q */
246       case 0x13 : /* CTRL-S */
247       case 0x14 : /* CTRL-T */
248       case 0x1b : /* CTRL-[ (aka ESC) */
249       case 0x1c : /* CTRL-\ */
250 	  if (putchar(0x01) < 0)
251 	    return (-1);
252 	  if (putchar(*buf ^ 0x40) < 0)
253 	    return (-1);
254 	  break;
255 
256       default :
257 	  if (putchar(*buf) < 0)
258 	    return (-1);
259 	  break;
260     }
261 
262   return ((ssize_t)bytes);
263 }
264