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

📄 efax.c

📁 使用efax的fax工具程序
💻 C
📖 第 1 页 / 共 4 页
字号:
#define Copyright         "Copyright 1995  Ed Casas"#define Version		  "efax v 0.7a"/*    Copyright (C) 1995  Ed Casas    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.    Please contact the author if you wish to use efax or efix for    purposes not covered by the GNU GPL.    You may contact the author by e-mail at: edc@cce.com, by mail    at: 2629 West 3rd Ave, Vancouver, BC, Canada, V6K 1M4, or by    fax at: +1 604 734 5291.*//*    Modified slightly by Robert LeBlanc <rjl@renaissoft.com> for    use with the Qfax suite of fax utilities.  The only change was    to make efax write its terminating status code to the RESULT    file (as specified in a "config.h" file), so that the spooler    can access this result at a later time.*/const char *Usage =  "Usage:\n"/*"  %s [ option ]... [ -r pat | -t num file... ]\n"*/  "  %s [ option ]... [ -r pat | -t num file... | -p num pat ]\n"  "Options:\n"  "  -c cap  set file format or receive capabilites to cap\n"  "  -d dev  use modem on device dev\n"  "  -g cmd  exec \"/bin/sh -c cmd\" for data calls\n"  "  -i str  send modem command ATstr at start\n"  "  -l id   set local indetification to id\n"  "  -o opt  use protocol option opt:\n"/*"      0     use class 2.0 instead of class 2 modem commands\n"*/  "      1     use class 1 modem commands\n"  "      a     if first [data mode] answer attempt fails retry as fax\n"  "      e     ignore errors in modem initialization commands\n"  "      r     reverse bit order on receive\n"    "      x     use XON instead of DC2 to trigger reception\n"  "      z     add 100 ms to pause before each modem comand (cumulative)\n"  "  -h hdr  use page header hdr (use %%d's for current page/total pages)\n"  "  -f fnt  use (PBM) font file fnt for headers\n"  "  -q ne   ask for retransmission if more than ne errors per page\n"  "  -s      share (unlock) modem device while waiting for call\n"  "  -v lvl  print messages of type in string lvl (ewinchamr)\n"  "  -w      don't answer phone, wait for OK or CONNECT instead\n"  "  -x fil  use uucp-style lock file fil\n"  "  -z str  send modem command ATstr when done\n"  "Commands:\n"  "  -r      answer and receive fax into files pat.001, pat.002, ... \n"  "  -t      send fax image files file... to telephone num\n"  "  -p      poll num for pat.001, ... \n"  ;#include <ctype.h>		/* ANSI C */#include <signal.h>    #include <stdio.h>#include <stdlib.h>#include <string.h>#include <time.h>#include "efaxlib.h"		/* EFAX */#include "efaxos.h"#include "../config.h"             /* QFAX 1.0 *//* constants... */#define FAXFILE "/dev/fax"  /* default fax modem device */			    /* delays and timeouts (t/o), in deciseconds */#define TO_RESET  26	    /* t/o for modem reset commands (per Hayes) */#define T_CMD     1	    /* pause before each modem command */#define TO_A      1200	    /* dial/answer (Phase A) - modem may t/o first */#define TO_DATAF  215	    /* software adaptive answer data connect t/o */#define T1 350		    /* T.30 T1 - waiting for DIS/DCS before Phase B */#define T2 60		    /* T.30 T2 - waiting for frame in Phase B */#define T3S 30		    /* T.30 response timeout (not T3) */#define T4 30		    /* T.30 T4 - between [re]transmissions of DIS */#define TO_DRAIN 136	    /* minimum buffer drain time (4k/300cps)(tx) */#define TO_RTCMD 20	    /* return to command mode after DLE-ETX (rx) */#define TO_FT    31	    /* max delay after +F[TR][MH] command */#define TO_CHAR  51	    /* per data character (max FILL length) */#define TO_ABRT  20	    /* max delay after sending abort sequence */#define TO_C2B    450	    /* Class 2 DIS to CONNECT:(DCS+TCF+CFR)xretries */#define TO_C2X    20	    /* Class 2 wait for XON: 2/5 of 5s timeout */#define TO_C2PP   200	    /* Class 2 wait for ppr: (ppm+ppr)x3retries + 2 */#define TO_C2R    600	    /* Class 2 receive: (TCF+FTT)x11 retrains + 5 */#define TO_C2EOR  120	    /* Class 2 end of data rx (4 retrans x 3 s) */#define CMDBUFSIZE 256      /* longest possible modem command or response */#define DEFDISLEN 3	    /* length of DIS initially transmitted */#define DEFCAP 1,3,0,2,0,0,0,0	/* default local capabilities */#define DLE_ETX "\020\003"  /* DLE-ETX (end of data) string */#define HDRSHFT 54	    /* shift header 6.7mm to image area */#define HDRSPCE 20	    /* number of scan lines inserted before image */#define HDRSTRT  4	    /* scan line where header is placed on image */#define IDLEN 20	    /* length of T.30 identification strings */#define LOCKPOLLDELAY 15    /* seconds between checks of lock files */#define MAXDIS 8	    /* maximum DIS frames sent without response (T1) */#define MAXERRPRT 32	    /* maximum number of reception errors to report */#define MAXFIFLEN 125	    /* max FIF len = MAXFRLEN - (adx+ctl+FCF) - FCS */#define MAXFRLEN 130        /* max frame length = 3.45s x 300 bps / 8 */#define MAXGETTY 512        /* maximum length of ``getty'' (-g) command */#define MAXICMD  100        /* maximum # of modem setup/reset commands */#define MAXLKFILE 16	    /* maximum number of lock files */#define MAXMSGBUF 8192	    /* maximum status/error message bytes held */#define MAXNULLS 2	    /* maximum consecutive received nulls saved */#define MAXTRAIN 2	    /* maximum training retries at lowest speed */#define MAXRESPB 1024	    /* maximum bytes of modem responses saved */#define MAXRETRY 3	    /* maximum retries of unacknowledged commands */#define MINWRITE  128       /* minimum bytes before write() to modem */#define NCAP 8              /* number of fields in a capability string */#define NTXRETRY  3	    /* maximum re-sends per page */const char *prompts[] = {		/* modem responses that are prompts */  "OOK", "-CONNECT FAX", "CCONNECT", "NNO CARRIER", "EERROR",  "NNO DIALTONE", "BBUSY", "NNO ANSWER", "E+FCERROR", 0 } ;enum promptcodes {			/* codes for modem prompts */   BUSY = 'B', CONNECT = 'C', OK = 'O', RING = 'R', NO = 'N',   ERROR = 'E' } ;			    /* signals to be caught so can hang up phone */const int catch [] = { CATCHSIGS, 0 } ;typedef int cap [ NCAP ] ;		/* remote/local capabilities */                                        /* capability fields... */enum  captype {	               VR, BR, WD, LN, DF, EC, BF, ST } ;const int capmax [ NCAP ] = {   1,  7,  2,  2,  3,  2,  1,  7 } ;					/* & maximum values */					/* characters per second for br */const int cps [ 8 ] = { 300, 600, 900, 1200, 1500, 1800, 900, 1200 } ;					/* next br = fallback [ br ] */const int fallback [ 8 ] = { 0, 0, 1, 2, 7, 4, 3, 6 } ;					/* minimum scan time in ms  */const int delay [ 8 ] = { 0 , 5, 10, 10, 20, 20, 40, 40 } ;					/* page width in pixels */const int pagewidth [ 3 ] = { 1728, 2048, 2432 } ;/* Table to convert between T.30 DIS/DCS/DTC FIF and Class 2-like   capability codes. Uses br=6, 7 for V.17 at 7200, 9600. */typedef const struct t30tabstruct{   char *name ;   u_char byte, shift, mask ;   u_char captodis[8], distocap[16], captodcs[8], dcstocap[16] ; } t30tabst ;#define X 0xff				/* invalid values */t30tabst t30tab [ NCAP ] = {  { "vr", 1, 1, 0x01, { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } },	   { "br", 1, 2, 0x0f,       { 0, 4, 12, 12, 13, 13 } ,      { 0, X, X, X, 1, X, X, X, 3, X, X, X, 3, 5, 3, X } ,      { 0, 4, 12, 8, 5, 1 } ,      { 0, 5, 5, X, 1, 4, 4, X, 3, 7, X, X, 2, 6, X, X } } ,  { "wd", 2, 6, 0x03, { 0, 2, 1 } , { 0, 2, 1, 2 } ,      { 0, 2, 1 } , { 0, 2, 1, 2 } },  { "ln", 2, 4, 0x03, { 0, 2, 1 } , { 0, 2, 1, X } ,      { 0, 2, 1 } , { 0, 2, 1, X } },  { "df", 1, 0, 0x01, { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } },  { "ec", 3, 4, 0x03, { 0, 2, 2 } , { 0, X, 2, X } ,       { 0, 3, 2 } , { 0, 0, 2, 1 } },   { "bf", 5, 5, 0x01, { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } },  { "st", 2, 1, 0x07,       { 7, 4, 3, 2, 6, 0, 5, 1 } , { 5, 7, 3, 2, 1, 6, 4, 0 } ,      { 7, 4, X, 2, X, 0, X, 1 } , { 5, 7, 3, 1, X, X, X, 0 } } } ;					/* values of capability fields */const char *capvaluestr [ NCAP ] [8] = {  { " 98lpi", "196lpi" } ,   { " 2400bps", " 4800bps", " 7200bps", " 9600bps", "  12kbps", "14.4kbps",    "7200V.17", "9600V.17" } ,  { "8.5\"/215mm", " 10\"/255mm", " 12\"/303mm" } ,  { "11\"/A4", "14\"/B4", " any  " } ,  { "1D" , "2D" }, { "   -   ", "ECM-256", "ECM-64 " }, { " - ", "BFT" },  { "0ms", "5ms", "10/5ms", "10ms", "20/10ms", "20ms", "40/20ms", "40ms" }} ;/* T.30 control frames */enum frametype {	     DIS=0x01, CSI,	NSF=0x04, CFR=0x21, FTT, MCF=0x31, RTN, RTP, PIN, PIP, DCS=0x41, TSI,	NSS=0x44, CRP=0x58, DCN=0x5f, EOM=0x71, MPS, EOP=0x074, PRI_EOM=0x79, PRI_MPS, PRI_EOP=0x7c, DTC=0x81, CIG, NSC=0x84 } ;/* Class 1 commands to [receive=0/transmit=1] [data=0/training=1] for   [baud rate=BR]. */const char *c1cmd [ 2 ]  [ 2 ] [ 8 ] = { { { "+FRM=24", "+FRM=48", "+FRM=72", "+FRM=96", "+FRM=122", "+FRM=146" ,    "+FRM=74", "+FRM=98" } ,  { "+FRM=24", "+FRM=48", "+FRM=72", "+FRM=96", "+FRM=121", "+FRM=145" ,    "+FRM=73", "+FRM=97" } } ,{ { "+FTM=24", "+FTM=48", "+FTM=72", "+FTM=96", "+FTM=122", "+FTM=146" ,    "+FTM=74", "+FTM=98", } ,  { "+FTM=24", "+FTM=48", "+FTM=72", "+FTM=96", "+FTM=121", "+FTM=145" ,    "+FTM=73", "+FTM=97" } }} ;/* Modem file & features */typedef struct modemstruct {  TFILE *f ;  int c1, c20 ;			/* use class 1/class 2.0 */  int cmdpause ;		/* delay before each init command */  u_char startchar ;		/* character to start reception */} MODEM ;/* Functions... *//* Return name of frame of type 'fr'. */const char *frname ( int fr ){static struct framenamestruct {  int code ;  const char *name ; } framenames [] = { {DIS,"DIS"},{CSI,"CSI"},{NSF,"NSF"},{CFR,"CFR"},{FTT,"FTT"},{MCF,"MCF"}, {RTN,"RTN"},{RTP,"RTP"},{PIN,"PIN"},{PIP,"PIP"},{DCS,"DCS"},{TSI,"TSI"}, {NSS,"NSS"},{CRP,"CRP"},{DCN,"DCN"},{EOM,"EOM"},{MPS,"MPS"},{EOP,"EOP"}, {PRI_EOM,"PRI-EOM"},{PRI_MPS,"PRI-MPS"},{PRI_EOP,"PRI-EOP"}, {DTC,"DTC"},{CIG,"CIG"},{NSC,"NSC"}, {0,0} }, *p ;  for ( p=framenames ; p->code && p->code != fr ; p++ ) ;  return p->code ? p->name : "UNKNOWN" ;}/* Send bytes to the modem, doing bit-reversal and escaping DLEs.  Flushes   buffer if enough characters stored.  Follow by call to tputs() or   tflush() when done to flush o/p buffer.  Returns 0 or 2 on errors. */int sendbuf ( MODEM *m, u_char *p, int n, int t ){  int err=0, c=0 ;  TFILE *f = m->f ;  u_char *order = m->f->obitorder ;  while ( n-- > 0 && c >= 0 ) {    c  = order [ *p++ ] ;    if ( c == DLE ) c = tputc ( DLE, f, t ) ;    if ( c >= 0 ) tputc ( c, f, t ) ;    if ( tobytes ( m->f ) >= MINWRITE ) tflush ( m->f, t ) ;  }  if ( c < 0 ) err = msg ( "ES2fax device write error:" ) ;  return err ;}/* Get a modem response into buffer s, storing up to n bytes.  The response   begins with most recent non-control character and ends with CR/LF.   Returns s or null if times-out in t deciseconds or on i/o error. Trace   messages are buffered to reduce possible timing problems. */char *tgets( MODEM *m, char *s, int n, int t ){  int c=0, state=0 ;  char *p = s ;  while ( state < 4 ) {    if ( ( c = tgetc ( m->f, t ) ) == EOF ) break ;    c &= 0x7f ;    if ( state == 0 ) msg ( "M-+ [" ) ;     msg ( "M-+ %s" , cname ( c ) ) ;    switch ( state ) {    case 0 :    case 1 : state =               ( iscntrl ( c ) ? 1 : (p=s, 2) ) ; break ;    case 2 : state = c == CR ? 3 : ( iscntrl ( c ) ? 1 :       2  ) ; break ;    case 3 : state = c == LF ? 4 : ( iscntrl ( c ) ? 1 : (p=s, 2) ) ; break ;    default: msg ( "Ecan't happen (tgets)" ) ;    }    if ( state == 2 && p < s+n-1 ) *p++ = c ;  }  *p = 0 ;  if ( p >= s+n-1 ) msg ( "W- modem response overflow" ) ;  if ( state ) msg ( "M- %s]" , c == EOF ? "<timeout>" : "" ) ;  return c == EOF ? 0 : s ;}/* Send character or string to modem immediately (for commands).  Return   like putc() and puts(). */int tputcnow ( MODEM *m, char c, int t ) {   return tputc ( c, m->f, t ) < 0 ? EOF : ( tflush ( m->f, t ) ? EOF : c ) ; }int tputs ( MODEM *m, const char *s, int t ){  int n=0 ;  while ( s && *s && ( n = tputcnow ( m, *s++, t ) ) != EOF ) ;  return n ;}/* Range-check capability. */int checkcap ( cap c ){  int err=0, i ;  for ( i=0 ; i<NCAP ; i++ )    if ( c[i] > capmax[i] || c[i] < 0 ) {      err = msg ( "E3%s = %d out of range, set to 0", t30tab[i].name, c[i] ) ;      c[i]=0 ;    }  return err ;}/* Print cap[ability] c using text values and prefix s. */void printcap ( char *s , cap c ){  int i ;  msg ( "N-+ %s" , s ) ;  checkcap ( c ) ;  for ( i=0 ; i<NCAP ; i++ )     msg ( "N-+  %s" , capvaluestr [ i ] [ c[i] ] ) ;  msg ( "N-" ) ;}/* Convert capability string to cap struct. Returns 0 or 2 on errors. */int str2cap ( char *s, cap c ){  int err=0, n ;  n = sscanf ( s, "%d,%d,%d,%d,%d,%d,%d,%d", 	      c+0, c+1, c+2, c+3,  c+4, c+5, c+6, c+7 ) ;  if ( n < NCAP ) msg ( "Wmissing value(s) in \"%s\"", s ) ;  checkcap ( c ) ;  return err ;}/* Convert a cap[ability] 'c' to a DIS/DCS/DTC FIF 'fif' of 'len' bytes.   Converts into DIS format if 'isdis' is true, else into DCS/DTC   format. */void mkdis ( cap c , u_char *fif , int len , int isdis ) {  int i, k ;  t30tabst *p ;  if ( len < 3 || len > 5 )     msg ( "Wstrange DCS/DIS length (%d)" , len ) ;  fif[0] = 0 ;  fif[1] = isdis ? 0xc0 : 0x40 ;  for ( i=2 ; i<len-1 ; i++ ) fif[i] = 0x01 ;       /* add extension bits */  fif[i] = 0 ;  checkcap ( c ) ;  for ( i=0 ; p=t30tab+i, i<NCAP ; i++ ) {    if ( ( k = ( isdis ? p->captodis : p->captodcs ) [ c [ i ] ] ) == X )      msg ( "E3mkdis: can't happen (invalid %s)", p->name ), k=0 ;    if ( p->byte < len ) fif [ p->byte ] |= k << p->shift ;  }}/* Return length of DIS/DTC FIF (counts extension bits). */int dislen ( u_char *fif ){  int n ;  for ( n=3 ; fif [ n-1 ] & 0x01 && n < MAXFIFLEN ; n++ ) ;  return n ;}/* Convert received DIS/DCS/DTC FIF to cap. Returns 0 or 3 if bad DIS/DCS   field. */int mkcap ( u_char *fif, cap c, int dis ) {  int err=0, i, j, k, len ;  t30tabst *p ;  len = dislen ( fif ) ;  for ( i=0 ; i<NCAP ; i++ ) {    p=t30tab+i ;    if ( p->byte >= len ) {      c [ i ] = 0 ;    } else {      j = ( fif [ p->byte ] >> p->shift ) & p->mask ;      k = ( dis ? p->distocap : p->dcstocap ) [ j ] ;      if ( k == X ) {	c [ i ] = 0 ;	err = msg("E3mkcap: bad %s field (%d) set to 0", p->name, j) ;      } else { 	c [ i ] = k ;      }    }  }  return err ;}/* Compute compatible local/remote capabilities. Used by the   sending station only and only for Class 1. Returns 0 if OK or

⌨️ 快捷键说明

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