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( &current_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