📄 efaxos.c
字号:
/* efaxos.c - O/S-dependent routines for efax */#include <errno.h>#include <fcntl.h>#include <signal.h>#include <stdio.h>#include <string.h>#include <sys/types.h>#include <sys/stat.h>#include <sys/time.h>#include <unistd.h>#ifndef FD_SET#include <sys/select.h> /* for AIX */#endif#include "efaxlib.h"#include "efaxos.h"#ifdef TERMIO#include <termio.h>#include <sys/ioctl.h>#define termios termio#define tcgetattr(fd, pt) ioctl(fd, TCGETA, pt)#define tcsetattr(fd, x, pt) ioctl(fd, TCSETAW, pt)#define cfsetospeed(pt, b) ((pt)->c_cflag = ((pt)->c_cflag & ~CBAUD) | b)#define cfsetispeed(pt, b)#define tcdrain(fd)#else#include <termios.h>#endif#ifdef TIOCSSOFTCAR#include <sys/ioctl.h>#endif/* millisecond delays (for systems without usleep). */void msleep ( int t ){ struct timeval timeout ; timeout.tv_sec = t / 1000 ; timeout.tv_usec = ( t % 1000 ) * 1000 ; if ( select ( 1 , 0 , 0 , 0 , &timeout ) < 0 ) msg ("ES2select failed in msleep:") ;}/* Return number of characters ready to read or < 0 on error. t is tenths of a second of idle time before timing out. If t is negative, waits forever. */int tdata ( TFILE *f, int t ){ int n ; fd_set fds ; struct timeval timeout ; if ( f->fd < 0 ) msg ( "Ecan't happen (faxdata)" ) ; timeout.tv_sec = t / 10 ; timeout.tv_usec = ( t % 10 ) * 100000 ; FD_ZERO ( &fds ) ; FD_SET ( f->fd, &fds ) ; n = select ( f->fd + 1, &fds, 0, 0, t<0 ? 0 : &timeout ) ; if ( n < 0 ) msg ( "ES2select failed in tdata():" ) ; return n ;}/* tundrflw is called only by the tgetc() macro when the buffer is empty. t is maximum idle time before giving up. Returns number of characters read or EOF on timeout or errors. */int tundrflw ( TFILE *f, int t ){ int n = tdata ( f, t ) ; if ( n > 0 ) if ( ( n = read( f->fd, f->ibuf, IBUFSIZE ) ) < 0 ) msg ( "ES2fax device read:" ) ; f->iq = ( f->ip = f->ibuf ) + ( n > 0 ? n : 0 ) ; return n > 0 ? n : EOF ;} /* Write stream output buffer to the file. Warns if called with full buffer (presumably called from tputc()). Returns 0 or EOF on error. */int tflush ( TFILE *f, int t ){ int n=0 ; unsigned char *p = f->obuf ; if ( f->op >= f->oq ) msg ( "Wfax output buffer overflow" ) ; while ( p < f->op && ( n = write( f->fd , p , f->op - p ) ) >= 0 ) p += n ? n : msg ( "Wwrote %d of %d bytes" , n , f->op - p ) ; return n >= 0 ? (f->op = f->obuf, 0) : (msg ("ESfax device write:") , EOF) ;} /* Compare current termios state with termios struct t. Returns 0 if equal, 1 otherwise. */int ckfld ( char *field, int set, int get ){ return set == get ? 0 : msg ( "W1 termios.%s is 0x%08x, not 0x%08x", field, get, set ) ;}int checktermio ( struct termios *t, TFILE *f ){ struct termios s ; int err=0 ; s.c_iflag=s.c_oflag=s.c_lflag=s.c_cflag=s.c_cc[VMIN]=s.c_cc[VTIME]=0 ; if ( tcgetattr ( f->fd , &s ) ) err = msg ("ES2tcgetattr failed:") ; if ( ! err ) return ckfld ( "iflag" , t->c_iflag, s.c_iflag ) || ckfld ( "oflag" , t->c_oflag , s.c_oflag ) || ckfld ( "lflag" , t->c_lflag , s.c_lflag ) || ckfld ( "cflag" , t->c_cflag , s.c_cflag ) || ckfld ( "START" , t->c_cc[VSTART] , s.c_cc[VSTART] ) || ckfld ( "STOP" , t->c_cc[VSTOP] , s.c_cc[VSTOP] ) || ckfld ( "MIN" , t->c_cc[VMIN] , s.c_cc[VMIN] ) || ckfld ( "TIME" , t->c_cc[VTIME] , s.c_cc[VTIME] ) ; return err ;}/* Set serial port mode. Sets raw, 8-bit, 19.2 kbps mode with no flow control or as required. Returns 0 or 2 on error. */int ttymode ( TFILE *f, enum ttymodes mode ){ int err=0 ; static struct termios t ; tcdrain ( f->fd ) ; tcflush ( f->fd , TCIOFLUSH ) ; /* make sure */ t.c_iflag = IGNBRK | IGNPAR | IXANY ; t.c_oflag = 0 ; t.c_cflag = CS8 | CREAD | CLOCAL ; t.c_lflag = 0 ; t.c_cc[VMIN] = 1 ; t.c_cc[VTIME] = 0 ; t.c_cc[VSTOP] = XOFF; t.c_cc[VSTART] = XON; cfsetospeed ( &t, B19200 ) ; cfsetispeed ( &t, B19200 ) ; if ( ! err ) switch ( mode ) { case COMMAND : break ; case DROPDTR : cfsetospeed ( &t, B0 ) ; break ; case SEND : t.c_iflag |= IXON ; break ; default : err = msg ("E2can't happen(ttymode)") ; break ; } tcdrain ( f->fd ) ; /* make *sure* output done B4 turn off f/c */ tcflow ( f->fd , TCOON ) ; /* in case XON got lost */ if ( ! err && tcsetattr ( f->fd , TCSANOW , &t ) ) err = msg ( "ES2tcsetattr failed:" ) ; if ( !err && checktermio ( &t, f ) ) err = msg ( "E2terminal mode not set properly" ) ; return err ;}/* Bit ordering: serial devices transmit LS bit first. T.4/T.30 says MS bit is sent first. `Normal' order therefore reverses bit order. */unsigned char reversebits [ 256 ], normalbits [ 256 ] ;/* Open a serial fax device as a TFILE. Returns 0 if OK, 1 if busy, 2 on error. */int ttyopen ( TFILE *f, char *fname, int reverse ){ int i, flags, err=0 ; if ( ! reversebits[1] ) for ( i=0 ; i<256 ; i++ ) normalbits [ reversebits [ i ] = i ] = ( i& 1 ? 128:0 ) | ( i& 2 ? 64:0 ) | ( i& 4 ? 32:0 ) | ( i& 8 ? 16:0 ) | ( i&16 ? 8:0 ) | ( i&32 ? 4:0 ) | ( i&64 ? 2:0 ) | ( i&128 ? 1:0 ) ; f->ip = f->iq = f->ibuf ; f->oq = ( f->op = f->obuf ) + OBUFSIZE ; f->obitorder = normalbits ; f->ibitorder = reverse ? reversebits : normalbits ; f->fd = open ( fname, O_RDWR | O_NDELAY ) ; if ( f->fd < 0 ) if ( errno == EBUSY ) err = 1 ; else err = msg ( "ES2tty device open\n%s:", fname ) ; if ( ! err ) if ( ( flags = fcntl( f->fd, F_GETFL, 0 ) ) < 0 || fcntl( f->fd, F_SETFL, ( flags & ~O_NDELAY ) ) < 0 ) err = msg ( "ES2fax device fcntl failed\n%s:", fname ) ;#ifdef TIOCSSOFTCAR { int arg = 1 ; if ( ! err ) if ( ioctl ( f->fd, TIOCSSOFTCAR, &arg ) ) msg ("WS unable to set software carrier:" ) ; }#endif return err ;} /* UUCP-style device locking using lock files *//* Test for UUCP lock file & remove stale locks. Returns 0 on null file name or if no longer locked, 1 if locked by another pid, 2 on error, 3 if locked by us. */int ttlocked ( char *fname ){ int err=0 ; FILE *f ; pid_t pid = 0 ; char buf [ FILENAME_MAX ] = "" ; if ( fname && *fname == HDBLKFLAG ) fname++ ; if ( fname && ( f = fopen ( fname , "r" ) ) ) { if ( fread ( buf, sizeof(char), FILENAME_MAX-1, f ) == sizeof(pid_t) || sscanf ( buf, "%d" , &pid ) != 1 ) pid = * (pid_t *) buf ; if ( kill ( pid, 0 ) && errno == ESRCH ) if ( remove ( fname ) ) err = msg ( "ES2can't remove stale lock %s from pid %d:", fname, pid ) ; else err = msg ( "I0removed stale lock %s from pid %d", fname, pid ) ; else if ( pid != getpid() ) err = 1 ; else err = 3 ; fclose ( f ) ; } return err ;}/* Create UUCP (text or binary) lock file. Returns 0 on null file name or if created, 1 if locked by another pid, 2 on error, 3 if locked by us. */int ttlock ( char *fname ){ int err=0, dirlen, hdb=0 ; FILE *f=0 ; pid_t pid = getpid ( ) ; char *p , buf [ FILENAME_MAX ] = "" ; if ( fname && *fname == HDBLKFLAG ) { fname++ ; hdb=1 ; } if ( fname && ! ( err = ttlocked ( fname ) ) ) { dirlen = ( p = strrchr( fname , '/' ) ) ? p-fname+1 : strlen ( fname ) ; sprintf ( buf , "%.*sTMP..%05d" , dirlen , fname , pid ) ; if ( ( f = fopen( buf, "w" ) ) && ( hdb ? (fprintf(f, "%10d\n", pid)>0) : fwrite(&pid, sizeof(pid_t), 1, f) ) ) { if ( rename ( buf , fname ) == 0 ) chmod ( fname , 0444 ) ; else if ( ! ( err = ttlocked ( fname ) ) ) err = msg ( "ES2can't rename lock file %s to %s:\n", buf, fname ) ; } else { err = msg ( "ES2can't open/write pre-lock file %s:\n", buf ) ; } } if ( f ) { fclose ( f ) ; if ( err ) remove ( buf ) ; } return err ;}/* Remove lock file. Returns 0 on null file name, doesn't exist, or was removed, 1 if the lock is to another pid, 2 on errors. */int ttunlock ( char *fname ){ int err = 0 ; if ( fname && *fname == HDBLKFLAG ) { fname++ ; } if ( fname && ( err = ttlocked ( fname ) ) ) { if ( err == 1 ) msg ( "Ewon't remove lock %s (not ours)" , fname ) ; if ( err == 3 ) if ( remove ( fname ) ) err = msg ( "ES2can't remove lock %s:", fname ) ; else err = 0 ; } return err ;}/* Lock all lock files. Returns 0 if all locks [already] applied, 1 if any are locked to other pids, 2 on any errors. */int lockall ( char **lkfiles ){ int err = 0 ; char **p = lkfiles ; while ( *p && ! err ) if ( ( err = ttlock ( *p++ ) ) == 3 ) err = 0 ; return err ; }/* Remove all lock files. Returns 0 if all locks removed, 2 on errors. */int unlockall ( char **lkfiles ){ int err = 0 ; char **p = lkfiles ; while ( *p ) if ( ttunlock ( *p++ ) ) err = 2 ; return err ; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -