Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
srohatgi01
GitHub Repository: srohatgi01/cups
Path: blob/master/backend/lpd.c
1090 views
1
/*
2
* Line Printer Daemon backend for CUPS.
3
*
4
* Copyright © 2007-2019 by Apple Inc.
5
* Copyright © 1997-2007 by Easy Software Products, all rights reserved.
6
*
7
* Licensed under Apache License v2.0. See the file "LICENSE" for more
8
* information.
9
*/
10
11
/*
12
* Include necessary headers.
13
*/
14
15
#include <cups/http-private.h>
16
#include "backend-private.h"
17
#include <stdarg.h>
18
#include <sys/types.h>
19
#include <sys/stat.h>
20
#include <stdio.h>
21
22
#ifdef _WIN32
23
# include <winsock.h>
24
#else
25
# include <sys/socket.h>
26
# include <netinet/in.h>
27
# include <arpa/inet.h>
28
# include <netdb.h>
29
#endif /* _WIN32 */
30
#ifdef __APPLE__
31
# include <CoreFoundation/CFNumber.h>
32
# include <CoreFoundation/CFPreferences.h>
33
#endif /* __APPLE__ */
34
35
36
/*
37
* Globals...
38
*/
39
40
static char tmpfilename[1024] = ""; /* Temporary spool file name */
41
static int abort_job = 0; /* Non-zero if we get SIGTERM */
42
43
44
/*
45
* Print mode...
46
*/
47
48
#define MODE_STANDARD 0 /* Queue a copy */
49
#define MODE_STREAM 1 /* Stream a copy */
50
51
52
/*
53
* The order for control and data files in LPD requests...
54
*/
55
56
#define ORDER_CONTROL_DATA 0 /* Control file first, then data */
57
#define ORDER_DATA_CONTROL 1 /* Data file first, then control */
58
59
60
/*
61
* What to reserve...
62
*/
63
64
#define RESERVE_NONE 0 /* Don't reserve a privileged port */
65
#define RESERVE_RFC1179 1 /* Reserve port 721-731 */
66
#define RESERVE_ANY 2 /* Reserve port 1-1023 */
67
68
69
/*
70
* Local functions...
71
*/
72
73
static int cups_rresvport(int *port, int family);
74
static int lpd_command(int lpd_fd, char *format, ...)
75
# ifdef __GNUC__
76
__attribute__ ((__format__ (__printf__, 2, 3)))
77
# endif /* __GNUC__ */
78
;
79
static int lpd_queue(const char *hostname, http_addrlist_t *addrlist, const char *printer, int print_fd, int snmp_fd, int mode, const char *user, const char *title, int copies, int banner, int format, int order, int reserve, int manual_copies, int timeout, int contimeout, const char *orighost) _CUPS_NONNULL((1,2,3,7,8,17));
80
static ssize_t lpd_write(int lpd_fd, char *buffer, size_t length);
81
static void sigterm_handler(int sig);
82
83
84
/*
85
* 'main()' - Send a file to the printer or server.
86
*
87
* Usage:
88
*
89
* printer-uri job-id user title copies options [file]
90
*/
91
92
int /* O - Exit status */
93
main(int argc, /* I - Number of command-line arguments (6 or 7) */
94
char *argv[]) /* I - Command-line arguments */
95
{
96
const char *device_uri; /* Device URI */
97
char scheme[255], /* Scheme in URI */
98
hostname[1024], /* Hostname */
99
username[255], /* Username info */
100
resource[1024], /* Resource info (printer name) */
101
*options, /* Pointer to options */
102
*name, /* Name of option */
103
*value, /* Value of option */
104
sep, /* Separator character */
105
title[256]; /* Title string */
106
int port; /* Port number */
107
http_addrlist_t *addrlist; /* List of addresses for printer */
108
int snmp_enabled = 1; /* Is SNMP enabled? */
109
int snmp_fd; /* SNMP socket */
110
int fd; /* Print file */
111
int status; /* Status of LPD job */
112
int mode; /* Print mode */
113
int banner; /* Print banner page? */
114
int format; /* Print format */
115
int order; /* Order of control/data files */
116
int reserve; /* Reserve privileged port? */
117
int sanitize_title; /* Sanitize title string? */
118
int manual_copies, /* Do manual copies? */
119
timeout, /* Timeout */
120
contimeout, /* Connection timeout */
121
copies; /* Number of copies */
122
ssize_t bytes = 0; /* Initial bytes read */
123
char buffer[16384]; /* Initial print buffer */
124
#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
125
struct sigaction action; /* Actions for POSIX signals */
126
#endif /* HAVE_SIGACTION && !HAVE_SIGSET */
127
int num_jobopts; /* Number of job options */
128
cups_option_t *jobopts = NULL; /* Job options */
129
130
131
/*
132
* Make sure status messages are not buffered...
133
*/
134
135
setbuf(stderr, NULL);
136
137
/*
138
* Ignore SIGPIPE and catch SIGTERM signals...
139
*/
140
141
#ifdef HAVE_SIGSET
142
sigset(SIGPIPE, SIG_IGN);
143
sigset(SIGTERM, sigterm_handler);
144
#elif defined(HAVE_SIGACTION)
145
memset(&action, 0, sizeof(action));
146
action.sa_handler = SIG_IGN;
147
sigaction(SIGPIPE, &action, NULL);
148
149
sigemptyset(&action.sa_mask);
150
sigaddset(&action.sa_mask, SIGTERM);
151
action.sa_handler = sigterm_handler;
152
sigaction(SIGTERM, &action, NULL);
153
#else
154
signal(SIGPIPE, SIG_IGN);
155
signal(SIGTERM, sigterm_handler);
156
#endif /* HAVE_SIGSET */
157
158
/*
159
* Check command-line...
160
*/
161
162
if (argc == 1)
163
{
164
printf("network lpd \"Unknown\" \"%s\"\n",
165
_cupsLangString(cupsLangDefault(), _("LPD/LPR Host or Printer")));
166
return (CUPS_BACKEND_OK);
167
}
168
else if (argc < 6 || argc > 7)
169
{
170
_cupsLangPrintf(stderr,
171
_("Usage: %s job-id user title copies options [file]"),
172
argv[0]);
173
return (CUPS_BACKEND_FAILED);
174
}
175
176
num_jobopts = cupsParseOptions(argv[5], 0, &jobopts);
177
178
/*
179
* Extract the hostname and printer name from the URI...
180
*/
181
182
while ((device_uri = cupsBackendDeviceURI(argv)) == NULL)
183
{
184
_cupsLangPrintFilter(stderr, "INFO", _("Unable to locate printer."));
185
sleep(10);
186
187
if (getenv("CLASS") != NULL)
188
return (CUPS_BACKEND_FAILED);
189
}
190
191
httpSeparateURI(HTTP_URI_CODING_ALL, device_uri, scheme, sizeof(scheme),
192
username, sizeof(username), hostname, sizeof(hostname), &port,
193
resource, sizeof(resource));
194
195
if (!port)
196
port = 515; /* Default to port 515 */
197
198
if (!username[0])
199
{
200
/*
201
* If no username is in the device URI, then use the print job user...
202
*/
203
204
strlcpy(username, argv[2], sizeof(username));
205
}
206
207
/*
208
* See if there are any options...
209
*/
210
211
mode = MODE_STANDARD;
212
banner = 0;
213
format = 'l';
214
order = ORDER_CONTROL_DATA;
215
reserve = RESERVE_ANY;
216
manual_copies = 1;
217
timeout = 300;
218
contimeout = 7 * 24 * 60 * 60;
219
220
#ifdef __APPLE__
221
/*
222
* We want to pass UTF-8 characters by default, not re-map them (3071945)
223
*/
224
225
sanitize_title = 0;
226
#else
227
/*
228
* Otherwise we want to re-map UTF-8 to "safe" characters by default...
229
*/
230
231
sanitize_title = 1;
232
#endif /* __APPLE__ */
233
234
if ((options = strchr(resource, '?')) != NULL)
235
{
236
/*
237
* Yup, terminate the device name string and move to the first
238
* character of the options...
239
*/
240
241
*options++ = '\0';
242
243
/*
244
* Parse options...
245
*/
246
247
while (*options)
248
{
249
/*
250
* Get the name...
251
*/
252
253
name = options;
254
255
while (*options && *options != '=' && *options != '+' && *options != '&')
256
options ++;
257
258
if ((sep = *options) != '\0')
259
*options++ = '\0';
260
261
if (sep == '=')
262
{
263
/*
264
* Get the value...
265
*/
266
267
value = options;
268
269
while (*options && *options != '+' && *options != '&')
270
options ++;
271
272
if (*options)
273
*options++ = '\0';
274
}
275
else
276
value = (char *)"";
277
278
/*
279
* Process the option...
280
*/
281
282
if (!_cups_strcasecmp(name, "banner"))
283
{
284
/*
285
* Set the banner...
286
*/
287
288
banner = !value[0] || !_cups_strcasecmp(value, "on") ||
289
!_cups_strcasecmp(value, "yes") || !_cups_strcasecmp(value, "true");
290
}
291
else if (!_cups_strcasecmp(name, "format") && value[0])
292
{
293
/*
294
* Set output format...
295
*/
296
297
if (strchr("cdfglnoprtv", value[0]))
298
format = value[0];
299
else
300
_cupsLangPrintFilter(stderr, "ERROR",
301
_("Unknown format character: \"%c\"."),
302
value[0]);
303
}
304
else if (!_cups_strcasecmp(name, "mode") && value[0])
305
{
306
/*
307
* Set control/data order...
308
*/
309
310
if (!_cups_strcasecmp(value, "standard"))
311
mode = MODE_STANDARD;
312
else if (!_cups_strcasecmp(value, "stream"))
313
mode = MODE_STREAM;
314
else
315
_cupsLangPrintFilter(stderr, "ERROR",
316
_("Unknown print mode: \"%s\"."), value);
317
}
318
else if (!_cups_strcasecmp(name, "order") && value[0])
319
{
320
/*
321
* Set control/data order...
322
*/
323
324
if (!_cups_strcasecmp(value, "control,data"))
325
order = ORDER_CONTROL_DATA;
326
else if (!_cups_strcasecmp(value, "data,control"))
327
order = ORDER_DATA_CONTROL;
328
else
329
_cupsLangPrintFilter(stderr, "ERROR",
330
_("Unknown file order: \"%s\"."), value);
331
}
332
else if (!_cups_strcasecmp(name, "reserve"))
333
{
334
/*
335
* Set port reservation mode...
336
*/
337
338
if (!value[0] || !_cups_strcasecmp(value, "on") ||
339
!_cups_strcasecmp(value, "yes") ||
340
!_cups_strcasecmp(value, "true") ||
341
!_cups_strcasecmp(value, "rfc1179"))
342
reserve = RESERVE_RFC1179;
343
else if (!_cups_strcasecmp(value, "any"))
344
reserve = RESERVE_ANY;
345
else
346
reserve = RESERVE_NONE;
347
}
348
else if (!_cups_strcasecmp(name, "manual_copies"))
349
{
350
/*
351
* Set manual copies...
352
*/
353
354
manual_copies = !value[0] || !_cups_strcasecmp(value, "on") ||
355
!_cups_strcasecmp(value, "yes") ||
356
!_cups_strcasecmp(value, "true");
357
}
358
else if (!_cups_strcasecmp(name, "sanitize_title"))
359
{
360
/*
361
* Set sanitize title...
362
*/
363
364
sanitize_title = !value[0] || !_cups_strcasecmp(value, "on") ||
365
!_cups_strcasecmp(value, "yes") ||
366
!_cups_strcasecmp(value, "true");
367
}
368
else if (!_cups_strcasecmp(name, "snmp"))
369
{
370
/*
371
* Enable/disable SNMP stuff...
372
*/
373
374
snmp_enabled = !value[0] || !_cups_strcasecmp(value, "on") ||
375
!_cups_strcasecmp(value, "yes") ||
376
!_cups_strcasecmp(value, "true");
377
}
378
else if (!_cups_strcasecmp(name, "timeout"))
379
{
380
/*
381
* Set the timeout...
382
*/
383
384
if (atoi(value) > 0)
385
timeout = atoi(value);
386
}
387
else if (!_cups_strcasecmp(name, "contimeout"))
388
{
389
/*
390
* Set the connection timeout...
391
*/
392
393
if (atoi(value) > 0)
394
contimeout = atoi(value);
395
}
396
}
397
}
398
399
if (mode == MODE_STREAM)
400
order = ORDER_CONTROL_DATA;
401
402
/*
403
* Find the printer...
404
*/
405
406
addrlist = backendLookup(hostname, port, NULL);
407
408
/*
409
* See if the printer supports SNMP...
410
*/
411
412
if (snmp_enabled)
413
snmp_fd = _cupsSNMPOpen(addrlist->addr.addr.sa_family);
414
else
415
snmp_fd = -1;
416
417
/*
418
* Wait for data from the filter...
419
*/
420
421
if (argc == 6)
422
{
423
if (!backendWaitLoop(snmp_fd, &(addrlist->addr), 0, backendNetworkSideCB))
424
return (CUPS_BACKEND_OK);
425
else if (mode == MODE_STANDARD &&
426
(bytes = read(0, buffer, sizeof(buffer))) <= 0)
427
return (CUPS_BACKEND_OK);
428
}
429
430
/*
431
* If we have 7 arguments, print the file named on the command-line.
432
* Otherwise, copy stdin to a temporary file and print the temporary
433
* file.
434
*/
435
436
if (argc == 6 && mode == MODE_STANDARD)
437
{
438
/*
439
* Copy stdin to a temporary file...
440
*/
441
442
if ((fd = cupsTempFd(tmpfilename, sizeof(tmpfilename))) < 0)
443
{
444
perror("DEBUG: Unable to create temporary file");
445
return (CUPS_BACKEND_FAILED);
446
}
447
448
_cupsLangPrintFilter(stderr, "INFO", _("Copying print data."));
449
450
if (bytes > 0)
451
write(fd, buffer, (size_t)bytes);
452
453
backendRunLoop(-1, fd, snmp_fd, &(addrlist->addr), 0, 0,
454
backendNetworkSideCB);
455
}
456
else if (argc == 6)
457
{
458
/*
459
* Stream from stdin...
460
*/
461
462
fd = 0;
463
}
464
else
465
{
466
fd = open(argv[6], O_RDONLY);
467
468
if (fd == -1)
469
{
470
_cupsLangPrintError("ERROR", _("Unable to open print file"));
471
return (CUPS_BACKEND_FAILED);
472
}
473
}
474
475
/*
476
* Sanitize the document title...
477
*/
478
479
strlcpy(title, argv[3], sizeof(title));
480
481
if (sanitize_title)
482
{
483
/*
484
* Sanitize the title string so that we don't cause problems on
485
* the remote end...
486
*/
487
488
char *ptr;
489
490
for (ptr = title; *ptr; ptr ++)
491
if (!isalnum(*ptr & 255) && !isspace(*ptr & 255))
492
*ptr = '_';
493
}
494
495
/*
496
* Queue the job...
497
*/
498
499
if (argc > 6)
500
{
501
if (manual_copies)
502
{
503
manual_copies = atoi(argv[4]);
504
copies = 1;
505
}
506
else
507
{
508
manual_copies = 1;
509
copies = atoi(argv[4]);
510
}
511
512
status = lpd_queue(hostname, addrlist, resource + 1, fd, snmp_fd, mode,
513
username, title, copies, banner, format, order, reserve,
514
manual_copies, timeout, contimeout,
515
cupsGetOption("job-originating-host-name", num_jobopts,
516
jobopts));
517
518
if (!status)
519
fprintf(stderr, "PAGE: 1 %d\n", atoi(argv[4]));
520
}
521
else
522
status = lpd_queue(hostname, addrlist, resource + 1, fd, snmp_fd, mode,
523
username, title, 1, banner, format, order, reserve, 1,
524
timeout, contimeout,
525
cupsGetOption("job-originating-host-name", num_jobopts,
526
jobopts));
527
528
/*
529
* Remove the temporary file if necessary...
530
*/
531
532
if (tmpfilename[0])
533
unlink(tmpfilename);
534
535
if (fd)
536
close(fd);
537
538
if (snmp_fd >= 0)
539
_cupsSNMPClose(snmp_fd);
540
541
/*
542
* Return the queue status...
543
*/
544
545
return (status);
546
}
547
548
549
/*
550
* 'cups_rresvport()' - A simple implementation of rresvport_af().
551
*/
552
553
static int /* O - Socket or -1 on error */
554
cups_rresvport(int *port, /* IO - Port number to bind to */
555
int family) /* I - Address family */
556
{
557
http_addr_t addr; /* Socket address */
558
int fd; /* Socket file descriptor */
559
560
561
/*
562
* Try to create an IPv4 socket...
563
*/
564
565
if ((fd = socket(family, SOCK_STREAM, 0)) < 0)
566
return (-1);
567
568
/*
569
* Initialize the address buffer...
570
*/
571
572
memset(&addr, 0, sizeof(addr));
573
addr.addr.sa_family = (sa_family_t)family;
574
575
/*
576
* Try to bind the socket to a reserved port...
577
*/
578
579
while (*port > 511)
580
{
581
/*
582
* Set the port number...
583
*/
584
585
_httpAddrSetPort(&addr, *port);
586
587
/*
588
* Try binding the port to the socket; return if all is OK...
589
*/
590
591
if (!bind(fd, (struct sockaddr *)&addr, (socklen_t)httpAddrLength(&addr)))
592
return (fd);
593
594
/*
595
* Stop if we have any error other than "address already in use"...
596
*/
597
598
if (errno != EADDRINUSE)
599
{
600
httpAddrClose(NULL, fd);
601
602
return (-1);
603
}
604
605
/*
606
* Try the next port...
607
*/
608
609
(*port)--;
610
}
611
612
/*
613
* Wasn't able to bind to a reserved port, so close the socket and return
614
* -1...
615
*/
616
617
#ifdef _WIN32
618
closesocket(fd);
619
#else
620
close(fd);
621
#endif /* _WIN32 */
622
623
return (-1);
624
}
625
626
627
/*
628
* 'lpd_command()' - Send an LPR command sequence and wait for a reply.
629
*/
630
631
static int /* O - Status of command */
632
lpd_command(int fd, /* I - Socket connection to LPD host */
633
char *format, /* I - printf()-style format string */
634
...) /* I - Additional args as necessary */
635
{
636
va_list ap; /* Argument pointer */
637
char buf[1024]; /* Output buffer */
638
ssize_t bytes; /* Number of bytes to output */
639
char status; /* Status from command */
640
641
642
/*
643
* Don't try to send commands if the job has been canceled...
644
*/
645
646
if (abort_job)
647
return (-1);
648
649
/*
650
* Format the string...
651
*/
652
653
va_start(ap, format);
654
bytes = vsnprintf(buf, sizeof(buf), format, ap);
655
va_end(ap);
656
657
fprintf(stderr, "DEBUG: lpd_command %2.2x %s", buf[0], buf + 1);
658
659
/*
660
* Send the command...
661
*/
662
663
fprintf(stderr, "DEBUG: Sending command string (" CUPS_LLFMT " bytes)...\n", CUPS_LLCAST bytes);
664
665
if (lpd_write(fd, buf, (size_t)bytes) < bytes)
666
{
667
perror("DEBUG: Unable to send LPD command");
668
return (-1);
669
}
670
671
/*
672
* Read back the status from the command and return it...
673
*/
674
675
fputs("DEBUG: Reading command status...\n", stderr);
676
677
if (recv(fd, &status, 1, 0) < 1)
678
{
679
_cupsLangPrintFilter(stderr, "WARNING", _("The printer did not respond."));
680
status = (char)errno;
681
}
682
683
fprintf(stderr, "DEBUG: lpd_command returning %d\n", status);
684
685
return (status);
686
}
687
688
689
/*
690
* 'lpd_queue()' - Queue a file using the Line Printer Daemon protocol.
691
*/
692
693
static int /* O - Zero on success, non-zero on failure */
694
lpd_queue(const char *hostname, /* I - Host to connect to */
695
http_addrlist_t *addrlist, /* I - List of host addresses */
696
const char *printer, /* I - Printer/queue name */
697
int print_fd, /* I - File to print */
698
int snmp_fd, /* I - SNMP socket */
699
int mode, /* I - Print mode */
700
const char *user, /* I - Requesting user */
701
const char *title, /* I - Job title */
702
int copies, /* I - Number of copies */
703
int banner, /* I - Print LPD banner? */
704
int format, /* I - Format specifier */
705
int order, /* I - Order of data/control files */
706
int reserve, /* I - Reserve ports? */
707
int manual_copies,/* I - Do copies by hand... */
708
int timeout, /* I - Timeout... */
709
int contimeout, /* I - Connection timeout */
710
const char *orighost) /* I - job-originating-host-name */
711
{
712
char localhost[255]; /* Local host name */
713
int error; /* Error number */
714
struct stat filestats; /* File statistics */
715
int lport; /* LPD connection local port */
716
int fd; /* LPD socket */
717
char control[10240], /* LPD control 'file' */
718
*cptr; /* Pointer into control file string */
719
char status; /* Status byte from command */
720
int delay; /* Delay for retries... */
721
char addrname[256]; /* Address name */
722
http_addrlist_t *addr; /* Socket address */
723
int have_supplies; /* Printer supports supply levels? */
724
int copy; /* Copies written */
725
time_t start_time; /* Time of first connect */
726
ssize_t nbytes; /* Number of bytes written */
727
off_t tbytes; /* Total bytes written */
728
char buffer[32768]; /* Output buffer */
729
#ifdef _WIN32
730
DWORD tv; /* Timeout in milliseconds */
731
#else
732
struct timeval tv; /* Timeout in secs and usecs */
733
#endif /* _WIN32 */
734
735
736
/*
737
* Remember when we started trying to connect to the printer...
738
*/
739
740
start_time = time(NULL);
741
742
/*
743
* Loop forever trying to print the file...
744
*/
745
746
while (!abort_job)
747
{
748
/*
749
* First try to reserve a port for this connection...
750
*/
751
752
fprintf(stderr, "DEBUG: Connecting to %s:%d for printer %s\n", hostname,
753
httpAddrPort(&(addrlist->addr)), printer);
754
_cupsLangPrintFilter(stderr, "INFO", _("Connecting to printer."));
755
756
for (lport = reserve == RESERVE_RFC1179 ? 732 : 1024, addr = addrlist,
757
delay = 5;;
758
addr = addr->next)
759
{
760
/*
761
* Stop if this job has been canceled...
762
*/
763
764
if (abort_job)
765
return (CUPS_BACKEND_FAILED);
766
767
/*
768
* Choose the next privileged port...
769
*/
770
771
if (!addr)
772
addr = addrlist;
773
774
lport --;
775
776
if (lport < 721 && reserve == RESERVE_RFC1179)
777
lport = 731;
778
else if (lport < 1)
779
lport = 1023;
780
781
#ifdef HAVE_GETEUID
782
if (geteuid() || !reserve)
783
#else
784
if (getuid() || !reserve)
785
#endif /* HAVE_GETEUID */
786
{
787
/*
788
* Just create a regular socket...
789
*/
790
791
if ((fd = socket(addr->addr.addr.sa_family, SOCK_STREAM, 0)) < 0)
792
{
793
perror("DEBUG: Unable to create socket");
794
sleep(1);
795
796
continue;
797
}
798
799
lport = 0;
800
}
801
else
802
{
803
/*
804
* We're running as root and want to comply with RFC 1179. Reserve a
805
* privileged lport between 721 and 731...
806
*/
807
808
if ((fd = cups_rresvport(&lport, addr->addr.addr.sa_family)) < 0)
809
{
810
perror("DEBUG: Unable to reserve port");
811
sleep(1);
812
813
continue;
814
}
815
}
816
817
/*
818
* Connect to the printer or server...
819
*/
820
821
if (abort_job)
822
{
823
close(fd);
824
825
return (CUPS_BACKEND_FAILED);
826
}
827
828
if (!connect(fd, &(addr->addr.addr), (socklen_t)httpAddrLength(&(addr->addr))))
829
break;
830
831
error = errno;
832
close(fd);
833
834
if (addr->next)
835
continue;
836
837
if (getenv("CLASS") != NULL)
838
{
839
/*
840
* If the CLASS environment variable is set, the job was submitted
841
* to a class and not to a specific queue. In this case, we want
842
* to abort immediately so that the job can be requeued on the next
843
* available printer in the class.
844
*/
845
846
_cupsLangPrintFilter(stderr, "INFO",
847
_("Unable to contact printer, queuing on next "
848
"printer in class."));
849
850
/*
851
* Sleep 5 seconds to keep the job from requeuing too rapidly...
852
*/
853
854
sleep(5);
855
856
return (CUPS_BACKEND_FAILED);
857
}
858
859
fprintf(stderr, "DEBUG: Connection error: %s\n", strerror(error));
860
861
if (errno == ECONNREFUSED || errno == EHOSTDOWN || errno == EHOSTUNREACH || errno == ETIMEDOUT || errno == ENOTCONN)
862
{
863
if (contimeout && (time(NULL) - start_time) > contimeout)
864
{
865
_cupsLangPrintFilter(stderr, "ERROR",
866
_("The printer is not responding."));
867
return (CUPS_BACKEND_FAILED);
868
}
869
870
switch (error)
871
{
872
case EHOSTDOWN :
873
_cupsLangPrintFilter(stderr, "WARNING",
874
_("The printer may not exist or "
875
"is unavailable at this time."));
876
break;
877
878
case EHOSTUNREACH :
879
default :
880
_cupsLangPrintFilter(stderr, "WARNING",
881
_("The printer is unreachable at "
882
"this time."));
883
break;
884
885
case ECONNREFUSED :
886
_cupsLangPrintFilter(stderr, "WARNING",
887
_("The printer is in use."));
888
break;
889
}
890
891
sleep((unsigned)delay);
892
893
if (delay < 30)
894
delay += 5;
895
}
896
else if (error == EADDRINUSE)
897
{
898
/*
899
* Try on another port...
900
*/
901
902
sleep(1);
903
}
904
else
905
{
906
_cupsLangPrintFilter(stderr, "ERROR",
907
_("The printer is not responding."));
908
sleep(30);
909
}
910
}
911
912
/*
913
* Set the timeout...
914
*/
915
916
#ifdef _WIN32
917
tv = (DWORD)(timeout * 1000);
918
919
setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(tv));
920
setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, (char *)&tv, sizeof(tv));
921
#else
922
tv.tv_sec = timeout;
923
tv.tv_usec = 0;
924
925
setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
926
setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv));
927
#endif /* _WIN32 */
928
929
fputs("STATE: -connecting-to-device\n", stderr);
930
_cupsLangPrintFilter(stderr, "INFO", _("Connected to printer."));
931
932
fprintf(stderr, "DEBUG: Connected to %s:%d (local port %d)...\n",
933
httpAddrString(&(addr->addr), addrname, sizeof(addrname)),
934
httpAddrPort(&(addr->addr)), lport);
935
936
/*
937
* See if the printer supports SNMP...
938
*/
939
940
if (snmp_fd >= 0)
941
have_supplies = !backendSNMPSupplies(snmp_fd, &(addrlist->addr), NULL,
942
NULL);
943
else
944
have_supplies = 0;
945
946
/*
947
* Check for side-channel requests...
948
*/
949
950
backendCheckSideChannel(snmp_fd, &(addrlist->addr));
951
952
/*
953
* Next, open the print file and figure out its size...
954
*/
955
956
if (print_fd)
957
{
958
/*
959
* Use the size from the print file...
960
*/
961
962
if (fstat(print_fd, &filestats))
963
{
964
close(fd);
965
966
perror("DEBUG: unable to stat print file");
967
return (CUPS_BACKEND_FAILED);
968
}
969
970
filestats.st_size *= manual_copies;
971
}
972
else
973
{
974
/*
975
* Use a "very large value" for the size so that the printer will
976
* keep printing until we close the connection...
977
*/
978
979
#ifdef _LARGEFILE_SOURCE
980
filestats.st_size = (size_t)(999999999999.0);
981
#else
982
filestats.st_size = 2147483647;
983
#endif /* _LARGEFILE_SOURCE */
984
}
985
986
/*
987
* Send a job header to the printer, specifying no banner page and
988
* literal output...
989
*/
990
991
if (lpd_command(fd, "\002%s\n",
992
printer)) /* Receive print job(s) */
993
{
994
close(fd);
995
return (CUPS_BACKEND_FAILED);
996
}
997
998
if (orighost && _cups_strcasecmp(orighost, "localhost"))
999
strlcpy(localhost, orighost, sizeof(localhost));
1000
else
1001
httpGetHostname(NULL, localhost, sizeof(localhost));
1002
1003
snprintf(control, sizeof(control),
1004
"H%.31s\n" /* RFC 1179, Section 7.2 - host name <= 31 chars */
1005
"P%.31s\n" /* RFC 1179, Section 7.2 - user name <= 31 chars */
1006
"J%.99s\n", /* RFC 1179, Section 7.2 - job name <= 99 chars */
1007
localhost, user, title);
1008
cptr = control + strlen(control);
1009
1010
if (banner)
1011
{
1012
snprintf(cptr, sizeof(control) - (size_t)(cptr - control),
1013
"C%.31s\n" /* RFC 1179, Section 7.2 - class name <= 31 chars */
1014
"L%s\n",
1015
localhost, user);
1016
cptr += strlen(cptr);
1017
}
1018
1019
while (copies > 0)
1020
{
1021
snprintf(cptr, sizeof(control) - (size_t)(cptr - control), "%cdfA%03d%.15s\n",
1022
format, (int)getpid() % 1000, localhost);
1023
cptr += strlen(cptr);
1024
copies --;
1025
}
1026
1027
snprintf(cptr, sizeof(control) - (size_t)(cptr - control),
1028
"UdfA%03d%.15s\n"
1029
"N%.131s\n", /* RFC 1179, Section 7.2 - sourcefile name <= 131 chars */
1030
(int)getpid() % 1000, localhost, title);
1031
1032
fprintf(stderr, "DEBUG: Control file is:\n%s", control);
1033
1034
if (order == ORDER_CONTROL_DATA)
1035
{
1036
/*
1037
* Check for side-channel requests...
1038
*/
1039
1040
backendCheckSideChannel(snmp_fd, &(addr->addr));
1041
1042
/*
1043
* Send the control file...
1044
*/
1045
1046
if (lpd_command(fd, "\002%d cfA%03d%.15s\n", (int)strlen(control),
1047
(int)getpid() % 1000, localhost))
1048
{
1049
close(fd);
1050
1051
return (CUPS_BACKEND_FAILED);
1052
}
1053
1054
fprintf(stderr, "DEBUG: Sending control file (%u bytes)\n",
1055
(unsigned)strlen(control));
1056
1057
if ((size_t)lpd_write(fd, control, strlen(control) + 1) < (strlen(control) + 1))
1058
{
1059
status = (char)errno;
1060
perror("DEBUG: Unable to write control file");
1061
1062
}
1063
else
1064
{
1065
if (read(fd, &status, 1) < 1)
1066
{
1067
_cupsLangPrintFilter(stderr, "WARNING",
1068
_("The printer did not respond."));
1069
status = (char)errno;
1070
}
1071
}
1072
1073
if (status != 0)
1074
_cupsLangPrintFilter(stderr, "ERROR",
1075
_("Remote host did not accept control file (%d)."),
1076
status);
1077
else
1078
_cupsLangPrintFilter(stderr, "INFO",
1079
_("Control file sent successfully."));
1080
}
1081
else
1082
status = 0;
1083
1084
if (status == 0)
1085
{
1086
/*
1087
* Check for side-channel requests...
1088
*/
1089
1090
backendCheckSideChannel(snmp_fd, &(addr->addr));
1091
1092
/*
1093
* Send the print file...
1094
*/
1095
1096
if (lpd_command(fd, "\003" CUPS_LLFMT " dfA%03d%.15s\n",
1097
CUPS_LLCAST filestats.st_size, (int)getpid() % 1000,
1098
localhost))
1099
{
1100
close(fd);
1101
1102
return (CUPS_BACKEND_FAILED);
1103
}
1104
1105
fprintf(stderr, "DEBUG: Sending data file (" CUPS_LLFMT " bytes)\n",
1106
CUPS_LLCAST filestats.st_size);
1107
1108
tbytes = 0;
1109
for (copy = 0; copy < manual_copies; copy ++)
1110
{
1111
lseek(print_fd, 0, SEEK_SET);
1112
1113
while ((nbytes = read(print_fd, buffer, sizeof(buffer))) > 0)
1114
{
1115
_cupsLangPrintFilter(stderr, "INFO",
1116
_("Spooling job, %.0f%% complete."),
1117
100.0 * tbytes / filestats.st_size);
1118
1119
if (lpd_write(fd, buffer, (size_t)nbytes) < nbytes)
1120
{
1121
perror("DEBUG: Unable to send print file to printer");
1122
break;
1123
}
1124
else
1125
tbytes += nbytes;
1126
}
1127
}
1128
1129
if (mode == MODE_STANDARD)
1130
{
1131
if (tbytes < filestats.st_size)
1132
status = (char)errno;
1133
else if (lpd_write(fd, "", 1) < 1)
1134
{
1135
perror("DEBUG: Unable to send trailing nul to printer");
1136
status = (char)errno;
1137
}
1138
else
1139
{
1140
/*
1141
* Read the status byte from the printer; if we can't read the byte
1142
* back now, we should set status to "errno", however at this point
1143
* we know the printer got the whole file and we don't necessarily
1144
* want to requeue it over and over...
1145
*/
1146
1147
if (recv(fd, &status, 1, 0) < 1)
1148
{
1149
_cupsLangPrintFilter(stderr, "WARNING",
1150
_("The printer did not respond."));
1151
status = 0;
1152
}
1153
}
1154
}
1155
else
1156
status = 0;
1157
1158
if (status != 0)
1159
_cupsLangPrintFilter(stderr, "ERROR",
1160
_("Remote host did not accept data file (%d)."),
1161
status);
1162
else
1163
_cupsLangPrintFilter(stderr, "INFO",
1164
_("Data file sent successfully."));
1165
}
1166
1167
if (status == 0 && order == ORDER_DATA_CONTROL)
1168
{
1169
/*
1170
* Check for side-channel requests...
1171
*/
1172
1173
backendCheckSideChannel(snmp_fd, &(addr->addr));
1174
1175
/*
1176
* Send control file...
1177
*/
1178
1179
if (lpd_command(fd, "\002%d cfA%03d%.15s\n", (int)strlen(control),
1180
(int)getpid() % 1000, localhost))
1181
{
1182
close(fd);
1183
1184
return (CUPS_BACKEND_FAILED);
1185
}
1186
1187
fprintf(stderr, "DEBUG: Sending control file (%lu bytes)\n",
1188
(unsigned long)strlen(control));
1189
1190
if ((size_t)lpd_write(fd, control, strlen(control) + 1) < (strlen(control) + 1))
1191
{
1192
status = (char)errno;
1193
perror("DEBUG: Unable to write control file");
1194
}
1195
else
1196
{
1197
if (read(fd, &status, 1) < 1)
1198
{
1199
_cupsLangPrintFilter(stderr, "WARNING",
1200
_("The printer did not respond."));
1201
status = (char)errno;
1202
}
1203
}
1204
1205
if (status != 0)
1206
_cupsLangPrintFilter(stderr, "ERROR",
1207
_("Remote host did not accept control file (%d)."),
1208
status);
1209
else
1210
_cupsLangPrintFilter(stderr, "INFO",
1211
_("Control file sent successfully."));
1212
}
1213
1214
fputs("STATE: +cups-waiting-for-job-completed\n", stderr);
1215
1216
/*
1217
* Collect the final supply levels as needed...
1218
*/
1219
1220
if (have_supplies)
1221
backendSNMPSupplies(snmp_fd, &(addr->addr), NULL, NULL);
1222
1223
/*
1224
* Close the socket connection and input file...
1225
*/
1226
1227
close(fd);
1228
1229
if (status == 0)
1230
return (CUPS_BACKEND_OK);
1231
1232
/*
1233
* Waiting for a retry...
1234
*/
1235
1236
sleep(30);
1237
}
1238
1239
/*
1240
* If we get here, then the job has been canceled...
1241
*/
1242
1243
return (CUPS_BACKEND_FAILED);
1244
}
1245
1246
1247
/*
1248
* 'lpd_write()' - Write a buffer of data to an LPD server.
1249
*/
1250
1251
static ssize_t /* O - Number of bytes written or -1 on error */
1252
lpd_write(int lpd_fd, /* I - LPD socket */
1253
char *buffer, /* I - Buffer to write */
1254
size_t length) /* I - Number of bytes to write */
1255
{
1256
ssize_t bytes, /* Number of bytes written */
1257
total; /* Total number of bytes written */
1258
1259
1260
if (abort_job)
1261
return (-1);
1262
1263
total = 0;
1264
while ((bytes = send(lpd_fd, buffer, length - (size_t)total, 0)) >= 0)
1265
{
1266
total += bytes;
1267
buffer += bytes;
1268
1269
if ((size_t)total == length)
1270
break;
1271
}
1272
1273
if (bytes < 0)
1274
return (-1);
1275
else
1276
return (total);
1277
}
1278
1279
1280
/*
1281
* 'sigterm_handler()' - Handle 'terminate' signals that stop the backend.
1282
*/
1283
1284
static void
1285
sigterm_handler(int sig) /* I - Signal */
1286
{
1287
(void)sig; /* remove compiler warnings... */
1288
1289
abort_job = 1;
1290
}
1291
1292