]> git.ipfire.org Git - thirdparty/cups.git/blame - backend/socket.c
Merge changes from 1.1.x into 1.2 devel.
[thirdparty/cups.git] / backend / socket.c
CommitLineData
43e2fc22 1/*
753453e4 2 * "$Id: socket.c,v 1.17.2.2 2001/12/26 16:52:07 mike Exp $"
43e2fc22 3 *
e73c6c0a 4 * AppSocket backend for the Common UNIX Printing System (CUPS).
43e2fc22 5 *
d2935a0f 6 * Copyright 1997-2001 by Easy Software Products, all rights reserved.
43e2fc22 7 *
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
13 * at:
14 *
15 * Attn: CUPS Licensing Information
16 * Easy Software Products
58ec2a95 17 * 44141 Airport View Drive, Suite 204
43e2fc22 18 * Hollywood, Maryland 20636-3111 USA
19 *
20 * Voice: (301) 373-9603
21 * EMail: cups-info@cups.org
22 * WWW: http://www.cups.org
23 *
24 * Contents:
25 *
decc1f36 26 * main() - Send a file to the printer or server.
43e2fc22 27 */
28
29/*
30 * Include necessary headers.
31 */
32
e73c6c0a 33#include <cups/cups.h>
34#include <stdio.h>
35#include <stdlib.h>
36#include <stdarg.h>
37#include <cups/string.h>
38#include <errno.h>
39#include <sys/types.h>
40#include <sys/stat.h>
4ff40357 41#include <signal.h>
e73c6c0a 42
43#if defined(WIN32) || defined(__EMX__)
44# include <winsock.h>
45#else
46# include <sys/socket.h>
47# include <netinet/in.h>
48# include <arpa/inet.h>
49# include <netdb.h>
50#endif /* WIN32 || __EMX__ */
51
52
53/*
54 * 'main()' - Send a file to the printer or server.
55 *
56 * Usage:
57 *
58 * printer-uri job-id user title copies options [file]
59 */
60
61int /* O - Exit status */
62main(int argc, /* I - Number of command-line arguments (6 or 7) */
63 char *argv[]) /* I - Command-line arguments */
64{
65 char method[255], /* Method in URI */
66 hostname[1024], /* Hostname */
67 username[255], /* Username info (not used) */
68 resource[1024]; /* Resource info (not used) */
69 FILE *fp; /* Print file */
3f9cb6c6 70 int copies; /* Number of copies to print */
e73c6c0a 71 int port; /* Port number */
10f725af 72 int delay; /* Delay for retries... */
e73c6c0a 73 int fd; /* AppSocket */
74 int error; /* Error code (if any) */
75 struct sockaddr_in addr; /* Socket address */
76 struct hostent *hostaddr; /* Host address */
7c88bf41 77 int wbytes; /* Number of bytes written */
78 size_t nbytes, /* Number of bytes read */
e73c6c0a 79 tbytes; /* Total number of bytes written */
7c88bf41 80 char buffer[8192], /* Output buffer */
81 *bufptr; /* Pointer into buffer */
e73c6c0a 82 struct timeval timeout; /* Timeout for select() */
83 fd_set input; /* Input set for select() */
4ff40357 84#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
85 struct sigaction action; /* Actions for POSIX signals */
86#endif /* HAVE_SIGACTION && !HAVE_SIGSET */
e73c6c0a 87
88
4b23f3b3 89 /*
90 * Make sure status messages are not buffered...
91 */
92
93 setbuf(stderr, NULL);
94
95 /*
96 * Check command-line...
97 */
98
68edc300 99 if (argc == 1)
100 {
d4c438d4 101 puts("network socket \"Unknown\" \"AppSocket/HP JetDirect\"");
68edc300 102 return (0);
103 }
104 else if (argc < 6 || argc > 7)
e73c6c0a 105 {
106 fprintf(stderr, "Usage: %s job-id user title copies options [file]\n",
107 argv[0]);
108 return (1);
109 }
110
111 /*
112 * If we have 7 arguments, print the file named on the command-line.
113 * Otherwise, send stdin instead...
114 */
115
116 if (argc == 6)
3f9cb6c6 117 {
118 fp = stdin;
119 copies = 1;
120 }
e73c6c0a 121 else
122 {
123 /*
124 * Try to open the print file...
125 */
126
127 if ((fp = fopen(argv[6], "rb")) == NULL)
128 {
decc1f36 129 perror("ERROR: unable to open print file");
e73c6c0a 130 return (1);
131 }
3f9cb6c6 132
133 copies = atoi(argv[4]);
e73c6c0a 134 }
135
136 /*
137 * Extract the hostname and port number from the URI...
138 */
139
140 httpSeparate(argv[0], method, username, hostname, &port, resource);
141
142 if (port == 0)
143 port = 9100; /* Default to HP JetDirect/Tektronix PhaserShare */
144
145 /*
146 * Then try to connect to the remote host...
147 */
148
753453e4 149 if ((hostaddr = httpGetHostByName(hostname)) == NULL)
e73c6c0a 150 {
2a0ef17a 151 fprintf(stderr, "ERROR: Unable to locate printer \'%s\' - %s\n",
e73c6c0a 152 hostname, strerror(errno));
153 return (1);
154 }
155
156 fprintf(stderr, "INFO: Attempting to connect to host %s on port %d\n",
157 hostname, port);
158
159 memset(&addr, 0, sizeof(addr));
160 memcpy(&(addr.sin_addr), hostaddr->h_addr, hostaddr->h_length);
161 addr.sin_family = hostaddr->h_addrtype;
162 addr.sin_port = htons(port);
163
3f9cb6c6 164 while (copies > 0)
e73c6c0a 165 {
10f725af 166 for (delay = 5;;)
e73c6c0a 167 {
3f9cb6c6 168 if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
e73c6c0a 169 {
2cc18dd2 170 perror("ERROR: Unable to create socket");
3f9cb6c6 171 return (1);
e73c6c0a 172 }
3f9cb6c6 173
174 if (connect(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0)
e73c6c0a 175 {
3f9cb6c6 176 error = errno;
177 close(fd);
178 fd = -1;
179
180 if (error == ECONNREFUSED)
181 {
10f725af 182 fprintf(stderr, "INFO: Network host \'%s\' is busy; will retry in %d seconds...\n",
183 hostname, delay);
184 sleep(delay);
185
186 if (delay < 30)
187 delay += 5;
3f9cb6c6 188 }
189 else
190 {
10f725af 191 perror("ERROR: Unable to connect to printer (retrying in 30 seconds)");
2cc18dd2 192 sleep(30);
3f9cb6c6 193 }
e73c6c0a 194 }
3f9cb6c6 195 else
196 break;
e73c6c0a 197 }
e73c6c0a 198
4ff40357 199 /*
200 * Now that we are "connected" to the port, ignore SIGTERM so that we
201 * can finish out any page data the driver sends (e.g. to eject the
202 * current page...
203 */
204
205#ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */
206 sigset(SIGTERM, SIG_IGN);
207#elif defined(HAVE_SIGACTION)
208 memset(&action, 0, sizeof(action));
209
210 sigemptyset(&action.sa_mask);
211 action.sa_handler = SIG_IGN;
212 sigaction(SIGTERM, &action, NULL);
213#else
214 signal(SIGTERM, SIG_IGN);
215#endif /* HAVE_SIGSET */
216
e73c6c0a 217 /*
3f9cb6c6 218 * Finally, send the print file...
e73c6c0a 219 */
220
3f9cb6c6 221 copies --;
7c88bf41 222
3f9cb6c6 223 if (fp != stdin)
e73c6c0a 224 {
3f9cb6c6 225 fputs("PAGE: 1 1\n", stderr);
226 rewind(fp);
e73c6c0a 227 }
e73c6c0a 228
3f9cb6c6 229 fputs("INFO: Connected to host, sending print job...\n", stderr);
e73c6c0a 230
3f9cb6c6 231 tbytes = 0;
232 while ((nbytes = fread(buffer, 1, sizeof(buffer), fp)) > 0)
e73c6c0a 233 {
234 /*
3f9cb6c6 235 * Write the print data to the printer...
236 */
237
238 tbytes += nbytes;
239 bufptr = buffer;
240
241 while (nbytes > 0)
242 {
243 if ((wbytes = send(fd, bufptr, nbytes, 0)) < 0)
244 {
245 perror("ERROR: Unable to send print file to printer");
246 break;
247 }
248
249 nbytes -= wbytes;
250 bufptr += wbytes;
251 }
252
253 /*
254 * Check for possible data coming back from the printer...
e73c6c0a 255 */
256
b5cb0608 257 timeout.tv_sec = 0;
3f9cb6c6 258 timeout.tv_usec = 0;
b5cb0608 259
3f9cb6c6 260 FD_ZERO(&input);
261 FD_SET(fd, &input);
b5cb0608 262#ifdef __hpux
263 if (select(fd + 1, (int *)&input, NULL, NULL, &timeout) > 0)
264#else
3f9cb6c6 265 if (select(fd + 1, &input, NULL, NULL, &timeout) > 0)
b5cb0608 266#endif /* __hpux */
3f9cb6c6 267 {
268 /*
269 * Grab the data coming back and spit it out to stderr...
270 */
271
272 if ((nbytes = recv(fd, buffer, sizeof(buffer), 0)) > 0)
273 fprintf(stderr, "INFO: Received %u bytes of back-channel data!\n",
274 nbytes);
275 }
276 else if (argc > 6)
277 fprintf(stderr, "INFO: Sending print file, %u bytes...\n", tbytes);
e73c6c0a 278 }
3f9cb6c6 279
b5cb0608 280 /*
281 * Shutdown the socket and wait for the other end to finish...
282 */
283
284 fputs("INFO: Print file sent, waiting for printer to finish...\n", stderr);
285
286 shutdown(fd, 1);
287
288 for (;;)
289 {
290 /*
291 * Wait a maximum of 90 seconds for backchannel data or a closed
292 * connection...
293 */
294
295 timeout.tv_sec = 90;
296 timeout.tv_usec = 0;
297
298 FD_ZERO(&input);
299 FD_SET(fd, &input);
300
301#ifdef __hpux
302 if (select(fd + 1, (int *)&input, NULL, NULL, &timeout) > 0)
303#else
304 if (select(fd + 1, &input, NULL, NULL, &timeout) > 0)
305#endif /* __hpux */
306 {
307 /*
308 * Grab the data coming back and spit it out to stderr...
309 */
310
311 if ((nbytes = recv(fd, buffer, sizeof(buffer), 0)) > 0)
312 fprintf(stderr, "INFO: Received %u bytes of back-channel data!\n",
313 nbytes);
314 else
315 break;
316 }
317 else
318 break;
319 }
320
3f9cb6c6 321 /*
322 * Close the socket connection...
323 */
324
325 close(fd);
e73c6c0a 326 }
327
328 /*
3f9cb6c6 329 * Close the input file and return...
e73c6c0a 330 */
331
e73c6c0a 332 if (fp != stdin)
333 fclose(fp);
334
753453e4 335 fputs("INFO: Ready to print.\n", stderr);
b5cb0608 336
e73c6c0a 337 return (0);
338}
43e2fc22 339
340
341/*
753453e4 342 * End of "$Id: socket.c,v 1.17.2.2 2001/12/26 16:52:07 mike Exp $".
43e2fc22 343 */