]>
git.ipfire.org Git - thirdparty/cups.git/blob - backend/socket.c
2 * "$Id: socket.c 4906 2006-01-10 20:53:28Z mike $"
4 * AppSocket backend for the Common UNIX Printing System (CUPS).
6 * Copyright 1997-2006 by Easy Software Products, all rights reserved.
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" 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
24 * This file is subject to the Apple OS-Developed Software exception.
28 * main() - Send a file to the printer or server.
32 * Include necessary headers.
35 #include <cups/backend.h>
36 #include <cups/http-private.h>
37 #include <cups/cups.h>
41 #include <cups/string.h>
43 #include <sys/types.h>
52 # include <sys/socket.h>
53 # include <netinet/in.h>
54 # include <arpa/inet.h>
60 * 'main()' - Send a file to the printer or server.
64 * printer-uri job-id user title copies options [file]
67 int /* O - Exit status */
68 main(int argc
, /* I - Number of command-line arguments (6 or 7) */
69 char *argv
[]) /* I - Command-line arguments */
71 char method
[255], /* Method in URI */
72 hostname
[1024], /* Hostname */
73 username
[255], /* Username info (not used) */
74 resource
[1024]; /* Resource info (not used) */
75 int fp
; /* Print file */
76 int copies
; /* Number of copies to print */
77 int port
; /* Port number */
78 char portname
[255]; /* Port name */
79 int delay
; /* Delay for retries... */
80 int fd
; /* AppSocket */
81 int error
; /* Error code (if any) */
82 http_addrlist_t
*addrlist
; /* Address list */
83 int rbytes
; /* Number of bytes read */
84 int wbytes
; /* Number of bytes written */
85 int nbytes
; /* Number of bytes read */
86 size_t tbytes
; /* Total number of bytes written */
87 char buffer
[8192], /* Output buffer */
88 *bufptr
; /* Pointer into buffer */
89 struct timeval timeout
; /* Timeout for select() */
90 fd_set input
, /* Input set for select() */
91 output
; /* Output set for select() */
92 #if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
93 struct sigaction action
; /* Actions for POSIX signals */
94 #endif /* HAVE_SIGACTION && !HAVE_SIGSET */
98 * Make sure status messages are not buffered...
101 setbuf(stderr
, NULL
);
104 * Ignore SIGPIPE signals...
108 sigset(SIGPIPE
, SIG_IGN
);
109 #elif defined(HAVE_SIGACTION)
110 memset(&action
, 0, sizeof(action
));
111 action
.sa_handler
= SIG_IGN
;
112 sigaction(SIGPIPE
, &action
, NULL
);
114 signal(SIGPIPE
, SIG_IGN
);
115 #endif /* HAVE_SIGSET */
118 * Check command-line...
123 puts("network socket \"Unknown\" \"AppSocket/HP JetDirect\"");
124 return (CUPS_BACKEND_OK
);
126 else if (argc
< 6 || argc
> 7)
128 fprintf(stderr
, "Usage: %s job-id user title copies options [file]\n",
130 return (CUPS_BACKEND_FAILED
);
134 * If we have 7 arguments, print the file named on the command-line.
135 * Otherwise, send stdin instead...
146 * Try to open the print file...
149 if ((fp
= open(argv
[6], O_RDONLY
)) < 0)
151 perror("ERROR: unable to open print file");
152 return (CUPS_BACKEND_FAILED
);
155 copies
= atoi(argv
[4]);
159 * Extract the hostname and port number from the URI...
162 httpSeparateURI(argv
[0], method
, sizeof(method
), username
, sizeof(username
),
163 hostname
, sizeof(hostname
), &port
,
164 resource
, sizeof(resource
));
167 port
= 9100; /* Default to HP JetDirect/Tektronix PhaserShare */
170 * Then try to connect to the remote host...
173 sprintf(portname
, "%d", port
);
175 if ((addrlist
= httpAddrGetList(hostname
, AF_UNSPEC
, portname
)) == NULL
)
177 fprintf(stderr
, "ERROR: Unable to locate printer \'%s\'!\n", hostname
);
178 return (CUPS_BACKEND_STOP
);
181 fprintf(stderr
, "INFO: Attempting to connect to host %s on port %d\n",
190 if (!httpAddrConnect(addrlist
, &fd
))
195 if (getenv("CLASS") != NULL
)
198 * If the CLASS environment variable is set, the job was submitted
199 * to a class and not to a specific queue. In this case, we want
200 * to abort immediately so that the job can be requeued on the next
201 * available printer in the class.
204 fprintf(stderr
, "INFO: Unable to connect to \"%s\", queuing on next printer in class...\n",
208 * Sleep 5 seconds to keep the job from requeuing too rapidly...
213 return (CUPS_BACKEND_FAILED
);
216 if (error
== ECONNREFUSED
|| error
== EHOSTDOWN
||
217 error
== EHOSTUNREACH
)
219 fprintf(stderr
, "INFO: Network host \'%s\' is busy; will retry in %d seconds...\n",
228 perror("ERROR: Unable to connect to printer (retrying in 30 seconds)");
237 * Now that we are "connected" to the port, ignore SIGTERM so that we
238 * can finish out any page data the driver sends (e.g. to eject the
239 * current page... Only ignore SIGTERM if we are printing data from
240 * stdin (otherwise you can't cancel raw jobs...)
245 #ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */
246 sigset(SIGTERM
, SIG_IGN
);
247 #elif defined(HAVE_SIGACTION)
248 memset(&action
, 0, sizeof(action
));
250 sigemptyset(&action
.sa_mask
);
251 action
.sa_handler
= SIG_IGN
;
252 sigaction(SIGTERM
, &action
, NULL
);
254 signal(SIGTERM
, SIG_IGN
);
255 #endif /* HAVE_SIGSET */
259 * Finally, send the print file...
266 fputs("PAGE: 1 1\n", stderr
);
267 lseek(fp
, 0, SEEK_SET
);
270 fputs("INFO: Connected to host, sending print job...\n", stderr
);
273 while ((nbytes
= read(fp
, buffer
, sizeof(buffer
))) > 0)
276 * Write the print data to the printer...
285 * See if we are ready to read or write...
295 while (select(fd
+ 1, &input
, &output
, NULL
, NULL
) < 0);
297 if (FD_ISSET(fd
, &input
))
300 * Read backchannel data...
303 if ((rbytes
= recv(fd
, resource
, sizeof(resource
), 0)) > 0)
305 fprintf(stderr
, "DEBUG: Received %d bytes of back-channel data!\n",
307 cupsBackchannelWrite(resource
, rbytes
, 1.0);
311 if (FD_ISSET(fd
, &output
))
314 * Write print data...
317 if ((wbytes
= send(fd
, bufptr
, nbytes
, 0)) < 0)
320 * Check for retryable errors...
323 if (errno
!= EAGAIN
&& errno
!= EINTR
)
325 perror("ERROR: Unable to send print file to printer");
332 * Update count and pointer...
345 fprintf(stderr
, "INFO: Sending print file, %lu bytes...\n",
346 (unsigned long)tbytes
);
350 * Shutdown the socket and wait for the other end to finish...
353 fputs("INFO: Print file sent, waiting for printer to finish...\n", stderr
);
360 * Wait a maximum of 90 seconds for backchannel data or a closed
371 if (select(fd
+ 1, (int *)&input
, NULL
, NULL
, &timeout
) > 0)
373 if (select(fd
+ 1, &input
, NULL
, NULL
, &timeout
) > 0)
377 * Grab the data coming back and spit it out to stderr...
380 if ((rbytes
= recv(fd
, resource
, sizeof(resource
), 0)) > 0)
382 fprintf(stderr
, "DEBUG: Received %d bytes of back-channel data!\n",
384 cupsBackchannelWrite(resource
, rbytes
, 1.0);
394 * Close the socket connection...
400 httpAddrFreeList(addrlist
);
403 * Close the input file and return...
410 fputs("INFO: Ready to print.\n", stderr
);
412 return (wbytes
< 0 ? CUPS_BACKEND_FAILED
: CUPS_BACKEND_OK
);
417 * End of "$Id: socket.c 4906 2006-01-10 20:53:28Z mike $".