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@*/

Generated on Tue Sep 17 15:59:59 2002 for rpm by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002