# rpmio/rpmlog.c

Go to the documentation of this file.

    00001
    00005 #include "system.h"
    00006 #include <stdarg.h>
    00007 #include "rpmlog.h"
    00008 #include "debug.h"
    00009
    00010 #ifndef va_copy
    00011 # ifdef __va_copy
    00012 #  define va_copy(DEST,SRC) __va_copy((DEST),(SRC))
    00013 # else
    00014 #  ifdef HAVE_VA_LIST_AS_ARRAY
    00015 #   define va_copy(DEST,SRC) (*(DEST) = *(SRC))
    00016 #  else
    00017 #   define va_copy(DEST,SRC) ((DEST) = (SRC))
    00018 #  endif
    00019 # endif
    00020 #endif
    00021
    00022 /*@access rpmlogRec @*/
    00023
    00024 /*@unchecked@*/
    00025 static int nrecs = 0;
    00026 /*@unchecked@*/
    00027 static /*@only@*/ /*@null@*/ rpmlogRec recs = NULL;
    00028
    00034 /*@unused@*/ static inline /*@null@*/ void *
    00035 _free(/*@only@*/ /*@null@*/ /*@out@*/ const void * p) /*@modifies p@*/
    00036 {
    00037     if (p != NULL)      free((void *)p);
    00038     return NULL;
    00039 }
    00040
    00041 int rpmlogGetNrecs(void)
    00042 {
    00043     return nrecs;
    00044 }
    00045
    00046 int rpmlogCode(void)
    00047 {
    00048     if (recs != NULL && nrecs > 0)
    00049         return recs[nrecs-1].code;
    00050     return -1;
    00051 }
    00052
    00053
    00054 const char * rpmlogMessage(void)
    00055 {
    00056     if (recs != NULL && nrecs > 0)
    00057         return recs[nrecs-1].message;
    00058     return _("(no error)");
    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 /*@unchecked@*/
    00102 static /*@unused@*/ unsigned rpmlogFacility = RPMLOG_USER;
    00103
    00104 int rpmlogSetMask (int mask)
    00105         /*@globals rpmlogMask @*/
    00106         /*@modifies rpmlogMask @*/
    00107 {
    00108     int omask = rpmlogMask;
    00109     if (mask)
    00110         rpmlogMask = mask;
    00111     return omask;
    00112 }
    00113
    00114 /*@unchecked@*/
    00115 static /*@null@*/ rpmlogCallback _rpmlogCallback = NULL;
    00116
    00117 rpmlogCallback rpmlogSetCallback(rpmlogCallback cb)
    00118         /*@globals _rpmlogCallback @*/
    00119         /*@modifies _rpmlogCallback @*/
    00120 {
    00121     rpmlogCallback ocb = _rpmlogCallback;
    00122     _rpmlogCallback = cb;
    00123     return ocb;
    00124 }
    00125
    00126 /*@-readonlytrans@*/    /* FIX: double indirection. */
    00127 /*@observer@*/ /*@unchecked@*/
    00128 static char *rpmlogMsgPrefix[] = {
    00129     N_("fatal error: "),
    00130     N_("fatal error: "),
    00131     N_("fatal error: "),
    00132     N_("error: "),
    00133     N_("warning: "),
    00134     "",
    00135     "",
    00136     "D: ",
    00137 };
    00138 /*@=readonlytrans@*/
    00139
    00140 #if !defined(HAVE_VSNPRINTF)
    00141 static inline int vsnprintf(char * buf, /*@unused@*/ int nb,
    00142         const char * fmt, va_list ap)
    00143 {
    00144     return vsprintf(buf, fmt, ap);
    00145 }
    00146 #endif
    00147
    00148 /*@-modfilesys@*/
    00149 /*@-compmempass@*/ /* FIX: rpmlogMsgPrefix[] dependent, not unqualified */
    00150 /*@-nullstate@*/ /* FIX: rpmlogMsgPrefix[] may be NULL */
    00151 static void vrpmlog (unsigned code, const char *fmt, va_list ap)
    00152         /*@globals nrecs, recs, internalState @*/
    00153         /*@modifies nrecs, recs, internalState @*/
    00154 {
    00155     unsigned pri = RPMLOG_PRI(code);
    00156     unsigned mask = RPMLOG_MASK(pri);
    00157     /*@unused@*/ unsigned fac = RPMLOG_FAC(code);
    00158     char *msgbuf, *msg;
    00159     int msgnb = BUFSIZ, nb;
    00160     FILE * msgout = stderr;
    00161
    00162     if ((mask & rpmlogMask) == 0)
    00163         return;
    00164
    00165     msgbuf = xmalloc(msgnb);
    00166     *msgbuf = '\0';
    00167
    00168     /* Allocate a sufficently large buffer for output. */
    00169     while (1) {
    00170         va_list apc;
    00171         /*@-sysunrecog -usedef@*/ va_copy(apc, ap); /*@=sysunrecog =usedef@*/
    00172         nb = vsnprintf(msgbuf, msgnb, fmt, apc);
    00173         if (nb > -1 && nb < msgnb)
    00174             break;
    00175         if (nb > -1)            /* glibc 2.1 (and later) */
    00176             msgnb = nb+1;
    00177         else                    /* glibc 2.0 */
    00178             msgnb *= 2;
    00179         msgbuf = xrealloc(msgbuf, msgnb);
    00180     }
    00181     msgbuf[msgnb - 1] = '\0';
    00182     msg = msgbuf;
    00183
    00184     /* Save copy of all messages at warning (or below == "more important"). */
    00185     /*@-branchstate@*/
    00186     if (pri <= RPMLOG_WARNING) {
    00187
    00188         if (recs == NULL)
    00189             recs = xmalloc((nrecs+2) * sizeof(*recs));
    00190         else
    00191             recs = xrealloc(recs, (nrecs+2) * sizeof(*recs));
    00192         recs[nrecs].code = code;
    00193         recs[nrecs].message = msg = xrealloc(msgbuf, strlen(msgbuf)+1);
    00194         msgbuf = NULL;          /* XXX don't free at exit. */
    00195         recs[nrecs+1].code = 0;
    00196         recs[nrecs+1].message = NULL;
    00197         ++nrecs;
    00198
    00199         if (_rpmlogCallback) {
    00200             /*@-noeffectuncon@*/ /* FIX: useless callback */
    00201             _rpmlogCallback();
    00202             /*@=noeffectuncon@*/
    00203             return;     /* XXX Preserve legacy rpmError behavior. */
    00204         }
    00205     }
    00206     /*@=branchstate@*/
    00207
    00208     /* rpmMessage behavior */
    00209
    00210     switch (pri) {
    00211     case RPMLOG_INFO:
    00212     case RPMLOG_NOTICE:
    00213         msgout = stdout;
    00214         break;
    00215
    00216     case RPMLOG_EMERG:
    00217     case RPMLOG_ALERT:
    00218     case RPMLOG_CRIT:
    00219     case RPMLOG_ERR: /* XXX Legacy rpmError behavior used stdout w/o prefix. */
    00220     case RPMLOG_WARNING:
    00221     case RPMLOG_DEBUG:
    00222         break;
    00223     }
    00224
    00225     if (rpmlogMsgPrefix[pri] && *rpmlogMsgPrefix[pri])
    00226         (void) fputs(_(rpmlogMsgPrefix[pri]), msgout);
    00227
    00228     (void) fputs(msg, msgout);
    00229     (void) fflush(msgout);
    00230     msgbuf = _free(msgbuf);
    00231     if (pri <= RPMLOG_CRIT)
    00232         exit(EXIT_FAILURE);
    00233 }
    00234 /*@=compmempass =nullstate@*/
    00235 /*@=modfilesys@*/
    00236
    00237 void rpmlog (int code, const char *fmt, ...)
    00238 {
    00239     va_list ap;
    00240
    00241     va_start(ap, fmt);
    00242     /*@-internalglobs@*/ /* FIX: shrug */
    00243     vrpmlog(code, fmt, ap);
    00244     /*@=internalglobs@*/
    00245     va_end(ap);
    00246 }
    00247
    00248 int rpmErrorCode(void)
    00249 {
    00250     return rpmlogCode();
    00251 }
    00252
    00253 const char * rpmErrorString(void)
    00254 {
    00255     return rpmlogMessage();
    00256 }
    00257
    00258 rpmlogCallback rpmErrorSetCallback(rpmlogCallback cb)
    00259 {
    00260     return rpmlogSetCallback(cb);
    00261 }