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