ARPDAS_QNX6 1.0
msg.c
Go to the documentation of this file.
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 }
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Defines