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

📄 efax.c

📁 用于使用moden进行传真的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
  return err ;}/* Log a sent/received HDLC frame.  Display of these messages is delayed to   avoid possible timing problems. */void logfr ( char *s , char *nm , uchar *p , int n ){  int i=0 ;  msg ( n > 10 ? "H- %s %d bytes:" : "H-+ %s %d bytes:" , s, n ) ;  for ( i=0 ; i<n ; i++ ) {    msg ( "H-+  %02x" , p[i] & 0xff ) ;    if ( ( i&0xf ) == 0xf && i != n-1 ) msg ( "H-" ) ;  }  msg ( "H-" ) ;  msg ( "I- %s %s", s, nm ) ;}/* Send HDLC control frame of type type.  Extra bits can be OR'ed   into the frame type (FCF) to indicate that this frame follows   a previous one (no +FTH required) and/or that more frames will   follow.  Sets up flag, address, and fax control field bytes in   `buf'.  Sends these plus `len` additional bytes.  Terminates   with DLE-ETX and checks response.  Returns 0 if OK, 2 or 3 on   error. */#define MORE_FR  0x100 #define SUB_FR   0x200 int nframes = 0 ;		/* counts frames sent/received */int putframe ( int type, uchar *buf, int len, TFILE *f, int t ){  int err=0 ;  buf [ 0 ] = 0xff ;  buf [ 1 ] = type & MORE_FR ? 0xc0 : 0xc8 ;  buf [ 2 ] = type & 0xff ;  if ( nframes++ && ! ( type & SUB_FR ) )    ckcmd ( f, &err, "+FTH=3" , TO_FT, CONNECT ) ;    if ( ! err ) {    if ( ! buf[len+2] ) {      msg ( "Wlast byte of frame is NULL" ) ;    }    /* ttymode ( f, SEND ) ; */    sendbuf ( f, buf, len+3, 0 ) ;    tput ( f, DLE_ETX, 2 ) ;     /* ttymode ( f, COMMAND ) ; */    logfr ( "sent", frname ( buf [ 2 ] ), buf, len+3 ) ;    ckcmd ( f, &err, 0, TO_DRAIN_H, ( type & MORE_FR ) ? CONNECT : OK ) ;  }  return err ;}/* Reverse bit and byte order of ID strings as per T.30 5.3.6.2.4-6 */void revcpy ( uchar *from , uchar *to ){  int i, j ;  for ( i=0, j=IDLEN-1 ; i<IDLEN ; i++, j-- )     to [ i ] = normalbits [ from [ j ] & 0xff ] ;}/* Check for missing initial 0xFF in HDLC frame and insert it if   missing.  Ugly fix for a still-hidden bug.  Also do bit   inversion if required. */int fixframe ( uchar *buf, int n, TFILE *f ){  int i;  if ( *buf == 0xc0 || *buf == 0xc8 ) {    for ( i=n; i >= 1 ; i-- )       buf[i]=buf[i-1] ;    buf[i] = 0xff ;    msg ("W HDLC frame missing initial 0xff" ) ;    n++ ;  }  if ( buf[1] == 0x03 || buf[1] == 0x13 ) {    for ( i=0 ; i < n ; i++ )       buf[i]=normalbits[buf[i]] ;    msg ("W bit-reversed HDLC frame, reversing bit order" ) ;    f->ibitorder = f->ibitorder == normalbits ? reversebits : normalbits ;  }  return n ;}/* Read HDLC frame data.  Returns 0 if OK, 1 on frame error, 3 on   timeout, invalid response or too-long frame. */int receive_frame_data ( TFILE *f, uchar *buf, int n, int *len ){  int err=0, c, i ;  for ( i=0 ; ( c = tgetd ( f, T3S ) ) >= 0  ; i++ )    if ( i < n ) buf[ i ] = c ;    if ( c == EOF ) {    err = msg ( "E3timed out reading frame data" ) ;  } else {        switch ( cmd ( f, 0, TO_RTCMD ) ) {    case OK:    case CONNECT:      break ;    case ERROR:    case NO:      err = msg ( "W1frame error" ) ;      break ;    case EOF:      err = msg ( "E3no response after frame data" ) ;      break ;    default:      err = msg ( "E3wrong response after frame data" ) ;      break ;    }  }  if ( i >= n )     err = msg ( "E3frame too long (%d, > %d max bytes)", i, n ) ;    if ( len ) *len = i ;  return err ;}/* Get a Class 1 command or response frame.  An attempt to match   and combine T.30 "Response Received?" and "Command Received?"   protocol flowcharts.   When receiving commands returns after first correct   non-optional frame or after the time given by getcmd has   elapsed.  This is instead of looping through main flowchart.   When receiving responses returns on the first detected   non-optional frame, after timeout T4, or on errors.   Returns immediately if gets a +FCERROR response so can retry   as data carrier.  Returns DCN as a valid frame instead of   hanging up.   Returns the command/response received, or EOF on timeout or   error. */int getfr ( TFILE *mf, uchar *buf, int getcmd ){  int err=0, frame=0, frlen, c, t ;  char remoteid [ IDLEN + 1 ] ;  time_t start ;  uchar *fif=buf+3 ;    start = 10*time(0) ;    t = getcmd ? ( getcmd > 1 ? getcmd : T2 ) : T4 ; Enter:  err = 0 ;  if ( nframes++ ) {    c = cmd ( mf, "+FRH=3", t ) ;  } else {    c = CONNECT ;		/* implied by ATA or ATD */  }    switch ( c ) {  case EOF:			/* time out */    tput ( mf, CAN_STR, 1 ) ;    ckcmd ( mf, 0, 0, TO_ABRT, OK ) ;    err = 1 ;    break ;  case NO:			/* S7 time out */    err = 1 ;    break ;  case MODULATION:		/* data carrier (or DHS) */    return -msg ( "W-2 wrong carrier" ) ;    break ;  case CONNECT:			/* frame */    break ;  default:			/* shouldn't happen */    err = msg ( "E3wrong response to receive-frame command" ) ;    break ;  }    if ( ! err )     err = receive_frame_data ( mf, buf, MAXFRLEN, &frlen ) ;    if ( ! err && frlen < 3 )     err = msg ( "E3received short frame (%d bytes)", frlen ) ;  logfr ( "received", frname ( buf [ 2 ] ), buf, frlen ) ;  if ( ! err ) {    frlen = fixframe ( buf, frlen, mf ) ;    frame = buf [ 2 ] & 0x7f ;    switch ( frame ) {    case CRP:      err = 1 ;    case NSF:    case NSC:    case NSS:      goto Enter ;    case CIG:    case CSI:    case TSI:      revcpy ( fif , (uchar*) remoteid ) ;      msg ( "I- remote ID -> %*.*s", IDLEN, IDLEN, remoteid ) ;      goto Enter ;    }  }    if ( err && getcmd && ( t -= 10*time(0) - start ) > 0 )     goto Enter ;  return err ? EOF : frame ;}/* Class 1 send/receive.    The logic in this function is a mess because it's meant to  mirror the flowchart in ITU-T recommendation T.30 which is the  protocol specification.  */int c1sndrcv ( 	      TFILE *mf, cap local, char *localid, 	      OFILE *outf, IFILE *inf, 	      int pages, char *header, faxfont *font, 	      int maxpgerr, int noretry, int calling ){   int err=0, rxpage=0, page=1, t, disbit, good, frame, last, nerr ;  int rxdislen, ppm, try=0, pagetry=0, retry=0, remtx=0, remrx=0 ;  int writepending=0, dp=0 ;  cap remote = { DEFCAP }, session = { DEFCAP } ;  char *fname=0 ;  uchar buf [ MAXFRLEN ], *fif=buf+3 ;  if ( ! calling ) goto RX ;  /* Class 1 Transmitter: */ T:  /* Transmitter Phase B - wait for DIS or DTC */  pagetry = 0 ;    frame = getfr ( mf, buf, T1 ) ;    if ( frame <= 0 ) {    err = msg ( "E3no answer from remote fax" ) ;    goto B ;  }    if ( frame != DIS && frame != DTC ) {    msg ( "W2 can't open page" ) ;    goto C ;  }  disbit = ( frame == DIS ) ? 0x80 : 0x00 ;  try = 0 ; A:				/* decide to send or receive after DIS/DTC */  if ( frame == DIS || frame == DTC ) {    rxdislen = dislen ( fif ) ;    mkcap ( fif, remote, 1 ) ;    remtx = fif[1] & 0x80 ;    remrx = fif[1] & 0x40 ;  }  msg ( "N remote has %sdocument(s) to send, and can %sreceive",       remtx ? "" : "no ", remrx ? "" : "not " ) ;  if ( pages > 0 ) {    if ( ! remrx ) msg ( "W remote cannot receive, trying anyways" ) ;     goto D ;  } else {    if ( ! remtx ) msg ( "W remote has nothing to send, trying anyways" )  ;     goto R ;  } D:				/* send DCS */  if ( rdpage ( inf, dp, &ppm, local, 0 ) ) {    err = msg ( "E2can't open page" ) ;    goto B ;  } D_2:  mincap ( local, remote, session ) ;  revcpy ( (uchar*) localid, fif ) ;  if ( ! err )     err = putframe ( TSI | MORE_FR | disbit, buf, IDLEN, mf, -1 ) ;    mkdis ( session, fif, DCSLEN, 0, pages ) ;  if ( ! err )     err = putframe ( DCS | SUB_FR | disbit, buf, DCSLEN, mf, -1 ) ;#ifdef USEFTS  if ( cmd ( mf, "+FTS=" MODDLY, T3S ) != OK )#endif    msleep ( TMOD ) ;		/* if +FTS not supported */  if ( ! err )     err = puttrain ( mf, c1cmd[SND][TRN][session[BR]], 		    TCFSECS*cps [ session[BR] ] ) ;  try++ ;  if ( ! err ) {    cmd ( mf, "+FRS=1", T3S ) ; /* wait for TCF carrier to drop */    frame = getfr ( mf, buf, 0 ) ;  }  if ( err || frame < 0 ) {    if ( try >= 3 ) {      goto C_timeout ;    } else {       goto D_2 ;    }  }    switch ( frame ) {  case DIS:  case DTC:    if ( try >= 3 ) goto C_timeout ;    else goto A ;  case FTT:    msg ( "I channel not usable at %d bps", 8*cps[session[BR]] ) ;    remote[BR] = fallback[session[BR]] ;    if ( remote[BR] >= 0 ) goto D_2 ;    else { err = msg ( "E2 channel not usable at lowest speed" ) ; goto C ; }  case CFR:    goto I_2 ;  default:    err = msg ( "E3 invalid response to DCS (0x%02x)", frame ) ;    goto C ;  }     I:				/* send a page */  if ( rdpage ( inf, dp, &ppm, local, 0 ) ) {    err = msg ( "E2can't open page" ) ;    goto B ;  } I_2:  ckcmd ( mf, &err, c1cmd [SND][DTA][session[BR]], TO_FT, CONNECT ) ;  if ( !err ) {    msleep ( 1000 ) ;    err = send_data ( mf, inf, page, pages, local, session, header, font ) ;  }  pagetry++ ;  if ( !err )    err = end_data ( mf, session, 0, 0 ) ;  #ifdef USEFTS  if ( cmd ( mf, "+FTS=" MODDLY, T3S ) != OK )#endif    msleep ( TMOD ) ;		/* if +FTS not supported */				/* fix ppm if on last page of stdin */  if ( lastpage ( inf ) ) ppm = EOP ;  try = 0 ; sendppm:  if ( !err ) err = putframe ( ppm | disbit, buf, 0, mf, -1 ) ;  try++ ;    frame = getfr ( mf, buf, 0 ) ;  if ( frame < 0 ) {    if ( try >= 3 ) {      goto C_timeout ;    } else {       goto sendppm ;    }  }  fname = inf->page->fname ;  switch ( noretry ? MCF : frame ) { /* common retry logic */  case MCF:  case RTP:  case PIP:    fname = inf->page->fname ;    if ( fname ) msg ( "Isent -> %s", fname ) ;    pagetry=0 ;    page++ ;    dp = 1 ;    break ;  case PIN:  case RTN:    dp = 0 ;    retry = pagetry < NTXRETRY ;    break ;  default:      err = msg ( "E3invalid post-page response (0x%02x)", frame ) ;    goto C ;  }    switch ( ppm ) {      case MPS:    switch ( frame ) {    case PIN: goto E ;    case PIP: goto E ;    case MCF: goto I ;    case RTP: goto D ;    case RTN: goto D ;    }  case EOP:    switch ( frame ) {    case PIN: goto E ;    case PIP: goto E ;    case MCF:     case RTP:       nextipage ( inf, 1 ) ;	/* skip ahead to mark all files done */      if ( remtx ) goto R ;	/* poll after sending */      else goto C ;    case RTN:       if ( retry ) goto D ;      else goto C ;    }      case EOM:    switch ( frame ) {    case PIN: goto E ;    case PIP: goto E ;    case MCF:     case RTP:     case RTN:       cmd ( mf, "+FRS=20", T3S ) ; /* wait for ppr carrier to drop */      if ( retry ) goto T ;      else goto T ;    }      }   E:				/* ignore PIN and PIP */  msg ( "W interrupt request ignored" ) ;  try=0 ;  goto A ;  /* Class 1 Receiver */ RX: R:  /* Receiver Phase B */

⌨️ 快捷键说明

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