- Main Page
- Related Pages
- Modules
- Data Structures
- Files

# 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 = xrealloc(msgbuf, strlen(msgbuf)+1);
    00266         msgbuf = NULL;          /* XXX don't free at exit. */
    00267         recs[nrecs+1].code = 0;
    00268         recs[nrecs].pri = 0;
    00269         recs[nrecs+1].message = NULL;
    00270         ++nrecs;
    00271     }
    00272
    00273     if (_rpmlogCallback) {
    00274         cbrc = _rpmlogCallback(&rec, _rpmlogCallbackData);
    00275         needexit += cbrc & RPMLOG_EXIT;
    00276     }
    00277
    00278     if (cbrc & RPMLOG_DEFAULT) {
    00279 /*@-usereleased@*/
    00280         cbrc = rpmlogDefault(&rec);
    00281 /*@=usereleased@*/
    00282         needexit += cbrc & RPMLOG_EXIT;
    00283     }
    00284
    00285 /*@-usereleased@*/      /* msgbuf is NULL or needs free'ing */
    00286     msgbuf = _free(msgbuf);
    00287 /*@=usereleased@*/
    00288     if (needexit)
    00289         exit(EXIT_FAILURE);
    00290 }
    00291 /*@=compmempass =nullstate@*/
    00292 /*@=modfilesys@*/
    00293
    00294 void rpmlog (int code, const char *fmt, ...)
    00295 {
    00296     va_list ap;
    00297
    00298     va_start(ap, fmt);
    00299     /*@-internalglobs@*/ /* FIX: shrug */
    00300     vrpmlog(code, fmt, ap);
    00301     /*@=internalglobs@*/
    00302     va_end(ap);
    00303 }