📄 service.c
字号:
* connection has been closed by the remote site will now result * in an error, in which case we send the message to stderr. */ sigaction( SIGPIPE, NULL, &saved ); sigaction( SIGPIPE, NULL, &act ); act.sa_handler = SIG_IGN; sigaction( SIGPIPE, &act, NULL ); /* Send message to client (inc. terminating '\0') */ result = protSend( PROT_ERROR, Data.client, err, strlen( err ) + 1 ); /* * Send to remote site failed. Perhaps remote site has closed * connection we send the error message to stderr instead. */ if( result <= 0 ) { fprintf( stderr, "%s\n", err ); } /* Restore SIGPIPE */ sigaction( SIGPIPE, &saved, NULL );} /* * Protocol handler for PROT_COMMAND * According to the subtype of the protocol message, * dial a number or hangup the modem */static void serviceCommandHandler( protType type, void* data, size_t length ){ switch( protSubTypeOf( type ) ) { case MDM_DIAL: /* Dial a number; data contains number */ serviceDial( data ); break; case MDM_HANGUP: /* Hangup the modem */ serviceHangup(); break; case MDM_EXIT: /* Quit */ exit( 0 ); }}static void serviceSignalHandler( int sig ){ switch( sig ) { case SIGPIPE: exit( 0 ); case SIGQUIT: case SIGTERM: exit( 1 ); case SIGHUP: /* Modem hangup */ /* No more writes to modem device */ Data.modem = -1; /* Inform user */ error( "Modem disconnected, exiting!" ); exit( 0 ); }}/* * Exit routine */static void serviceExit(){ static int exiting = 0; /* * In error situations, it can happen that * this routine gets called recursively. So * we need a sort of semaphore to assure that * serviceHangup and mdm_reset are called just * once. */ if( exiting == 0 ) { /* Set semaphore */ exiting++; /* Hangup the modem */ if( Data.connected ) serviceHangup(); /* Only do the following when a modem was allocated */ if( Data.allocated == 1 ) { /* * Write a message to the acces log indicating the disconnection * of the client. When no modem was allocated we forget this user */ fprintf( ACCESS_LOG, "%s[%s] Disconnect from: \"%s@%s\"\n", timeStamp(), Data.localHost, Data.remoteUser, Data.remoteHost ); fflush( ACCESS_LOG ); } /* Reset modem device and terminal unless Data.modem is invalid * after SIGHUP has been received. */ if( Data.modem != -1 ) { /* Reset the modem */ mdm_reset( Data.modem ); ttyReset(); ttyHangup(); } /* Close and unlock modem device */ ttyClose(); shutdown( Data.client, 2 ); if( close( Data.client ) == -1 ) { FAIL( "close" ); exit( 1 ); } closeLog(); }}/* * This routine checks whether a user/host is allowed * to dial a number. * The routine executes a program (VERIFY_NUMBER or as defined in * configuration file as verify_number) that * actually does the check. * * The program is executed with the following arguments: * * argv: 0 1 2 3 * VERIFY_NUMBER remoteUser remoteHost number * * where VERIFY_NUMBER is the name of the program. * The program should return 0 when the user has permission * to dial the number and 1 otherwise. * * Function return: * 1 The user does not have permission to dial the number, * 0 The user does have permission. * */static int serviceCheckNumber( void ){ int retval; /* * Execute VERIFY_NUMBER script */ retval = sys_cmd( get_verify_number(), Data.remoteUser, Data.remoteHost, Data.number, NULL ); if( retval == -1 ) { FAIL1( "sys_cmd", get_verify_number() ); exit( 1 ); } /* Abnormal termination */ if( !WIFEXITED( retval ) ) exit( 1 ); if( WIFEXITED( retval ) ) return WEXITSTATUS( retval ); return 1;} /* * This routine dials a phonenumber. */static void serviceDial( const char* number ){ int result; /* If already connected, first disconnect */ if( Data.connected ) serviceHangup(); /* Save number to dial */ Data.number = strdup( number ); /* Check if user has permission to dial the number */ if( serviceCheckNumber() == 1) { error( "No permission to dial %s", number ); exit( 1 ); } /* Dial the number */ mdm_dial( Data.modem, number ); /* Wait on any reply from the modem */ result = matchText( connectStr, MATCH_ALL, serviceReadModem ); switch( result ) { /* CONNECT */ case 0: /* Save current time */ time( &Data.connected_since ); /* We're connected now */ Data.connected = 1; /* We are connected, get connectspeed from modem */ result = matchText( speedStr, MATCH_ALL, serviceReadModem ); /* Send speed as PROT_REPLY to client */ result = protSend( PROT_REPLY | MDM_CONNECT, Data.client, speedStr[result], strlen( speedStr[result] ) + 1 ); /* Result is evalutated below */ break; /* NO CARRIER */ case 1: result = protSend( PROT_REPLY | MDM_NO_CARIER, Data.client, NULL, 0 ); /* Result is evalutated below */ break; /* NO DIALTONE */ case 2: result = protSend( PROT_REPLY | MDM_NO_DIALTONE, Data.client, NULL, 0 ); /* Result is evalutated below */ break; /* ERROR */ case 3: result = protSend( PROT_REPLY | MDM_ERROR, Data.client, NULL, 0 ); /* Result is evalutated below */ break; /* NO ANSWER */ case 4: result = protSend( PROT_REPLY | MDM_NO_ANSWER, Data.client, NULL, 0 ); /* Result is evalutated below */ break; /* BUSY */ case 5: result = protSend( PROT_REPLY | MDM_BUSY, Data.client, NULL, 0 ); /* Result is evalutated below */ break; default: error( "UNKNOWN result: %d", result ); exit( 1 ); } /* result value of protSend is evaluated here */ /* EOF */ if( result == 0 ) exit( 0 ); /* Error */ if( result < 0 ) { FAIL( "protSend" ); exit( 1 ); }}/* * Hangup the modem and write a log message to * ACCOUNT_LOG * The log message is as follows: * * remoteUser@remoteHost,modemDevice,number,localHost,[startTime],[endTime] * */static void serviceHangup(){ char buf[100]; struct tm* tm; /* Hangup modem deice, unless Data.modem is invalid after * SIGHUP has been received. */ if( Data.modem != -1 ) mdm_hangup( Data.modem ); /* No log message when not connected */ if( !Data.connected ) return; tm = localtime( &Data.connected_since ); strftime( buf, sizeof(buf), "[%c]", tm ); fprintf( ACCOUNT_LOG, "%s@%s,%s,%s,%s,%s,%s\n", Data.remoteUser, Data.remoteHost, ttyDev(), Data.number, Data.localHost, buf, timeStamp() ); fflush( ACCOUNT_LOG ); /* We're not connected anymore */ Data.connected = 0;}/* * Function that reads a character from modem. * This function is used by matchText * * This function will be interrupted when data from * the client arrives. In that case, the function * longjumps to the loop in serviceMainLoop(). * * By doing so, the process does not block when waiting * for input from the modem. * */static char serviceReadModem(){ int retval; char c; fd_set fds; /* Make set of descriptors */ FD_ZERO( &fds ); FD_SET( Data.modem, &fds ); FD_SET( Data.client, &fds ); /* Wait on input on any of the descriptors in fds */ TEMP_FAILURE_RETRY( retval, select( FD_SETSIZE, &fds, NULL, NULL, NULL ) ); if( retval == -1 ) { FAIL( "select" ); exit( 1 ); } /* Input arrived from client, longjump tp serviceMainLoop() */ if( FD_ISSET( Data.client, &fds ) ) { longjmp( saved_env, 1 ); } /* * Data ready from modem, we can no savely * read that data and return. */ TEMP_FAILURE_RETRY( retval, read( Data.modem, &c, 1 ) ); if( retval < 0 ) { FAIL( "read" ); exit( 1 ); } if( retval == 0 ) { exit( 0 ); } /* Send data as PROT_DATA to client */ retval = protSend( PROT_DATA, Data.client, &c, 1 ); if( retval == 0 ) exit( 0 ); if( retval < 0 ) { FAIL( "protSend" ); exit( 1 ); } return c;}/* * EOF modemd/service.c */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -