00001 
00006 #include "system.h"
00007 #include <stdarg.h>
00008 #include "rpmlog.h"
00009 #include "debug.h"
00010 
00011 #ifndef va_copy
00012 # ifdef __va_copy
00013 #  define va_copy(DEST,SRC) __va_copy((DEST),(SRC))
00014 # else
00015 #  ifdef HAVE_VA_LIST_AS_ARRAY
00016 #   define va_copy(DEST,SRC) (*(DEST) = *(SRC))
00017 #  else
00018 #   define va_copy(DEST,SRC) ((DEST) = (SRC))
00019 #  endif
00020 # endif
00021 #endif
00022 
00023 
00024 
00025 
00026 static int nrecs = 0;
00027 
00028 static   rpmlogRec recs = NULL;
00029 
00035  static inline  void *
00036 _free(   const void * p) 
00037 {
00038     if (p != NULL)      free((void *)p);
00039     return NULL;
00040 }
00041 
00042 int rpmlogGetNrecs(void)
00043 {
00044     return nrecs;
00045 }
00046 
00047 int rpmlogCode(void)
00048 {
00049     if (recs != NULL && nrecs > 0)
00050         return recs[nrecs-1].code;
00051     return -1;
00052 }
00053 
00054 
00055 const char * rpmlogMessage(void)
00056 {
00057     if (recs != NULL && nrecs > 0)
00058         return recs[nrecs-1].message;
00059     return _("(no error)");
00060 }
00061 
00062 
00063 void rpmlogPrint(FILE *f)
00064 {
00065     int i;
00066 
00067     if (f == NULL)
00068         f = stderr;
00069 
00070     if (recs)
00071     for (i = 0; i < nrecs; i++) {
00072         rpmlogRec rec = recs + i;
00073         if (rec->message && *rec->message)
00074             fprintf(f, "    %s", rec->message);
00075     }
00076 }
00077 
00078 
00079 void rpmlogClose (void)
00080         
00081         
00082 {
00083     int i;
00084 
00085     if (recs)
00086     for (i = 0; i < nrecs; i++) {
00087         rpmlogRec rec = recs + i;
00088         rec->message = _free(rec->message);
00089     }
00090     recs = _free(recs);
00091     nrecs = 0;
00092 }
00093 
00094 void rpmlogOpen ( const char *ident,  int option,
00095                  int facility)
00096 {
00097 }
00098 
00099 
00100 static unsigned rpmlogMask = RPMLOG_UPTO( RPMLOG_NOTICE );
00101 
00102 
00103 static  unsigned rpmlogFacility = RPMLOG_USER;
00104 
00105 int rpmlogSetMask (int mask)
00106         
00107         
00108 {
00109     int omask = rpmlogMask;
00110     if (mask)
00111         rpmlogMask = mask;
00112     return omask;
00113 }
00114 
00115 
00116 static  rpmlogCallback _rpmlogCallback = NULL;
00117 
00118 rpmlogCallback rpmlogSetCallback(rpmlogCallback cb)
00119         
00120         
00121 {
00122     rpmlogCallback ocb = _rpmlogCallback;
00123     _rpmlogCallback = cb;
00124     return ocb;
00125 }
00126 
00127  
00128 static FILE * _stdlog = NULL;
00129 
00130 FILE * rpmlogSetFile(FILE * fp)
00131         
00132         
00133 {
00134     FILE * ofp = _stdlog;
00135     _stdlog = fp;
00136     return ofp;
00137 }
00138 
00139     
00140  
00141 static char *rpmlogMsgPrefix[] = {
00142     N_("fatal error: "),
00143     N_("fatal error: "),
00144     N_("fatal error: "),
00145     N_("error: "),      
00146     N_("warning: "),    
00147     "",                 
00148     "",                 
00149     "D: ",              
00150 };
00151 
00152 
00153 #if !defined(HAVE_VSNPRINTF)
00154 static inline int vsnprintf(char * buf,  int nb,
00155         const char * fmt, va_list ap)
00156 {
00157     return vsprintf(buf, fmt, ap);
00158 }
00159 #endif
00160 
00161 
00162  
00163  
00164 static void vrpmlog (unsigned code, const char *fmt, va_list ap)
00165         
00166         
00167 {
00168     unsigned pri = RPMLOG_PRI(code);
00169     unsigned mask = RPMLOG_MASK(pri);
00170      unsigned fac = RPMLOG_FAC(code);
00171     char *msgbuf, *msg;
00172     int msgnb = BUFSIZ, nb;
00173     FILE * msgout = (_stdlog ? _stdlog : stderr);
00174 
00175     if ((mask & rpmlogMask) == 0)
00176         return;
00177 
00178 
00179     msgbuf = xmalloc(msgnb);
00180     *msgbuf = '\0';
00181 
00182     
00183     while (1) {
00184         va_list apc;
00185          va_copy(apc, ap); 
00186         nb = vsnprintf(msgbuf, msgnb, fmt, apc);
00187         if (nb > -1 && nb < msgnb)
00188             break;
00189         if (nb > -1)            
00190             msgnb = nb+1;
00191         else                    
00192             msgnb *= 2;
00193         msgbuf = xrealloc(msgbuf, msgnb);
00194 
00195         va_end(apc);
00196 
00197     }
00198     msgbuf[msgnb - 1] = '\0';
00199     msg = msgbuf;
00200 
00201     
00202     
00203     if (pri <= RPMLOG_WARNING) {
00204 
00205         if (recs == NULL)
00206             recs = xmalloc((nrecs+2) * sizeof(*recs));
00207         else
00208             recs = xrealloc(recs, (nrecs+2) * sizeof(*recs));
00209         recs[nrecs].code = code;
00210         recs[nrecs].message = msg = xrealloc(msgbuf, strlen(msgbuf)+1);
00211         msgbuf = NULL;          
00212         recs[nrecs+1].code = 0;
00213         recs[nrecs+1].message = NULL;
00214         ++nrecs;
00215 
00216         if (_rpmlogCallback) {
00217              
00218             _rpmlogCallback();
00219             
00220             return;     
00221         }
00222     }
00223     
00224 
00225 
00226     
00227 
00228     switch (pri) {
00229     case RPMLOG_INFO:
00230     case RPMLOG_NOTICE:
00231         msgout = (_stdlog ? _stdlog : stdout);
00232         break;
00233 
00234     case RPMLOG_EMERG:
00235     case RPMLOG_ALERT:
00236     case RPMLOG_CRIT:
00237     case RPMLOG_ERR: 
00238     case RPMLOG_WARNING:
00239     case RPMLOG_DEBUG:
00240         break;
00241     }
00242 
00243     if (rpmlogMsgPrefix[pri] && *rpmlogMsgPrefix[pri])
00244         (void) fputs(_(rpmlogMsgPrefix[pri]), msgout);
00245 
00246     (void) fputs(msg, msgout);
00247     (void) fflush(msgout);
00248     msgbuf = _free(msgbuf);
00249     if (pri <= RPMLOG_CRIT)
00250         exit(EXIT_FAILURE);
00251 }
00252 
00253 
00254 
00255 void rpmlog (int code, const char *fmt, ...)
00256 {
00257     va_list ap;
00258 
00259     va_start(ap, fmt);
00260      
00261     vrpmlog(code, fmt, ap);
00262     
00263     va_end(ap);
00264 }
00265 
00266 int rpmErrorCode(void)
00267 {
00268     return rpmlogCode();
00269 }
00270 
00271 const char * rpmErrorString(void)
00272 {
00273     return rpmlogMessage();
00274 }
00275 
00276 rpmlogCallback rpmErrorSetCallback(rpmlogCallback cb)
00277 {
00278     return rpmlogSetCallback(cb);
00279 }
00280