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