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