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