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