]>
git.ipfire.org Git - thirdparty/cups.git/blob - systemv/lp.c
2 * "$Id: lp.c 6649 2007-07-11 21:46:42Z mike $"
4 * "lp" command for the Common UNIX Printing System (CUPS).
6 * Copyright 2007 by Apple Inc.
7 * Copyright 1997-2007 by Easy Software Products.
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/".
17 * main() - Parse options and send files for printing.
18 * restart_job() - Restart a job.
19 * set_job_attrs() - Set job attributes.
20 * sighandler() - Signal catcher for when we print from stdin...
24 * Include necessary headers...
30 #include <cups/string.h>
31 #include <cups/cups.h>
32 #include <cups/i18n.h>
46 int restart_job(const char *command
, int job_id
);
47 int set_job_attrs(const char *command
, int job_id
, int num_options
,
48 cups_option_t
*options
);
55 char tempfile
[1024]; /* Temporary file for printing from stdin */
59 * 'main()' - Parse options and send files for printing.
63 main(int argc
, /* I - Number of command-line arguments */
64 char *argv
[]) /* I - Command-line arguments */
66 int i
, j
; /* Looping vars */
67 int job_id
; /* Job ID */
68 char *printer
, /* Printer name */
69 *instance
, /* Instance name */
70 *val
, /* Option value */
71 *title
; /* Job title */
72 int priority
; /* Job priority (1-100) */
73 int num_copies
; /* Number of copies per file */
74 int num_files
; /* Number of files to print */
75 const char *files
[1000]; /* Files to print */
76 cups_dest_t
*dest
; /* Selected destination */
77 int num_options
; /* Number of options */
78 cups_option_t
*options
; /* Options */
79 int end_options
; /* No more options? */
80 int silent
; /* Silent or verbose output? */
81 char buffer
[8192]; /* Copy buffer */
82 ssize_t bytes
; /* Bytes copied */
83 off_t filesize
; /* Size of temp file */
84 int temp
; /* Temporary file descriptor */
85 #if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
86 struct sigaction action
; /* Signal action */
87 struct sigaction oldaction
; /* Old signal action */
88 #endif /* HAVE_SIGACTION && !HAVE_SIGSET*/
93 * Solaris does some rather strange things to re-queue remote print
94 * jobs. On bootup, the "lp" command is run as "printd" to re-spool
95 * any remote jobs in /var/spool/print. Since CUPS doesn't need this
96 * nonsense, we just need to add the necessary check here to prevent
97 * lp from causing boot problems...
100 if ((val
= strrchr(argv
[0], '/')) != NULL
)
105 if (!strcmp(val
, "printd"))
109 _cupsSetLocale(argv
);
121 for (i
= 1; i
< argc
; i
++)
122 if (argv
[i
][0] == '-' && argv
[i
][1] && !end_options
)
125 case 'E' : /* Encrypt */
127 cupsSetEncryption(HTTP_ENCRYPT_REQUIRED
);
129 _cupsLangPrintf(stderr
,
130 _("%s: Sorry, no encryption support compiled in!\n"),
132 #endif /* HAVE_SSL */
135 case 'U' : /* Username */
136 if (argv
[i
][2] != '\0')
137 cupsSetUser(argv
[i
] + 2);
143 _cupsLangPrintf(stderr
,
144 _("%s: Error - expected username after "
150 cupsSetUser(argv
[i
]);
154 case 'c' : /* Copy to spool dir (always enabled) */
157 case 'd' : /* Destination printer or class */
158 if (argv
[i
][2] != '\0')
159 printer
= argv
[i
] + 2;
166 _cupsLangPrintf(stderr
,
167 _("%s: Error - expected destination after "
176 if ((instance
= strrchr(printer
, '/')) != NULL
)
179 if ((dest
= cupsGetNamedDest(NULL
, printer
, instance
)) != NULL
)
181 for (j
= 0; j
< dest
->num_options
; j
++)
182 if (cupsGetOption(dest
->options
[j
].name
, num_options
, options
) == NULL
)
183 num_options
= cupsAddOption(dest
->options
[j
].name
,
184 dest
->options
[j
].value
,
185 num_options
, &options
);
189 case 'f' : /* Form */
196 _cupsLangPrintf(stderr
,
197 _("%s: Error - expected form after \'-f\' "
204 _cupsLangPrintf(stderr
, _("%s: Warning - form option ignored!\n"),
208 case 'h' : /* Destination host */
209 if (argv
[i
][2] != '\0')
210 cupsSetServer(argv
[i
] + 2);
217 _cupsLangPrintf(stderr
,
218 _("%s: Error - expected hostname after "
224 cupsSetServer(argv
[i
]);
228 case 'i' : /* Change job */
237 _cupsLangPrintf(stderr
,
238 _("%s: Expected job ID after \'-i\' option!\n"),
248 _cupsLangPrintf(stderr
,
249 _("%s: Error - cannot print files and alter "
250 "jobs simultaneously!\n"),
255 if (strrchr(val
, '-') != NULL
)
256 job_id
= atoi(strrchr(val
, '-') + 1);
262 _cupsLangPrintf(stderr
, _("%s: Error - bad job ID!\n"), argv
[0]);
267 case 'm' : /* Send email when job is done */
269 case 'p' : /* Notify on completion */
271 case 'w' : /* Write to console or email */
273 char email
[1024]; /* EMail address */
276 snprintf(email
, sizeof(email
), "mailto:%s@%s", cupsUser(),
277 httpGetHostname(NULL
, buffer
, sizeof(buffer
)));
278 num_options
= cupsAddOption("notify-recipient-uri", email
,
279 num_options
, &options
);
285 case 'n' : /* Number of copies */
286 if (argv
[i
][2] != '\0')
287 num_copies
= atoi(argv
[i
] + 2);
294 _cupsLangPrintf(stderr
,
295 _("%s: Error - expected copies after "
301 num_copies
= atoi(argv
[i
]);
304 sprintf(buffer
, "%d", num_copies
);
305 num_options
= cupsAddOption("copies", buffer
, num_options
, &options
);
308 case 'o' : /* Option */
309 if (argv
[i
][2] != '\0')
310 num_options
= cupsParseOptions(argv
[i
] + 2, num_options
, &options
);
317 _cupsLangPrintf(stderr
,
318 _("%s: Error - expected option string after "
324 num_options
= cupsParseOptions(argv
[i
], num_options
, &options
);
329 case 'p' : /* Queue priority */
331 case 'q' : /* Queue priority */
332 if (argv
[i
][2] != '\0')
333 priority
= atoi(argv
[i
] + 2);
338 _cupsLangPrintf(stderr
,
339 _("%s: Error - expected priority after "
340 "\'-%c\' option!\n"),
341 argv
[0], argv
[i
][1]);
347 priority
= atoi(argv
[i
]);
351 * For 100% Solaris compatibility, need to add:
353 * priority = 99 * (39 - priority) / 39 + 1;
355 * However, to keep CUPS lp the same across all platforms
356 * we will break compatibility this far...
359 if (priority
< 1 || priority
> 100)
361 _cupsLangPrintf(stderr
,
362 _("%s: Error - priority must be between 1 and "
368 sprintf(buffer
, "%d", priority
);
369 num_options
= cupsAddOption("job-priority", buffer
, num_options
, &options
);
372 case 's' : /* Silent */
376 case 't' : /* Title */
377 if (argv
[i
][2] != '\0')
385 _cupsLangPrintf(stderr
,
386 _("%s: Error - expected title after "
396 case 'y' : /* mode-list */
403 _cupsLangPrintf(stderr
,
404 _("%s: Error - expected mode list after "
411 _cupsLangPrintf(stderr
,
412 _("%s: Warning - mode option ignored!\n"),
416 case 'H' : /* Hold job */
425 _cupsLangPrintf(stderr
,
426 _("%s: Error - expected hold name after "
435 if (!strcmp(val
, "hold"))
436 num_options
= cupsAddOption("job-hold-until", "indefinite",
437 num_options
, &options
);
438 else if (!strcmp(val
, "resume") ||
439 !strcmp(val
, "release"))
440 num_options
= cupsAddOption("job-hold-until", "no-hold",
441 num_options
, &options
);
442 else if (!strcmp(val
, "immediate"))
443 num_options
= cupsAddOption("job-priority", "100",
444 num_options
, &options
);
445 else if (!strcmp(val
, "restart"))
449 _cupsLangPrintf(stderr
,
450 _("%s: Need job ID (\'-i jobid\') before "
451 "\'-H restart\'!\n"),
456 if (restart_job(argv
[0], job_id
))
460 num_options
= cupsAddOption("job-hold-until", val
,
461 num_options
, &options
);
464 case 'P' : /* Page list */
473 _cupsLangPrintf(stderr
,
474 _("%s: Error - expected page list after "
483 num_options
= cupsAddOption("page-ranges", val
, num_options
,
487 case 'S' : /* character set */
494 _cupsLangPrintf(stderr
,
495 _("%s: Error - expected character set after "
502 _cupsLangPrintf(stderr
,
503 _("%s: Warning - character set option ignored!\n"),
507 case 'T' : /* Content-Type */
514 _cupsLangPrintf(stderr
,
515 _("%s: Error - expected content type after "
522 _cupsLangPrintf(stderr
,
523 _("%s: Warning - content type option ignored!\n"),
527 case '-' : /* Stop processing options */
532 _cupsLangPrintf(stderr
, _("%s: Error - unknown option \'%c\'!\n"),
533 argv
[0], argv
[i
][1]);
536 else if (!strcmp(argv
[i
], "-"))
538 if (num_files
|| job_id
)
540 _cupsLangPrintf(stderr
,
541 _("%s: Error - cannot print from stdin if files or a "
542 "job ID are provided!\n"),
549 else if (num_files
< 1000 && job_id
== 0)
555 if (access(argv
[i
], R_OK
) != 0)
557 _cupsLangPrintf(stderr
, _("%s: Error - unable to access \"%s\" - %s\n"),
558 argv
[0], argv
[i
], strerror(errno
));
562 files
[num_files
] = argv
[i
];
567 if ((title
= strrchr(argv
[i
], '/')) != NULL
)
574 _cupsLangPrintf(stderr
, _("%s: Error - too many files - \"%s\"\n"),
578 * See if we are altering an existing job...
582 return (set_job_attrs(argv
[0], job_id
, num_options
, options
));
585 * See if we have any files to print; if not, print from stdin...
590 if ((dest
= cupsGetNamedDest(NULL
, NULL
, NULL
)) != NULL
)
592 printer
= dest
->name
;
594 for (j
= 0; j
< dest
->num_options
; j
++)
595 if (cupsGetOption(dest
->options
[j
].name
, num_options
, options
) == NULL
)
596 num_options
= cupsAddOption(dest
->options
[j
].name
,
597 dest
->options
[j
].value
,
598 num_options
, &options
);
606 if ((printer
= getenv("LPDEST")) == NULL
)
608 if ((printer
= getenv("PRINTER")) != NULL
)
610 if (!strcmp(printer
, "lp"))
619 if (printer
&& !cupsGetNamedDest(NULL
, printer
, NULL
))
620 _cupsLangPrintf(stderr
,
621 _("%s: Error - %s environment variable names "
622 "non-existent destination \"%s\"!\n"),
623 argv
[0], val
, printer
);
624 else if (cupsLastError() == IPP_NOT_FOUND
)
625 _cupsLangPrintf(stderr
,
626 _("%s: Error - no default destination available.\n"),
629 _cupsLangPrintf(stderr
,
630 _("%s: Error - scheduler not responding!\n"),
637 job_id
= cupsPrintFiles(printer
, num_files
, files
, title
, num_options
, options
);
643 # if defined(HAVE_SIGSET)
644 sigset(SIGHUP
, sighandler
);
645 if (sigset(SIGINT
, sighandler
) == SIG_IGN
)
646 sigset(SIGINT
, SIG_IGN
);
647 sigset(SIGTERM
, sighandler
);
648 # elif defined(HAVE_SIGACTION)
649 memset(&action
, 0, sizeof(action
));
650 action
.sa_handler
= sighandler
;
652 sigaction(SIGHUP
, &action
, NULL
);
653 sigaction(SIGINT
, NULL
, &oldaction
);
654 if (oldaction
.sa_handler
!= SIG_IGN
)
655 sigaction(SIGINT
, &action
, NULL
);
656 sigaction(SIGTERM
, &action
, NULL
);
658 signal(SIGHUP
, sighandler
);
659 if (signal(SIGINT
, sighandler
) == SIG_IGN
)
660 signal(SIGINT
, SIG_IGN
);
661 signal(SIGTERM
, sighandler
);
665 temp
= cupsTempFd(tempfile
, sizeof(tempfile
));
669 _cupsLangPrintf(stderr
,
670 _("%s: Error - unable to create temporary file \"%s\" - %s\n"),
671 argv
[0], tempfile
, strerror(errno
));
675 while ((bytes
= read(0, buffer
, sizeof(buffer
))) > 0)
676 if (write(temp
, buffer
, bytes
) < 0)
678 _cupsLangPrintf(stderr
,
679 _("%s: Error - unable to write to temporary file "
681 argv
[0], tempfile
, strerror(errno
));
687 filesize
= lseek(temp
, 0, SEEK_CUR
);
692 _cupsLangPrintf(stderr
,
693 _("%s: Error - stdin is empty, so no job has been sent.\n"),
700 job_id
= cupsPrintFile(printer
, tempfile
, title
, num_options
, options
);
702 job_id
= cupsPrintFile(printer
, tempfile
, "(stdin)", num_options
, options
);
709 _cupsLangPrintf(stderr
, "%s: %s\n", argv
[0], cupsLastErrorString());
713 _cupsLangPrintf(stdout
, _("request id is %s-%d (%d file(s))\n"),
714 printer
, job_id
, num_files
);
721 * 'restart_job()' - Restart a job.
724 int /* O - Exit status */
725 restart_job(const char *command
, /* I - Command name */
726 int job_id
) /* I - Job ID */
728 http_t
*http
; /* HTTP connection to server */
729 ipp_t
*request
; /* IPP request */
730 char uri
[HTTP_MAX_URI
]; /* URI for job */
733 http
= httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption());
735 request
= ippNewRequest(IPP_RESTART_JOB
);
737 sprintf(uri
, "ipp://localhost/jobs/%d", job_id
);
739 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
740 "job-uri", NULL
, uri
);
742 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_NAME
,
743 "requesting-user-name", NULL
, cupsUser());
745 ippDelete(cupsDoRequest(http
, request
, "/jobs"));
747 if (cupsLastError() > IPP_OK_CONFLICT
)
749 _cupsLangPrintf(stderr
, "%s: %s\n", command
, cupsLastErrorString());
758 * 'set_job_attrs()' - Set job attributes.
761 int /* O - Exit status */
762 set_job_attrs(const char *command
, /* I - Command name */
763 int job_id
, /* I - Job ID */
764 int num_options
,/* I - Number of options */
765 cups_option_t
*options
) /* I - Options */
767 http_t
*http
; /* HTTP connection to server */
768 ipp_t
*request
; /* IPP request */
769 char uri
[HTTP_MAX_URI
]; /* URI for job */
772 if (num_options
== 0)
775 http
= httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption());
777 request
= ippNewRequest(IPP_SET_JOB_ATTRIBUTES
);
779 sprintf(uri
, "ipp://localhost/jobs/%d", job_id
);
781 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
782 "job-uri", NULL
, uri
);
784 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_NAME
,
785 "requesting-user-name", NULL
, cupsUser());
787 cupsEncodeOptions(request
, num_options
, options
);
789 ippDelete(cupsDoRequest(http
, request
, "/jobs"));
791 if (cupsLastError() > IPP_OK_CONFLICT
)
793 _cupsLangPrintf(stderr
, "%s: %s\n", command
, cupsLastErrorString());
803 * 'sighandler()' - Signal catcher for when we print from stdin...
807 sighandler(int s
) /* I - Signal number */
810 * Remove the temporary file we're using to print from stdin...
825 * End of "$Id: lp.c 6649 2007-07-11 21:46:42Z mike $".