?? efax.c
字號:
#define Copyright "Copyright 1999 Ed Casas"#define Version "efax v 0.9"/* Copyright (C) 1999 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Please contact the author if you wish to use efax or efix in ways 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.*/const char *Usage = "Usage:\n" " %s [ option ]... [ -t num [ file... ] ]\n" "Options:\n" " -a str use command ATstr to answer\n" " -c cap set modem and receive capabilites to cap\n" " -d dev use modem on device dev\n" " -e cmd exec \"/bin/sh -c cmd\" for voice calls\n" " -f fnt use (PBM) font file fnt for headers\n" " -g cmd exec \"/bin/sh -c cmd\" for data calls\n" " -h hdr use page header hdr (use %%d's for current page/total pages)\n" " -i str send modem command ATstr at start\n" " -j str send modem command ATstr after set fax mode\n" " -k str send modem command ATstr when done\n" " -l id set local identification 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" " 2 use class 2 modem commands\n" " a if first [data mode] answer attempt fails retry as fax\n" " e ignore errors in modem initialization commands\n" " f use virtual flow control\n" " h use hardware flow control\n" " l halve lock file polling interval\n" " n ignore page retransmission requests\n" " r do not reverse received bit order for Class 2 modems\n" " x use XON instead of DC2 to trigger reception\n" " z add 100 ms to pause before each modem comand (cumulative)\n" " -q ne ask for retransmission if more than ne errors per page\n" " -r pat save received pages into files pat.001, pat.002, ... \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" "Commands:\n" " -t dial num and send fax image files file... \n" ;#include <ctype.h> /* ANSI C */#include <stdio.h>#include <stdlib.h>#include <string.h>#include <time.h>#include "efaxio.h" /* EFAX */#include "efaxlib.h"#include "efaxmsg.h"#include "efaxos.h"/* constants... */ /* delays and timeouts (t/o), in deciseconds */#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 TMOD 55 /* T.30 pause between v.21&v.29, 75-20 ms */#define TO_A 1200 /* dial/answer (Phase A) - modem may t/o first */#define TO_ABRT 20 /* max delay after sending abort sequence */#define TO_CHAR 102 /* per data character (2x max FILL length) */#define TO_DATAF 80 /* software adaptive answer data connect t/o */#define TO_DRAIN_H 136 /* minimum HDLC buffer drain time (4k/300cps) */#define TO_DRAIN_D 300 /* minimum data buffer drain time */#define TO_FT 31 /* max delay after +F[TR][MH] command */#define TO_RTCMD 20 /* return to command mode after DLE-ETX (rx) */#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 ANSCMD "A" /* default modem command to answer calls */#define DCSLEN 3 /* length of FIF for DCS commands sent */#define DEFDISLEN 3 /* length of DIS initially transmitted */#define DEFCAP 1,3,0,2,0,0,0,0 /* default local capabilities */#define DEFID " " /* default local ID */#define DEFPAT "%m%d%H%M%S" /* default received file name pattern */#define HDRSHFT 54 /* shift header right 6.7mm into image area */#define HDRSPCE 20 /* number of scan lines inserted before image */#define HDRSTRT 4 /* scan line where header is placed on image */#define HDRCHRH 24 /* header character height (pels, at 196lpi) */#define HDRCHRW 12 /* header character width (pels) */#define IDLEN 20 /* length of T.30 ID strings, must be 20 */#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 exec'ed (-g, -e) commands */#define MAXICMD 100 /* maximum # of modem setup/reset commands */#define MAXLKFILE 16 /* maximum number of lock files */#define MAXNULLS 2 /* maximum consecutive received nulls saved */#define MAXPGERR 10 /* maximum received errors allowed per page */#define MAXTRAIN 2 /* maximum training retries at lowest speed */#define MAXRETRY 3 /* maximum retries of unacknowledged commands */#define NCAP 8 /* number of fields in a capability string */#define NTXRETRY 3 /* maximum re-sends per page */typedef int cap [ NCAP ] ; /* remote/local capabilities */ /* capability fields... */enum captype { VR, BR, WD, LN, DF, EC, BF, ST } ;int capmax [ NCAP ] = { 1, 7, 2, 2, 3, 2, 1, 7 } ; /* & maximum values */ /* vertical resolution, dpi */int vresolution [ 2 ] = { 98, 196 } ; /* characters per second for br */int cps [ 8 ] = { 300, 600, 900, 1200, 1500, 1800, 900, 1200 } ; /* next br = fallback [ br ] */ /* 0, 1, 2, 3, 4, 5, 6, 7 */int fallback [ 8 ] = {-1, 0, 1, 2, 7, 4, 3, 6 } ; /* negotiation speed index */ /* 0, 1, 2, 3, 4, 5, 6, 7 */int brindex [ 8 ] = { 0, 1, 2, 3, 4, 7, 5, 6 } ; /* minimum scan time in ms */int mst [ 8 ] = { 0 , 5, 10, 10, 20, 20, 40, 40 } ; /* page width in pixels */int pagewidth [ 5 ] = { 1728, 2048, 2432, 1216, 864 } ;/* 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 struct t30tabstruct{ char *name ; uchar byte, shift, mask ; uchar safeval ; uchar captodis[8], distocap[16], captodcs[8], dcstocap[16] ; } t30tabst ;#define X 0xff /* invalid values */t30tabst t30tab [ NCAP ] = { { "vr", 1, 1, 0x01, 0, { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } }, { "br", 1, 2, 0x0f, 0, { 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, { 0, 2, 1 } , { 0, 2, 1, 2 } , { 0, 2, 1 } , { 0, 2, 1, 2 } }, { "ln", 2, 4, 0x03, 0, { 0, 2, 1 } , { 0, 2, 1, X } , { 0, 2, 1 } , { 0, 2, 1, X } }, { "df", 1, 0, 0x01, 0, { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } }, { "ec", 3, 4, 0x03, 0, { 0, 2, 2 } , { 0, X, 2, X } , { 0, 3, 2 } , { 0, 0, 2, 1 } }, { "bf", 5, 5, 0x01, 0, { 0, 1 } , { 0, 1 } , { 0, 1 } , { 0, 1 } }, { "st", 2, 1, 0x07, 7, { 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 */char *capvaluestr [ NCAP ] [8] = { { " 98lpi", "196lpi" } , { " 2400bps", " 4800bps", " 7200bps", " 9600bps", " 12kbps", "14.4kbps", "7200V.17", "9600V.17" } , { "8.5\"/215mm", " 10\"/255mm", " 12\"/303mm", " 6\"/151mm", "4.2\"/107mm" } , { "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=0x74, PRI_EOM=0x79, PRI_MPS, PRI_EOP=0x7c, DTC=0x81, CIG, NSC=0x84 } ;enum commanddtype { RCV=0, SND=1, DTA=0, TRN=1 } ;/* Class 1 commands to [receive=0/transmit=1] [data=0/training=1] for [baud rate=BR]. */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" } }} ;struct c2msgstruct{ int min, max ; char *msg ;} c2msg [] = { { 0, 9, "Call Placement and Termination:" }, { 0, 0, " Normal and proper end of connection" }, { 1, 1, " Ring Detect without successful handshake" }, { 2, 2, " Call aborted, from +FK[S] or CAN" }, { 3, 3, " No Loop Current" }, { 4, 4, " Ringback Detected, no answer" }, { 5, 5, " Ringback Detected, answer without CED" }, { 10, 19, "Transmit Phase A & Miscellaneous Errors:" }, { 10, 10, " Unspecified Phase A error" }, { 11, 11, " No Answer (T.30 T1 timeout)" }, { 20, 39, "Transmit Phase B Hangup Codes:" }, { 20, 20, " Unspecified Transmit Phase B error" }, { 21, 21, " Remote cannot receive or send" }, { 22, 22, " COMREC error in transmit Phase B" }, { 23, 23, " COMREC invalid command received" }, { 24, 24, " RSPREC error" }, { 25, 25, " DCS sent three times without response" }, { 26, 26, " DIS/DTC received 3 times; DCS not recognized" }, { 27, 27, " Failure to train at 2400 bps or +FMINSP value" }, { 28, 28, " RSPREC invalid response received" }, { 40, 49, "Transmit Phase C Hangup Codes:" }, { 40, 40, " Unspecified Transmit Phase C error" }, { 41, 41, " Unspecified image format error" }, { 42, 42, " Image conversion error" }, { 43, 43, " DTE to DCE data underflow" }, { 44, 44, " Unrecognized transparent data command" }, { 45, 45, " Image error, line length wrong" }, { 46, 46, " Image error, page length wrong" }, { 47, 47, " Image error, wrong compression code" }, { 50, 69, "Transmit Phase D Hangup Codes:" }, { 50, 50, " Unspecified Transmit Phase D error" }, { 51, 51, " RSPREC error" }, { 52, 52, " No response to MPS repeated 3 times" }, { 53, 53, " Invalid response to MPS" }, { 54, 54, " No response to EOP repeated 3 times" }, { 55, 55, " Invalid response to EOP" }, { 56, 56, " No response to EOM repeated 3 times" }, { 57, 57, " Invalid response to EOM" }, { 58, 58, " Unable to continue after PIN or PIP" }, { 70, 89, "Receive Phase B Hangup Codes:" }, { 70, 70, " Unspecified Receive Phase B error" }, { 71, 71, " RSPREC error" }, { 72, 72, " COMREC error" }, { 73, 73, " T.30 T2 timeout, expected page not received" }, { 74, 74, " T.30 T1 timeout, after EOM received" }, { 90, 99, "Receive Phase C Hangup Codes:" }, { 90, 90, " Unspecified Receive Phase C error" }, { 91, 91, " Missing EOL after 5 seconds" }, { 92, 92, " Unused code" }, { 93, 93, " DCE to DTE buffer overflow" }, { 94, 94, " Bad CRC or frame (ECM or BFT modes)" }, { 100, 119, "Receive Phase D Hangup Codes:" }, { 100, 100, " Unspecified Receive Phase D errors" }, { 101, 101, " RSPREC invalid response received" }, { 102, 102, " COMREC invalid response received" }, { 103, 103, " Unable to continue after PIN or PIP" }, { 120, 255, "Reserved Codes" }, { -1, -1, "" }} ;/* meaning of efax return codes */char *errormsg [] = { "success", "number busy or modem in use", "unrecoverable error", "invalid modem response", "no response from modem", "terminated by signal", "internal error" } ;/* Functions... *//* Return name of frame of type 'fr'. */char *frname ( int fr ){ static struct framenamestruct { int code ; char *name ; } framenames [] = { {NSC,"NSC - poller features"}, /* these 3 frames must be first */ {CIG,"CIG - poller ID"}, {DTC,"DTC - poller capabilities"}, {NSF,"NSF - answering features"}, {CSI,"CSI - answering ID"}, {DIS,"DIS - answering capabilities"}, {NSS,"NSS - caller features"}, {TSI,"TSI - caller ID"}, {DCS,"DCS - session format"}, {CFR,"CFR - channel OK"}, {FTT,"FTT - channel not OK"}, {MPS,"MPS - not done"}, {EOM,"EOM - not done, new format"}, {EOP,"EOP - done"}, {PRI_MPS,"PRI-MPS - not done, call operator"}, {PRI_EOM,"PRI-EOM - not done, new format, call operator"}, {PRI_EOP,"PRI-EOP - done, call operator"}, {MCF,"MCF - page OK"}, {RTP,"RTP - page OK, check channel"}, {PIP,"PIP - page OK, call operator"}, {RTN,"RTN - page not OK, check channel"}, {PIN,"PIN - page not OK, call operator"}, {CRP,"CRP - repeat command"}, {DCN,"DCN - disconnect"}, {0,0} }, *p ; for ( p=framenames ; p->code ; p++ ) if ( fr == p->code || ( fr & 0x7f ) == p->code) break ; return p->code ? p->name : "UNKNOWN" ;}/* 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, uchar *fif, int len, int isdis, int t4tx ) { int i, k ; t30tabst *p ; len = len > DCSLEN ? DCSLEN : len ; fif[0] = 0 ; fif[1] = ( isdis && t4tx ? 0x80 : 0 ) | 0x40 ; for ( i=2 ; i<len-1 ; i++ ) fif[i] = 0x01 ; /* add extension bits */ fif[i] = 0 ; checkcap ( c ) ; for ( i=0 ; i<NCAP ; i++ ) { p = t30tab + 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 ( uchar *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 ( uchar *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 ] = p->safeval ; err = msg("E3mkcap: bad %s field (%d) set to %d", p->name, j, c [ i ] ) ; } 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 3 if no compatible settings possible. */int mincap ( cap local, cap remote, cap session )
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -