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