]>
git.ipfire.org Git - thirdparty/cups.git/blob - systemv/lp.c
2 * "$Id: lp.c 4906 2006-01-10 20:53:28Z mike $"
4 * "lp" command for the Common UNIX Printing System (CUPS).
6 * Copyright 1997-2006 by Easy Software Products.
8 * These coded instructions, statements, and computer programs are the
9 * property of Easy Software Products and are protected by Federal
10 * copyright law. Distribution and use rights are outlined in the file
11 * "LICENSE.txt" which should have been included with this file. If this
12 * file is missing or damaged please contact Easy Software Products
15 * Attn: CUPS Licensing Information
16 * Easy Software Products
17 * 44141 Airport View Drive, Suite 204
18 * Hollywood, Maryland 20636 USA
20 * Voice: (301) 373-9600
21 * EMail: cups-info@cups.org
22 * WWW: http://www.cups.org
26 * main() - Parse options and send files for printing.
27 * restart_job() - Restart a job.
28 * set_job_attrs() - Set job attributes.
29 * sighandler() - Signal catcher for when we print from stdin...
33 * Include necessary headers...
39 #include <cups/string.h>
40 #include <cups/cups.h>
41 #include <cups/i18n.h>
55 int restart_job(int job_id
);
56 int set_job_attrs(int job_id
, int num_options
, cups_option_t
*options
);
63 char tempfile
[1024]; /* Temporary file for printing from stdin */
67 * 'main()' - Parse options and send files for printing.
71 main(int argc
, /* I - Number of command-line arguments */
72 char *argv
[]) /* I - Command-line arguments */
74 int i
, j
; /* Looping vars */
75 int job_id
; /* Job ID */
76 char *printer
, /* Printer name */
77 *instance
, /* Instance name */
78 *val
, /* Option value */
79 *title
; /* Job title */
80 int priority
; /* Job priority (1-100) */
81 int num_copies
; /* Number of copies per file */
82 int num_files
; /* Number of files to print */
83 const char *files
[1000]; /* Files to print */
84 int num_dests
; /* Number of destinations */
85 cups_dest_t
*dests
, /* Destinations */
86 *dest
; /* Selected destination */
87 int num_options
; /* Number of options */
88 cups_option_t
*options
; /* Options */
89 int silent
; /* Silent or verbose output? */
90 char buffer
[8192]; /* Copy buffer */
91 int temp
; /* Temporary file descriptor */
92 #if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
93 struct sigaction action
; /* Signal action */
94 struct sigaction oldaction
; /* Old signal action */
95 #endif /* HAVE_SIGACTION && !HAVE_SIGSET*/
100 * Solaris does some rather strange things to re-queue remote print
101 * jobs. On bootup, the "lp" command is run as "printd" to re-spool
102 * any remote jobs in /var/spool/print. Since CUPS doesn't need this
103 * nonsense, we just need to add the necessary check here to prevent
104 * lp from causing boot problems...
107 if ((val
= strrchr(argv
[0], '/')) != NULL
)
112 if (!strcmp(val
, "printd"))
126 for (i
= 1; i
< argc
; i
++)
127 if (argv
[i
][0] == '-' && argv
[i
][1])
130 case 'E' : /* Encrypt */
132 cupsSetEncryption(HTTP_ENCRYPT_REQUIRED
);
134 _cupsLangPrintf(stderr
, NULL
,
135 _("%s: Sorry, no encryption support compiled in!\n"),
137 #endif /* HAVE_SSL */
140 case 'c' : /* Copy to spool dir (always enabled) */
143 case 'd' : /* Destination printer or class */
144 if (argv
[i
][2] != '\0')
145 printer
= argv
[i
] + 2;
152 _cupsLangPuts(stderr
, NULL
,
153 _("lp: Expected destination after -d option!\n"));
160 if ((instance
= strrchr(printer
, '/')) != NULL
)
164 num_dests
= cupsGetDests(&dests
);
166 if ((dest
= cupsGetDest(printer
, instance
, num_dests
, dests
)) != NULL
)
168 for (j
= 0; j
< dest
->num_options
; j
++)
169 if (cupsGetOption(dest
->options
[j
].name
, num_options
, options
) == NULL
)
170 num_options
= cupsAddOption(dest
->options
[j
].name
,
171 dest
->options
[j
].value
,
172 num_options
, &options
);
176 case 'f' : /* Form */
183 _cupsLangPuts(stderr
, NULL
,
184 _("lp: Expected form after -f option!\n"));
189 fputs("lp: Warning - form option ignored!\n", stderr
);
192 case 'h' : /* Destination host */
193 if (argv
[i
][2] != '\0')
194 cupsSetServer(argv
[i
] + 2);
201 _cupsLangPuts(stderr
, NULL
,
202 _("lp: Expected hostname after -h option!\n"));
206 cupsSetServer(argv
[i
]);
210 case 'i' : /* Change job */
219 _cupsLangPuts(stderr
, NULL
,
220 _("lp: Expected job ID after -i option!\n"));
229 _cupsLangPuts(stderr
, NULL
,
230 _("lp: Error - cannot print files and alter "
231 "jobs simultaneously!\n"));
235 if (strrchr(val
, '-') != NULL
)
236 job_id
= atoi(strrchr(val
, '-') + 1);
242 _cupsLangPuts(stderr
, NULL
, _("lp: Error - bad job ID!\n"));
247 case 'm' : /* Send email when job is done */
249 case 'p' : /* Notify on completion */
251 case 'w' : /* Write to console or email */
254 case 'n' : /* Number of copies */
255 if (argv
[i
][2] != '\0')
256 num_copies
= atoi(argv
[i
] + 2);
263 _cupsLangPuts(stderr
, NULL
,
264 _("lp: Expected copies after -n option!\n"));
268 num_copies
= atoi(argv
[i
]);
271 sprintf(buffer
, "%d", num_copies
);
272 num_options
= cupsAddOption("copies", buffer
, num_options
, &options
);
275 case 'o' : /* Option */
276 if (argv
[i
][2] != '\0')
277 num_options
= cupsParseOptions(argv
[i
] + 2, num_options
, &options
);
284 _cupsLangPuts(stderr
, NULL
,
285 _("lp: Expected option string after -o option!\n"));
289 num_options
= cupsParseOptions(argv
[i
], num_options
, &options
);
294 case 'p' : /* Queue priority */
296 case 'q' : /* Queue priority */
297 if (argv
[i
][2] != '\0')
298 priority
= atoi(argv
[i
] + 2);
303 _cupsLangPrintf(stderr
, NULL
,
304 _("lp: Expected priority after -%c option!\n"),
311 priority
= atoi(argv
[i
]);
315 * For 100% Solaris compatibility, need to add:
317 * priority = 99 * (39 - priority) / 39 + 1;
319 * However, to keep CUPS lp the same across all platforms
320 * we will break compatibility this far...
323 if (priority
< 1 || priority
> 100)
325 _cupsLangPuts(stderr
, NULL
,
326 _("lp: Priority must be between 1 and 100.\n"));
330 sprintf(buffer
, "%d", priority
);
331 num_options
= cupsAddOption("job-priority", buffer
, num_options
, &options
);
334 case 's' : /* Silent */
338 case 't' : /* Title */
339 if (argv
[i
][2] != '\0')
347 _cupsLangPuts(stderr
, NULL
,
348 _("lp: Expected title after -t option!\n"));
356 case 'y' : /* mode-list */
363 _cupsLangPuts(stderr
, NULL
,
364 _("lp: Expected mode list after -y option!\n"));
369 _cupsLangPuts(stderr
, NULL
,
370 _("lp: Warning - mode option ignored!\n"));
373 case 'H' : /* Hold job */
382 _cupsLangPuts(stderr
, NULL
,
383 _("lp: Expected hold name after -H option!\n"));
390 if (!strcmp(val
, "hold"))
391 num_options
= cupsAddOption("job-hold-until", "indefinite",
392 num_options
, &options
);
393 else if (!strcmp(val
, "resume") ||
394 !strcmp(val
, "release"))
395 num_options
= cupsAddOption("job-hold-until", "no-hold",
396 num_options
, &options
);
397 else if (!strcmp(val
, "immediate"))
398 num_options
= cupsAddOption("job-priority", "100",
399 num_options
, &options
);
400 else if (!strcmp(val
, "restart"))
404 _cupsLangPuts(stderr
, NULL
,
405 _("lp: Need job ID (-i) before \"-H restart\"!\n"));
409 if (restart_job(job_id
))
413 num_options
= cupsAddOption("job-hold-until", val
,
414 num_options
, &options
);
417 case 'P' : /* Page list */
426 _cupsLangPuts(stderr
, NULL
,
427 _("lp: Expected page list after -P option!\n"));
434 num_options
= cupsAddOption("page-ranges", val
, num_options
,
438 case 'S' : /* character set */
445 _cupsLangPuts(stderr
, NULL
,
446 _("lp: Expected character set after -S option!\n"));
451 _cupsLangPuts(stderr
, NULL
,
452 _("lp: Warning - character set option ignored!\n"));
455 case 'T' : /* Content-Type */
462 _cupsLangPuts(stderr
, NULL
,
463 _("lp: Expected content type after -T option!\n"));
468 _cupsLangPuts(stderr
, NULL
,
469 _("lp: Warning - content type option ignored!\n"));
473 _cupsLangPrintf(stderr
, NULL
, _("lp: Unknown option \'%c\'!\n"),
477 else if (!strcmp(argv
[i
], "-"))
479 if (num_files
|| job_id
)
481 _cupsLangPuts(stderr
, NULL
,
482 _("lp: Error - cannot print from stdin if files or a "
483 "job ID are provided!\n"));
489 else if (num_files
< 1000 && job_id
== 0)
495 if (access(argv
[i
], R_OK
) != 0)
497 _cupsLangPrintf(stderr
, NULL
, _("lp: Unable to access \"%s\" - %s\n"),
498 argv
[i
], strerror(errno
));
502 files
[num_files
] = argv
[i
];
507 if ((title
= strrchr(argv
[i
], '/')) != NULL
)
514 _cupsLangPrintf(stderr
, NULL
, _("lp: Too many files - \"%s\"\n"),
518 * See if we are altering an existing job...
522 return (set_job_attrs(job_id
, num_options
, options
));
525 * See if we have any files to print; if not, print from stdin...
531 num_dests
= cupsGetDests(&dests
);
533 if ((dest
= cupsGetDest(NULL
, NULL
, num_dests
, dests
)) != NULL
)
535 printer
= dest
->name
;
537 for (j
= 0; j
< dest
->num_options
; j
++)
538 if (cupsGetOption(dest
->options
[j
].name
, num_options
, options
) == NULL
)
539 num_options
= cupsAddOption(dest
->options
[j
].name
,
540 dest
->options
[j
].value
,
541 num_options
, &options
);
549 if ((printer
= getenv("LPDEST")) == NULL
)
551 if ((printer
= getenv("PRINTER")) != NULL
)
553 if (!strcmp(printer
, "lp"))
562 if (printer
&& !cupsGetDest(printer
, NULL
, num_dests
, dests
))
563 _cupsLangPrintf(stderr
, NULL
,
564 _("lp: error - %s environment variable names "
565 "non-existent destination \"%s\"!\n"),
567 else if (cupsLastError() == IPP_NOT_FOUND
)
568 _cupsLangPuts(stderr
, NULL
,
569 _("lp: error - no default destination available.\n"));
571 _cupsLangPuts(stderr
, NULL
,
572 _("lp: error - scheduler not responding!\n"));
578 job_id
= cupsPrintFiles(printer
, num_files
, files
, title
, num_options
, options
);
584 # if defined(HAVE_SIGSET)
585 sigset(SIGHUP
, sighandler
);
586 if (sigset(SIGINT
, sighandler
) == SIG_IGN
)
587 sigset(SIGINT
, SIG_IGN
);
588 sigset(SIGTERM
, sighandler
);
589 # elif defined(HAVE_SIGACTION)
590 memset(&action
, 0, sizeof(action
));
591 action
.sa_handler
= sighandler
;
593 sigaction(SIGHUP
, &action
, NULL
);
594 sigaction(SIGINT
, NULL
, &oldaction
);
595 if (oldaction
.sa_handler
!= SIG_IGN
)
596 sigaction(SIGINT
, &action
, NULL
);
597 sigaction(SIGTERM
, &action
, NULL
);
599 signal(SIGHUP
, sighandler
);
600 if (signal(SIGINT
, sighandler
) == SIG_IGN
)
601 signal(SIGINT
, SIG_IGN
);
602 signal(SIGTERM
, sighandler
);
606 temp
= cupsTempFd(tempfile
, sizeof(tempfile
));
610 _cupsLangPrintf(stderr
, NULL
,
611 _("lp: unable to create temporary file \"%s\" - %s\n"),
612 tempfile
, strerror(errno
));
616 while ((i
= read(0, buffer
, sizeof(buffer
))) > 0)
617 if (write(temp
, buffer
, i
) < 0)
619 _cupsLangPrintf(stderr
, NULL
,
620 _("lp: error - unable to write to temporary file "
622 tempfile
, strerror(errno
));
628 i
= lseek(temp
, 0, SEEK_CUR
);
633 _cupsLangPuts(stderr
, NULL
,
634 _("lp: stdin is empty, so no job has been sent.\n"));
640 job_id
= cupsPrintFile(printer
, tempfile
, title
, num_options
, options
);
642 job_id
= cupsPrintFile(printer
, tempfile
, "(stdin)", num_options
, options
);
649 _cupsLangPrintf(stderr
, NULL
,
650 _("lp: unable to print file: %s\n"),
651 ippErrorString(cupsLastError()));
655 _cupsLangPrintf(stdout
, NULL
,
656 _("request id is %s-%d (%d file(s))\n"),
657 printer
, job_id
, num_files
);
664 * 'restart_job()' - Restart a job.
667 int /* O - Exit status */
668 restart_job(int job_id
) /* I - Job ID */
670 http_t
*http
; /* HTTP connection to server */
671 ipp_t
*request
, /* IPP request */
672 *response
; /* IPP response */
673 cups_lang_t
*language
; /* Language for request */
674 char uri
[HTTP_MAX_URI
]; /* URI for job */
677 http
= httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption());
679 language
= cupsLangDefault();
682 request
->request
.op
.operation_id
= IPP_RESTART_JOB
;
683 request
->request
.op
.request_id
= 1;
685 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_CHARSET
,
686 "attributes-charset", NULL
, cupsLangEncoding(language
));
688 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_LANGUAGE
,
689 "attributes-natural-language", NULL
, language
->language
);
691 sprintf(uri
, "ipp://localhost/jobs/%d", job_id
);
693 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
694 "job-uri", NULL
, uri
);
696 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_NAME
,
697 "requesting-user-name", NULL
, cupsUser());
699 if ((response
= cupsDoRequest(http
, request
, "/jobs")) != NULL
)
701 if (response
->request
.status
.status_code
> IPP_OK_CONFLICT
)
703 _cupsLangPrintf(stderr
, NULL
, _("lp: restart-job failed: %s\n"),
704 ippErrorString(response
->request
.status
.status_code
));
713 _cupsLangPrintf(stderr
, NULL
, _("lp: restart-job failed: %s\n"),
714 ippErrorString(cupsLastError()));
723 * 'set_job_attrs()' - Set job attributes.
726 int /* O - Exit status */
727 set_job_attrs(int job_id
, /* I - Job ID */
728 int num_options
,/* I - Number of options */
729 cups_option_t
*options
) /* I - Options */
731 http_t
*http
; /* HTTP connection to server */
732 ipp_t
*request
, /* IPP request */
733 *response
; /* IPP response */
734 cups_lang_t
*language
; /* Language for request */
735 char uri
[HTTP_MAX_URI
]; /* URI for job */
738 if (num_options
== 0)
741 http
= httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption());
743 language
= cupsLangDefault();
746 request
->request
.op
.operation_id
= IPP_SET_JOB_ATTRIBUTES
;
747 request
->request
.op
.request_id
= 1;
749 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_CHARSET
,
750 "attributes-charset", NULL
, cupsLangEncoding(language
));
752 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_LANGUAGE
,
753 "attributes-natural-language", NULL
, language
->language
);
755 sprintf(uri
, "ipp://localhost/jobs/%d", job_id
);
757 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
,
758 "job-uri", NULL
, uri
);
760 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_NAME
,
761 "requesting-user-name", NULL
, cupsUser());
763 cupsEncodeOptions(request
, num_options
, options
);
765 if ((response
= cupsDoRequest(http
, request
, "/jobs")) != NULL
)
767 if (response
->request
.status
.status_code
> IPP_OK_CONFLICT
)
769 _cupsLangPrintf(stderr
, NULL
, _("lp: set-job-attributes failed: %s\n"),
770 ippErrorString(response
->request
.status
.status_code
));
779 _cupsLangPrintf(stderr
, NULL
, _("lp: set-job-attributes failed: %s\n"),
780 ippErrorString(cupsLastError()));
790 * 'sighandler()' - Signal catcher for when we print from stdin...
794 sighandler(int s
) /* I - Signal number */
797 * Remove the temporary file we're using to print from stdin...
812 * End of "$Id: lp.c 4906 2006-01-10 20:53:28Z mike $".