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