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 /*@unchecked@*/ /*@null@*/
00128 static FILE * _stdlog = NULL;
00129 
00130 FILE * rpmlogSetFile(FILE * fp)
00131         /*@globals _stdlog @*/
00132         /*@modifies _stdlog @*/
00133 {
00134     FILE * ofp = _stdlog;
00135     _stdlog = fp;
00136     return ofp;
00137 }
00138 
00139 /*@-readonlytrans@*/    /* FIX: double indirection. */
00140 /*@observer@*/ /*@unchecked@*/
00141 static char *rpmlogMsgPrefix[] = {
00142     N_("fatal error: "),
00143     N_("fatal error: "),
00144     N_("fatal error: "),
00145     N_("error: "),      
00146     N_("warning: "),    
00147     "",                 
00148     "",                 
00149     "D: ",              
00150 };
00151 /*@=readonlytrans@*/
00152 
00153 #if !defined(HAVE_VSNPRINTF)
00154 static inline int vsnprintf(char * buf, /*@unused@*/ int nb,
00155         const char * fmt, va_list ap)
00156 {
00157     return vsprintf(buf, fmt, ap);
00158 }
00159 #endif
00160 
00161 /*@-modfilesys@*/
00162 /*@-compmempass@*/ /* FIX: rpmlogMsgPrefix[] dependent, not unqualified */
00163 /*@-nullstate@*/ /* FIX: rpmlogMsgPrefix[] may be NULL */
00164 static void vrpmlog (unsigned code, const char *fmt, va_list ap)
00165         /*@globals nrecs, recs, internalState @*/
00166         /*@modifies nrecs, recs, internalState @*/
00167 {
00168     unsigned pri = RPMLOG_PRI(code);
00169     unsigned mask = RPMLOG_MASK(pri);
00170     /*@unused@*/ unsigned fac = RPMLOG_FAC(code);
00171     char *msgbuf, *msg;
00172     int msgnb = BUFSIZ, nb;
00173     FILE * msgout = (_stdlog ? _stdlog : stderr);
00174 
00175     if ((mask & rpmlogMask) == 0)
00176         return;
00177 
00178 /*@-boundswrite@*/
00179     msgbuf = xmalloc(msgnb);
00180     *msgbuf = '\0';
00181 
00182     /* Allocate a sufficently large buffer for output. */
00183     while (1) {
00184         va_list apc;
00185         /*@-sysunrecog -usedef@*/ va_copy(apc, ap); /*@=sysunrecog =usedef@*/
00186         nb = vsnprintf(msgbuf, msgnb, fmt, apc);
00187         if (nb > -1 && nb < msgnb)
00188             break;
00189         if (nb > -1)            /* glibc 2.1 (and later) */
00190             msgnb = nb+1;
00191         else                    /* glibc 2.0 */
00192             msgnb *= 2;
00193         msgbuf = xrealloc(msgbuf, msgnb);
00194 /*@-mods@*/
00195         va_end(apc);
00196 /*@=mods@*/
00197     }
00198     msgbuf[msgnb - 1] = '\0';
00199     msg = msgbuf;
00200 
00201     /* Save copy of all messages at warning (or below == "more important"). */
00202     /*@-branchstate@*/
00203     if (pri <= RPMLOG_WARNING) {
00204 
00205         if (recs == NULL)
00206             recs = xmalloc((nrecs+2) * sizeof(*recs));
00207         else
00208             recs = xrealloc(recs, (nrecs+2) * sizeof(*recs));
00209         recs[nrecs].code = code;
00210         recs[nrecs].message = msg = xrealloc(msgbuf, strlen(msgbuf)+1);
00211         msgbuf = NULL;          /* XXX don't free at exit. */
00212         recs[nrecs+1].code = 0;
00213         recs[nrecs+1].message = NULL;
00214         ++nrecs;
00215 
00216         if (_rpmlogCallback) {
00217             /*@-noeffectuncon@*/ /* FIX: useless callback */
00218             _rpmlogCallback();
00219             /*@=noeffectuncon@*/
00220             return;     /* XXX Preserve legacy rpmError behavior. */
00221         }
00222     }
00223     /*@=branchstate@*/
00224 /*@=boundswrite@*/
00225 
00226     /* rpmMessage behavior */
00227 
00228     switch (pri) {
00229     case RPMLOG_INFO:
00230     case RPMLOG_NOTICE:
00231         msgout = (_stdlog ? _stdlog : stdout);
00232         break;
00233 
00234     case RPMLOG_EMERG:
00235     case RPMLOG_ALERT:
00236     case RPMLOG_CRIT:
00237     case RPMLOG_ERR: /* XXX Legacy rpmError behavior used stdout w/o prefix. */
00238     case RPMLOG_WARNING:
00239     case RPMLOG_DEBUG:
00240         break;
00241     }
00242 
00243     if (rpmlogMsgPrefix[pri] && *rpmlogMsgPrefix[pri])
00244         (void) fputs(_(rpmlogMsgPrefix[pri]), msgout);
00245 
00246     (void) fputs(msg, msgout);
00247     (void) fflush(msgout);
00248     msgbuf = _free(msgbuf);
00249     if (pri <= RPMLOG_CRIT)
00250         exit(EXIT_FAILURE);
00251 }
00252 /*@=compmempass =nullstate@*/
00253 /*@=modfilesys@*/
00254 
00255 void rpmlog (int code, const char *fmt, ...)
00256 {
00257     va_list ap;
00258 
00259     va_start(ap, fmt);
00260     /*@-internalglobs@*/ /* FIX: shrug */
00261     vrpmlog(code, fmt, ap);
00262     /*@=internalglobs@*/
00263     va_end(ap);
00264 }
00265 
00266 int rpmErrorCode(void)
00267 {
00268     return rpmlogCode();
00269 }
00270 
00271 const char * rpmErrorString(void)
00272 {
00273     return rpmlogMessage();
00274 }
00275 
00276 rpmlogCallback rpmErrorSetCallback(rpmlogCallback cb)
00277 {
00278     return rpmlogSetCallback(cb);
00279 }
00280 /*@=boundsread@*/

Generated on Fri Oct 12 08:44:54 2007 for rpm by  doxygen 1.5.2