1/* 2 * "$Id: bcp.c 11093 2013-07-03 20:48:42Z msweet $" 3 * 4 * TBCP port monitor for CUPS. 5 * 6 * Copyright 2007-2010 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 ppd_file_t *ppd; /* PPD file */ 53 54 55 /* 56 * Check command-line... 57 */ 58 59 if (argc < 6 || argc > 7) 60 { 61 _cupsLangPrintf(stderr, 62 _("Usage: %s job-id user title copies options [file]"), 63 argv[0]); 64 return (1); 65 } 66 67 if (argc == 6) 68 { 69 copies = 1; 70 fp = stdin; 71 } 72 else 73 { 74 copies = atoi(argv[4]); 75 fp = fopen(argv[6], "rb"); 76 77 if (!fp) 78 { 79 perror(argv[6]); 80 return (1); 81 } 82 } 83 84 /* 85 * Open the PPD file as needed... 86 */ 87 88 ppd = ppdOpenFile(getenv("PPD")); 89 90 /* 91 * Copy the print file to stdout... 92 */ 93 94 while (copies > 0) 95 { 96 copies --; 97 98 if (ppd && ppd->jcl_begin) 99 fputs(ppd->jcl_begin, stdout); 100 if (ppd && ppd->jcl_ps) 101 fputs(ppd->jcl_ps, stdout); 102 103 if (!ppd || ppd->language_level == 1) 104 { 105 /* 106 * Use setsoftwareiomode for BCP mode... 107 */ 108 109 puts("%!PS-Adobe-3.0 ExitServer"); 110 puts("%%Title: (BCP - Level 1)"); 111 puts("%%EndComments"); 112 puts("%%BeginExitServer: 0"); 113 puts("serverdict begin 0 exitserver"); 114 puts("%%EndExitServer"); 115 puts("statusdict begin"); 116 puts("/setsoftwareiomode known {100 setsoftwareiomode}"); 117 puts("end"); 118 puts("%EOF"); 119 } 120 else 121 { 122 /* 123 * Use setdevparams for BCP mode... 124 */ 125 126 puts("%!PS-Adobe-3.0"); 127 puts("%%Title: (BCP - Level 2)"); 128 puts("%%EndComments"); 129 puts("currentsysparams"); 130 puts("/CurInputDevice 2 copy known {"); 131 puts("get"); 132 puts("<</Protocol /Binary>> setdevparams"); 133 puts("}{"); 134 puts("pop pop"); 135 puts("} ifelse"); 136 puts("%EOF"); 137 } 138 139 if (ppd && ppd->jcl_end) 140 fputs(ppd->jcl_end, stdout); 141 else if (!ppd || ppd->num_filters == 0) 142 putchar(0x04); 143 144 /* 145 * Loop until we see end-of-file... 146 */ 147 148 do 149 { 150 linelen = sizeof(line); 151 if (psgets(line, &linelen, fp) == NULL) 152 break; 153 } 154 while (pswrite(line, linelen, stdout) > 0); 155 156 fflush(stdout); 157 } 158 159 return (0); 160} 161 162 163/* 164 * 'psgets()' - Get a line from a file. 165 * 166 * Note: 167 * 168 * This function differs from the gets() function in that it 169 * handles any combination of CR, LF, or CR LF to end input 170 * lines. 171 */ 172 173static char * /* O - String or NULL if EOF */ 174psgets(char *buf, /* I - Buffer to read into */ 175 size_t *bytes, /* IO - Length of buffer */ 176 FILE *fp) /* I - File to read from */ 177{ 178 char *bufptr; /* Pointer into buffer */ 179 int ch; /* Character from file */ 180 size_t len; /* Max length of string */ 181 182 183 len = *bytes - 1; 184 bufptr = buf; 185 ch = EOF; 186 187 while ((bufptr - buf) < len) 188 { 189 if ((ch = getc(fp)) == EOF) 190 break; 191 192 if (ch == '\r') 193 { 194 /* 195 * Got a CR; see if there is a LF as well... 196 */ 197 198 ch = getc(fp); 199 200 if (ch != EOF && ch != '\n') 201 { 202 ungetc(ch, fp); /* Nope, save it for later... */ 203 ch = '\r'; 204 } 205 else 206 *bufptr++ = '\r'; 207 break; 208 } 209 else if (ch == '\n') 210 break; 211 else 212 *bufptr++ = ch; 213 } 214 215 /* 216 * Add a trailing newline if it is there... 217 */ 218 219 if (ch == '\n' || ch == '\r') 220 { 221 if ((bufptr - buf) < len) 222 *bufptr++ = ch; 223 else 224 ungetc(ch, fp); 225 } 226 227 /* 228 * Nul-terminate the string and return it (or NULL for EOF). 229 */ 230 231 *bufptr = '\0'; 232 *bytes = bufptr - buf; 233 234 if (ch == EOF && bufptr == buf) 235 return (NULL); 236 else 237 return (buf); 238} 239 240 241/* 242 * 'pswrite()' - Write data from a file. 243 */ 244 245static size_t /* O - Number of bytes written */ 246pswrite(const char *buf, /* I - Buffer to write */ 247 size_t bytes, /* I - Bytes to write */ 248 FILE *fp) /* I - File to write to */ 249{ 250 size_t count; /* Remaining bytes */ 251 252 253 for (count = bytes; count > 0; count --, buf ++) 254 switch (*buf) 255 { 256 case 0x04 : /* CTRL-D */ 257 if (bytes == 1) 258 { 259 /* 260 * Don't quote the last CTRL-D... 261 */ 262 263 putchar(0x04); 264 break; 265 } 266 267 case 0x01 : /* CTRL-A */ 268 case 0x03 : /* CTRL-C */ 269 case 0x05 : /* CTRL-E */ 270 case 0x11 : /* CTRL-Q */ 271 case 0x13 : /* CTRL-S */ 272 case 0x14 : /* CTRL-T */ 273 case 0x1c : /* CTRL-\ */ 274 if (putchar(0x01) < 0) 275 return (-1); 276 if (putchar(*buf ^ 0x40) < 0) 277 return (-1); 278 break; 279 280 default : 281 if (putchar(*buf) < 0) 282 return (-1); 283 break; 284 } 285 286 return (bytes); 287} 288 289 290/* 291 * End of "$Id: bcp.c 11093 2013-07-03 20:48:42Z msweet $". 292 */ 293