ARPDAS_QNX6 1.0
|
00001 /* msg.c */ 00002 #include <unistd.h> 00003 #include <string.h> 00004 #include <errno.h> 00005 #include <stdarg.h> 00006 #include <stdlib.h> 00007 #include <time.h> 00008 #include "oui.h" 00009 #include "nortlib.h" 00010 #include "msg.h" 00011 #include "tm.h" 00012 00013 /** Handle -h option 00014 */ 00015 const char *msghdr_init(const char *hdr_default, int argc, char **argv) { 00016 const char *hdr = hdr_default; 00017 int c; 00018 00019 optind = OPTIND_RESET; 00020 opterr = 0; 00021 while ((c = getopt(argc, argv, opt_string)) != -1) { 00022 switch (c) { 00023 case 'h': hdr = optarg; break; 00024 default: break; // could check for errors 00025 } 00026 } 00027 return hdr; 00028 } 00029 00030 #define MSG_MAX_HDR_LEN 10 00031 static char msg_app_hdr[MSG_MAX_HDR_LEN+1]; 00032 static int write_to_memo = 1, write_to_stderr = 0, write_to_file = 0; 00033 FILE *memo_fp, *file_fp; 00034 00035 void msg_set_hdr(const char *hdr) { 00036 strncpy( msg_app_hdr, hdr, MSG_MAX_HDR_LEN ); 00037 msg_app_hdr[MSG_MAX_HDR_LEN] = '\0'; 00038 } 00039 00040 /* 00041 <opts> "vo:mVs" 00042 00043 <sort> 00044 -v add a level of verbosity 00045 -o <error filename> Write to specified file 00046 -m write to memo [default] 00047 -V write to stderr 00048 -s no message sounds 00049 */ 00050 void msg_init_options(const char *hdr, int argc, char **argv) { 00051 int c; 00052 00053 msg_set_hdr(hdr); 00054 optind = OPTIND_RESET; 00055 opterr = 0; 00056 while ((c = getopt(argc, argv, opt_string)) != -1) { 00057 switch (c) { 00058 case 'v': --nl_debug_level; break; 00059 case 'o': 00060 file_fp = fopen( optarg, "a" ); 00061 if ( file_fp == NULL ) { 00062 fprintf( stderr, "Unable to open output file: '%s'\n", optarg ); 00063 exit(1); 00064 } 00065 write_to_file = 1; 00066 break; 00067 case 'm': write_to_memo = 2; break; 00068 case 'V': write_to_stderr = 1; break; 00069 case '?': 00070 fprintf( stderr, "Unrecognized option: '-%c'\n", optopt ); 00071 exit(1); 00072 default: break; // could check for errors 00073 } 00074 } 00075 if ( ( write_to_file || write_to_stderr ) && write_to_memo == 1 ) 00076 write_to_memo = 0; 00077 if ( write_to_memo ) { 00078 memo_fp = fopen( tm_dev_name( "memo" ), "w" ); 00079 if ( memo_fp == NULL ) { 00080 fprintf( stderr, "Unable to contact memo\n" ); 00081 write_to_stderr = 1; 00082 write_to_memo = 0; 00083 } 00084 } 00085 } 00086 00087 static void write_msg( char *buf, int nb, FILE *fp, char *dest ) { 00088 int rv = fwrite( buf, 1, nb, fp ); 00089 if ( rv == -1 ) { 00090 fprintf( stderr, "Memo: error %s writing to %s\n", 00091 strerror(errno), dest ); 00092 } 00093 fflush(fp); 00094 } 00095 00096 /** 00097 * msg() supports the nl_error() interface, but provides 00098 * a considerable amount of additional functionality to 00099 * support logging of messages within an application with 00100 * multiple executables. Through command-line options, msg() 00101 * can be configured to log to stderr and/or to a log file 00102 * and/or to the memo application, and adds a timestamp 00103 * to each message. See nl_error() for definition of the 00104 * level options. 00105 * @return the level argument. 00106 */ 00107 int msg( int level, const char *fmt, ...) { 00108 va_list args; 00109 int rv; 00110 00111 va_start(args, fmt); 00112 rv = msgv( level, fmt, args ); 00113 va_end(args); 00114 return rv; 00115 } 00116 00117 /** 00118 * msgv() is a version of the msg() function that 00119 * takes a va_list for format arguments, allowing 00120 * more complex reporting functions to built on 00121 * top of the msg() functionality. Internally 00122 * msg() calls msgv(). 00123 * @return the level argument. 00124 */ 00125 #define MSG_MAX_INTERNAL 250 00126 int msgv( int level, const char *fmt, va_list args ) { 00127 char *lvlmsg; 00128 char msgbuf[MSG_MAX_INTERNAL+2]; 00129 time_t now = time(NULL); 00130 struct tm *tm = gmtime(&now); 00131 char *tbuf = asctime(tm); 00132 int nb; 00133 00134 switch ( level ) { 00135 case -1: 00136 case 0: lvlmsg = ""; break; 00137 case 1: lvlmsg = "[WARNING] "; break; 00138 case 2: lvlmsg = "[ERROR] "; break; 00139 case 3: lvlmsg = "[FATAL] "; break; 00140 default: 00141 if ( level >= 4 ) lvlmsg = "[INTERNAL] "; 00142 else if ( level < nl_debug_level ) return level; 00143 else lvlmsg = "[DEBUG] "; 00144 break; 00145 } 00146 strncpy(msgbuf, tbuf+11, 9); // index, length of time string 00147 strncpy( msgbuf+9, lvlmsg, MSG_MAX_INTERNAL-9 ); 00148 nb = 9 + strlen(lvlmsg); 00149 nb += snprintf( msgbuf+nb, MSG_MAX_INTERNAL-nb, "%s: ", msg_app_hdr ); 00150 // I am guaranteed that we have not yet overflowed the buffer 00151 nb += vsnprintf( msgbuf+nb, MSG_MAX_INTERNAL-nb, fmt, args ); 00152 if ( nb > MSG_MAX_INTERNAL ) nb = MSG_MAX_INTERNAL; 00153 if ( msgbuf[nb-1] != '\n' ) msgbuf[nb++] = '\n'; 00154 // msgbuf[nb] = '\0'; 00155 // nb may be as big as MSG_MAX_INTERNAL+1 00156 // we don't need to transmit the trailing nul 00157 00158 if ( write_to_memo ) 00159 write_msg( msgbuf, nb, memo_fp ? memo_fp : stderr, "memo" ); 00160 if ( write_to_file ) write_msg( msgbuf, nb, file_fp, "file" ); 00161 if ( write_to_stderr ) write_msg( msgbuf, nb, stderr, "stderr" ); 00162 if ( level >= 4 ) abort(); 00163 if ( level == 3 ) exit(1); 00164 if ( level == -1 ) exit(0); 00165 return level; 00166 }