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
12 #include "utilities.h"
13 #include "getopt.h"
14 #include "errorcodes.h"
15
16 /**** ENDINCLUDE ****/
17
18 /*
19 * Time_str: return "cleaned up" ctime() string...
20 *
21 * in YY/MO/DY/hr:mn:sc
22 * Thu Aug 4 12:34:17 BST 1994 -> 12:34:17
23 */
24
Time_str(int shortform,time_t t)25 char *Time_str(int shortform, time_t t)
26 {
27 static char buffer[99];
28 struct tm *tmptr;
29 struct timeval tv;
30
31 tv.tv_usec = 0;
32 if( t == 0 ){
33 if( gettimeofday( &tv, 0 ) == -1 ){
34 Errorcode = JFAIL;
35 logerr_die(LOG_ERR, "Time_str: gettimeofday failed");
36 }
37 t = tv.tv_sec;
38 }
39 tmptr = localtime( &t );
40 if( shortform && Full_time_DYN == 0 ){
41 plp_snprintf( buffer, sizeof(buffer),
42 "%02d:%02d:%02d.%03d",
43 tmptr->tm_hour, tmptr->tm_min, tmptr->tm_sec,
44 (int)(tv.tv_usec/1000) );
45 } else {
46 plp_snprintf( buffer, sizeof(buffer),
47 "%d-%02d-%02d-%02d:%02d:%02d.%03d",
48 tmptr->tm_year+1900, tmptr->tm_mon+1, tmptr->tm_mday,
49 tmptr->tm_hour, tmptr->tm_min, tmptr->tm_sec,
50 (int)(tv.tv_usec/1000) );
51 }
52 /* now format the time */
53 if( Ms_time_resolution_DYN == 0 ){
54 char *s;
55 if( ( s = safestrrchr( buffer, '.' )) ){
56 *s = 0;
57 }
58 }
59 return( buffer );
60 }
61
62
63 /*
64 * Pretty_time: return "cleaned up" ctime() string...
65 *
66 * in YY/MO/DY/hr:mn:sc
67 * Thu Aug 4 12:34:17 BST 1994 -> 12:34:17
68 */
69
Pretty_time(time_t t)70 char *Pretty_time( time_t t )
71 {
72 static char buffer[99];
73 struct tm *tmptr;
74 struct timeval tv;
75
76 tv.tv_usec = 0;
77 if( t == 0 ){
78 if( gettimeofday( &tv, 0 ) == -1 ){
79 Errorcode = JFAIL;
80 logerr_die(LOG_ERR, "Time_str: gettimeofday failed");
81 }
82 t = tv.tv_sec;
83 }
84 tmptr = localtime( &t );
85 strftime( buffer, sizeof(buffer), "%b %d %H:%M:%S %Y", tmptr );
86
87 return( buffer );
88 }
89
Convert_to_time_t(char * str)90 time_t Convert_to_time_t( char *str )
91 {
92 time_t t = 0;
93 if(str) t = strtol(str,0,0);
94 DEBUG5("Convert_to_time_t: %s = %ld", str, (long)t );
95 return(t);
96 }
97
98 /***************************************************************************
99 * Use for copyright printing
100 ***************************************************************************/
101
Printlist(const char ** m,int fd)102 void Printlist( const char **m, int fd )
103 {
104 if( m ){
105 for( ; *m; ++m ){
106 Write_fd_str(fd, *m);
107 Write_fd_str(fd,"\n");
108 }
109 }
110 }
111
112
113 /***************************************************************************
114 * Utility functions: write a string to a fd (bombproof)
115 * write a char array to a fd (fairly bombproof)
116 * Note that there is a race condition here that is unavoidable;
117 * The problem is that there is no portable way to disable signals;
118 * post an alarm; <enable signals and do a read simultaneously>
119 * There is a solution that involves forking a subprocess, but this
120 * is so painful as to be not worth it. Most of the timeouts
121 * in the LPR stuff are in the order of minutes, so this is not a problem.
122 *
123 * Note: we do the write first and then check for timeout.
124 ***************************************************************************/
125
126 /*
127 * Write_fd_len( fd, msg, len )
128 * returns:
129 * 0 - success
130 * <0 - failure
131 */
132
Write_fd_len(int fd,const char * msg,int len)133 int Write_fd_len( int fd, const char *msg, int len )
134 {
135 int i;
136
137 i = len;
138 while( len > 0 && (i = write( fd, msg, len ) ) >= 0 ){
139 len -= i, msg += i;
140 }
141 return( (i < 0) ? -1 : 0 );
142 }
143
144 /*
145 * Write_fd_len_timeout( timeout, fd, msg, len )
146 * returns:
147 * 0 - success
148 * <0 - failure
149 */
150
Write_fd_len_timeout(int timeout,int fd,const char * msg,int len)151 int Write_fd_len_timeout( int timeout, int fd, const char *msg, int len )
152 {
153 int i;
154 if( timeout > 0 ){
155 if( Set_timeout() ){
156 Set_timeout_alarm( timeout );
157 i = Write_fd_len( fd, msg, len );
158 } else {
159 i = -1;
160 }
161 Clear_timeout();
162 } else {
163 i = Write_fd_len( fd, msg, len );
164 }
165 return( i < 0 ? -1 : 0 );
166 }
167
168 /*
169 * Write_fd_str_timeout( fd, msg )
170 * returns:
171 * 0 - success
172 * <0 - failure
173 */
174
Write_fd_str(int fd,const char * msg)175 int Write_fd_str( int fd, const char *msg )
176 {
177 if( msg && *msg ){
178 return( Write_fd_len( fd, msg, safestrlen(msg) ));
179 }
180 return( 0 );
181 }
182
183
184 /*
185 * Write_fd_str_timeout( timeout, fd, msg )
186 * returns:
187 * 0 - success
188 * <0 - failure
189 */
190
Write_fd_str_timeout(int timeout,int fd,const char * msg)191 int Write_fd_str_timeout( int timeout, int fd, const char *msg )
192 {
193 if( msg && *msg ){
194 return( Write_fd_len_timeout( timeout, fd, msg, safestrlen(msg) ) );
195 }
196 return( 0 );
197 }
198
199
200 /*
201 * Read_fd_len_timeout( timeout, fd, msg, len )
202 * returns:
203 * n>0 - read n
204 * 0 - EOF
205 * <0 - failure
206 */
207
Read_fd_len_timeout(int timeout,int fd,char * msg,int len)208 int Read_fd_len_timeout( int timeout, int fd, char *msg, int len )
209 {
210 int i;
211 if( timeout > 0 ){
212 if( Set_timeout() ){
213 Set_timeout_alarm( timeout );
214 i = ok_read( fd, msg, len );
215 } else {
216 i = -1;
217 errno = EINTR;
218 }
219 Clear_timeout();
220 } else {
221 i = ok_read( fd, msg, len );
222 }
223 return( i );
224 }
225
226
227 /**************************************************************
228 *
229 * signal handling:
230 * SIGALRM should be the only signal that terminates system calls;
231 * all other signals should NOT terminate them.
232 * This signal() emulation function attepts to do just that.
233 * (Derived from Advanced Programming in the UNIX Environment, Stevens, 1992)
234 *
235 **************************************************************/
236
237
238 /* solaris 2.3 note: don't compile this with "gcc -ansi -pedantic";
239 * due to a bug in the header file, struct sigaction doesn't
240 * get declared. :(
241 */
242
243 /* plp_signal will set flags so that signal handlers will continue
244 * Note that in Solaris, you MUST reinstall the
245 * signal hanlders in the signal handler! The default action is
246 * to try to restart the system call - note that the code should
247 * be written so that you check for error returns from a system call
248 * and continue if no error.
249 * WARNING: read/write may terminate early? who knows...
250 * See plp_signal_break.
251 */
252
plp_signal(int signo,plp_sigfunc_t func)253 plp_sigfunc_t plp_signal (int signo, plp_sigfunc_t func)
254 {
255 #ifdef HAVE_SIGACTION
256 struct sigaction act, oact;
257
258 act.sa_handler = func;
259 (void) sigemptyset (&act.sa_mask);
260 act.sa_flags = 0;
261 # ifdef SA_RESTART
262 act.sa_flags |= SA_RESTART; /* SVR4, 4.3+BSD */
263 # endif
264 if (sigaction (signo, &act, &oact) < 0) {
265 return (SIG_ERR);
266 }
267 return (plp_sigfunc_t) oact.sa_handler;
268 #else
269 /* sigaction is not supported. Just set the signals. */
270 return (plp_sigfunc_t)signal (signo, func);
271 #endif
272 }
273
274 /* plp_signal_break is similar to plp_signal, but will cause
275 * TERMINATION of a system call if possible. This allows
276 * you to force a signal to cause termination of a system
277 * wait or other action.
278 * WARNING: read/write may terminate early? who knows... so
279 * beware if you are expecting this and don't believe that
280 * you got an entire buffer read/written.
281 */
282
plp_signal_break(int signo,plp_sigfunc_t func)283 plp_sigfunc_t plp_signal_break (int signo, plp_sigfunc_t func)
284 {
285 #ifdef HAVE_SIGACTION
286 struct sigaction act, oact;
287
288 act.sa_handler = func;
289 (void) sigemptyset (&act.sa_mask);
290 act.sa_flags = 0;
291 # ifdef SA_INTERRUPT
292 act.sa_flags |= SA_INTERRUPT; /* SunOS */
293 # endif
294 if (sigaction (signo, &act, &oact) < 0) {
295 return (SIG_ERR);
296 }
297 return (plp_sigfunc_t) oact.sa_handler;
298 #else
299 /* sigaction is not supported. Just set the signals. */
300 return (plp_sigfunc_t)signal (signo, func);
301 #endif
302 }
303
304 /**************************************************************/
305
plp_block_all_signals(plp_block_mask * oblock)306 void plp_block_all_signals ( plp_block_mask *oblock )
307 {
308 #ifdef HAVE_SIGPROCMASK
309 sigset_t block;
310
311 (void) sigfillset (&block); /* block all signals */
312 if (sigprocmask (SIG_SETMASK, &block, oblock) < 0)
313 logerr_die(LOG_ERR, "plp_block_all_signals: sigprocmask failed");
314 #else
315 *oblock = sigblock( ~0 ); /* block all signals */
316 #endif
317 }
318
319
plp_unblock_all_signals(plp_block_mask * oblock)320 void plp_unblock_all_signals ( plp_block_mask *oblock )
321 {
322 #ifdef HAVE_SIGPROCMASK
323 sigset_t block;
324
325 (void) sigemptyset (&block); /* block all signals */
326 if (sigprocmask (SIG_SETMASK, &block, oblock) < 0)
327 logerr_die(LOG_ERR, "plp_unblock_all_signals: sigprocmask failed");
328 #else
329 *oblock = sigblock( 0 ); /* unblock all signals */
330 #endif
331 }
332
plp_set_signal_mask(plp_block_mask * in,plp_block_mask * out)333 void plp_set_signal_mask ( plp_block_mask *in, plp_block_mask *out )
334 {
335 #ifdef HAVE_SIGPROCMASK
336 if (sigprocmask (SIG_SETMASK, in, out ) < 0)
337 logerr_die(LOG_ERR, "plp_set_signal_mask: sigprocmask failed");
338 #else
339 sigset_t block;
340 if( in ) block = sigsetmask( *in );
341 else block = sigblock( 0 );
342 if( out ) *out = block;
343 #endif
344 }
345
plp_unblock_one_signal(int sig,plp_block_mask * oblock)346 void plp_unblock_one_signal ( int sig, plp_block_mask *oblock )
347 {
348 #ifdef HAVE_SIGPROCMASK
349 sigset_t block;
350
351 (void) sigemptyset (&block); /* clear out signals */
352 (void) sigaddset (&block, sig ); /* clear out signals */
353 if (sigprocmask (SIG_UNBLOCK, &block, oblock ) < 0)
354 logerr_die(LOG_ERR, "plp_unblock_one_signal: sigprocmask failed");
355 #else
356 *oblock = sigblock( 0 );
357 (void) sigsetmask (*oblock & ~ sigmask(sig) );
358 #endif
359 }
360
plp_block_one_signal(int sig,plp_block_mask * oblock)361 void plp_block_one_signal( int sig, plp_block_mask *oblock )
362 {
363 #ifdef HAVE_SIGPROCMASK
364 sigset_t block;
365
366 (void) sigemptyset (&block); /* clear out signals */
367 (void) sigaddset (&block, sig ); /* clear out signals */
368 if (sigprocmask (SIG_BLOCK, &block, oblock ) < 0)
369 logerr_die(LOG_ERR, "plp_block_one_signal: sigprocmask failed");
370 #else
371 *oblock = sigblock( sigmask( sig ) );
372 #endif
373 }
374
plp_sigpause(void)375 void plp_sigpause( void )
376 {
377 #ifdef HAVE_SIGPROCMASK
378 sigset_t block;
379 (void) sigemptyset (&block); /* clear out signals */
380 (void) sigsuspend( &block );
381 #else
382 (void)sigpause( 0 );
383 #endif
384 }
385
386 /**************************************************************
387 * Bombproof versions of strcasecmp() and strncasecmp();
388 **************************************************************/
389
390 /* case insensitive compare for OS without it */
safestrcasecmp(const char * s1,const char * s2)391 int safestrcasecmp (const char *s1, const char *s2)
392 {
393 int c1, c2, d = 0;
394 if( (s1 == s2) ) return(0);
395 if( (s1 == 0 ) && s2 ) return( -1 );
396 if( s1 && (s2 == 0 ) ) return( 1 );
397 for (;;) {
398 c1 = *((unsigned char *)s1); s1++;
399 c2 = *((unsigned char *)s2); s2++;
400 if( isupper(c1) ) c1 = tolower(c1);
401 if( isupper(c2) ) c2 = tolower(c2);
402 if( (d = (c1 - c2 )) || c1 == 0 ) break;
403 }
404 return( d );
405 }
406
407 /* case insensitive compare for OS without it */
safestrncasecmp(const char * s1,const char * s2,int len)408 int safestrncasecmp (const char *s1, const char *s2, int len )
409 {
410 int c1, c2, d = 0;
411 if( (s1 == s2) && s1 == 0 ) return(0);
412 if( (s1 == 0 ) && s2 ) return( -1 );
413 if( s1 && (s2 == 0 ) ) return( 1 );
414 for (;len>0;--len){
415 c1 = *((unsigned char *)s1); s1++;
416 c2 = *((unsigned char *)s2); s2++;
417 if( isupper(c1) ) c1 = tolower(c1);
418 if( isupper(c2) ) c2 = tolower(c2);
419 if( (d = (c1 - c2 )) || c1 == 0 ) return(d);
420 }
421 return( 0 );
422 }
423
424 /* perform safe comparison, even with null pointers */
safestrcmp(const char * s1,const char * s2)425 int safestrcmp( const char *s1, const char *s2 )
426 {
427 if( (s1 == s2) ) return(0);
428 if( (s1 == 0 ) && s2 ) return( -1 );
429 if( s1 && (s2 == 0 ) ) return( 1 );
430 return( strcmp(s1, s2) );
431 }
432
433
434 /* perform safe comparison, even with null pointers */
safestrlen(const char * s1)435 int safestrlen( const char *s1 )
436 {
437 if( s1 ) return(strlen(s1));
438 return(0);
439 }
440
441
442 /* perform safe comparison, even with null pointers */
safestrncmp(const char * s1,const char * s2,int len)443 int safestrncmp( const char *s1, const char *s2, int len )
444 {
445 if( (s1 == s2) && s1 == 0 ) return(0);
446 if( (s1 == 0 ) && s2 ) return( -1 );
447 if( s1 && (s2 == 0 ) ) return( 1 );
448 return( strncmp(s1, s2, len) );
449 }
450
451
452 /* perform safe strchr, even with null pointers */
safestrchr(const char * s1,int c)453 char *safestrchr( const char *s1, int c )
454 {
455 if( s1 ) return( strchr( s1, c ) );
456 return( 0 );
457 }
458
459
460 /* perform safe strrchr, even with null pointers */
safestrrchr(const char * s1,int c)461 char *safestrrchr( const char *s1, int c )
462 {
463 if( s1 ) return( strrchr( s1, c ) );
464 return( 0 );
465 }
466
467
468 /* perform safe strchr, even with null pointers */
safestrpbrk(const char * s1,const char * s2)469 char *safestrpbrk( const char *s1, const char *s2 )
470 {
471 if( s1 && s2 ) return( strpbrk( s1, s2 ) );
472 return( 0 );
473 }
474
475 /***************************************************************************
476 * plp_usleep() with select - simple minded way to avoid problems
477 ***************************************************************************/
plp_usleep(int i)478 int plp_usleep( int i )
479 {
480 struct timeval t;
481 DEBUG3("plp_usleep: starting usleep %d", i );
482 if( i > 0 ){
483 memset( &t, 0, sizeof(t) );
484 t.tv_usec = i%1000000;
485 t.tv_sec = i/1000000;
486 i = select( 0, NULL, NULL, NULL, &t );
487 DEBUG3("plp_usleep: select done, status %d", i );
488 }
489 return( i );
490 }
491
492
493 /***************************************************************************
494 * plp_sleep() with select - simple minded way to avoid problems
495 ***************************************************************************/
plp_sleep(int i)496 int plp_sleep( int i )
497 {
498 struct timeval t;
499 DEBUG3("plp_sleep: starting sleep %d", i );
500 if( i > 0 ){
501 memset( &t, 0, sizeof(t) );
502 t.tv_sec = i;
503 i = select( 0, NULL, NULL, NULL, &t );
504 DEBUG3("plp_sleep: select done, status %d", i );
505 }
506 return( i );
507 }
508
509
510 /***************************************************************************
511 * int get_max_processes()
512 * get the maximum number of processes allowed
513 ***************************************************************************/
514
Get_max_servers(void)515 int Get_max_servers( void )
516 {
517 int n = 0; /* We need some sort of limit here */
518
519 #if defined(HAVE_GETRLIMIT) && defined(RLIMIT_NPROC)
520 struct rlimit pcount;
521 if( getrlimit(RLIMIT_NPROC, &pcount) == -1 ){
522 fatal(LOG_ERR, "Get_max_servers: getrlimit failed" );
523 }
524 n = pcount.rlim_cur;
525 #ifdef RLIMIT_INFINITY
526 if( pcount.rlim_cur == RLIM_INFINITY ){
527 n = Max_servers_active_DYN;
528 DEBUG1("Get_max_servers: using %d", n );
529 }
530 #endif
531
532 DEBUG1("Get_max_servers: getrlimit returns %d", n );
533 #else
534 # if defined(HAVE_SYSCONF) && defined(_SC_CHILD_MAX)
535 if( n == 0 && (n = sysconf(_SC_CHILD_MAX)) < 0 ){
536 fatal(LOG_ERR, "Get_max_servers: sysconf failed" );
537 }
538 DEBUG1("Get_max_servers: sysconf returns %d", n );
539 # else
540 # if defined(CHILD_MAX)
541 n = CHILD_MAX;
542 DEBUG1("Get_max_servers: CHILD_MAX %d", n );
543 # else
544 n = 0;
545 DEBUG1("Get_max_servers: default %d", n );
546 # endif
547 # endif
548 #endif
549 n = n/4;
550 if(( n > 0 && n > Max_servers_active_DYN)
551 || (n <= 0 && Max_servers_active_DYN) ){
552 n = Max_servers_active_DYN;
553 }
554 if( n <= 0 ) n = 32;
555
556 DEBUG1("Get_max_servers: returning %d", n );
557 return( n );
558 }
559
560
561 /***************************************************************************
562 * int Get_max_fd()
563 * get the maximum number of file descriptors allowed
564 ***************************************************************************/
565
Get_max_fd(void)566 int Get_max_fd( void )
567 {
568 int n = 0; /* We need some sort of limit here */
569
570 #if defined(HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE)
571 struct rlimit pcount;
572 if( getrlimit(RLIMIT_NOFILE, &pcount) == -1 ){
573 fatal(LOG_ERR, "Get_max_fd: getrlimit failed" );
574 }
575 n = pcount.rlim_cur;
576 DEBUG4("Get_max_fd: getrlimit returns %d", n );
577 #else
578 # if defined(HAVE_SYSCONF) && defined(_SC_OPEN_MAX)
579 if( n == 0 && (n = sysconf(_SC_OPEN_MAX)) < 0 ){
580 fatal(LOG_ERR, "Get_max_servers: sysconf failed" );
581 }
582 DEBUG4("Get_max_fd: sysconf returns %d", n );
583 # else
584 n = 20;
585 DEBUG4("Get_max_fd: using default %d", n );
586 # endif
587 #endif
588
589 if( n <= 0 || n > 10240 ){
590 /* we have some systems that will return a VERY
591 * large or negative number for unlimited FD's. Well, we
592 * don't want to use a large number here. So we
593 * will make it a small number. The actual number of
594 * file descriptors open by processes is VERY conservative.
595 */
596 n = 256;
597 }
598
599 DEBUG1("Get_max_fd: returning %d", n );
600 return( n );
601 }
602
603
Brk_check_size(void)604 char *Brk_check_size( void )
605 {
606 static char b[128];
607 static char* Top_of_mem; /* top of allocated memory */
608 char *s = sbrk(0);
609 int v = s - Top_of_mem;
610 if( Top_of_mem == 0 ){
611 plp_snprintf(b, sizeof(b), "BRK: initial value 0x%lx", Cast_ptr_to_long(s) );
612 } else {
613 plp_snprintf(b, sizeof(b), "BRK: new value 0x%lx, increment %d", Cast_ptr_to_long(s), v );
614 }
615 Top_of_mem = s;
616 return(b);
617 }
618
mystrncat(char * s1,const char * s2,int len)619 char *mystrncat( char *s1, const char *s2, int len )
620 {
621 int size;
622 s1[len-1] = 0;
623 size = safestrlen( s1 );
624 if( s2 && len - size > 0 ){
625 strncpy( s1+size, s2, len - size );
626 }
627 return( s1 );
628 }
mystrncpy(char * s1,const char * s2,int len)629 char *mystrncpy( char *s1, const char *s2, int len )
630 {
631 s1[0] = 0;
632 if( s2 && len-1 > 0 ){
633 strncpy( s1, s2, len-1 );
634 s1[len-1] = 0;
635 }
636 return( s1 );
637 }
638
639 /*
640 * Set_non_block_io(fd)
641 * Set_block_io(fd)
642 * Set blocking or non-blocking IO
643 * Dies if unsuccessful
644 * Get_nonblock_io(fd)
645 * Returns O_NONBLOCK flag value
646 */
647
Get_nonblock_io(int fd)648 int Get_nonblock_io( int fd )
649 {
650 int mask;
651 /* we set IO to non-blocking on fd */
652
653 if( (mask = fcntl( fd, F_GETFL, 0 ) ) == -1 ){
654 return(-1);
655 }
656 mask &= O_NONBLOCK;
657 return( mask );
658 }
659
Set_nonblock_io(int fd)660 int Set_nonblock_io( int fd )
661 {
662 int mask;
663 /* we set IO to non-blocking on fd */
664
665 if( (mask = fcntl( fd, F_GETFL, 0 ) ) == -1 ){
666 return(-1);
667 }
668 mask |= O_NONBLOCK;
669 if( (mask = fcntl( fd, F_SETFL, mask ) ) == -1 ){
670 return(-1);
671 }
672 return(0);
673 }
674
Set_block_io(int fd)675 int Set_block_io( int fd )
676 {
677 int mask;
678 /* we set IO to blocking on fd */
679
680 if( (mask = fcntl( fd, F_GETFL, 0 ) ) == -1 ){
681 return(-1);
682 }
683 mask &= ~O_NONBLOCK;
684 if( (mask = fcntl( fd, F_SETFL, mask ) ) == -1 ){
685 return(-1);
686 }
687 return(0);
688 }
689
690 /*
691 * Read_write_timeout
692 * int readfd, char *inbuffer, int maxinlen -
693 * read data from this fd into this buffer before this timeout
694 * int *readlen - reports number of bytes read
695 * int writefd, char **outbuffer, int *outlen -
696 * **outbuffer and **outlen are updated after write
697 * write data from to this fd from this buffer before this timeout
698 * int timeout
699 * > 0 - wait total of this long
700 * 0 - wait indefinitely
701 * -1 - do not wait
702 * Returns:
703 * **outbuffer, *outlen updated
704 * 0 - success
705 * JRDERR - IO error on output
706 * JTIMEOUT - Timeout
707 * JWRERR - IO error on input
708 */
709
Read_write_timeout(int readfd,char * inbuffer,int maxinlen,int * readlen,int writefd,char ** outbuffer,int * outlen,int timeout)710 int Read_write_timeout(
711 int readfd, char *inbuffer, int maxinlen, int *readlen,
712 int writefd, char **outbuffer, int *outlen, int timeout )
713 {
714 time_t start_t, current_t;
715 int elapsed, m, err, done, retval;
716 struct timeval timeval, *tp;
717 fd_set readfds, writefds; /* for select() */
718 struct stat statb;
719
720 DEBUG4( "Read_write_timeout: read(fd %d, buffer 0x%lx, maxinlen %d, readlen 0x%lx->%d",
721 readfd, Cast_ptr_to_long(inbuffer), maxinlen, Cast_ptr_to_long(readlen),
722 readlen?*readlen:0 );
723 DEBUG4( "Read_write_timeout: write(fd %d, buffer 0x%lx->0x%lx, len 0x%lx->%d, timeout %d)",
724 writefd, Cast_ptr_to_long(outbuffer), Cast_ptr_to_long(outbuffer?*outbuffer:0),
725 Cast_ptr_to_long(outlen), outlen?*outlen:0, timeout );
726
727 retval = done = 0;
728 time( &start_t );
729
730 if( *outlen == 0 ) return( retval );
731 if( readfd > 0 ){
732 if( fstat( readfd, &statb ) ){
733 Errorcode = JABORT;
734 fatal(LOG_ERR, "Read_write_timeout: readfd %d closed", readfd );
735 }
736 Set_nonblock_io( readfd );
737 } else {
738 Errorcode = JABORT;
739 fatal(LOG_ERR, "Read_write_timeout: no readfd %d", readfd );
740 }
741 if( writefd > 0 ){
742 if( fstat( writefd, &statb ) ){
743 Errorcode = JABORT;
744 fatal(LOG_ERR, "Read_write_timeout: writefd %d closed",
745 writefd );
746 }
747 Set_nonblock_io( writefd );
748 } else {
749 Errorcode = JABORT;
750 fatal(LOG_ERR, "Read_write_timeout: no write %d", writefd );
751 }
752
753 while(!done){
754 tp = 0;
755 memset( &timeval, 0, sizeof(timeval) );
756 m = 0;
757 if( timeout > 0 ){
758 time( ¤t_t );
759 elapsed = current_t - start_t;
760 if( timeout > 0 && elapsed >= timeout ){
761 break;
762 }
763 timeval.tv_sec = m = timeout - elapsed;
764 tp = &timeval;
765 DEBUG4("Read_write_timeout: timeout now %d", m );
766 } else if( timeout < 0 ){
767 /* we simply poll once */
768 tp = &timeval;
769 }
770 FD_ZERO( &writefds );
771 FD_ZERO( &readfds );
772 m = 0;
773 FD_SET( writefd, &writefds );
774 if( m <= writefd ) m = writefd+1;
775 FD_SET( readfd, &readfds );
776 if( m <= readfd ) m = readfd+1;
777 errno = 0;
778 DEBUG4("Read_write_timeout: starting select" );
779 m = select( m, &readfds, &writefds, NULL, tp );
780 err = errno;
781 DEBUG4("Read_write_timeout: select returned %d, errno '%s'",
782 m, Errormsg(err) );
783 if( m < 0 ){
784 if( err != EINTR ){
785 logerr(LOG_INFO, "Read_write_timeout: select returned %d, errno '%s'",
786 m, Errormsg(err) );
787 retval = JTIMEOUT;
788 done = 1;
789 }
790 } else if( m == 0 ){
791 /* timeout */
792 retval = JTIMEOUT;
793 done = 1;
794 } else {
795 if( FD_ISSET( readfd, &readfds ) ){
796 DEBUG4("Read_write_timeout: read possible on fd %d", readfd );
797 m = ok_read( readfd, inbuffer, maxinlen );
798 DEBUG4("Read_write_timeout: read() returned %d", m );
799 if( readlen ) *readlen = m;
800 /* caller leaves space for this */
801 if( m >= 0 ) inbuffer[m] = 0;
802 if( m < 0 ) retval = JRDERR;
803 done = 1;
804 }
805 if( FD_ISSET( writefd, &writefds ) ){
806 DEBUG4("Read_write_timeout: write possible on fd %d", writefd );
807 Set_nonblock_io( writefd );
808 m = write( writefd, *outbuffer, *outlen );
809 err = errno;
810 Set_block_io( writefd );
811 DEBUG4("Read_write_timeout: wrote %d", m );
812 if( m < 0 ){
813 /* we have EOF on the file descriptor */
814 retval = JWRERR;
815 done = 1;
816 } else {
817 *outlen -= m;
818 *outbuffer += m;
819 if( *outlen == 0 ){
820 done = 1;
821 }
822 }
823 errno = err;
824 }
825 }
826 }
827 err = errno;
828 errno = err;
829 return( retval );
830 }
831
832 /***************************************************************************
833 * Set up alarms so LPRng doesn't hang forever during transfers.
834 ***************************************************************************/
835
836 /*
837 * timeout_alarm
838 * When we get the alarm, we close the file descriptor (if any)
839 * we are working with. When we next do an option, it will fail
840 * Note that this will cause any ongoing read/write operation to fail
841 * We then to a longjmp to the routine, returning a non-zero value
842 * We set an alarm using:
843 *
844 * if( (setjmp(Timeout_env)==0 && Set_timeout_alarm(t,s)) ){
845 * timeout dependent stuff
846 * }
847 * Clear_alarm
848 * We define the Set_timeout macro as:
849 * #define Set_timeout(t,s) (setjmp(Timeout_env)==0 && Set_timeout_alarm(t,s))
850 */
851
timeout_alarm(int sig UNUSED)852 static plp_signal_t timeout_alarm (int sig UNUSED)
853 {
854 Alarm_timed_out = 1;
855 signal( SIGALRM, SIG_IGN );
856 errno = EINTR;
857 #if defined(HAVE_SIGLONGJMP)
858 siglongjmp(Timeout_env,1);
859 #else
860 longjmp(Timeout_env,1);
861 #endif
862 }
863
864
timeout_break(int sig UNUSED)865 static plp_signal_t timeout_break (int sig UNUSED)
866 {
867 Alarm_timed_out = 1;
868 signal( SIGALRM, SIG_IGN );
869 }
870
871
872 /***************************************************************************
873 * Set_timeout( int timeout, int *socket )
874 * Set up a timeout to occur; note that you can call this
875 * routine several times without problems, but you must call the
876 * Clear_timeout routine sooner or later to reset the timeout function.
877 * A timeout value of 0 never times out
878 * Clear_alarm()
879 * Turns off the timeout alarm
880 ***************************************************************************/
Set_timeout_signal_handler(int timeout,plp_sigfunc_t handler)881 void Set_timeout_signal_handler( int timeout, plp_sigfunc_t handler )
882 {
883 int err = errno;
884 sigset_t oblock;
885
886 alarm(0);
887 signal(SIGALRM, SIG_IGN);
888 plp_unblock_one_signal( SIGALRM, &oblock );
889 Alarm_timed_out = 0;
890 Timeout_pending = 0;
891
892 if( timeout > 0 ){
893 Timeout_pending = timeout;
894 plp_signal_break(SIGALRM, handler);
895 alarm (timeout);
896 }
897 errno = err;
898 }
899
900
Set_timeout_alarm(int timeout)901 void Set_timeout_alarm( int timeout )
902 {
903 Set_timeout_signal_handler( timeout, timeout_alarm );
904 }
905
Set_timeout_break(int timeout)906 void Set_timeout_break( int timeout )
907 {
908 Set_timeout_signal_handler( timeout, timeout_break );
909 }
910
Clear_timeout(void)911 void Clear_timeout( void )
912 {
913 int err = errno;
914
915 signal( SIGALRM, SIG_IGN );
916 alarm(0);
917 Timeout_pending = 0;
918 errno = err;
919 }
920
921 /*
922 * setuid.c:
923 * routines to manipulate user-ids securely (and hopefully, portably).
924 * The * internals of this are very hairy, because
925 * (a) there's lots of sanity checking
926 * (b) there's at least three different setuid-swapping
927 * semantics to support :(
928 *
929 *
930 * Note that the various functions saves errno then restores it afterwards;
931 * this means it's safe to do "root_to_user();some_syscall();user_to_root();"
932 * and errno will be from the system call.
933 *
934 * "root" is the user who owns the setuid executable (privileged).
935 * "user" is the user who runs it.
936 * "daemon" owns data files used by the LPRng utilities (spool directories, etc).
937 * and is set by the 'user' entry in the configuration file.
938 *
939 * To_ruid( user ); -- set ruid to user, euid to root
940 * To_euid( user ); -- set euid to user, ruid to root
941 * To_euid_root(); -- set euid to root, ruid to root
942 * To_daemon(); -- set euid to daemon, ruid to root
943 * To_user(); -- set euid to user, ruid to root
944 * Full_daemon_perms() -- set both UID and EUID, one way, no return
945 *
946 */
947
948 /***************************************************************************
949 * Commentary:
950 * Patrick Powell Sat Apr 15 07:56:30 PDT 1995
951 *
952 * This has to be one of the ugliest parts of any portability suite.
953 * The following models are available:
954 * 1. process has <uid, euid> (old SYSV, BSD)
955 * 2. process has <uid, euid, saved uid, saved euid> (new SYSV, BSD)
956 *
957 * There are several possibilites:
958 * 1. need euid root to do some operations
959 * 2. need euid user to do some operations
960 * 3. need euid daemon to do some operations
961 *
962 * Group permissions are almost useless for a server;
963 * usually you are running as a specified group ID and do not
964 * need to change. Client programs are slightly different.
965 * You need to worry about permissions when creating a file;
966 * for this reason most client programs do a u mask(0277) before any
967 * file creation to ensure that nobody can read the file, and create
968 * it with only user access permissions.
969 *
970 * > int setuid(uid) uid_t uid;
971 * > int seteuid(euid) uid_t euid;
972 * > int setruid(ruid) uid_t ruid;
973 * >
974 * > DESCRIPTION
975 * > setuid() (setgid()) sets both the real and effective user ID
976 * > (group ID) of the current process as specified by uid (gid)
977 * > (see NOTES).
978 * >
979 * > seteuid() (setegid()) sets the effective user ID (group ID)
980 * > of the current process.
981 * >
982 * > setruid() (setrgid()) sets the real user ID (group ID) of
983 * > the current process.
984 * >
985 * > These calls are only permitted to the super-user or if the
986 * > argument is the real or effective user (group) ID of the
987 * > calling process.
988 * >
989 * > SYSTEM V DESCRIPTION
990 * > If the effective user ID of the calling process is not
991 * > super-user, but if its real user (group) ID is equal to uid
992 * > (gid), or if the saved set-user (group) ID from execve(2V)
993 * > is equal to uid (gid), then the effective user (group) ID is
994 * > set to uid (gid).
995 * > ....... etc etc
996 *
997 * Conclusions:
998 * 1. if EUID == ROOT or RUID == ROOT then you can set EUID, UID to anything
999 * 3. if EUID is root, you can set EUID
1000 *
1001 * General technique:
1002 * Initialization
1003 * - use setuid() system call to force EUID/RUID = ROOT
1004 *
1005 * Change
1006 * - assumes that initialization has been carried out and
1007 * EUID == ROOT or RUID = ROOT
1008 * - Use the seteuid() system call to set EUID
1009 *
1010 ***************************************************************************/
1011
1012 #if !defined(HAVE_SETREUID) && !defined(HAVE_SETEUID) && !defined(HAVE_SETRESUID)
1013 #error You need one of setreuid(), seteuid(), setresuid()
1014 #endif
1015
1016 /***************************************************************************
1017 * Commentary
1018 * setuid(), setreuid(), and now setresuid()
1019 * This is probably the easiest road.
1020 * Note: we will use the most feature ridden one first, as it probably
1021 * is necessary on some wierd system.
1022 * Patrick Powell Fri Aug 11 22:46:39 PDT 1995
1023 ***************************************************************************/
1024 #if !defined(HAVE_SETEUID) && !defined(HAVE_SETREUID) && defined(HAVE_SETRESUID)
1025 # define setreuid(x,y) (setresuid( (x), (y), -1))
1026 # define HAVE_SETREUID
1027 #endif
1028
1029 /***************************************************************************
1030 * Setup_uid()
1031 * 1. gets the original EUID, RUID, EGID, RGID
1032 * 2. if UID 0 or EUID 0 forces both UID and EUID to 0 (test)
1033 * 3. Sets the EUID to the original RUID
1034 * This leaves the UID (EUID)
1035 ***************************************************************************/
1036
Setup_uid(void)1037 void Setup_uid(void)
1038 {
1039 int err = errno;
1040 static int SetRootUID; /* did we set UID to root yet? */
1041
1042 if( SetRootUID == 0 ){
1043 OriginalEUID = geteuid();
1044 OriginalRUID = getuid();
1045 OriginalEGID = getegid();
1046 OriginalRGID = getgid();
1047 DEBUG1("Setup_uid: OriginalEUID %ld, OriginalRUID %ld",
1048 (long)OriginalEUID, (long)OriginalRUID );
1049 DEBUG1("Setup_uid: OriginalEGID %ld, OriginalRGID %ld",
1050 (long)OriginalEGID, (long)OriginalRGID );
1051 /* we now make sure that we are able to use setuid() */
1052 /* notice that setuid() will work if EUID or RUID is 0 */
1053 if( OriginalEUID == ROOTUID || OriginalRUID == ROOTUID ){
1054 /* set RUID/EUID to ROOT - possible if EUID or UID is 0 */
1055 if(
1056 # ifdef HAVE_SETEUID
1057 setuid( (uid_t)ROOTUID ) || seteuid( OriginalRUID )
1058 # else
1059 setuid( (uid_t)ROOTUID ) || setreuid( ROOTUID, OriginalRUID )
1060 # endif
1061 ){
1062 fatal(LOG_ERR,
1063 "Setup_uid: RUID/EUID Start %ld/%ld seteuid failed",
1064 (long)OriginalRUID, (long)OriginalEUID);
1065 }
1066 if( getuid() != ROOTUID ){
1067 fatal(LOG_ERR,
1068 "Setup_uid: IMPOSSIBLE! RUID/EUID Start %ld/%ld, now %ld/%ld",
1069 (long)OriginalRUID, (long)OriginalEUID,
1070 (long)getuid(), (long)geteuid() );
1071 }
1072 UID_root = 1;
1073 }
1074 DEBUG1( "Setup_uid: Original RUID/EUID %ld/%ld, RUID/EUID %ld/%ld",
1075 (long)OriginalRUID, (long)OriginalEUID,
1076 (long)getuid(), (long)geteuid() );
1077 SetRootUID = 1;
1078 }
1079 errno = err;
1080 }
1081
1082 /***************************************************************************
1083 * seteuid_wrapper()
1084 * 1. you must have done the initialization
1085 * 2. check to see if you need to do anything
1086 * 3. check to make sure you can
1087 ***************************************************************************/
seteuid_wrapper(uid_t to)1088 static int seteuid_wrapper( uid_t to )
1089 {
1090 int err = errno;
1091 uid_t euid;
1092
1093
1094 DEBUG4(
1095 "seteuid_wrapper: Before RUID/EUID %ld/%ld, DaemonUID %ld, UID_root %ld",
1096 (long)OriginalRUID, (long)OriginalEUID, (long)DaemonUID, (long)UID_root );
1097 if( UID_root ){
1098 /* be brutal: set both to root */
1099 if( setuid( ROOTUID ) ){
1100 logerr_die(LOG_ERR,
1101 "seteuid_wrapper: setuid() failed!!");
1102 }
1103 #if defined(HAVE_SETEUID)
1104 if( seteuid( to ) ){
1105 logerr_die(LOG_ERR,
1106 "seteuid_wrapper: seteuid() failed!!");
1107 }
1108 #else
1109 if( setreuid( ROOTUID, to) ){
1110 logerr_die(LOG_ERR,
1111 "seteuid_wrapper: setreuid() failed!!");
1112 }
1113 #endif
1114 }
1115 euid = geteuid();
1116 DEBUG4( "seteuid_wrapper: After uid/euid %ld/%ld", (long)getuid(), (long)euid );
1117 errno = err;
1118 return( to != euid );
1119 }
1120
1121
1122 /***************************************************************************
1123 * setruid_wrapper()
1124 * 1. you must have done the initialization
1125 * 2. check to see if you need to do anything
1126 * 3. check to make sure you can
1127 ***************************************************************************/
setruid_wrapper(uid_t to)1128 static int setruid_wrapper( uid_t to )
1129 {
1130 int err = errno;
1131 uid_t ruid;
1132
1133
1134 DEBUG4(
1135 "setruid_wrapper: Before RUID/EUID %ld/%ld, DaemonUID %ld, UID_root %ld",
1136 (long)OriginalRUID, (long)OriginalEUID, (long)DaemonUID, (long)UID_root );
1137 if( UID_root ){
1138 /* be brutal: set both to root */
1139 if( setuid( ROOTUID ) ){
1140 logerr_die(LOG_ERR,
1141 "setruid_wrapper: setuid() failed!!");
1142 }
1143 #if defined(HAVE_SETRUID)
1144 if( setruid( to ) ){
1145 logerr_die(LOG_ERR,
1146 "setruid_wrapper: setruid() failed!!");
1147 }
1148 #elif defined(HAVE_SETREUID)
1149 if( setreuid( to, ROOTUID) ){
1150 logerr_die(LOG_ERR,
1151 "setruid_wrapper: setreuid() failed!!");
1152 }
1153 #elif defined(__CYGWIN__)
1154 if( seteuid( to ) ){
1155 logerr_die(LOG_ERR,
1156 "setruid_wrapper: seteuid() failed!!");
1157 }
1158 #else
1159 # error - you do not have a way to set ruid
1160 #endif
1161 }
1162 ruid = getuid();
1163 DEBUG4( "setruid_wrapper: After uid/euid %ld/%ld", (long)getuid(), (long)geteuid() );
1164 errno = err;
1165 return( to != ruid );
1166 }
1167
1168
1169 /*
1170 * Superhero functions - change the EUID to the requested one
1171 * - these are really idiot level, as all of the tough work is done
1172 * in Setup_uid() and seteuid_wrapper()
1173 * We also change the groups, just to be nasty as well, except for
1174 * To_ruid and To_uid, which only does the RUID and EUID
1175 * Sigh... To every rule there is an exception.
1176 */
To_euid_root(void)1177 int To_euid_root(void)
1178 {
1179 return( seteuid_wrapper( ROOTUID ) );
1180 }
1181
1182 static int To_daemon_called;
1183
To_daemon(void)1184 int To_daemon(void)
1185 {
1186 Set_full_group( DaemonUID, DaemonGID );
1187 To_daemon_called = 1;
1188 return( seteuid_wrapper( DaemonUID ) );
1189 }
1190
To_user(void)1191 int To_user(void)
1192 {
1193 if( To_daemon_called ){
1194 Errorcode = JABORT;
1195 logmsg(LOG_ERR, "To_user: LOGIC ERROR! To_daemon has been called");
1196 abort();
1197 }
1198 /* Set_full_group( OriginalRUID, OriginalRGID ); */
1199 return( seteuid_wrapper( OriginalRUID ) );
1200 }
To_ruid(int ruid)1201 int To_ruid(int ruid)
1202 {
1203 return( setruid_wrapper( ruid ) );
1204 }
To_euid(int euid)1205 int To_euid( int euid )
1206 {
1207 return( seteuid_wrapper( euid ) );
1208 }
1209
1210 /*
1211 * set both uid and euid to the same value, using setuid().
1212 * This is unrecoverable!
1213 */
1214
setuid_wrapper(uid_t to)1215 int setuid_wrapper(uid_t to)
1216 {
1217 int err = errno;
1218 if( UID_root ){
1219 /* Note: you MUST use setuid() to force saved_setuid correctly */
1220 if( setuid( (uid_t)ROOTUID ) ){
1221 logerr_die(LOG_ERR, "setuid_wrapper: setuid(ROOTUID) failed!!");
1222 }
1223 if( setuid( to ) ){
1224 logerr_die(LOG_ERR, "setuid_wrapper: setuid(%ld) failed!!", (long)to);
1225 }
1226 if( to ) UID_root = 0;
1227 }
1228 DEBUG4("after setuid: (%ld, %ld)", (long)getuid(),(long)geteuid());
1229 errno = err;
1230 return( to != getuid() || to != geteuid() );
1231 }
1232
Full_daemon_perms(void)1233 int Full_daemon_perms(void)
1234 {
1235 Setup_uid();
1236 Set_full_group( DaemonUID, DaemonGID );
1237 return(setuid_wrapper(DaemonUID));
1238 }
1239
Full_root_perms(void)1240 int Full_root_perms(void)
1241 {
1242 Setup_uid();
1243 Set_full_group( ROOTUID, ROOTUID );
1244 return(setuid_wrapper( ROOTUID ));
1245 }
1246
Full_user_perms(void)1247 int Full_user_perms(void)
1248 {
1249 Setup_uid();
1250 Set_full_group( OriginalRUID, OriginalRGID );
1251 return(setuid_wrapper(OriginalRUID));
1252 }
1253
1254
1255 /***************************************************************************
1256 * Getdaemon()
1257 * get daemon uid
1258 *
1259 ***************************************************************************/
1260
Getdaemon(void)1261 int Getdaemon(void)
1262 {
1263 const char *str = 0;
1264 char *t;
1265 struct passwd *pw;
1266 int uid;
1267
1268 str = Daemon_user_DYN;
1269 DEBUG4( "Getdaemon: using '%s'", str );
1270 if(!str) str = "daemon";
1271 t = (char*)str;
1272 uid = strtol( str, &t, 10 );
1273 if( str == t || *t ){
1274 /* try getpasswd */
1275 pw = getpwnam( str );
1276 if( pw ){
1277 uid = pw->pw_uid;
1278 }
1279 }
1280 DEBUG4( "Getdaemon: uid '%d'", uid );
1281 if( uid == ROOTUID ) uid = getuid();
1282 DEBUG4( "Getdaemon: final uid '%d'", uid );
1283 return( uid );
1284 }
1285
1286 /***************************************************************************
1287 * Getdaemon_group()
1288 * get daemon gid
1289 *
1290 ***************************************************************************/
1291
Getdaemon_group(void)1292 int Getdaemon_group(void)
1293 {
1294 const char *str = 0;
1295 char *t;
1296 struct group *gr;
1297 gid_t gid;
1298
1299 str = Daemon_group_DYN;
1300 DEBUG4( "Getdaemon_group: Daemon_group_DYN '%s'", str );
1301 if( !str ) str = "daemon";
1302 DEBUG4( "Getdaemon_group: name '%s'", str );
1303 t = (char*)str;
1304 gid = strtol( str, &t, 10 );
1305 if( str == t ){
1306 /* try getpasswd */
1307 gr = getgrnam( str );
1308 if( gr ){
1309 gid = gr->gr_gid;
1310 }
1311 }
1312 DEBUG4( "Getdaemon_group: gid '%ld'", (long)gid );
1313 if( gid == 0 ) gid = getgid();
1314 DEBUG4( "Getdaemon_group: final gid '%ld'", (long)gid );
1315 return( gid );
1316 }
1317
1318 /***************************************************************************
1319 * set daemon uid and group
1320 * 1. get the current EUID
1321 * 2. set up the permissions changing
1322 * 3. set the RGID/EGID
1323 ***************************************************************************/
1324
Set_full_group(int euid,int gid)1325 int Set_full_group( int euid, int gid )
1326 {
1327 int status=0;
1328 int err;
1329 struct passwd *pw = 0;
1330
1331 DEBUG4( "Set_full_group: euid '%d'", euid );
1332
1333 /* get the user we want to set the groups for */
1334 pw = getpwuid(euid);
1335 if( UID_root ){
1336 setuid(ROOTUID); /* set RUID/EUID to root */
1337 #if defined(HAVE_INITGROUPS)
1338 if( pw ){
1339 /* froth froth... initgroups() uses the same buffer as
1340 * getpwuid... SHRIEK so we need to copy the user name
1341 */
1342 char user[256];
1343 safestrncpy(user,pw->pw_name);
1344 if( safestrlen(user) != safestrlen(pw->pw_name) ){
1345 fatal(LOG_ERR, "Set_full_group: CONFIGURATION BOTCH! safestrlen of user name '%s' = %d larger than buffer size %d",
1346 pw->pw_name, (int)safestrlen(pw->pw_name), (int)sizeof(user) );
1347 }
1348 if( initgroups(user, pw->pw_gid ) == -1 ){
1349 err = errno;
1350 logerr_die(LOG_ERR, "Set_full_group: initgroups failed '%s'",
1351 Errormsg( err ) );
1352 }
1353 } else
1354 #endif
1355 #if defined(HAVE_SETGROUPS)
1356 if( setgroups(0,0) == -1 ){
1357 err = errno;
1358 logerr_die(LOG_ERR, "Set_full_group: setgroups failed '%s'",
1359 Errormsg( err ) );
1360 }
1361 #endif
1362 status = setgid( gid );
1363 if( status < 0 ){
1364 err = errno;
1365 logerr_die(LOG_ERR, "Set_full_group: setgid '%d' failed '%s'",
1366 gid, Errormsg( err ) );
1367 }
1368 }
1369 return( 0 );
1370 }
1371
Setdaemon_group(void)1372 int Setdaemon_group(void)
1373 {
1374 Set_full_group( DaemonUID, DaemonGID );
1375 return( 0 );
1376 }
1377
1378
1379 /*
1380 * Testing magic:
1381 * if we are running SUID
1382 * We have set our RUID to root and EUID daemon
1383 * However, we may want to run as another UID for testing.
1384 * The config file allows us to do this, but we set the SUID values
1385 * from the hardwired defaults before we read the configuration file.
1386 * After reading the configuration file, we check the current
1387 * DaemonUID and the requested Daemon UID. If the requested
1388 * Daemon UID == 0, then we run as the user which started LPD.
1389 */
1390
Reset_daemonuid(void)1391 void Reset_daemonuid(void)
1392 {
1393 uid_t uid;
1394 uid = Getdaemon(); /* get the config file daemon id */
1395 DaemonGID = Getdaemon_group(); /* get the config file daemon id */
1396 if( uid != DaemonUID ){
1397 if( uid == ROOTUID ){
1398 DaemonUID = OriginalRUID; /* special case for testing */
1399 } else {
1400 DaemonUID = uid;
1401 }
1402 }
1403 DEBUG4( "DaemonUID %ld", (long)DaemonUID );
1404 }
1405
1406
1407 #ifdef HAVE_SYS_MOUNT_H
1408 # include <sys/mount.h>
1409 #endif
1410 #ifdef HAVE_SYS_STATVFS_H
1411 # include <sys/statvfs.h>
1412 #endif
1413 #ifdef HAVE_SYS_STATFS_H
1414 # include <sys/statfs.h>
1415 #endif
1416 #if defined(HAVE_SYS_VFS_H) && !defined(SOLARIS)
1417 # include <sys/vfs.h>
1418 #endif
1419
1420 # if USE_STATFS_TYPE == STATVFS
1421 # define plp_statfs(path,buf) statvfs(path,buf)
1422 # define plp_struct_statfs struct statvfs
1423 # define statfs(path, buf) statvfs(path, buf)
1424 # define USING "STATVFS"
1425 # define BLOCKSIZE(f) (double)(f.f_frsize?f.f_frsize:f.f_bsize)
1426 # define BLOCKS(f) (double)f.f_bavail
1427 # endif
1428
1429 # if USE_STATFS_TYPE == ULTRIX_STATFS
1430 # define plp_statfs(path,buf) statfs(path,buf)
1431 # define plp_struct_statfs struct fs_data
1432 # define USING "ULTRIX_STATFS"
1433 # define BLOCKSIZE(f) (double)f.fd_bsize
1434 # define BLOCKS(f) (double)f.fd_bfree
1435 # endif
1436
1437 # if USE_STATFS_TYPE == SVR3_STATFS
1438 # define plp_struct_statfs struct statfs
1439 # define plp_statfs(path,buf) statfs(path,buf,sizeof(struct statfs),0)
1440 # define USING "SV3_STATFS"
1441 # define BLOCKSIZE(f) (double)f.f_bsize
1442 # define BLOCKS(f) (double)f.f_bfree
1443 # endif
1444
1445 # if USE_STATFS_TYPE == STATFS
1446 # define plp_struct_statfs struct statfs
1447 # define plp_statfs(path,buf) statfs(path,buf)
1448 # define USING "STATFS"
1449 # define BLOCKSIZE(f) (double)f.f_bsize
1450 # define BLOCKS(f) (double)f.f_bavail
1451 # endif
1452
1453
1454 /***************************************************************************
1455 * Check_space() - check to see if there is enough space
1456 ***************************************************************************/
1457
Space_avail(const char * pathname)1458 double Space_avail( const char *pathname )
1459 {
1460 double space = 0;
1461 plp_struct_statfs fsb;
1462
1463 if( plp_statfs( pathname, &fsb ) == -1 ){
1464 DEBUG2( "Check_space: cannot stat '%s'", pathname );
1465 } else {
1466 space = BLOCKS(fsb) * (BLOCKSIZE(fsb)/1024.0);
1467 }
1468 return(space);
1469 }
1470
1471 /* VARARGS2 */
1472 #ifdef HAVE_STDARGS
safefprintf(int fd,const char * format,...)1473 int safefprintf (int fd, const char *format,...)
1474 #else
1475 int safefprintf (va_alist) va_dcl
1476 #endif
1477 {
1478 #ifndef HAVE_STDARGS
1479 int fd;
1480 char *format;
1481 #endif
1482 char buf[10240];
1483 VA_LOCAL_DECL
1484
1485 VA_START (format);
1486 VA_SHIFT (fd, int);
1487 VA_SHIFT (format, char *);
1488
1489 (void) plp_vsnprintf(buf, sizeof(buf), format, ap);
1490 return Write_fd_str( fd, buf );
1491 }
1492