ftp://ftp.metalab.unc.edu/pub/Linux/apps/serialcomm/fax/efax-0.9.tar.gz
[efax.git] / efaxmsg.c
1 #include <ctype.h>              /* ANSI C */
2 #include <errno.h>
3 #include <stdio.h>
4 #include <string.h>
5 #include <stdarg.h> 
6 #include <time.h>
7
8 #include "efaxmsg.h"
9
10 #define MAXTSTAMP 80            /* maximum length of a time stamp */
11 #define MAXMSGBUF 4096          /* maximum status/error message bytes held */
12
13 #define NLOG 2
14
15 char *verb[NLOG] = { "ewin", "" } ;
16 char *argv0 = "" ;
17
18 int nxtoptind = 1 ;             /* for communication with nextopt() */
19 char *nxtoptarg ;
20
21
22 /* For systems without strerror(3) */
23
24 #ifdef NO_STRERROR
25 extern int sys_nerr;
26 extern char *sys_errlist[];
27
28 extern char *strerror( int i )       
29 {
30   return ( i >= 0 && i < sys_nerr ) ? sys_errlist[i] : "Unknown Error" ;
31 }
32 #endif
33
34
35 /* Print time stamp. */
36
37 time_t tstamp ( time_t last, FILE *f )
38 {
39   time_t now ;
40   char tbuf [ MAXTSTAMP ] ;
41
42   now = time ( 0 ) ;
43
44   strftime ( tbuf, MAXTSTAMP,  ( now - last > 600 ) ? "%c" : "%M:%S",
45             localtime( &now ) ) ;
46   fputs ( tbuf, f ) ;
47
48   return now ;
49 }
50
51
52 /* Return string corresponding to character c. */
53
54 char *cname ( uchar c ) 
55 {
56 #define CNAMEFMT "<0x%02x>"
57 #define CNAMELEN 6+1
58   static char *cnametab [ 256 ] = { /* character names */
59   "<NUL>","<SOH>","<STX>","<ETX>", "<EOT>","<ENQ>","<ACK>","<BEL>",
60   "<BS>", "<HT>", "<LF>", "<VT>",  "<FF>", "<CR>", "<SO>", "<SI>", 
61   "<DLE>","<XON>","<DC2>","<XOFF>","<DC4>","<NAK>","<SYN>","<ETB>",
62   "<CAN>","<EM>", "<SUB>","<ESC>", "<FS>", "<GS>", "<RS>", "<US>" } ;
63   static char names[ (127-32)*2 + 129*(CNAMELEN) ] ;
64   char *p=names ;
65   static int i=0 ;
66     
67   if ( ! i ) {
68     for ( i=32 ; i<256 ; i++ ) {
69       cnametab [ i ] = p ;
70       sprintf ( p, i<127 ? "%c" : CNAMEFMT, i ) ;
71       p += strlen ( p ) + 1 ;
72     }
73   }
74
75   return cnametab [ c ] ;
76
77
78 /* Print a message with a variable number of printf()-type
79    arguments if the first character appears in the global
80    verb[ose] string.  Other leading characters and digits do
81    additional actions: + allows the message to be continued on
82    the same line, '-' buffers the message instead of printing it,
83    E, and W expand into strings, S prints the error message for
84    the most recent system error, a digit sets the return value, a
85    space ends prefix but isn't printed.  Returns 0 if no prefix
86    digit. */
87
88 enum  msgflags { E=0x01, W=0x02, S=0x04, NOFLSH=0x08, NOLF=0x10 } ;
89
90 int msg ( char *fmt, ... ) 
91
92   static int init=0 ;
93   static FILE *logfile [ NLOG ] ;
94   static char msgbuf [ NLOG ] [ MAXMSGBUF ] ;
95   static time_t logtime [ NLOG ] = { 0, 0 } ;
96   static int atcol1 [ NLOG ] = { 1, 1 } ;
97   
98   int err=0, i, flags=0 ;
99   char *p ;
100   
101   va_list ap ;
102   va_start ( ap, fmt ) ;
103
104   if ( ! init ) {
105     logfile[0] = stderr ;
106     logfile[1] = stdout ;
107     for ( i=0 ; i<NLOG ; i++ )
108       setvbuf ( logfile[i], msgbuf[i], _IOFBF, MAXMSGBUF ) ;
109     cname ( 0 ) ;
110     init = 1 ;
111   }
112   
113   for ( i=0 ; i<NLOG ; i++ ) {
114
115     for ( p=fmt ; *p ; p++ ) {
116       switch ( *p ) {
117       case ' ': p++ ; goto print ;
118       case 'E': flags |= E ; break ;
119       case 'W': flags |= W ; break ;
120       case 'S': flags |= S ; break ;
121       case '+': flags |= NOLF ; break ;
122       case '-': flags |= NOFLSH ; break ;
123       default: 
124         if ( isdigit ( *p ) ) {
125           err = *p - '0' ; 
126         } else if ( ! isupper ( *p ) ) {
127           goto print ;
128         }
129       }
130     }
131       
132     print:
133
134     if ( strchr ( verb[i], tolower ( *fmt ) ) ) {
135       
136       if ( atcol1[i] ) {
137         fprintf ( logfile[i], "%s: ", argv0 ) ;
138         logtime[i] = tstamp ( logtime[i], logfile[i] ) ; 
139         fputs ( ( flags & E ) ? " Error: " : 
140                 ( flags & W ) ? " Warning: " : 
141                 " ",
142                 logfile[i] ) ;
143       }
144       vfprintf( logfile[i], p, ap ) ;
145       if ( flags & S ) fprintf ( logfile[i], " %s", strerror ( errno ) ) ;
146       if ( ! ( flags & NOLF ) ) fputs ( "\n", logfile[i] ) ;
147       atcol1[i] = flags & NOLF ? 0 : 1 ;
148       if ( ! ( flags & NOFLSH ) ) fflush ( logfile[i] ) ;
149       
150     }
151     
152   }
153   
154   va_end ( ap ) ;
155   
156   return err ;
157 }
158
159
160 /* Simple (one option per argument) version of getopt(3). */
161
162 int nextopt( int argc, char **argv, char *args )
163 {
164   char *a, *p ;
165
166   if ( nxtoptind >= argc || *(a = argv[nxtoptind]) != '-' ) return -1 ;
167   nxtoptind++ ;
168
169   if ( ! *(a+1) || ( ( p = strchr ( args, *(a+1) ) ) == 0 ) )
170     return msg ( "Eunknown option (%s)", a ), '?' ; 
171
172   if ( *(p+1) != ':' ) nxtoptarg = 0 ;
173   else
174     if ( *(a+2) ) nxtoptarg = a+2 ;
175     else
176       if ( nxtoptind >= argc ) return msg ( "Eno argument for (%s)", a ), '?' ;
177       else nxtoptarg = argv [ nxtoptind++ ] ;
178   return *(a+1) ;
179 }
180