1 /***************************************************************************
2 * LPRng - An Extended Print Spooler System
3 *
4 * Copyright 1988-2003, Patrick Powell, San Diego, CA
5 * papowell@lprng.com
6 * See LICENSE for conditions of use.
7 *
8 ***************************************************************************/
9
10 #include "lp.h"
11 #include "child.h"
12 #include "fileopen.h"
13 #include "errorcodes.h"
14 #include "initialize.h"
15 #include "linksupport.h"
16 #include "lpd_logger.h"
17 #include "getqueue.h"
18 #include "getopt.h"
19 #include "proctitle.h"
20 #include "lockfile.h"
21 #include "lpd_worker.h"
22 #include "lpd_jobs.h"
23 #include "lpd_dispatch.h"
24 #include "user_auth.h"
25
26 /* force local definitions */
27 #undef EXTERN
28 #undef DEFINE
29 #undef DEFS
30
31 #define EXTERN
32 #define DEFINE(X) X
33 #define DEFS
34
35 #include "lpd.h"
36
37 char* Lpd_listen_port_arg; /* command line listen port value */
38 #ifdef IPP_STUBS
39 char* Ipp_listen_port_arg; /* command line listen port value */
40 #endif /* not IPP_STUBS */
41 char* Lpd_port_arg; /* command line port value */
42 char* Lpd_socket_arg; /* command line unix socket value */
43
44 #if HAVE_TCPD_H
45 #include <tcpd.h>
46 int allow_severity = LOG_INFO;
47 int deny_severity = LOG_WARNING;
48 #endif
49
50
51 /**** ENDINCLUDE ****/
52
53 /***************************************************************************
54 * main()
55 * - top level of LPD Lite. This is a cannonical method of handling
56 * input. Note that we assume that the LPD daemon will handle all
57 * of the dirty work associated with formatting, printing, etc.
58 *
59 * 1. get the debug level from command line arguments
60 * 2. set signal handlers for cleanup
61 * 3. get the Host computer Name and user Name
62 * 4. scan command line arguments
63 * 5. check command line arguments for consistency
64 *
65 ****************************************************************************/
66
67 static char *malloc_area;
68
main(int argc,char * argv[],char * envp[])69 int main(int argc, char *argv[], char *envp[])
70 {
71 int sock = 0; /* socket for listen */
72 pid_t pid; /* pid */
73 fd_set defreadfds, readfds; /* for select() */
74 int max_socks = 0; /* maximum number of sockets */
75 int lockfd; /* the lock file descriptor */
76 int err;
77 time_t last_time; /* time that last Start_all was done */
78 time_t server_started_time; /* time servers were started */
79 plp_status_t status;
80 int max_servers;
81 int start_fd = 0;
82 pid_t start_pid = 0, logger_process_pid = 0;
83 int request_pipe[2], status_pipe[2];
84 pid_t last_fork_pid_value;
85 struct line_list args;
86 int first_scan = 1;
87 int unix_sock = 0;
88 #ifdef IPP_STUBS
89 int ipp_sock = 0;
90 #endif /* not IPP_STUBS */
91 int fd_available;
92
93 Init_line_list( &args );
94 Is_server = 1; /* we are the LPD server */
95 Logger_fd = -1;
96
97 #ifndef NODEBUG
98 Debug = 0;
99 #endif
100 if(DEBUGL3){
101 int n;
102 LOGDEBUG("lpd: argc %d", argc );
103 for( n = 0; n < argc; ++n ){
104 LOGDEBUG(" [%d] '%s'", n, argv[n] );
105 }
106 LOGDEBUG("lpd: env" );
107 for( n = 0; envp[n]; ++n ){
108 LOGDEBUG(" [%d] '%s'", n, envp[n] );
109 }
110 }
111
112 /* set signal handlers */
113 (void) plp_signal(SIGHUP, (plp_sigfunc_t)Reinit);
114 (void) plp_signal(SIGINT, cleanup_INT);
115 (void) plp_signal(SIGQUIT, cleanup_QUIT);
116 (void) plp_signal(SIGTERM, cleanup_TERM);
117 (void) signal(SIGUSR1, SIG_IGN);
118 (void) signal(SIGUSR2, SIG_IGN);
119 (void) signal(SIGCHLD, SIG_DFL);
120 (void) signal(SIGPIPE, SIG_IGN);
121
122 /*
123 the next bit of insanity is caused by the interaction of signal(2) and execve(2)
124 man signal(2):
125
126 When a process which has installed signal handlers forks, the child pro-
127 cess inherits the signals. All caught signals may be reset to their de-
128 fault action by a call to the execve(2) function; ignored signals remain
129 ignored.
130
131
132 man execve(2):
133
134 Signals set to be ignored in the calling process are set to be ignored in
135 ^^^^^^^
136 signal(SIGCHLD, SIG_IGN) <- in the acroread code???
137
138 the new process. Signals which are set to be caught in the calling pro-
139 cess image are set to default action in the new process image. Blocked
140 signals remain blocked regardless of changes to the signal action. The
141 signal stack is reset to be undefined (see sigaction(2) for more informa-
142 tion).
143
144
145 ^&*(*&^!!! &*())&*&*!!! and again, I say, &*()(&*!!!
146
147 This means that if you fork/execve a child, then you better make sure
148 that you set up its signal/mask stuff correctly.
149
150 So if somebody blocks all signals and then starts up LPD, it will not work
151 correctly.
152
153 */
154
155 { plp_block_mask oblock; plp_unblock_all_signals( &oblock ); }
156
157
158 Get_parms(argc, argv); /* scan input args */
159
160 Initialize(argc, argv, envp, 'D' );
161 DEBUG1("Get_parms: UID_root %ld, OriginalRUID %ld", (long)UID_root, (long)OriginalRUID);
162
163 if( UID_root && (OriginalRUID != ROOTUID) ){
164 fatal(LOG_ERR, "lpd installed SETUID root and started by user %ld! Possible hacker attack", (long)OriginalRUID);
165 }
166
167 Setup_configuration();
168
169 /* get the maximum number of servers allowed */
170 max_servers = Get_max_servers();
171 if(DEBUGL1){
172 int max_file_descriptors = Get_max_fd();
173 DEBUG1( "lpd: maximum servers %d, maximum file descriptors %d ",
174 max_servers, max_file_descriptors );
175 }
176
177 if( Lockfile_DYN == 0 ){
178 logerr_die(LOG_INFO, _("No LPD lockfile specified!") );
179 }
180
181 /* chdir to the root directory */
182 if( chdir( "/" ) == -1 ){
183 Errorcode = JABORT;
184 logerr_die(LOG_ERR, "cannot chdir to /");
185 }
186 pid = Get_lpd_pid();
187 #if defined(__CYGWIN__)
188 if( (pid > 0) && ( kill(pid,0) || (errno != ESRCH) )) {
189 DIEMSG( _("Another print spooler active, possibly lpd process '%ld'"),
190 (long)pid );
191 }
192 lockfd = Lock_lpd_pid();
193 if( lockfd < 0 ){
194 DIEMSG( _("cannot open or lock lockfile - %s"), Errormsg(errno) );
195 }
196 Set_lpd_pid( lockfd );
197 close( lockfd );
198 lockfd = -1;
199 #else
200 lockfd = Lock_lpd_pid();
201 if( lockfd < 0 ){
202 DIEMSG( _("Another print spooler active, possibly lpd process '%ld'"),
203 (long)pid );
204 }
205 Set_lpd_pid( lockfd );
206 #endif
207
208 {
209 char *s;
210 s = Lpd_listen_port_arg;
211 if( ISNULL(s) ) s = Lpd_listen_port_DYN;
212 if( ISNULL(s) ) s = Lpd_port_DYN;
213 if( !ISNULL(s) && safestrcasecmp( s,"off") && strtol(s,0,0) ){
214 sock = Link_listen(s);
215 DEBUG1("lpd: listening socket fd %d",sock);
216 if( sock < 0 ){
217 Errorcode = 1;
218 DIEMSG("Cannot bind to lpd port '%s'", s);
219 }
220 if( sock >= max_socks ) max_socks = sock;
221 }
222
223 #ifdef IPP_STUBS
224 s = Ipp_listen_port_arg;
225 if( ISNULL(s) ) s = Ipp_listen_port_DYN;
226 if( !ISNULL(s) && safestrcasecmp( s,"off") && strtol(s,0,0) ){
227 ipp_sock = Link_listen(s);
228 DEBUG1("lpd: listening socket fd %d",ipp_sock);
229 if( ipp_sock < 0 ){
230 Errorcode = 1;
231 DIEMSG("Cannot bind to lpd port '%s'", s);
232 }
233 if( ipp_sock >= max_socks ) max_socks = ipp_sock;
234 }
235
236 #endif /* not IPP_STUBS */
237 s = Lpd_socket_arg;
238 if( ISNULL(s) ) s = Unix_socket_path_DYN;
239 if( !ISNULL(s) && safestrcasecmp( s,"off") ){
240 unix_sock = Unix_link_listen(s);
241 DEBUG1("lpd: unix listening socket fd %d, path '%s'",unix_sock, s);
242 if( unix_sock < 0 ){
243 Errorcode = 1;
244 DIEMSG("Cannot bind to UNIX socket '%s'", s );
245 }
246 if( unix_sock >= max_socks ) max_socks = unix_sock;
247 }
248 }
249
250 /* setting nonblocking on the listening fd
251 * will prevent a problem with terminations of connections
252 * before ACCEPT has completed
253 * 1. user connects, does the 3 Way Handshake
254 * 2. before accept() is done, a RST packet is sent
255 * 3. a select() will succeed, but the accept() will hang
256 * 4. if the non-blocking mode is used, then the select will
257 * succeed and the accept() will fail
258 */
259 Set_nonblock_io(sock);
260
261 /*
262 * At this point you are the server for the LPD port
263 * you need to fork to allow the regular user to continue
264 * you put the child in its separate process group as well
265 */
266 if( (pid = dofork(1)) < 0 ){
267 logerr_die(LOG_ERR, _("lpd: main() dofork failed") );
268 } else if( pid ){
269 if( Foreground_LPD ){
270 while( (pid = plp_waitpid( pid, &status, 0)) > 0 ){
271 DEBUG1( "lpd: process %ld, status '%s'",
272 (long)pid, Decode_status(&status));
273 }
274 }
275 Errorcode = 0;
276 exit(0);
277 }
278
279 /* set up the log file and standard environment - do not
280 fool around with anything but fd 0,1,2 which should be safe
281 as we made sure that the fd 0,1,2 existed.
282 */
283
284 Setup_log( Logfile_LPD );
285
286 Name = "Waiting";
287 setproctitle( "lpd %s", Name );
288
289 /*
290 * Write the PID into the lockfile
291 */
292
293 #if defined(__CYGWIN__)
294 lockfd = Lock_lpd_pid();
295 if( lockfd < 0 ) {
296 DIEMSG( "Can't open lockfile for writing" );
297 }
298 Set_lpd_pid( lockfd );
299 close( lockfd );
300 lockfd = -1;
301 #else
302 Set_lpd_pid( lockfd );
303 #endif
304
305
306 if( Drop_root_DYN ){
307 Full_daemon_perms();
308 }
309
310 /* establish the pipes for low level processes to use */
311 if( pipe( request_pipe ) == -1 ){
312 logerr_die(LOG_ERR, _("lpd: pipe call failed") );
313 }
314 Max_open(request_pipe[0]); Max_open(request_pipe[1]);
315 DEBUG2( "lpd: fd request_pipe(%d,%d)",request_pipe[0],request_pipe[1]);
316 Lpd_request = request_pipe[1];
317 Set_nonblock_io( Lpd_request );
318
319 Logger_fd = -1;
320 logger_process_pid = -1;
321 if( Logger_destination_DYN ){
322 if( pipe( status_pipe ) == -1 ){
323 logerr_die(LOG_ERR, _("lpd: pipe call failed") );
324 }
325 Max_open(status_pipe[0]); Max_open(status_pipe[1]);
326 Logger_fd = status_pipe[1];
327 DEBUG2( "lpd: fd status_pipe(%d,%d)",status_pipe[0],status_pipe[1]);
328 logger_process_pid = Start_logger( status_pipe[0] );
329 if( logger_process_pid < 0 ){
330 logerr_die(LOG_ERR, _("lpd: cannot start initial logger process") );
331 }
332 }
333
334 /* open a connection to logger */
335 setmessage(0,LPD,"Starting");
336
337 /*
338 * set up the select parameters
339 */
340
341 FD_ZERO( &defreadfds );
342 if( sock > 0 ) FD_SET( sock, &defreadfds );
343 if( unix_sock > 0 ) FD_SET( unix_sock, &defreadfds );
344 #ifdef IPP_STUBS
345 if( ipp_sock > 0 ) FD_SET( ipp_sock, &defreadfds );
346 #endif /* not IPP_STUBS */
347 FD_SET( request_pipe[0], &defreadfds );
348
349 /*
350 * start waiting for connections from processes
351 */
352
353 last_time = time( (void *)0 );
354 server_started_time = 0;
355
356 start_pid = last_fork_pid_value = Start_all(first_scan, &start_fd );
357 Fork_error( last_fork_pid_value );
358 if( start_pid > 0 ){
359 first_scan = 0;
360 }
361
362 malloc_area = sbrk(0);
363
364 #ifdef DMALLOC
365 DEBUG1( "lpd: LOOP START - sbrk 0x%lx", (long)malloc_area );
366 {
367 extern int dmalloc_outfile_fd;
368 char buffer[128];
369 plp_snprintf(buffer,sizeof(buffer), "lpd: LOOP START - sbrk 0x%lx\n", (long)malloc_area );
370 Write_fd_str(dmalloc_outfile_fd, buffer );
371 dmalloc_log_unfreed();
372 }
373 #endif
374
375
376 do{
377 struct timeval timeval, *timeout;
378 time_t this_time = time( (void *)0 );
379 int elapsed_time;
380
381 #ifdef DMALLOC
382 /* check for memory leaks */
383 {
384 char *s = sbrk(0);
385 int n = s - malloc_area;
386 DEBUG1("lpd: LOOP - sbrk 0x%lx", (long)s );
387 if( n > 1024 ){
388 extern int dmalloc_outfile_fd;
389 char buffer[128];
390 plp_snprintf(buffer,sizeof(buffer), "lpd: LOOP sbrk reports 0x%lx, or %d more memory\n", (long)s, n );
391 Write_fd_str(dmalloc_outfile_fd, buffer );
392 dmalloc_log_unfreed();
393 DEBUG1( "lpd: LOOP sbrk reports 0x%lx, or %d more memory", (long)s, n );
394 malloc_area += n;
395 }
396 }
397 #endif
398
399 /* set up the timeout values */
400
401 timeout = 0;
402 memset(&timeval, 0, sizeof(timeval));
403 if(DEBUGL3){ int fd; fd = dup(0); LOGDEBUG("lpd: next fd %d",fd); close(fd); };
404
405 DEBUG2( "lpd: Poll_time %d, Force_poll %d, start_pid %ld, start_fd %d, Started_server %d",
406 Poll_time_DYN, Force_poll_DYN, (long)start_pid, start_fd, Started_server );
407
408 if(DEBUGL1)Dump_line_list("lpd - Servers_line_list",&Servers_line_list );
409
410 /*
411 * collect zombies. If one exits, you can set last_fork_pid_value
412 * to 0, as you may now be able to start a process
413 */
414
415 while( (pid = plp_waitpid( -1, &status, WNOHANG)) > 0 ){
416 DEBUG1( "lpd: process %d, status '%s'",
417 pid, Decode_status(&status));
418 if( pid == logger_process_pid ){
419 /* ARGH! the logger process died */
420 logger_process_pid = -1;
421 }
422 if( pid == start_pid ){
423 start_pid = -1;
424 }
425 last_fork_pid_value = 0;
426 }
427
428 /*
429 * if the Logger process dies, then you have real problems,
430 * so you need to start it up.
431 */
432 if( last_fork_pid_value >= 0 && Logger_fd > 0 && logger_process_pid <= 0 ){
433 DEBUG1( "lpd: restarting logger process");
434 last_fork_pid_value = logger_process_pid = Start_logger( status_pipe[0] );
435 Fork_error( last_fork_pid_value );
436 DEBUG1("lpd: logger_process_pid %d", logger_process_pid );
437 }
438
439 /* you really do not want to start up more proceses until you can
440 */
441 if( last_fork_pid_value < 0 ){
442 goto waitloop;
443 }
444
445 /*
446 * Check to see if you need to rescan the spool queues
447 * - you have done all of the work in the Servers_line_list
448 * started by the last scan
449 * - it is time to do a new scan
450 */
451
452 elapsed_time = (this_time - last_time);
453 if( Poll_time_DYN > 0 && start_pid <= 0 ){
454 int doit, scanned_queue_count;
455 DEBUG1("lpd: checking for scan, start_fd %d, start_pid %ld, Poll_time_DYN %d, elapsed_time %d, Started_server %d, Force_poll %d",
456 start_fd, (long)start_pid, Poll_time_DYN, elapsed_time, Started_server, Force_poll_DYN );
457 if( elapsed_time >= Poll_time_DYN ){
458 for( scanned_queue_count = doit = 0;
459 scanned_queue_count == 0 && doit < Servers_line_list.count; ++doit ){
460 char *s = Servers_line_list.list[doit];
461 if( s && cval(s) == '.' ) ++scanned_queue_count;
462 }
463 DEBUG1( "lpd: timeout checking for scan, scanned_queue_count %d", scanned_queue_count);
464 if( scanned_queue_count == 0
465 && ( Started_server || Force_poll_DYN ) ){
466 last_fork_pid_value = start_pid = Start_all(first_scan, &start_fd );
467 Fork_error( last_fork_pid_value );
468 DEBUG1( "lpd: restarting poll, start_pid %ld, start_fd %d", (long)start_pid, start_fd);
469 if( start_fd > 0 ){
470 first_scan = 0;
471 Started_server = 0;
472 last_time = this_time;
473 } else {
474 /* argh! process exhaustion */
475 goto waitloop;
476 }
477 }
478 } else {
479 /* oops... need to wait longer */
480 timeout = &timeval;
481 timeval.tv_sec = Poll_time_DYN - elapsed_time;
482 }
483 }
484
485 /*
486 * check to see if there are any spool queues that require
487 * service. This is the case when
488 * - time since last startup was non-zero
489 * - Servers_line_list has an entry
490 * OR you have had a forced startup request
491 */
492 if( Servers_line_list.count ){
493 int number_of_servers = Countpid();
494 int server_processes_started = 0;
495 int doit;
496 char *server_to_start = 0;
497 int forced_start = 0;
498 elapsed_time = this_time - server_started_time;
499 /* find the first entry WITHOUT a '.' as first character */
500 if(DEBUGL1)Dump_line_list("lpd: Servers_line_list", &Servers_line_list );
501 for( forced_start = doit = 0; !forced_start && doit < Servers_line_list.count; ++doit ){
502 server_to_start = Servers_line_list.list[doit];
503 if( server_to_start && cval(server_to_start) != '.' ){
504 forced_start = 1;
505 break;
506 }
507 server_to_start = 0;
508 }
509
510 #ifdef DMALLOC
511 /* check for memory leaks */
512 {
513 char *s = sbrk(0);
514 int n = s - malloc_area;
515 DEBUG1("lpd: BEFORE POLL SERVICE - sbrk 0x%lx, cnt %d", (long)s, Servers_line_list.count );
516 if( n > 1024 ){
517 extern int dmalloc_outfile_fd;
518 char buffer[128];
519 plp_snprintf(buffer,sizeof(buffer), "lpd: BEFORE POLL SERVICE sbrk reports 0x%lx, or %d more memory\n", (long)s, n );
520 Write_fd_str(dmalloc_outfile_fd, buffer );
521 dmalloc_log_unfreed();
522 DEBUG1( "lpd: BEFORE POLL SERVICE sbrk reports 0x%lx, or %d more memory", (long)s, n );
523 malloc_area += n;
524 }
525 }
526 #endif
527
528 while( (elapsed_time > Poll_start_interval_DYN || forced_start )
529 && Servers_line_list.count > 0 && server_processes_started < Poll_servers_started_DYN
530 && number_of_servers + server_processes_started < max_servers-4 ){
531 DEBUG1("lpd: elapsed time %d, server_started_time %d, max_servers %d, number_of_servers %d, started %d",
532 (int)elapsed_time, (int)server_started_time, max_servers, number_of_servers, server_processes_started );
533
534 /* find the first entry WITHOUT a '.' as first character */
535 for( forced_start = doit = 0; doit < Servers_line_list.count; ++doit ){
536 server_to_start = Servers_line_list.list[doit];
537 if( server_to_start && cval(server_to_start) != '.' ){
538 forced_start = 1;
539 break;
540 }
541 server_to_start = 0;
542 }
543 /* Ok, then settle for the first entry */
544 if( !server_to_start ){
545 doit = 0;
546 server_to_start = Servers_line_list.list[doit];
547 if( cval(server_to_start) == '.' ) ++server_to_start;
548 }
549 if( !ISNULL(server_to_start) ){
550 server_started_time = this_time;
551 DEBUG1("lpd: starting server '%s'", server_to_start );
552 Free_line_list(&args);
553 Set_str_value(&args,PRINTER,server_to_start);
554 last_fork_pid_value = pid = Start_worker( "queue", Service_queue, &args, 0 );
555 Fork_error( last_fork_pid_value );
556 Free_line_list(&args);
557 if( pid > 0 ){
558 Remove_line_list( &Servers_line_list, doit );
559 Started_server = 1;
560 server_started_time = this_time;
561 if( forced_start ){
562 ++number_of_servers;
563 } else {
564 ++server_processes_started;
565 }
566 } else {
567 /* argh! process exhaustion */
568 goto waitloop;
569 }
570 } else {
571 /* empty line... */
572 Remove_line_list( &Servers_line_list, doit );
573 }
574 }
575
576 #ifdef DMALLOC
577 /* check for memory leaks */
578 {
579 char *s = sbrk(0);
580 int n = s - malloc_area;
581 DEBUG1("lpd: AFTER POLL SERVICE - sbrk 0x%lx, cnt %d", (long)s, Servers_line_list.count );
582 if( n > 1024 ){
583 extern int dmalloc_outfile_fd;
584 char buffer[128];
585 plp_snprintf(buffer,sizeof(buffer), "lpd: AFTER POLL SERVICE sbrk reports 0x%lx, or %d more memory\n", (long)s, n );
586 Write_fd_str(dmalloc_outfile_fd, buffer );
587 dmalloc_log_unfreed();
588 DEBUG1( "lpd: AFTER POLL SERVICE sbrk reports 0x%lx, or %d more memory", (long)s, n );
589 malloc_area += n;
590 }
591 }
592 #endif
593
594 }
595 /* we see if we have any work to do
596 * and then schedule a timeout if necessary to start a process
597 * NOTE: if the Poll_start_interval value is 0,
598 * then we will wait until a process exits
599 */
600 if( Servers_line_list.count > 0 && Poll_start_interval_DYN ){
601 int time_left;
602 elapsed_time = this_time - server_started_time;
603 time_left = Poll_start_interval_DYN - elapsed_time;
604 if( time_left < 0 ) time_left = 0;
605 timeout = &timeval;
606 if( timeval.tv_sec == 0 || timeval.tv_sec > time_left ){
607 timeval.tv_sec = time_left;
608 }
609 }
610
611 waitloop:
612 /*
613 * the place where we actually do some waiting
614 */
615
616
617 DEBUG1("lpd: Started_server %d, last_fork_pid_value %ld, active servers %d, max %d",
618 Started_server, (long)last_fork_pid_value, Countpid(), max_servers );
619 /* do not accept incoming call if no worker available */
620 readfds = defreadfds;
621 if( Countpid() >= max_servers || last_fork_pid_value < 0 ){
622 DEBUG1( "lpd: not accepting requests" );
623 if( sock > 0 ) FD_CLR( sock, &readfds );
624 if( unix_sock > 0 ) FD_CLR( unix_sock, &readfds );
625 #ifdef IPP_STUBS
626 if( ipp_sock > 0 ) FD_CLR( ipp_sock, &readfds );
627 #endif /* not IPP_STUBS */
628 timeval.tv_sec = 10;
629 timeout = &timeval;
630 }
631
632 if( request_pipe[0] >= max_socks ){
633 max_socks = request_pipe[0]+1;
634 }
635 if( start_fd > 0 ){
636 FD_SET( start_fd, &readfds );
637 if( start_fd >= max_socks ){
638 max_socks = start_fd+1;
639 }
640 }
641
642 DEBUG1( "lpd: starting select timeout '%s', %d sec, max_socks %d",
643 timeout?"yes":"no", (int)(timeout?timeout->tv_sec:0), max_socks );
644 if(DEBUGL2){
645 int i;
646 for(i=0; i < max_socks; ++i ){
647 if( FD_ISSET( i, &readfds ) ){
648 LOGDEBUG( "lpd: waiting for fd %d to be readable", i );
649 }
650 }
651 }
652 Setup_waitpid_break();
653 errno = 0;
654 fd_available = select( max_socks,
655 &readfds, NULL, NULL, timeout );
656 err = errno;
657 Setup_waitpid();
658 if(DEBUGL1){
659 int i;
660 LOGDEBUG( "lpd: select returned %d, error '%s'",
661 fd_available, Errormsg(err) );
662 for(i=0; fd_available > 0 && i < max_socks; ++i ){
663 if( FD_ISSET( i, &readfds ) ){
664 LOGDEBUG( "lpd: fd %d readable", i );
665 }
666 }
667 }
668 /* if we got a SIGHUP then we reread configuration */
669 if( Reread_config || !Use_info_cache_DYN ){
670 DEBUG1( "lpd: rereading configuration" );
671 /* we need to force the LPD logger to use new printcap information */
672 if( Reread_config ){
673 if( logger_process_pid > 0 ) kill( logger_process_pid, SIGINT );
674 setmessage(0,LPD,"Restart");
675 Reread_config = 0;
676 }
677 Setup_configuration();
678 }
679 /* mark this as a timeout */
680 if( fd_available < 0 ){
681 if( err != EINTR ){
682 errno = err;
683 logerr_die(LOG_ERR, _("lpd: select error!"));
684 break;
685 }
686 continue;
687 } else if( fd_available == 0 ){
688 DEBUG1( "lpd: signal or time out, last_fork_pid_value %d", last_fork_pid_value );
689 /* we try to fork now */
690 if( last_fork_pid_value < 0 ) last_fork_pid_value = 1;
691 continue;
692 }
693 if( sock > 0 && FD_ISSET( sock, &readfds ) ){
694 DEBUG1("lpd: accept on LPD socket");
695 Accept_connection( sock );
696 }
697 if( unix_sock > 0 && FD_ISSET( unix_sock, &readfds ) ){
698 DEBUG1("lpd: accept on UNIX socket");
699 Accept_connection( unix_sock );
700 }
701 #ifdef IPP_STUBS
702 if( ipp_sock > 0 && FD_ISSET( ipp_sock, &readfds ) ){
703 DEBUG1("lpd: accept on IPP socket");
704 Accept_connection( ipp_sock );
705 }
706 #endif /* not IPP_STUBS */
707 if( FD_ISSET( request_pipe[0], &readfds )
708 && Read_server_status( request_pipe[0] ) == 0 ){
709 Errorcode = JABORT;
710 logerr_die(LOG_ERR, _("lpd: Lpd_request pipe EOF! cannot happen") );
711 }
712 if( start_fd > 0 && FD_ISSET( start_fd, &readfds ) ){
713 start_fd = Read_server_status( start_fd );
714 }
715 }while( 1 );
716 Free_line_list(&args);
717 cleanup(0);
718 }
719
720 /***************************************************************************
721 * Setup_log( char *logfile, int sock )
722 * Purpose: to set up a standard error logging environment
723 * saveme will prevent STDIN from being clobbered
724 * 1. dup 'sock' to fd 0, close sock
725 * 2. opens /dev/null on fd 1
726 * 3. If logfile is "-" or NULL, output file is alread opened
727 * 4. Open logfile; if unable to, then open /dev/null for output
728 ***************************************************************************/
Setup_log(char * logfile)729 static void Setup_log(char *logfile )
730 {
731 struct stat statb;
732
733 close(0); close(1);
734 if (open("/dev/null", O_RDONLY, 0) != 0) {
735 logerr_die(LOG_ERR, _("Setup_log: open /dev/null failed"));
736 }
737 if (open("/dev/null", O_WRONLY, 0) != 1) {
738 logerr_die(LOG_ERR, _("Setup_log: open /dev/null failed"));
739 }
740
741 /*
742 * open logfile; if it is "-", use STDERR; if Foreground is set, use stderr
743 */
744 if( fstat(2,&statb) == -1 && dup2(1,2) == -1 ){
745 logerr_die(LOG_ERR, _("Setup_log: dup2(%d,%d) failed"), 1, 2);
746 }
747 if( logfile == 0 ){
748 if( !Foreground_LPD && dup2(1,2) == -1 ){
749 logerr_die(LOG_ERR, _("Setup_log: dup2(%d,%d) failed"), 1, 2);
750 }
751 } else if( safestrcmp(logfile, "-") ){
752 close(2);
753 if( Checkwrite(logfile, &statb, O_WRONLY|O_APPEND, 0, 0) != 2) {
754 logerr_die(LOG_ERR, _("Setup_log: open %s failed"), logfile );
755 }
756 }
757 }
758
759 /***************************************************************************
760 * Reinit()
761 * Reinitialize the database/printcap/permissions information
762 * 1. free any allocated memory
763 ***************************************************************************/
764
Reinit(void)765 static void Reinit(void)
766 {
767 Reread_config = 1;
768 (void) plp_signal (SIGHUP, (plp_sigfunc_t)Reinit);
769 }
770
771
772 /***************************************************************************
773 * Get_lpd_pid() and Set_lpd_pid()
774 * Get and set the LPD pid into the LPD status file
775 ***************************************************************************/
776
Get_lpd_pid(void)777 int Get_lpd_pid(void)
778 {
779 pid_t pid;
780 char *path;
781
782 path = safestrdup3( Lockfile_DYN,".", Lpd_port_DYN, __FILE__, __LINE__ );
783 pid = Read_pid_from_file( path );
784 if( path ) free(path); path = 0;
785 return(pid);
786 }
787
Set_lpd_pid(int lockfd)788 static void Set_lpd_pid(int lockfd)
789 {
790 /* we write our PID */
791 if( ftruncate( lockfd, 0 ) ){
792 logerr_die(LOG_ERR, _("lpd: Cannot truncate lock file") );
793 }
794 Server_pid = getpid();
795 DEBUG1( "lpd: writing lockfile fd %d with pid '%ld'",lockfd, (long)Server_pid );
796 Write_pid( lockfd, Server_pid, (char *)0 );
797 }
798
Lock_lpd_pid(void)799 int Lock_lpd_pid(void)
800 {
801 int lockfd;
802 char *path;
803 struct stat statb;
804 int euid = geteuid();
805
806 path = safestrdup3( Lockfile_DYN,".", Lpd_port_DYN, __FILE__, __LINE__ );
807 To_euid_root();
808 lockfd = Checkwrite( path, &statb, O_RDWR, 1, 0 );
809 if( lockfd < 0 ){
810 logerr_die(LOG_ERR, _("lpd: Cannot open lock file '%s'"), path );
811 }
812 #if !defined(__CYGWIN__)
813 fchown( lockfd, DaemonUID, DaemonGID );
814 fchmod( lockfd, (statb.st_mode & ~0777) | 0644 );
815 #endif
816 To_euid(euid);
817 if( Do_lock( lockfd, 0 ) < 0 ){
818 close( lockfd );
819 lockfd = -1;
820 }
821 return(lockfd);
822 }
823
Read_server_status(int fd)824 int Read_server_status( int fd )
825 {
826 int status, count, found, n;
827 char buffer[LINEBUFFER];
828 char *name;
829 fd_set readfds; /* for select() */
830 struct timeval timeval;
831 struct line_list l;
832
833 buffer[0] = 0;
834 errno = 0;
835
836 DEBUG1( "Read_server_status: starting" );
837
838 Init_line_list(&l);
839 while(1){
840 FD_ZERO( &readfds );
841 FD_SET( fd, &readfds );
842 memset(&timeval,0, sizeof(timeval));
843 status = select( fd+1,
844 &readfds, NULL, NULL, &timeval );
845 DEBUG1( "Read_server_status: select status %d", status);
846 if( status == 0 ){
847 break;
848 } else if( status < 0 ){
849 close(fd);
850 fd = 0;
851 break;
852 }
853 status = ok_read(fd,buffer,sizeof(buffer)-1);
854 DEBUG1( "Read_server_status: read status %d", status );
855 if( status <= 0 ){
856 close(fd);
857 fd = -1;
858 break;
859 }
860 buffer[status] = 0;
861 DEBUG1( "Read_server_status: read status %d '%s'", status, buffer );
862 /* we split up read line and record information */
863 Split(&l,buffer,Whitespace,0,0,0,0,0,0);
864 if(DEBUGL1)Dump_line_list("Read_server_status - input", &l );
865 for( count = 0; count < l.count; ++count ){
866 name = l.list[count];
867 if( ISNULL(name) ) continue;
868 found = 0;
869 for( n = 0;!found && n < Servers_line_list.count; ++n ){
870 found = !safestrcasecmp( Servers_line_list.list[n], name);
871 }
872 if( !found ){
873 Add_line_list(&Servers_line_list,name,0,0,0);
874 }
875 Started_server = 1;
876 }
877 Free_line_list(&l);
878 }
879 Free_line_list(&l);
880
881 #ifdef DMALLOC
882 {
883 char *s = sbrk(0);
884 int n = s - malloc_area;
885 DEBUG1("lpd: READ_SERVER_STATUS - sbrk 0x%lx, cnt %d", (long)s, Servers_line_list.count );
886 if( n > 1024 ){
887 extern int dmalloc_outfile_fd;
888 char buffer[128];
889 plp_snprintf(buffer,sizeof(buffer), "lpd: READ_SERVER_STATSUS sbrk reports 0x%lx, or %d more memory\n", (long)s, n );
890 Write_fd_str(dmalloc_outfile_fd, buffer );
891 dmalloc_log_unfreed();
892 DEBUG1( "lpd: READ_SERVER_STATUS sbrk reports 0x%lx, or %d more memory", (long)s, n );
893 malloc_area += n;
894 }
895 }
896 #endif
897
898 if(DEBUGL2)Dump_line_list("Read_server_status - waiting for start",
899 &Servers_line_list );
900 return(fd);
901 }
902
903 /***************************************************************************
904 * void Get_parms(int argc, char *argv[])
905 * 1. Scan the argument list and get the flags
906 * 2. Check for duplicate information
907 ***************************************************************************/
908
usage(void)909 static void usage(void)
910 {
911 FPRINTF( STDERR,
912 _("usage: %s [-FV][-D dbg][-L log][-P path][-p port][-R remote LPD TCP/IP destination port]\n"
913 " Options\n"
914 " -D dbg - set debug level and flags\n"
915 " -F - run in foreground, log to STDERR\n"
916 " -L logfile - append log information to logfile\n"
917 " -V - show version info\n"
918 " -p port - TCP/IP listen port, 'off' disables TCP/IP listening port (lpd_listen_port)\n"
919 " -P path - UNIX socket path, 'off' disables UNIX listening socket (unix_socket_path)\n"
920 " -R port - remote LPD server port (lpd_port)\n"), Name );
921 {
922 char buffer[128];
923 FPRINTF( STDERR, "Security Supported: %s\n", ShowSecuritySupported(buffer,sizeof(buffer)) );
924 }
925 Parse_debug("=",-1);
926 FPRINTF( STDERR, "%s\n", Version );
927 exit(1);
928 }
929
930 static const char LPD_optstr[] /* LPD options */
931 = "D:FL:VX:p:P:" ;
932
Get_parms(int argc,char * argv[])933 static void Get_parms(int argc, char *argv[] )
934 {
935 int option, verbose = 0;
936
937 while ((option = Getopt (argc, argv, LPD_optstr )) != EOF){
938 switch (option) {
939 case 'D': Parse_debug(Optarg, 1); break;
940 case 'F': Foreground_LPD = 1; break;
941 case 'L': Logfile_LPD = Optarg; break;
942 case 'V': ++verbose; break;
943 case 'X': Worker_LPD = Optarg; break;
944 case 'p': Lpd_listen_port_arg = Optarg; break;
945 case 'P': Lpd_socket_arg = Optarg; break;
946 default: usage(); break;
947 }
948 }
949 if( Optind != argc ){
950 usage();
951 }
952 if( verbose ) {
953 FPRINTF( STDERR, "%s\n", Version );
954 if( verbose > 1 ) Printlist( Copyright, 1 );
955 exit(0);
956 }
957 }
958
959
960 /*
961 * Accept_connection
962 * - accept the connection and fork the child to handle it
963 */
Accept_connection(int sock)964 static void Accept_connection( int sock )
965 {
966 struct line_list args;
967 struct sockaddr sinaddr;
968 int newsock, err;
969 pid_t pid;
970 socklen_t len;
971 Init_line_list(&args);
972 len = sizeof( sinaddr );
973 newsock = accept( sock, &sinaddr, &len );
974 err = errno;
975 DEBUG1("Accept_connection: connection fd %d", newsock );
976 if( newsock > 0 ){
977 #if defined(TCPWRAPPERS)
978 /*
979 * libwrap/tcp_wrappers:
980 * draht@suse.de, Mon Jan 28 2002
981 */
982 struct request_info wrap_req;
983
984 request_init(&wrap_req, RQ_DAEMON, "lpd" , RQ_FILE, newsock, NULL);
985 fromhost(&wrap_req);
986 openlog("lpd", LOG_PID, LOG_LPR); /* we syslog(3) initialized, no closelog(). */
987 if (hosts_access(&wrap_req)) {
988 /* We accept. */
989 syslog(LOG_INFO, "connection from %s", eval_client(&wrap_req));
990 } else {
991 syslog(LOG_WARNING, "connection refused from %s", eval_client(&wrap_req));
992 close( newsock );
993 return;
994 }
995 #endif
996
997 pid = Start_worker( "server", Service_connection, &args, newsock );
998 if( pid < 0 ){
999 logerr(LOG_INFO, _("lpd: fork() failed") );
1000 /* this was written with an impossible condition, why?
1001 safefprintf(newsock, "\002%s\n", _("Server load too high"));
1002 */
1003 } else {
1004 DEBUG1( "lpd: listener pid %ld running", (long)pid );
1005 }
1006 close( newsock );
1007 Free_line_list(&args);
1008 } else {
1009 errno = err;
1010 logerr(LOG_INFO, _("lpd: accept on listening socket failed") );
1011 }
1012 }
1013
1014 /*
1015 * int Start_all( int first_scan, int *start_fd )
1016 * returns the pid of the process doing the scanning
1017 */
1018
Start_all(int first_scan,int * start_fd)1019 static pid_t Start_all( int first_scan, int *start_fd )
1020 {
1021 struct line_list args;
1022 int p[2];
1023 pid_t pid;
1024
1025 Init_line_list(&args);
1026
1027 DEBUG1( "Start_all: first_scan %d", first_scan );
1028 if( pipe(p) == -1 ){
1029 logerr_die(LOG_INFO, _("Start_all: pipe failed!") );
1030 }
1031 Max_open(p[0]); Max_open(p[1]);
1032 DEBUG1( "Start_all: fd pipe(%d,%d)",p[0],p[1]);
1033
1034 Set_str_value(&args,CALL,"all");
1035 Set_decimal_value(&args,FIRST_SCAN,first_scan);
1036
1037 pid = Start_worker( "all", Service_all, &args, p[1]);
1038 close(p[1]);
1039 if( pid < 0 ){
1040 close( p[0] );
1041 p[0] = -1;
1042 }
1043 DEBUG1("Start_all: pid %ld, fd %d", (long)pid, p[0] );
1044 if( start_fd ) *start_fd = p[0];
1045 return(pid);
1046 }
1047
sigchld_handler(int signo UNUSED)1048 plp_signal_t sigchld_handler (int signo UNUSED)
1049 {
1050 signal( SIGCHLD, SIG_DFL );
1051 write(Lpd_request,"\n", 1);
1052 }
1053
Setup_waitpid(void)1054 static void Setup_waitpid (void)
1055 {
1056 signal( SIGCHLD, SIG_DFL );
1057 }
1058
Setup_waitpid_break(void)1059 static void Setup_waitpid_break (void)
1060 {
1061 (void) plp_signal_break(SIGCHLD, sigchld_handler);
1062 }
1063
Fork_error(pid_t last_fork_pid_value)1064 static void Fork_error( pid_t last_fork_pid_value )
1065 {
1066 DEBUG1("Fork_error: %ld", (long)last_fork_pid_value );
1067 if( last_fork_pid_value < 0 ){
1068 logmsg(LOG_CRIT, "LPD: fork failed! LPD not accepting any requests");
1069 }
1070 }
1071