]>
git.ipfire.org Git - thirdparty/cups.git/blob - backend/socket.c
2 * "$Id: socket.c 5241 2006-03-07 22:07:44Z 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 *options
, /* Pointer to options */
76 name
[255], /* Name of option */
77 value
[255], /* Value of option */
78 *ptr
; /* Pointer into name or value */
79 int fp
; /* Print file */
80 int copies
; /* Number of copies to print */
81 int waiteof
; /* Wait for end-of-file? */
82 int port
; /* Port number */
83 char portname
[255]; /* Port name */
84 int delay
; /* Delay for retries... */
85 int fd
; /* AppSocket */
86 int error
; /* Error code (if any) */
87 http_addrlist_t
*addrlist
; /* Address list */
88 int rbytes
; /* Number of bytes read */
89 int wbytes
; /* Number of bytes written */
90 int nbytes
; /* Number of bytes read */
91 size_t tbytes
; /* Total number of bytes written */
92 char buffer
[8192], /* Output buffer */
93 *bufptr
; /* Pointer into buffer */
94 struct timeval timeout
; /* Timeout for select() */
95 fd_set input
, /* Input set for select() */
96 output
; /* Output set for select() */
97 #if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
98 struct sigaction action
; /* Actions for POSIX signals */
99 #endif /* HAVE_SIGACTION && !HAVE_SIGSET */
103 * Make sure status messages are not buffered...
106 setbuf(stderr
, NULL
);
109 * Ignore SIGPIPE signals...
113 sigset(SIGPIPE
, SIG_IGN
);
114 #elif defined(HAVE_SIGACTION)
115 memset(&action
, 0, sizeof(action
));
116 action
.sa_handler
= SIG_IGN
;
117 sigaction(SIGPIPE
, &action
, NULL
);
119 signal(SIGPIPE
, SIG_IGN
);
120 #endif /* HAVE_SIGSET */
123 * Check command-line...
128 puts("network socket \"Unknown\" \"AppSocket/HP JetDirect\"");
129 return (CUPS_BACKEND_OK
);
131 else if (argc
< 6 || argc
> 7)
133 fprintf(stderr
, "Usage: %s job-id user title copies options [file]\n",
135 return (CUPS_BACKEND_FAILED
);
139 * If we have 7 arguments, print the file named on the command-line.
140 * Otherwise, send stdin instead...
151 * Try to open the print file...
154 if ((fp
= open(argv
[6], O_RDONLY
)) < 0)
156 perror("ERROR: unable to open print file");
157 return (CUPS_BACKEND_FAILED
);
160 copies
= atoi(argv
[4]);
164 * Extract the hostname and port number from the URI...
167 httpSeparateURI(HTTP_URI_CODING_ALL
, cupsBackendDeviceURI(argv
),
168 method
, sizeof(method
), username
, sizeof(username
),
169 hostname
, sizeof(hostname
), &port
,
170 resource
, sizeof(resource
));
173 port
= 9100; /* Default to HP JetDirect/Tektronix PhaserShare */
176 * Get options, if any...
181 if ((options
= strchr(resource
, '?')) != NULL
)
184 * Yup, terminate the device name string and move to the first
185 * character of the options...
200 for (ptr
= name
; *options
&& *options
!= '=';)
201 if (ptr
< (name
+ sizeof(name
) - 1))
213 for (ptr
= value
; *options
&& *options
!= '+' && *options
!= '&';)
214 if (ptr
< (value
+ sizeof(value
) - 1))
218 if (*options
== '+' || *options
== '&')
225 * Process the option...
228 if (!strcasecmp(name
, "waiteof"))
231 * Set the wait-for-eof value...
234 waiteof
= !value
[0] || !strcasecmp(value
, "on") ||
235 !strcasecmp(value
, "yes") || !strcasecmp(value
, "true");
241 * Then try to connect to the remote host...
244 sprintf(portname
, "%d", port
);
246 if ((addrlist
= httpAddrGetList(hostname
, AF_UNSPEC
, portname
)) == NULL
)
248 fprintf(stderr
, "ERROR: Unable to locate printer \'%s\'!\n", hostname
);
249 return (CUPS_BACKEND_STOP
);
252 fprintf(stderr
, "INFO: Attempting to connect to host %s on port %d\n",
259 fputs("STATE: +connecting-to-device\n", stderr
);
263 if (!httpAddrConnect(addrlist
, &fd
))
268 if (getenv("CLASS") != NULL
)
271 * If the CLASS environment variable is set, the job was submitted
272 * to a class and not to a specific queue. In this case, we want
273 * to abort immediately so that the job can be requeued on the next
274 * available printer in the class.
277 fprintf(stderr
, "INFO: Unable to connect to \"%s\", queuing on next printer in class...\n",
281 * Sleep 5 seconds to keep the job from requeuing too rapidly...
286 return (CUPS_BACKEND_FAILED
);
289 if (error
== ECONNREFUSED
|| error
== EHOSTDOWN
||
290 error
== EHOSTUNREACH
)
292 fprintf(stderr
, "INFO: Network host \'%s\' is busy; will retry in %d seconds...\n",
301 perror("ERROR: Unable to connect to printer (retrying in 30 seconds)");
309 fputs("STATE: -connecting-to-device\n", stderr
);
312 * Now that we are "connected" to the port, ignore SIGTERM so that we
313 * can finish out any page data the driver sends (e.g. to eject the
314 * current page... Only ignore SIGTERM if we are printing data from
315 * stdin (otherwise you can't cancel raw jobs...)
320 #ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */
321 sigset(SIGTERM
, SIG_IGN
);
322 #elif defined(HAVE_SIGACTION)
323 memset(&action
, 0, sizeof(action
));
325 sigemptyset(&action
.sa_mask
);
326 action
.sa_handler
= SIG_IGN
;
327 sigaction(SIGTERM
, &action
, NULL
);
329 signal(SIGTERM
, SIG_IGN
);
330 #endif /* HAVE_SIGSET */
334 * Finally, send the print file...
341 fputs("PAGE: 1 1\n", stderr
);
342 lseek(fp
, 0, SEEK_SET
);
345 fputs("INFO: Connected to host, sending print job...\n", stderr
);
348 while ((nbytes
= read(fp
, buffer
, sizeof(buffer
))) > 0)
351 * Write the print data to the printer...
360 * See if we are ready to read or write...
370 while (select(fd
+ 1, &input
, &output
, NULL
, NULL
) < 0);
372 if (FD_ISSET(fd
, &input
))
375 * Read backchannel data...
378 if ((rbytes
= recv(fd
, resource
, sizeof(resource
), 0)) > 0)
380 fprintf(stderr
, "DEBUG: Received %d bytes of back-channel data!\n",
382 cupsBackChannelWrite(resource
, rbytes
, 1.0);
386 if (FD_ISSET(fd
, &output
))
389 * Write print data...
392 if ((wbytes
= send(fd
, bufptr
, nbytes
, 0)) < 0)
395 * Check for retryable errors...
398 if (errno
!= EAGAIN
&& errno
!= EINTR
)
400 perror("ERROR: Unable to send print file to printer");
407 * Update count and pointer...
420 fprintf(stderr
, "INFO: Sending print file, %lu bytes...\n",
421 (unsigned long)tbytes
);
427 * Shutdown the socket and wait for the other end to finish...
430 fputs("INFO: Print file sent, waiting for printer to finish...\n", stderr
);
437 * Wait a maximum of 90 seconds for backchannel data or a closed
448 if (select(fd
+ 1, (int *)&input
, NULL
, NULL
, &timeout
) > 0)
450 if (select(fd
+ 1, &input
, NULL
, NULL
, &timeout
) > 0)
454 * Grab the data coming back and spit it out to stderr...
457 if ((rbytes
= recv(fd
, resource
, sizeof(resource
), 0)) > 0)
459 fprintf(stderr
, "DEBUG: Received %d bytes of back-channel data!\n",
461 cupsBackChannelWrite(resource
, rbytes
, 1.0);
472 * Close the socket connection...
478 httpAddrFreeList(addrlist
);
481 * Close the input file and return...
488 fputs("INFO: Ready to print.\n", stderr
);
490 return (wbytes
< 0 ? CUPS_BACKEND_FAILED
: CUPS_BACKEND_OK
);
495 * End of "$Id: socket.c 5241 2006-03-07 22:07:44Z mike $".