• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • File List
  • Globals

rpmio/rpmlog.c

Go to the documentation of this file.
00001 
00005 #include "system.h"
00006 #include <stdarg.h>
00007 #define _RPMLOG_INTERNAL
00008 #include <rpmlog.h>
00009 #include "debug.h"
00010 
00011 /*@access rpmlogRec @*/
00012 
00013 /*@unchecked@*/
00014 static int nrecs = 0;
00015 /*@unchecked@*/
00016 static /*@only@*/ /*@null@*/ rpmlogRec recs = NULL;
00017 
00023 /*@unused@*/ static inline /*@null@*/ void *
00024 _free(/*@only@*/ /*@null@*/ /*@out@*/ const void * p) /*@modifies p@*/
00025 {
00026     if (p != NULL)      free((void *)p);
00027     return NULL;
00028 }
00029 
00030 int rpmlogGetNrecs(void)
00031 {
00032     return nrecs;
00033 }
00034 
00035 int rpmlogCode(void)
00036 {
00037     if (recs != NULL && nrecs > 0)
00038         return recs[nrecs-1].code;
00039     return -1;
00040 }
00041 
00042 const char * rpmlogMessage(void)
00043 {
00044     if (recs != NULL && nrecs > 0)
00045         return recs[nrecs-1].message;
00046     return _("(no error)");
00047 }
00048 
00049 const char * rpmlogRecMessage(rpmlogRec rec)
00050 {
00051     assert(rec != NULL);
00052     return (rec->message);
00053 }
00054 
00055 rpmlogLvl rpmlogRecPriority(rpmlogRec rec)
00056 {
00057     assert(rec != NULL);
00058     return (rec->pri);
00059 }
00060 
00061 /*@-modfilesys@*/
00062 void rpmlogPrint(FILE *f)
00063 {
00064     int i;
00065 
00066     if (f == NULL)
00067         f = stderr;
00068 
00069     if (recs)
00070     for (i = 0; i < nrecs; i++) {
00071         rpmlogRec rec = recs + i;
00072         if (rec->message && *rec->message)
00073             fprintf(f, "    %s", rec->message);
00074     }
00075 }
00076 /*@=modfilesys@*/
00077 
00078 void rpmlogClose (void)
00079         /*@globals recs, nrecs @*/
00080         /*@modifies recs, nrecs @*/
00081 {
00082     int i;
00083 
00084     if (recs)
00085     for (i = 0; i < nrecs; i++) {
00086         rpmlogRec rec = recs + i;
00087         rec->message = _free(rec->message);
00088     }
00089     recs = _free(recs);
00090     nrecs = 0;
00091 }
00092 
00093 void rpmlogOpen (/*@unused@*/ const char *ident, /*@unused@*/ int option,
00094                 /*@unused@*/ int facility)
00095 {
00096 }
00097 
00098 /*@unchecked@*/
00099 static unsigned rpmlogMask = RPMLOG_UPTO( RPMLOG_NOTICE );
00100 
00101 #if 0
00102 /*@unchecked@*/
00103 static /*@unused@*/ unsigned rpmlogFacility = RPMLOG_USER;
00104 #endif
00105 
00106 int rpmlogSetMask (int mask)
00107         /*@globals rpmlogMask @*/
00108         /*@modifies rpmlogMask @*/
00109 {
00110     int omask = rpmlogMask;
00111     if (mask)
00112         rpmlogMask = mask;
00113     return omask;
00114 }
00115 
00116 /*@unchecked@*/
00117 static /*@null@*/ rpmlogCallback _rpmlogCallback = NULL;
00118 
00119 /*@unchecked@*/
00120 static rpmlogCallbackData _rpmlogCallbackData = NULL;
00121 
00122 rpmlogCallback rpmlogSetCallback(rpmlogCallback cb, rpmlogCallbackData data)
00123         /*@globals _rpmlogCallback, _rpmlogCallbackData @*/
00124         /*@modifies _rpmlogCallback, _rpmlogCallbackData @*/
00125 {
00126     rpmlogCallback ocb = _rpmlogCallback;
00127     _rpmlogCallback = cb;
00128     _rpmlogCallbackData = data;
00129     return ocb;
00130 }
00131 
00132 void rpmlogGetCallback(rpmlogCallback *cb, rpmlogCallbackData *data)
00133         /*@globals _rpmlogCallback, _rpmlogCallbackData @*/
00134 {
00135     *cb = _rpmlogCallback;
00136     *data = _rpmlogCallbackData;
00137     return;
00138 }
00139 
00140 /*@unchecked@*/ /*@null@*/
00141 static FILE * _stdlog = NULL;
00142 
00143 static int rpmlogDefault(rpmlogRec rec)
00144         /*@globals fileSystem @*/
00145         /*@modifies fileSystem @*/
00146 {
00147     FILE *msgout = (_stdlog ? _stdlog : stderr);
00148 
00149     switch (rec->pri) {
00150     case RPMLOG_INFO:
00151     case RPMLOG_NOTICE:
00152         msgout = (_stdlog ? _stdlog : stdout);
00153         break;
00154     case RPMLOG_EMERG:
00155     case RPMLOG_ALERT:
00156     case RPMLOG_CRIT:
00157     case RPMLOG_ERR:
00158     case RPMLOG_WARNING:
00159     case RPMLOG_DEBUG:
00160     default:
00161         break;
00162     }
00163 
00164     (void) fputs(rpmlogLevelPrefix(rec->pri), msgout);
00165 
00166     if (rec->message)
00167         (void) fputs(rec->message, msgout);
00168     (void) fflush(msgout);
00169 
00170     return (rec->pri <= RPMLOG_CRIT ? RPMLOG_EXIT : 0);
00171 }
00172 
00173 FILE * rpmlogSetFile(FILE * fp)
00174         /*@globals _stdlog @*/
00175         /*@modifies _stdlog @*/
00176 {
00177     FILE * ofp = _stdlog;
00178     _stdlog = fp;
00179     return ofp;
00180 }
00181 
00182 /*@-readonlytrans@*/    /* FIX: double indirection. */
00183 /*@observer@*/ /*@unchecked@*/
00184 static const char *rpmlogMsgPrefix[] = {
00185     N_("fatal error: "),
00186     N_("fatal error: "),
00187     N_("fatal error: "),
00188     N_("error: "),      
00189     N_("warning: "),    
00190     "",                 
00191     "",                 
00192     "D: ",              
00193 };
00194 /*@=readonlytrans@*/
00195 
00196 const char * rpmlogLevelPrefix(rpmlogLvl pri)
00197 {
00198     return rpmlogMsgPrefix[pri&0x7];
00199 }
00200 
00201 #if !defined(HAVE_VSNPRINTF)
00202 static inline int vsnprintf(char * buf, /*@unused@*/ int nb,
00203         const char * fmt, va_list ap)
00204 {
00205     return vsprintf(buf, fmt, ap);
00206 }
00207 #endif
00208 
00209 /*@-modfilesys@*/
00210 /*@-compmempass@*/ /* FIX: rpmlogMsgPrefix[] dependent, not unqualified */
00211 /*@-nullstate@*/ /* FIX: rpmlogMsgPrefix[] may be NULL */
00212 static void vrpmlog (unsigned code, const char *fmt, va_list ap)
00213         /*@globals nrecs, recs, internalState @*/
00214         /*@modifies nrecs, recs, internalState @*/
00215 {
00216     unsigned pri = RPMLOG_PRI(code);
00217     unsigned mask = RPMLOG_MASK(pri);
00218 #if 0
00219     /*@unused@*/ unsigned fac = RPMLOG_FAC(code);
00220 #endif
00221     char *msgbuf, *msg;
00222     size_t msgnb = BUFSIZ;
00223     int nb;
00224     int cbrc = RPMLOG_DEFAULT;
00225     int needexit = 0;
00226     struct rpmlogRec_s rec;
00227 
00228     if ((mask & rpmlogMask) == 0)
00229         return;
00230 
00231     msgbuf = xmalloc(msgnb);
00232     *msgbuf = '\0';
00233 
00234     /* Allocate a sufficently large buffer for output. */
00235     while (1) {
00236         va_list apc;
00237         /*@-unrecog -usedef@*/ va_copy(apc, ap); /*@=unrecog =usedef@*/
00238         nb = vsnprintf(msgbuf, msgnb, fmt, apc);
00239         if (nb > -1 && (size_t)nb < msgnb)
00240             break;
00241         if (nb > -1)            /* glibc 2.1 (and later) */
00242             msgnb = nb+1;
00243         else                    /* glibc 2.0 */
00244             msgnb *= 2;
00245         msgbuf = xrealloc(msgbuf, msgnb);
00246 /*@-mods@*/
00247         va_end(apc);
00248 /*@=mods@*/
00249     }
00250     msgbuf[msgnb - 1] = '\0';
00251     msg = msgbuf;
00252 
00253     rec.code = code;
00254     rec.message = msg;
00255     rec.pri = pri;
00256 
00257     /* Save copy of all messages at warning (or below == "more important"). */
00258     if (pri <= RPMLOG_WARNING) {
00259         if (recs == NULL)
00260             recs = xmalloc((nrecs+2) * sizeof(*recs));
00261         else
00262             recs = xrealloc(recs, (nrecs+2) * sizeof(*recs));
00263         recs[nrecs].code = rec.code;
00264         recs[nrecs].pri = rec.pri;
00265         recs[nrecs].message = xstrdup(msgbuf);
00266         recs[nrecs+1].code = 0;
00267         recs[nrecs].pri = 0;
00268         recs[nrecs+1].message = NULL;
00269         ++nrecs;
00270     }
00271 
00272     if (_rpmlogCallback) {
00273         cbrc = _rpmlogCallback(&rec, _rpmlogCallbackData);
00274         needexit += cbrc & RPMLOG_EXIT;
00275     }
00276 
00277     if (cbrc & RPMLOG_DEFAULT) {
00278 /*@-usereleased@*/
00279         cbrc = rpmlogDefault(&rec);
00280 /*@=usereleased@*/
00281         needexit += cbrc & RPMLOG_EXIT;
00282     }
00283 
00284 /*@-usereleased@*/      /* msgbuf is NULL or needs free'ing */
00285     msgbuf = _free(msgbuf);
00286 /*@=usereleased@*/
00287     if (needexit)
00288         exit(EXIT_FAILURE);
00289 }
00290 /*@=compmempass =nullstate@*/
00291 /*@=modfilesys@*/
00292 
00293 void rpmlog (int code, const char *fmt, ...)
00294 {
00295     va_list ap;
00296 
00297     va_start(ap, fmt);
00298     /*@-internalglobs@*/ /* FIX: shrug */
00299     vrpmlog(code, fmt, ap);
00300     /*@=internalglobs@*/
00301     va_end(ap);
00302 }

Generated on Mon Nov 29 2010 05:18:47 for rpm by  doxygen 1.7.2