Main Page Modules Data Structures File List Data Fields Globals Related Pages

# rpmio/rpmlog.c

Go to the documentation of this file.

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