]> git.ipfire.org Git - thirdparty/cups.git/blame - backend/lpd.c
Mirror 1.1.x changes.
[thirdparty/cups.git] / backend / lpd.c
CommitLineData
43e2fc22 1/*
04e01993 2 * "$Id: lpd.c,v 1.28.2.9 2002/08/27 18:36:16 mike Exp $"
43e2fc22 3 *
e73c6c0a 4 * Line Printer Daemon backend for the Common UNIX Printing System (CUPS).
43e2fc22 5 *
839c43aa 6 * Copyright 1997-2002 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
8784b6a6 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 *
dab1a4d8 24 * This file is subject to the Apple OS-Developed Software exception.
25 *
43e2fc22 26 * Contents:
27 *
decc1f36 28 * main() - Send a file to the printer or server.
29 * lpd_command() - Send an LPR command sequence and wait for a reply.
30 * lpd_queue() - Queue a file using the Line Printer Daemon protocol.
f8529e1a 31 * lpd_write() - Write a buffer of data to an LPD server.
e73c6c0a 32 */
33
34/*
35 * Include necessary headers.
36 */
37
38#include <cups/cups.h>
39#include <stdio.h>
40#include <stdlib.h>
41#include <stdarg.h>
8056639c 42#include <ctype.h>
e73c6c0a 43#include <cups/string.h>
44#include <errno.h>
45#include <sys/types.h>
46#include <sys/stat.h>
4ff40357 47#include <signal.h>
e73c6c0a 48
c3026ddc 49#ifdef WIN32
e73c6c0a 50# include <winsock.h>
51#else
52# include <sys/socket.h>
53# include <netinet/in.h>
54# include <arpa/inet.h>
55# include <netdb.h>
c3026ddc 56#endif /* WIN32 */
e73c6c0a 57
55d0f521 58
f8529e1a 59/*
60 * The order for control and data files in LPD requests...
61 */
62
63#define ORDER_CONTROL_DATA 0
64#define ORDER_DATA_CONTROL 1
65
66
55d0f521 67/*
68 * It appears that rresvport() is never declared on most systems...
69 */
70
71extern int rresvport(int *port);
e73c6c0a 72
73
74/*
75 * Local functions...
76 */
77
78static int lpd_command(int lpd_fd, char *format, ...);
79static int lpd_queue(char *hostname, char *printer, char *filename,
04e01993 80 int fromstdin, char *user, char *title, int copies,
81 int banner, int format, int order, int reserve,
82 int manual_copies);
f8529e1a 83static int lpd_write(int lpd_fd, char *buffer, int length);
e73c6c0a 84
85
86/*
87 * 'main()' - Send a file to the printer or server.
43e2fc22 88 *
e73c6c0a 89 * Usage:
43e2fc22 90 *
e73c6c0a 91 * printer-uri job-id user title copies options [file]
43e2fc22 92 */
93
e73c6c0a 94int /* O - Exit status */
95main(int argc, /* I - Number of command-line arguments (6 or 7) */
96 char *argv[]) /* I - Command-line arguments */
97{
98 char method[255], /* Method in URI */
99 hostname[1024], /* Hostname */
100 username[255], /* Username info (not used) */
101 resource[1024], /* Resource info (printer name) */
72a039d0 102 *options, /* Pointer to options */
103 name[255], /* Name of option */
104 value[255], /* Value of option */
105 *ptr, /* Pointer into name or value */
8056639c 106 filename[1024], /* File to print */
107 title[256]; /* Title string */
e73c6c0a 108 int port; /* Port number (not used) */
109 int status; /* Status of LPD job */
72a039d0 110 int banner; /* Print banner page? */
111 int format; /* Print format */
f8529e1a 112 int order; /* Order of control/data files */
9ba7fc54 113 int reserve; /* Reserve priviledged port? */
04e01993 114 int manual_copies, /* Do manual copies? */
115 copies; /* Number of copies */
e73c6c0a 116
117
4b23f3b3 118 /*
119 * Make sure status messages are not buffered...
120 */
121
122 setbuf(stderr, NULL);
123
124 /*
125 * Check command-line...
126 */
127
68edc300 128 if (argc == 1)
129 {
d4c438d4 130 puts("network lpd \"Unknown\" \"LPD/LPR Host or Printer\"");
68edc300 131 return (0);
132 }
133 else if (argc < 6 || argc > 7)
e73c6c0a 134 {
135 fprintf(stderr, "Usage: %s job-id user title copies options [file]\n",
136 argv[0]);
137 return (1);
138 }
139
140 /*
141 * If we have 7 arguments, print the file named on the command-line.
142 * Otherwise, copy stdin to a temporary file and print the temporary
143 * file.
144 */
145
146 if (argc == 6)
147 {
148 /*
149 * Copy stdin to a temporary file...
150 */
151
1b5bf964 152 int fd; /* Temporary file */
e73c6c0a 153 char buffer[8192]; /* Buffer for copying */
154 int bytes; /* Number of bytes read */
155
156
1b5bf964 157 if ((fd = cupsTempFd(filename, sizeof(filename))) < 0)
e73c6c0a 158 {
c8f9565c 159 perror("ERROR: unable to create temporary file");
e73c6c0a 160 return (1);
161 }
162
163 while ((bytes = fread(buffer, 1, sizeof(buffer), stdin)) > 0)
1b5bf964 164 if (write(fd, buffer, bytes) < bytes)
e73c6c0a 165 {
c8f9565c 166 perror("ERROR: unable to write to temporary file");
1b5bf964 167 close(fd);
e73c6c0a 168 unlink(filename);
169 return (1);
170 }
171
1b5bf964 172 close(fd);
e73c6c0a 173 }
174 else
def978d5 175 strlcpy(filename, argv[6], sizeof(filename));
e73c6c0a 176
177 /*
178 * Extract the hostname and printer name from the URI...
179 */
180
181 httpSeparate(argv[0], method, username, hostname, &port, resource);
182
72a039d0 183 /*
184 * See if there are any options...
185 */
186
04e01993 187 banner = 0;
188 format = 'l';
189 order = ORDER_CONTROL_DATA;
190 reserve = 0;
191 manual_copies = 1;
72a039d0 192
193 if ((options = strchr(resource, '?')) != NULL)
194 {
195 /*
196 * Yup, terminate the device name string and move to the first
197 * character of the options...
198 */
199
200 *options++ = '\0';
201
202 /*
203 * Parse options...
204 */
205
206 while (*options)
207 {
208 /*
209 * Get the name...
210 */
211
212 for (ptr = name; *options && *options != '=';)
213 *ptr++ = *options++;
214 *ptr = '\0';
215
216 if (*options == '=')
217 {
218 /*
219 * Get the value...
220 */
221
222 options ++;
223
224 for (ptr = value; *options && *options != '+';)
225 *ptr++ = *options++;
226 *ptr = '\0';
227
228 if (*options == '+')
229 options ++;
230 }
231 else
232 value[0] = '\0';
233
234 /*
235 * Process the option...
236 */
237
238 if (strcasecmp(name, "banner") == 0)
239 {
240 /*
241 * Set the banner...
242 */
243
244 banner = !value[0] ||
245 strcasecmp(value, "on") == 0 ||
246 strcasecmp(value, "yes") == 0 ||
247 strcasecmp(value, "true") == 0;
248 }
249 else if (strcasecmp(name, "format") == 0 && value[0])
250 {
251 /*
252 * Set output format...
253 */
254
255 if (strchr("cdfglnoprtv", value[0]) != NULL)
256 format = value[0];
257 else
258 fprintf(stderr, "ERROR: Unknown format character \"%c\"\n", value[0]);
259 }
f8529e1a 260 else if (strcasecmp(name, "order") == 0 && value[0])
261 {
262 /*
263 * Set control/data order...
264 */
265
266 if (strcasecmp(value, "control,data") == 0)
267 order = ORDER_CONTROL_DATA;
268 else if (strcasecmp(value, "data,control") == 0)
269 order = ORDER_DATA_CONTROL;
270 else
271 fprintf(stderr, "ERROR: Unknown file order \"%s\"\n", value);
272 }
9ba7fc54 273 else if (strcasecmp(name, "reserve") == 0)
274 {
275 /*
276 * Set port reservation mode...
277 */
278
279 reserve = !value[0] ||
280 strcasecmp(value, "on") == 0 ||
281 strcasecmp(value, "yes") == 0 ||
282 strcasecmp(value, "true") == 0;
283 }
04e01993 284 else if (strcasecmp(name, "manual_copies") == 0)
285 {
286 /*
287 * Set port reservation mode...
288 */
289
290 manual_copies = !value[0] ||
291 strcasecmp(value, "on") == 0 ||
292 strcasecmp(value, "yes") == 0 ||
293 strcasecmp(value, "true") == 0;
294 }
72a039d0 295 }
296 }
297
8056639c 298 /*
299 * Sanitize the document title...
300 */
301
def978d5 302 strlcpy(title, argv[3], sizeof(title));
8056639c 303
304 for (ptr = title; *ptr; ptr ++)
305 if (!isalnum(*ptr) && !isspace(*ptr))
306 *ptr = '_';
307
e73c6c0a 308 /*
309 * Queue the job...
310 */
311
3f9cb6c6 312 if (argc > 6)
313 {
04e01993 314 if (manual_copies)
315 {
316 manual_copies = atoi(argv[4]);
317 copies = 1;
318 }
319 else
320 {
321 manual_copies = 1;
322 copies = atoi(argv[4]);
323 }
324
325 status = lpd_queue(hostname, resource + 1, filename, 0,
326 argv[2] /* user */, title, copies,
327 banner, format, order, reserve, manual_copies);
3f9cb6c6 328
329 if (!status)
330 fprintf(stderr, "PAGE: 1 %d\n", atoi(argv[4]));
331 }
332 else
04e01993 333 status = lpd_queue(hostname, resource + 1, filename, 1,
9ba7fc54 334 argv[2] /* user */, title, 1,
04e01993 335 banner, format, order, reserve, 1);
e73c6c0a 336
337 /*
338 * Remove the temporary file if necessary...
339 */
340
341 if (argc < 7)
342 unlink(filename);
343
344 /*
345 * Return the queue status...
346 */
347
348 return (status);
349}
350
351
43e2fc22 352/*
e73c6c0a 353 * 'lpd_command()' - Send an LPR command sequence and wait for a reply.
43e2fc22 354 */
355
e73c6c0a 356static int /* O - Status of command */
357lpd_command(int fd, /* I - Socket connection to LPD host */
358 char *format, /* I - printf()-style format string */
359 ...) /* I - Additional args as necessary */
360{
361 va_list ap; /* Argument pointer */
362 char buf[1024]; /* Output buffer */
363 int bytes; /* Number of bytes to output */
364 char status; /* Status from command */
365
366
367 /*
368 * Format the string...
369 */
370
371 va_start(ap, format);
6a536282 372 bytes = vsnprintf(buf, sizeof(buf), format, ap);
e73c6c0a 373 va_end(ap);
374
d21a7597 375 fprintf(stderr, "DEBUG: lpd_command %2.2x %s", buf[0], buf + 1);
e73c6c0a 376
377 /*
378 * Send the command...
379 */
380
85e96ec0 381 fprintf(stderr, "DEBUG: Sending command string (%d bytes)...\n", bytes);
382
f8529e1a 383 if (lpd_write(fd, buf, bytes) < bytes)
e73c6c0a 384 return (-1);
385
386 /*
387 * Read back the status from the command and return it...
388 */
389
85e96ec0 390 fprintf(stderr, "DEBUG: Reading command status...\n");
391
e73c6c0a 392 if (recv(fd, &status, 1, 0) < 1)
393 return (-1);
394
c8f9565c 395 fprintf(stderr, "DEBUG: lpd_command returning %d\n", status);
e73c6c0a 396
397 return (status);
398}
399
400
401/*
402 * 'lpd_queue()' - Queue a file using the Line Printer Daemon protocol.
403 */
404
405static int /* O - Zero on success, non-zero on failure */
406lpd_queue(char *hostname, /* I - Host to connect to */
407 char *printer, /* I - Printer/queue name */
408 char *filename, /* I - File to print */
04e01993 409 int fromstdin, /* I - Printing from stdin? */
e73c6c0a 410 char *user, /* I - Requesting user */
72a039d0 411 char *title, /* I - Job title */
412 int copies, /* I - Number of copies */
413 int banner, /* I - Print LPD banner? */
f8529e1a 414 int format, /* I - Format specifier */
9ba7fc54 415 int order, /* I - Order of data/control files */
04e01993 416 int reserve, /* I - Reserve ports? */
417 int manual_copies) /* I - Do copies by hand... */
e73c6c0a 418{
419 FILE *fp; /* Job file */
420 char localhost[255]; /* Local host name */
421 int error; /* Error number */
422 struct stat filestats; /* File statistics */
423 int port; /* LPD connection port */
424 int fd; /* LPD socket */
425 char control[10240], /* LPD control 'file' */
426 *cptr; /* Pointer into control file string */
427 char status; /* Status byte from command */
428 struct sockaddr_in addr; /* Socket address */
429 struct hostent *hostaddr; /* Host address */
430 size_t nbytes, /* Number of bytes written */
431 tbytes; /* Total bytes written */
432 char buffer[8192]; /* Output buffer */
4ff40357 433#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
434 struct sigaction action; /* Actions for POSIX signals */
435#endif /* HAVE_SIGACTION && !HAVE_SIGSET */
e73c6c0a 436
437
438 /*
439 * First try to reserve a port for this connection...
440 */
441
753453e4 442 if ((hostaddr = httpGetHostByName(hostname)) == NULL)
e73c6c0a 443 {
444 fprintf(stderr, "ERROR: Unable to locate printer \'%s\' - %s",
445 hostname, strerror(errno));
446 return (1);
447 }
448
449 fprintf(stderr, "INFO: Attempting to connect to host %s for printer %s\n",
450 hostname, printer);
451
452 memset(&addr, 0, sizeof(addr));
453 memcpy(&(addr.sin_addr), hostaddr->h_addr, hostaddr->h_length);
454 addr.sin_family = hostaddr->h_addrtype;
455 addr.sin_port = htons(515); /* LPD/printer service */
456
457 for (port = 732;;)
458 {
9ba7fc54 459 if (getuid() || !reserve)
55d0f521 460 {
461 /*
9ba7fc54 462 * Just create a regular socket...
55d0f521 463 */
464
465 if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
466 {
467 perror("ERROR: Unable to create socket");
468 return (1);
469 }
470 }
471 else
e73c6c0a 472 {
55d0f521 473 /*
9ba7fc54 474 * We're running as root and want to comply with RFC 1179. Reserve a
55d0f521 475 * priviledged port between 721 and 732...
476 */
477
478 if ((fd = rresvport(&port)) < 0)
479 {
480 perror("ERROR: Unable to reserve port");
481 sleep(30);
482 continue;
483 }
e73c6c0a 484 }
485
486 if (connect(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0)
487 {
488 error = errno;
489 close(fd);
490 fd = -1;
491
4c2096b8 492 if (error == ECONNREFUSED || error == EHOSTDOWN ||
493 error == EHOSTUNREACH)
e73c6c0a 494 {
495 fprintf(stderr, "INFO: Network host \'%s\' is busy; will retry in 30 seconds...",
496 hostname);
497 sleep(30);
498 }
499 else if (error == EADDRINUSE)
500 {
501 port --;
502 if (port < 721)
503 port = 732;
504 }
505 else
506 {
decc1f36 507 perror("ERROR: Unable to connect to printer");
2cc18dd2 508 sleep(30);
e73c6c0a 509 }
510 }
511 else
512 break;
513 }
514
55d0f521 515 fprintf(stderr, "INFO: Connected from port %d...\n", port);
85e96ec0 516
4ff40357 517 /*
518 * Now that we are "connected" to the port, ignore SIGTERM so that we
519 * can finish out any page data the driver sends (e.g. to eject the
04e01993 520 * current page... Only ignore SIGTERM if we are printing data from
521 * stdin (otherwise you can't cancel raw jobs...)
4ff40357 522 */
523
04e01993 524 if (fromstdin)
525 {
4ff40357 526#ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */
04e01993 527 sigset(SIGTERM, SIG_IGN);
4ff40357 528#elif defined(HAVE_SIGACTION)
04e01993 529 memset(&action, 0, sizeof(action));
4ff40357 530
04e01993 531 sigemptyset(&action.sa_mask);
532 action.sa_handler = SIG_IGN;
533 sigaction(SIGTERM, &action, NULL);
4ff40357 534#else
04e01993 535 signal(SIGTERM, SIG_IGN);
4ff40357 536#endif /* HAVE_SIGSET */
04e01993 537 }
4ff40357 538
e73c6c0a 539 /*
540 * Next, open the print file and figure out its size...
541 */
542
543 if (stat(filename, &filestats))
544 {
c8f9565c 545 perror("ERROR: unable to stat print file");
e73c6c0a 546 return (1);
547 }
548
04e01993 549 filestats.st_size *= manual_copies;
550
e73c6c0a 551 if ((fp = fopen(filename, "rb")) == NULL)
552 {
c8f9565c 553 perror("ERROR: unable to open print file for reading");
e73c6c0a 554 return (1);
555 }
556
557 /*
558 * Send a job header to the printer, specifying no banner page and
559 * literal output...
560 */
561
562 lpd_command(fd, "\002%s\n", printer); /* Receive print job(s) */
563
564 gethostname(localhost, sizeof(localhost));
c8f9565c 565 localhost[31] = '\0'; /* RFC 1179, Section 7.2 - host name < 32 chars */
e73c6c0a 566
72a039d0 567 snprintf(control, sizeof(control), "H%s\nP%s\nJ%s\n", localhost, user, title);
e73c6c0a 568 cptr = control + strlen(control);
569
72a039d0 570 if (banner)
571 {
572 snprintf(cptr, sizeof(control) - (cptr - control), "L%s\n", user);
573 cptr += strlen(cptr);
574 }
575
e73c6c0a 576 while (copies > 0)
577 {
72a039d0 578 snprintf(cptr, sizeof(control) - (cptr - control), "%cdfA%03d%s\n", format,
970017a4 579 getpid() % 1000, localhost);
e73c6c0a 580 cptr += strlen(cptr);
581 copies --;
582 }
583
6a536282 584 snprintf(cptr, sizeof(control) - (cptr - control),
d21a7597 585 "UdfA%03d%s\nNdfA%03d%s\n",
970017a4 586 getpid() % 1000, localhost,
587 getpid() % 1000, localhost);
e73c6c0a 588
c8f9565c 589 fprintf(stderr, "DEBUG: Control file is:\n%s", control);
e73c6c0a 590
f8529e1a 591 if (order == ORDER_CONTROL_DATA)
592 {
593 lpd_command(fd, "\002%d cfA%03.3d%s\n", strlen(control), getpid() % 1000,
594 localhost);
595
ba31b514 596 fprintf(stderr, "INFO: Sending control file (%lu bytes)\n", (unsigned long)strlen(control));
e73c6c0a 597
f8529e1a 598 if (lpd_write(fd, control, strlen(control) + 1) < (strlen(control) + 1))
599 {
600 status = errno;
601 perror("ERROR: Unable to write control file");
602 }
603 else if (read(fd, &status, 1) < 1)
604 status = errno;
e73c6c0a 605
f8529e1a 606 if (status != 0)
607 fprintf(stderr, "ERROR: Remote host did not accept control file (%d)\n",
608 status);
609 else
610 fputs("INFO: Control file sent successfully\n", stderr);
e73c6c0a 611 }
e73c6c0a 612 else
f8529e1a 613 status = 0;
614
615 if (status == 0)
e73c6c0a 616 {
617 /*
618 * Send the print file...
619 */
620
03ccea6f 621 lpd_command(fd, "\003%u dfA%03.3d%s\n", (unsigned)filestats.st_size,
e73c6c0a 622 getpid() % 1000, localhost);
623
c8f9565c 624 fprintf(stderr, "INFO: Sending data file (%u bytes)\n",
decc1f36 625 (unsigned)filestats.st_size);
e73c6c0a 626
627 tbytes = 0;
04e01993 628 while (manual_copies > 0)
e73c6c0a 629 {
04e01993 630 rewind(fp);
e73c6c0a 631
04e01993 632 while ((nbytes = fread(buffer, 1, sizeof(buffer), fp)) > 0)
e73c6c0a 633 {
04e01993 634 fprintf(stderr, "INFO: Spooling LPR job, %u%% complete...\n",
635 (unsigned)(100.0f * tbytes / filestats.st_size));
636
637 if (lpd_write(fd, buffer, nbytes) < nbytes)
638 {
639 perror("ERROR: Unable to send print file to printer");
640 break;
641 }
642 else
643 tbytes += nbytes;
e73c6c0a 644 }
04e01993 645
646 manual_copies --;
e73c6c0a 647 }
648
e73c6c0a 649 if (tbytes < filestats.st_size)
f8529e1a 650 status = errno;
651 else if (lpd_write(fd, "", 1) < 1)
652 status = errno;
653 else if (recv(fd, &status, 1, 0) < 1)
654 status = errno;
655
656 if (status != 0)
e73c6c0a 657 fprintf(stderr, "ERROR: Remote host did not accept data file (%d)\n",
658 status);
659 else
c8f9565c 660 fputs("INFO: Data file sent successfully\n", stderr);
e73c6c0a 661 }
662
f8529e1a 663 if (status == 0 && order == ORDER_DATA_CONTROL)
664 {
665 lpd_command(fd, "\002%d cfA%03.3d%s\n", strlen(control), getpid() % 1000,
666 localhost);
667
ba31b514 668 fprintf(stderr, "INFO: Sending control file (%lu bytes)\n", (unsigned long)strlen(control));
f8529e1a 669
670 if (lpd_write(fd, control, strlen(control) + 1) < (strlen(control) + 1))
671 {
672 status = errno;
673 perror("ERROR: Unable to write control file");
674 }
675 else if (read(fd, &status, 1) < 1)
676 status = errno;
677
678 if (status != 0)
679 fprintf(stderr, "ERROR: Remote host did not accept control file (%d)\n",
680 status);
681 else
682 fputs("INFO: Control file sent successfully\n", stderr);
683 }
684
e73c6c0a 685 /*
686 * Close the socket connection and input file and return...
687 */
688
689 close(fd);
690 fclose(fp);
691
692 return (status);
693}
43e2fc22 694
695
696/*
f8529e1a 697 * 'lpd_write()' - Write a buffer of data to an LPD server.
698 */
699
700static int /* O - Number of bytes written or -1 on error */
701lpd_write(int lpd_fd, /* I - LPD socket */
702 char *buffer, /* I - Buffer to write */
703 int length) /* I - Number of bytes to write */
704{
705 int bytes, /* Number of bytes written */
706 total; /* Total number of bytes written */
707
708
709 total = 0;
710 while ((bytes = send(lpd_fd, buffer, length - total, 0)) >= 0)
711 {
712 total += bytes;
713 buffer += bytes;
714
715 if (total == length)
716 break;
717 }
718
719 if (bytes < 0)
720 return (-1);
721 else
722 return (length);
723}
724
725
c3026ddc 726#ifndef HAVE_RRESVPORT
f8529e1a 727/*
c3026ddc 728 * 'rresvport()' - A simple implementation of rresvport().
729 */
730
731int /* O - Socket or -1 on error */
732rresvport(int *port) /* IO - Port number to bind to */
733{
734 struct sockaddr_in addr; /* Socket address */
735 int fd; /* Socket file descriptor */
736
737
738 /*
739 * Try to create an IPv4 socket...
740 */
741
742 if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
743 return (-1);
744
745 /*
746 * Initialize the address buffer...
747 */
748
749 memset(&addr, 0, sizeof(addr));
750
751 addr.sin_family = AF_INET;
752 addr.sin_addr.s_addr = INADDR_ANY;
753
754 /*
755 * Try to bind the socket to a reserved port; unlike the standard
756 * BSD rresvport(), we limit the port number to 721 through 732
757 * (instead of 512 to 1023) since RFC 1179 defines the local port
758 * number between 721 and 732...
759 */
760
761 while (*port > 720)
762 {
763 /*
764 * Set the port number...
765 */
766
767 addr.sin_port = htons(*port);
768
769 /*
770 * Try binding the port to the socket; return if all is OK...
771 */
772
773 if (!bind(fd, (struct sockaddr *)&addr, sizeof(addr)))
774 return (fd);
775
776 /*
777 * Stop if we have any error other than "address already in use"...
778 */
779
780 if (errno != EADDRINUSE)
781 {
782# ifdef WIN32
783 closesocket(fd);
784# else
785 close(fd);
786# endif /* WIN32 */
787
788 return (-1);
789 }
790
791 /*
792 * Try the next port...
793 */
794
795 (*port)--;
796 }
797
798 /*
799 * Wasn't able to bind to a reserved port, so close the socket and return
800 * -1...
801 */
802
803# ifdef WIN32
804 closesocket(fd);
805# else
806 close(fd);
807# endif /* WIN32 */
808
809 return (-1);
810}
811#endif /* !HAVE_RRESVPORT */
812
813/*
04e01993 814 * End of "$Id: lpd.c,v 1.28.2.9 2002/08/27 18:36:16 mike Exp $".
43e2fc22 815 */