/************************************************************************** * LPRng IFHP Filter * Copyright 1994-1999 Patrick Powell, San Diego, CA **************************************************************************/ /**** HEADER *****/ static char *const _id = "$Id: open_device.c,v 1.23 2004/02/25 15:56:25 papowell Exp papowell $"; #include "ifhp.h" void Open_device( char *device ) { int fd = -1; struct stat statb; int attempt = 0; DEBUG1("Open_device: device '%s'", device); if( fstat(1,&statb) == 0 && S_ISSOCK(statb.st_mode) ){ char msg[32]; DEBUG1("Open_device: closing socket"); shutdown(1,1); while( read(1,msg,sizeof(msg)) > 0 ); } close(1); DEBUG1("Open_device: closed fd 1"); Errorcode = 0; if( (device[0] == '/') ){ for( ; fd < 0; ++attempt, plp_usleep(Dev_sleep * 1000) ){ DEBUG1("Open_device: device '%s', attempt %d", device, attempt); fd = open( device, (Status?O_RDWR:O_WRONLY)|O_APPEND|O_CREAT|O_NONBLOCK, 0600 ); /*Set_max_fd(fd);*/ if( fd < 0 ){ if( Dev_retries < 0 || (Dev_retries >0 && attempt >= Dev_retries) ){ Errorcode = JABORT; LOGERR_DIE(LOG_INFO)"Open_device: open '%s' failed", device); } } else { break; } } if( isatty( fd ) && Stty_args){ Do_stty( fd, Stty_args ); } /* can we get status */ } else { fd = Link_open( device ); } if( fd != 1 ){ Errorcode = JABORT; LOGERR_DIE(LOG_INFO)"Open_device: did not open on fd 1"); } if( Status ){ Status = Fd_readable(1, &Poll_for_status); } Set_block_io(1); Set_keepalive(1); DEBUG1("Open_device: success"); } void Set_keepalive( int sock ) { #ifdef SO_KEEPALIVE int option = 0; int len; len = sizeof( option ); setsockopt( sock, SOL_SOCKET, SO_KEEPALIVE, (char *)&option, sizeof(option) ); #endif } int Link_open( char * device ) { char *s, *end; int fd = -1, port, option, attempt = 1; struct hostent *hostent; struct sockaddr_in sin; int src_port = 0; char *dcopy = 0; dcopy = safestrdup( device,__FILE__,__LINE__ ); if( (end = strchr( dcopy, '%' )) == 0 ){ Errorcode = JABORT; FATAL(LOG_INFO)"Link_open: missing port number '%s'",device ); } *end++ = 0; s = end; port = strtol( end, &s, 0 ); if( port <= 0 ){ Errorcode = JABORT; FATAL(LOG_INFO)"Link_open: bad port number '%s'",end ); } end = s; if( end && *end ){ *end++ = 0; src_port = strtol( end, 0, 0 ); } hostent = gethostbyname(dcopy); if( hostent && hostent->h_addrtype != AF_INET ){ Errorcode = JABORT; FATAL(LOG_INFO)"Link_open: bad address type for host '%s'", device); cleanup(0); } for( ; fd < 0; ++attempt, plp_usleep(Dev_sleep * 1000) ){ memset( &sin, 0, sizeof(sin) ); sin.sin_family = AF_INET; /* * set up the address information */ if( hostent ){ memmove( &sin.sin_addr, hostent->h_addr, hostent->h_length ); } else { sin.sin_addr.s_addr = inet_addr(dcopy); if( (int)sin.sin_addr.s_addr == -1){ Errorcode = JABORT; FATAL(LOG_INFO)"Link_open: getconnection: unknown host '%s'", device); cleanup(0); } } sin.sin_port = htons( port ); DEBUG1("Link_open: destination '%s' port %d, attempt %d", inet_ntoa( sin.sin_addr ), ntohs( sin.sin_port ), attempt ); fd = socket (AF_INET, SOCK_STREAM, 0); if( fd < 0 ){ Errorcode = JABORT; LOGERR_DIE(LOG_INFO) "Link_open: socket() failed" ); if( Dev_retries <= 0 || (Dev_retries > 0 && attempt >= Dev_retries) ){ Errorcode = JABORT; LOGERR_DIE(LOG_INFO)"Link_open: open '%s' failed", device); } continue; } option = 1; if( setsockopt( fd, SOL_SOCKET, SO_REUSEADDR, (char *)&option, sizeof(option) ) ){ Errorcode = JABORT; LOGERR_DIE(LOG_INFO) "Link_open: setsockopt failed" ); } if( src_port ){ struct sockaddr_in src_sin; memset( &src_sin, 0, sizeof(src_sin) ); src_sin.sin_family = AF_INET; src_sin.sin_port = htons( src_port ); if( bind( fd, (struct sockaddr *)&src_sin, sizeof( src_sin )) < 0 ){ LOGERR(LOG_INFO)"Link_open: bind failed"); close(fd); fd = -1; ++src_port; continue; } } if( connect(fd, (struct sockaddr *) & sin, sizeof (sin)) < 0 ){ Errorcode = JFAIL; LOGERR(LOG_INFO)"Link_open: connect to '%s port %d' failed", inet_ntoa( sin.sin_addr ), ntohs( sin.sin_port ) ); close(fd); fd = -1; continue; } if( fd >= 0 ) break; } if( dcopy ) free(dcopy); dcopy = 0; return(fd); } #if !defined(HAVE_INET_NTOP) /*************************************************************************** * inet_ntop( int family, const void *addr, * const char *strptr, int len ) * p means presentation, i.e. - ASCII C string * n means numeric, i.e. - network byte ordered address * family = AF_Protocol or AF_Protocol6 * addr = binary to convert * strptr = string where to place * len = length ***************************************************************************/ const char *inet_ntop( int family, const void *addr, char *str, size_t len ) { char *s; if( family != AF_INET ){ FATAL(LOG_INFO) "inet_ntop: bad family '%d'", family ); } s = inet_ntoa(((struct in_addr *)addr)[0]); strncpy( str, s, len ); return(str); } #endif const char *inet_ntop_sockaddr( struct sockaddr *addr, char *str, int len ) { void *a = 0; /* we get the printable from the socket address */ if( addr->sa_family == AF_INET ){ a = &((struct sockaddr_in *)addr)->sin_addr; #if defined(IN6_ADDR) } else if( addr->sa_family == AF_INET6 ){ a = &((struct sockaddr_in6 *)addr)->sin6_addr; #endif } else { FATAL(LOG_INFO)"inet_ntop_sockaddr: bad family '%d'", addr->sa_family ); } return( inet_ntop( addr->sa_family, a, str, len ) ); }