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