⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 virtmodem.c

📁 Modem通讯程序包
💻 C
字号:
/* * $Id: virtmodem.c,v 1.7 1998/02/17 09:53:39 mdejonge Exp $ * *   $Source: /home/mdejonge/CVS/projects/modem/tests/virtmodem.c,v $ * $Revision: 1.7 $ *    Author: Merijn de Jonge *     Email: mdejonge@wins.uva.nl * * * * This file is part of the modem communication package. * Copyright (C) 1996-1998  Merijn de Jonge *  * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. *  * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. *  * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * */#ifdef HAVE_CONFIG_H#include <config.h>#endif#include <stdio.h>#include <sys/types.h>#include <unistd.h>#include <signal.h>#include <string.h>#include <time.h>#include <setjmp.h>#include <sys/wait.h>#include <stdlib.h>#include <libport/libport.h>#include <liberror/liberror.h>#include <libtty/libtty.h>/* Device name of virtual modem */static char* virtModemDev;/* Shell script executed to simulate a connection with a remote site */#define VIRTMODEMSCRIPT  "./virtmodem.sh"static pid_t   childPid = -1;static jmp_buf saved_env;static int terminated = 0;typedef struct {   int master;   int slave;   char slaveDevName[20];} PTY;PTY remote;PTY local;/*  * Open pseudo terminal and return PTY structure with file descriptors * and name of slave terminal */PTY openPty(){   PTY pty;      /* Open master device */   pty.master = openPtyMaster( pty.slaveDevName );   if( pty.master == -1 )   {      FAIL( "openPty" );      exit( 1 );   }      /* And open slave pty */   pty.slave = openPtySlave( pty.slaveDevName );   if( pty.slave == -1 )   {      FAIL( "openPtySlave" );      exit( 1 );   }   return pty;}void signalHandler( int sig ){   switch( sig )   {      case SIGCHLD:         /* Exit when child has died */         if( childPid == -1 )            return;         if( waitpid( childPid, NULL, 0 ) == -1 )         {            FAIL( "waitpid" );            exit( 1 );         }         childPid = -1;         /* Close pseudo terminal (That is, simulte a modem hangup */         close( local.master );                  /* Indicate that we're done */         terminated = 1;         return;      case SIGINT:         exit( 0 );   }}/* Fork and execute child program (VIRTMODEMSCRIPT) */void startChild(){   childPid = fork();   switch( childPid )   {      case -1:         FAIL( "fork" );         exit( 1 );      case 0:         /* stdin/stdout connected to remote pseudo terminal */         dup2( remote.slave, STDIN_FILENO );         dup2( remote.slave, STDOUT_FILENO );                  execl( VIRTMODEMSCRIPT, VIRTMODEMSCRIPT, NULL );         FAIL1( "execl", VIRTMODEMSCRIPT );          _exit( 1 );   }}/*  * Exit routine, remove symbolic link to pseudo terminal and * kill child process if it still exists. */void myExit(){   if( unlink( virtModemDev ) == -1 )   {      FAIL1( "unlink", virtModemDev );   }   if( childPid != -1 )   {      kill( childPid, SIGHUP );   }}void copyData(){      int    from;   int    to;   int    result;   fd_set fds;   int    bytes;   char   buf[512];   /* Copy data between pseudo terminals until exit */   while( 1 )   {      FD_ZERO( &fds );      FD_SET( remote.master, &fds );      FD_SET( local.master, &fds );            /* Use select to wait for any data */      TEMP_FAILURE_RETRY( result,                          select( FD_SETSIZE, &fds, NULL, NULL, NULL ) );      if( result == -1 )      {         /* If we got an error because telnet session has terminated,          * We long jump to start a new session          */         if( terminated == 1 )            longjmp( saved_env, 1 );         FAIL( "select" );         exit( 1 );      }            /* Data from remote pseudo terminal */      if( FD_ISSET( remote.master, &fds ) )      {         from = remote.master;         to   = local.master;      }      else      /* Data from local pseudo terminal */      if( FD_ISSET( local.master, &fds ) )      {         from = local.master;         to   = remote.master;      }      else      {          error( "Unknown error during select" );         exit( 1 );      }            /* read data from sending pseudo terminal... */      TEMP_FAILURE_RETRY( bytes, read( from, buf, sizeof buf ) );      if( bytes < 0 )      {         FAIL( "read" );         exit( 1 );      }      if( bytes == 0 )      {           /* Telnet session terminated; start a new session */         if( childPid != -1 )            kill( childPid, SIGHUP );         /* long jump to restart telnet session */         longjmp( saved_env, 1 );      }               /* ... and send it to the other pseudo terminal */      TEMP_FAILURE_RETRY( bytes, write( to, buf, bytes ) );      if( bytes < 0 )      {         FAIL( "write" );         exit( 1 );      }      if( bytes == 0 )      {           /* Telnet session terminated; start a new session */            if( childPid != -1 )               kill( childPid, SIGHUP );         /* Long jump to restart telnet session */         longjmp( saved_env, 1 );      }   }}int main( int argc, char* argv[] ){   struct sigaction act;   int    result;   if( argc != 2 )   {      error( "usage: %s dev", argv[0] );      error( "   dev   name of virtual modem device (/tmp/virtmodem for example)" );            exit( 1 );   }   virtModemDev = argv[1];      /* Install handler for SIGINT and SIGCHLD*/   sigemptyset( &act.sa_mask );   act.sa_handler = signalHandler;#ifdef SA_RESTART   act.sa_flags   = SA_RESTART;#endif               sigaction( SIGINT, &act, NULL );   sigaction( SIGCHLD, &act, NULL );   /* Cleanup required on termination */   atexit( myExit );   /* Open remote pseudo terminals */   remote = openPty();      /* Continuously spawn a telnet session and     * copy data between telnet session and modem server    */   while( 1 )   {      if( setjmp( saved_env ) == 1 )      /* Non-local jump from copyData when telnet session terminates       * We resart and spawn a  new session       */         continue;      /* Open local pseudo terminal */      local  = openPty();      /* put local slave into raw terminal mode */      ttySetRaw( local.slave );      /* Remove symbolic link if it still exists */      unlink( virtModemDev );      /* Create symbolic link to opended local pseudo terminal device */      result = symlink( local.slaveDevName, virtModemDev );      if( result == -1 )      {         FAIL1( "symlink", virtModemDev );         exit( 1 );      }      /* Fork child process */      startChild();      terminated = 0;            /* Copy data between teh two pseudo terminals */      copyData();   }   }/* EOF tests/virtmodem.c */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -