]>
git.ipfire.org Git - thirdparty/cups.git/blob - backend/socket.c
4 * AppSocket backend for the Common UNIX Printing System (CUPS).
6 * Copyright 1997-2005 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/cups.h>
39 #include <cups/http-private.h>
40 #include <cups/string.h>
42 #include <sys/types.h>
51 # include <sys/socket.h>
52 # include <netinet/in.h>
53 # include <arpa/inet.h>
62 void print_backchannel(const unsigned char *buffer
, int nbytes
);
66 * 'main()' - Send a file to the printer or server.
70 * printer-uri job-id user title copies options [file]
73 int /* O - Exit status */
74 main(int argc
, /* I - Number of command-line arguments (6 or 7) */
75 char *argv
[]) /* I - Command-line arguments */
77 int i
; /* Looping var */
78 char method
[255], /* Method in URI */
79 hostname
[1024], /* Hostname */
80 username
[255], /* Username info (not used) */
81 resource
[1024]; /* Resource info (not used) */
82 int fp
; /* Print file */
83 int copies
; /* Number of copies to print */
84 int port
; /* Port number */
85 int delay
; /* Delay for retries... */
86 int fd
; /* AppSocket */
87 int error
; /* Error code (if any) */
88 http_addr_t addr
; /* Socket address */
89 struct hostent
*hostaddr
; /* Host address */
90 int wbytes
; /* Number of bytes written */
91 int nbytes
; /* Number of bytes read */
92 size_t tbytes
; /* Total number of bytes written */
93 char buffer
[8192], /* Output buffer */
94 *bufptr
; /* Pointer into buffer */
95 struct timeval timeout
; /* Timeout for select() */
96 fd_set input
; /* Input 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\"");
131 else if (argc
< 6 || argc
> 7)
133 fprintf(stderr
, "Usage: %s job-id user title copies options [file]\n",
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");
160 copies
= atoi(argv
[4]);
164 * Extract the hostname and port number from the URI...
167 httpSeparate(argv
[0], method
, username
, hostname
, &port
, resource
);
170 port
= 9100; /* Default to HP JetDirect/Tektronix PhaserShare */
173 * Then try to connect to the remote host...
176 if ((hostaddr
= httpGetHostByName(hostname
)) == NULL
)
178 fprintf(stderr
, "ERROR: Unable to locate printer \'%s\' - %s\n",
179 hostname
, hstrerror(h_errno
));
183 fprintf(stderr
, "INFO: Attempting to connect to host %s on port %d\n",
192 if ((fd
= socket(AF_INET
, SOCK_STREAM
, 0)) < 0)
194 perror("ERROR: Unable to create socket");
198 for (i
= 0; hostaddr
->h_addr_list
[i
]; i
++)
200 httpAddrLoad(hostaddr
, port
, i
, &addr
);
202 if (!connect(fd
, (struct sockaddr
*)&addr
, sizeof(addr
)))
206 if (!hostaddr
->h_addr_list
[i
])
212 if (getenv("CLASS") != NULL
)
215 * If the CLASS environment variable is set, the job was submitted
216 * to a class and not to a specific queue. In this case, we want
217 * to abort immediately so that the job can be requeued on the next
218 * available printer in the class.
221 fprintf(stderr
, "INFO: Unable to connect to \"%s\", queuing on next printer in class...\n",
225 * Sleep 5 seconds to keep the job from requeuing too rapidly...
233 if (error
== ECONNREFUSED
|| error
== EHOSTDOWN
||
234 error
== EHOSTUNREACH
)
236 fprintf(stderr
, "INFO: Network host \'%s\' is busy; will retry in %d seconds...\n",
245 perror("ERROR: Unable to connect to printer (retrying in 30 seconds)");
254 * Now that we are "connected" to the port, ignore SIGTERM so that we
255 * can finish out any page data the driver sends (e.g. to eject the
256 * current page... Only ignore SIGTERM if we are printing data from
257 * stdin (otherwise you can't cancel raw jobs...)
262 #ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */
263 sigset(SIGTERM
, SIG_IGN
);
264 #elif defined(HAVE_SIGACTION)
265 memset(&action
, 0, sizeof(action
));
267 sigemptyset(&action
.sa_mask
);
268 action
.sa_handler
= SIG_IGN
;
269 sigaction(SIGTERM
, &action
, NULL
);
271 signal(SIGTERM
, SIG_IGN
);
272 #endif /* HAVE_SIGSET */
276 * Finally, send the print file...
283 fputs("PAGE: 1 1\n", stderr
);
284 lseek(fp
, 0, SEEK_SET
);
287 fputs("INFO: Connected to host, sending print job...\n", stderr
);
290 while ((nbytes
= read(fp
, buffer
, sizeof(buffer
))) > 0)
293 * Write the print data to the printer...
301 if ((wbytes
= send(fd
, bufptr
, nbytes
, 0)) < 0)
303 perror("ERROR: Unable to send print file to printer");
315 * Check for possible data coming back from the printer...
323 if (select(fd
+ 1, &input
, NULL
, NULL
, &timeout
) > 0)
326 * Grab the data coming back and spit it out to stderr...
329 if ((nbytes
= recv(fd
, buffer
, sizeof(buffer
), 0)) > 0)
331 fprintf(stderr
, "INFO: Received %d bytes of back-channel data!\n",
333 print_backchannel((unsigned char *)buffer
, nbytes
);
337 fprintf(stderr
, "INFO: Sending print file, %lu bytes...\n",
338 (unsigned long)tbytes
);
342 * Shutdown the socket and wait for the other end to finish...
345 fputs("INFO: Print file sent, waiting for printer to finish...\n", stderr
);
352 * Wait a maximum of 90 seconds for backchannel data or a closed
363 if (select(fd
+ 1, (int *)&input
, NULL
, NULL
, &timeout
) > 0)
365 if (select(fd
+ 1, &input
, NULL
, NULL
, &timeout
) > 0)
369 * Grab the data coming back and spit it out to stderr...
372 if ((nbytes
= recv(fd
, buffer
, sizeof(buffer
), 0)) > 0)
374 fprintf(stderr
, "INFO: Received %d bytes of back-channel data!\n",
376 print_backchannel((unsigned char *)buffer
, nbytes
);
386 * Close the socket connection...
393 * Close the input file and return...
404 * 'print_backchannel()' - Print the contents of a back-channel buffer.
408 print_backchannel(const unsigned char *buffer
, /* I - Data buffer */
409 int nbytes
) /* I - Number of bytes */
411 char line
[255], /* Formatted line */
412 *lineptr
; /* Pointer into line */
415 for (lineptr
= line
; nbytes
> 0; buffer
++, nbytes
--)
417 if (*buffer
< 0x20 || *buffer
>= 0x7f)
419 snprintf(lineptr
, sizeof(line
) - (lineptr
- line
), "<%02X>", *buffer
);
420 lineptr
+= strlen(lineptr
);
423 *lineptr
++ = *buffer
;
425 if ((lineptr
- line
) > 72)
428 fprintf(stderr
, "DEBUG: DATA: %s\n", line
);
436 fprintf(stderr
, "DEBUG: DATA: %s\n", line
);