1/* 2 * "$Id: lpr.c 11560 2014-02-06 20:10:19Z msweet $" 3 * 4 * "lpr" command for CUPS. 5 * 6 * Copyright 2007-2014 by Apple Inc. 7 * Copyright 1997-2007 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 16/* 17 * Include necessary headers... 18 */ 19 20#include <cups/cups-private.h> 21 22 23/* 24 * 'main()' - Parse options and send files for printing. 25 */ 26 27int 28main(int argc, /* I - Number of command-line arguments */ 29 char *argv[]) /* I - Command-line arguments */ 30{ 31 int i, j; /* Looping var */ 32 int job_id; /* Job ID */ 33 char ch; /* Option character */ 34 char *printer, /* Destination printer or class */ 35 *instance; /* Instance */ 36 const char *title, /* Job title */ 37 *val; /* Environment variable name */ 38 int num_copies; /* Number of copies per file */ 39 int num_files; /* Number of files to print */ 40 const char *files[1000]; /* Files to print */ 41 cups_dest_t *dest; /* Selected destination */ 42 int num_options; /* Number of options */ 43 cups_option_t *options; /* Options */ 44 int deletefile; /* Delete file after print? */ 45 char buffer[8192]; /* Copy buffer */ 46 47 48 _cupsSetLocale(argv); 49 50 deletefile = 0; 51 printer = NULL; 52 dest = NULL; 53 num_options = 0; 54 options = NULL; 55 num_files = 0; 56 title = NULL; 57 58 for (i = 1; i < argc; i ++) 59 if (argv[i][0] == '-') 60 { 61 switch (ch = argv[i][1]) 62 { 63 case 'E' : /* Encrypt */ 64#ifdef HAVE_SSL 65 cupsSetEncryption(HTTP_ENCRYPT_REQUIRED); 66#else 67 _cupsLangPrintf(stderr, _("%s: Sorry, no encryption support."), 68 argv[0]); 69#endif /* HAVE_SSL */ 70 break; 71 72 case 'U' : /* Username */ 73 if (argv[i][2] != '\0') 74 cupsSetUser(argv[i] + 2); 75 else 76 { 77 i ++; 78 if (i >= argc) 79 { 80 _cupsLangPrintf(stderr, 81 _("%s: Error - expected username after " 82 "\"-U\" option."), argv[0]); 83 return (1); 84 } 85 86 cupsSetUser(argv[i]); 87 } 88 break; 89 90 case 'H' : /* Connect to host */ 91 if (argv[i][2] != '\0') 92 cupsSetServer(argv[i] + 2); 93 else 94 { 95 i ++; 96 97 if (i >= argc) 98 { 99 _cupsLangPrintf(stderr, 100 _("%s: Error - expected hostname after " 101 "\"-H\" option."), argv[0]); 102 return (1); 103 } 104 else 105 cupsSetServer(argv[i]); 106 } 107 break; 108 109 case '1' : /* TROFF font set 1 */ 110 case '2' : /* TROFF font set 2 */ 111 case '3' : /* TROFF font set 3 */ 112 case '4' : /* TROFF font set 4 */ 113 case 'i' : /* indent */ 114 case 'w' : /* width */ 115 if (argv[i][2] == '\0') 116 { 117 i ++; 118 119 if (i >= argc) 120 { 121 _cupsLangPrintf(stderr, 122 _("%s: Error - expected value after \"-%c\" " 123 "option."), argv[0], ch); 124 return (1); 125 } 126 } 127 128 case 'c' : /* CIFPLOT */ 129 case 'd' : /* DVI */ 130 case 'f' : /* FORTRAN */ 131 case 'g' : /* plot */ 132 case 'n' : /* Ditroff */ 133 case 't' : /* Troff */ 134 case 'v' : /* Raster image */ 135 _cupsLangPrintf(stderr, 136 _("%s: Warning - \"%c\" format modifier not " 137 "supported - output may not be correct."), 138 argv[0], ch); 139 break; 140 141 case 'o' : /* Option */ 142 if (argv[i][2] != '\0') 143 num_options = cupsParseOptions(argv[i] + 2, num_options, &options); 144 else 145 { 146 i ++; 147 if (i >= argc) 148 { 149 _cupsLangPrintf(stderr, 150 _("%s: Error - expected option=value after " 151 "\"-o\" option."), argv[0]); 152 return (1); 153 } 154 155 num_options = cupsParseOptions(argv[i], num_options, &options); 156 } 157 break; 158 159 case 'l' : /* Literal/raw */ 160 num_options = cupsAddOption("raw", "true", num_options, &options); 161 break; 162 163 case 'p' : /* Prettyprint */ 164 num_options = cupsAddOption("prettyprint", "true", num_options, 165 &options); 166 break; 167 168 case 'h' : /* Suppress burst page */ 169 num_options = cupsAddOption("job-sheets", "none", num_options, 170 &options); 171 break; 172 173 case 's' : /* Don't use symlinks */ 174 break; 175 176 case 'm' : /* Mail on completion */ 177 { 178 char email[1024]; /* EMail address */ 179 180 181 snprintf(email, sizeof(email), "mailto:%s@%s", cupsUser(), 182 httpGetHostname(NULL, buffer, sizeof(buffer))); 183 num_options = cupsAddOption("notify-recipient-uri", email, 184 num_options, &options); 185 } 186 break; 187 188 case 'q' : /* Queue file but don't print */ 189 num_options = cupsAddOption("job-hold-until", "indefinite", 190 num_options, &options); 191 break; 192 193 case 'r' : /* Remove file after printing */ 194 deletefile = 1; 195 break; 196 197 case 'P' : /* Destination printer or class */ 198 if (argv[i][2] != '\0') 199 printer = argv[i] + 2; 200 else 201 { 202 i ++; 203 if (i >= argc) 204 { 205 _cupsLangPrintf(stderr, 206 _("%s: Error - expected destination after " 207 "\"-P\" option."), argv[0]); 208 return (1); 209 } 210 211 printer = argv[i]; 212 } 213 214 if ((instance = strrchr(printer, '/')) != NULL) 215 *instance++ = '\0'; 216 217 if ((dest = cupsGetNamedDest(NULL, printer, instance)) != NULL) 218 { 219 for (j = 0; j < dest->num_options; j ++) 220 if (cupsGetOption(dest->options[j].name, num_options, 221 options) == NULL) 222 num_options = cupsAddOption(dest->options[j].name, 223 dest->options[j].value, 224 num_options, &options); 225 } 226 else if (cupsLastError() == IPP_STATUS_ERROR_BAD_REQUEST || 227 cupsLastError() == IPP_STATUS_ERROR_VERSION_NOT_SUPPORTED) 228 { 229 _cupsLangPrintf(stderr, 230 _("%s: Error - add '/version=1.1' to server " 231 "name."), argv[0]); 232 return (1); 233 } 234 break; 235 236 case '#' : /* Number of copies */ 237 if (argv[i][2] != '\0') 238 num_copies = atoi(argv[i] + 2); 239 else 240 { 241 i ++; 242 if (i >= argc) 243 { 244 _cupsLangPrintf(stderr, 245 _("%s: Error - expected copies after " 246 "\"-#\" option."), argv[0]); 247 return (1); 248 } 249 250 num_copies = atoi(argv[i]); 251 } 252 253 sprintf(buffer, "%d", num_copies); 254 num_options = cupsAddOption("copies", buffer, num_options, &options); 255 break; 256 257 case 'C' : /* Class */ 258 case 'J' : /* Job name */ 259 case 'T' : /* Title */ 260 if (argv[i][2] != '\0') 261 title = argv[i] + 2; 262 else 263 { 264 i ++; 265 if (i >= argc) 266 { 267 _cupsLangPrintf(stderr, 268 _("%s: Error - expected name after \"-%c\" " 269 "option."), argv[0], ch); 270 return (1); 271 } 272 273 title = argv[i]; 274 } 275 break; 276 277 default : 278 _cupsLangPrintf(stderr, 279 _("%s: Error - unknown option \"%c\"."), argv[0], 280 argv[i][1]); 281 return (1); 282 } 283 } 284 else if (num_files < 1000) 285 { 286 /* 287 * Print a file... 288 */ 289 290 if (access(argv[i], R_OK) != 0) 291 { 292 _cupsLangPrintf(stderr, 293 _("%s: Error - unable to access \"%s\" - %s"), 294 argv[0], argv[i], strerror(errno)); 295 return (1); 296 } 297 298 files[num_files] = argv[i]; 299 num_files ++; 300 301 if (title == NULL) 302 { 303 if ((title = strrchr(argv[i], '/')) != NULL) 304 title ++; 305 else 306 title = argv[i]; 307 } 308 } 309 else 310 _cupsLangPrintf(stderr, 311 _("%s: Error - too many files - \"%s\"."), argv[0], 312 argv[i]); 313 /* 314 * See if we have any files to print; if not, print from stdin... 315 */ 316 317 if (printer == NULL) 318 { 319 if ((dest = cupsGetNamedDest(NULL, NULL, NULL)) != NULL) 320 { 321 printer = dest->name; 322 323 for (j = 0; j < dest->num_options; j ++) 324 if (cupsGetOption(dest->options[j].name, num_options, options) == NULL) 325 num_options = cupsAddOption(dest->options[j].name, 326 dest->options[j].value, 327 num_options, &options); 328 } 329 else if (cupsLastError() == IPP_STATUS_ERROR_BAD_REQUEST || 330 cupsLastError() == IPP_STATUS_ERROR_VERSION_NOT_SUPPORTED) 331 { 332 _cupsLangPrintf(stderr, 333 _("%s: Error - add '/version=1.1' to server " 334 "name."), argv[0]); 335 return (1); 336 } 337 } 338 339 if (printer == NULL) 340 { 341 val = NULL; 342 343 if ((printer = getenv("LPDEST")) == NULL) 344 { 345 if ((printer = getenv("PRINTER")) != NULL) 346 { 347 if (!strcmp(printer, "lp")) 348 printer = NULL; 349 else 350 val = "PRINTER"; 351 } 352 } 353 else 354 val = "LPDEST"; 355 356 if (printer && !cupsGetNamedDest(NULL, printer, NULL)) 357 _cupsLangPrintf(stderr, 358 _("%s: Error - %s environment variable names " 359 "non-existent destination \"%s\"."), argv[0], val, 360 printer); 361 else if (cupsLastError() == IPP_NOT_FOUND) 362 _cupsLangPrintf(stderr, 363 _("%s: Error - no default destination available."), 364 argv[0]); 365 else 366 _cupsLangPrintf(stderr, _("%s: Error - scheduler not responding."), 367 argv[0]); 368 369 return (1); 370 } 371 372 if (num_files > 0) 373 { 374 job_id = cupsPrintFiles(printer, num_files, files, title, num_options, options); 375 376 if (deletefile && job_id > 0) 377 { 378 /* 379 * Delete print files after printing... 380 */ 381 382 for (i = 0; i < num_files; i ++) 383 unlink(files[i]); 384 } 385 } 386 else if ((job_id = cupsCreateJob(CUPS_HTTP_DEFAULT, printer, 387 title ? title : "(stdin)", 388 num_options, options)) > 0) 389 { 390 http_status_t status; /* Write status */ 391 const char *format; /* Document format */ 392 ssize_t bytes; /* Bytes read */ 393 394 if (cupsGetOption("raw", num_options, options)) 395 format = CUPS_FORMAT_RAW; 396 else if ((format = cupsGetOption("document-format", num_options, 397 options)) == NULL) 398 format = CUPS_FORMAT_AUTO; 399 400 status = cupsStartDocument(CUPS_HTTP_DEFAULT, printer, job_id, NULL, 401 format, 1); 402 403 while (status == HTTP_CONTINUE && 404 (bytes = read(0, buffer, sizeof(buffer))) > 0) 405 status = cupsWriteRequestData(CUPS_HTTP_DEFAULT, buffer, (size_t)bytes); 406 407 if (status != HTTP_CONTINUE) 408 { 409 _cupsLangPrintf(stderr, _("%s: Error - unable to queue from stdin - %s."), 410 argv[0], httpStatus(status)); 411 cupsFinishDocument(CUPS_HTTP_DEFAULT, printer); 412 cupsCancelJob2(CUPS_HTTP_DEFAULT, printer, job_id, 0); 413 return (1); 414 } 415 416 if (cupsFinishDocument(CUPS_HTTP_DEFAULT, printer) != IPP_OK) 417 { 418 _cupsLangPrintf(stderr, "%s: %s", argv[0], cupsLastErrorString()); 419 cupsCancelJob2(CUPS_HTTP_DEFAULT, printer, job_id, 0); 420 return (1); 421 } 422 } 423 424 if (job_id < 1) 425 { 426 _cupsLangPrintf(stderr, "%s: %s", argv[0], cupsLastErrorString()); 427 return (1); 428 } 429 430 return (0); 431} 432 433 434/* 435 * End of "$Id: lpr.c 11560 2014-02-06 20:10:19Z msweet $". 436 */ 437