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 }

Generated on Wed Oct 25 06:55:49 2006 for rpm by  doxygen 1.4.7