rpm
5.2.1
|
00001 00005 #include "system.h" 00006 #include <stdarg.h> 00007 #define _RPMLOG_INTERNAL 00008 #include <rpmlog.h> 00009 #include "debug.h" 00010 00011 /*@access rpmlogRec @*/ 00012 00013 /*@unchecked@*/ 00014 static int nrecs = 0; 00015 /*@unchecked@*/ 00016 static /*@only@*/ /*@null@*/ rpmlogRec recs = NULL; 00017 00023 /*@unused@*/ static inline /*@null@*/ void * 00024 _free(/*@only@*/ /*@null@*/ /*@out@*/ const void * p) /*@modifies p@*/ 00025 { 00026 if (p != NULL) free((void *)p); 00027 return NULL; 00028 } 00029 00030 int rpmlogGetNrecs(void) 00031 { 00032 return nrecs; 00033 } 00034 00035 int rpmlogCode(void) 00036 { 00037 if (recs != NULL && nrecs > 0) 00038 return recs[nrecs-1].code; 00039 return -1; 00040 } 00041 00042 const char * rpmlogMessage(void) 00043 { 00044 if (recs != NULL && nrecs > 0) 00045 return recs[nrecs-1].message; 00046 return _("(no error)"); 00047 } 00048 00049 const char * rpmlogRecMessage(rpmlogRec rec) 00050 { 00051 assert(rec != NULL); 00052 return (rec->message); 00053 } 00054 00055 rpmlogLvl rpmlogRecPriority(rpmlogRec rec) 00056 { 00057 assert(rec != NULL); 00058 return (rec->pri); 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, 00094 /*@unused@*/ int option, 00095 /*@unused@*/ int facility) 00096 { 00097 } 00098 00099 /*@unchecked@*/ 00100 static unsigned rpmlogMask = RPMLOG_UPTO( RPMLOG_NOTICE ); 00101 00102 #if 0 00103 /*@unchecked@*/ 00104 static /*@unused@*/ unsigned rpmlogFacility = RPMLOG_USER; 00105 #endif 00106 00107 int rpmlogSetMask (int mask) 00108 /*@globals rpmlogMask @*/ 00109 /*@modifies rpmlogMask @*/ 00110 { 00111 int omask = rpmlogMask; 00112 if (mask) 00113 rpmlogMask = mask; 00114 return omask; 00115 } 00116 00117 /*@unchecked@*/ /*@null@*/ 00118 static rpmlogCallback _rpmlogCallback; 00119 00120 /*@unchecked@*/ /*@null@*/ 00121 static rpmlogCallbackData _rpmlogCallbackData; 00122 00123 rpmlogCallback rpmlogSetCallback(rpmlogCallback cb, rpmlogCallbackData data) 00124 /*@globals _rpmlogCallback, _rpmlogCallbackData @*/ 00125 /*@modifies _rpmlogCallback, _rpmlogCallbackData @*/ 00126 { 00127 rpmlogCallback ocb = _rpmlogCallback; 00128 _rpmlogCallback = cb; 00129 _rpmlogCallbackData = data; 00130 return ocb; 00131 } 00132 00133 void rpmlogGetCallback(rpmlogCallback *cb, rpmlogCallbackData *data) 00134 /*@globals _rpmlogCallback, _rpmlogCallbackData @*/ 00135 { 00136 *cb = _rpmlogCallback; 00137 *data = _rpmlogCallbackData; 00138 return; 00139 } 00140 00141 /*@unchecked@*/ /*@null@*/ 00142 static FILE * _stdlog = NULL; 00143 00144 static int rpmlogDefault(rpmlogRec rec) 00145 /*@globals fileSystem @*/ 00146 /*@modifies fileSystem @*/ 00147 { 00148 FILE *msgout = (_stdlog ? _stdlog : stderr); 00149 00150 switch (rec->pri) { 00151 case RPMLOG_INFO: 00152 case RPMLOG_NOTICE: 00153 msgout = (_stdlog ? _stdlog : stdout); 00154 break; 00155 case RPMLOG_EMERG: 00156 case RPMLOG_ALERT: 00157 case RPMLOG_CRIT: 00158 case RPMLOG_ERR: 00159 case RPMLOG_WARNING: 00160 case RPMLOG_DEBUG: 00161 default: 00162 break; 00163 } 00164 00165 (void) fputs(rpmlogLevelPrefix(rec->pri), msgout); 00166 00167 if (rec->message) 00168 (void) fputs(rec->message, msgout); 00169 (void) fflush(msgout); 00170 00171 return (rec->pri <= RPMLOG_CRIT ? RPMLOG_EXIT : 0); 00172 } 00173 00174 FILE * rpmlogSetFile(FILE * fp) 00175 /*@globals _stdlog @*/ 00176 /*@modifies _stdlog @*/ 00177 { 00178 FILE * ofp = _stdlog; 00179 _stdlog = fp; 00180 return ofp; 00181 } 00182 00183 /*@-readonlytrans@*/ /* FIX: double indirection. */ 00184 /*@observer@*/ /*@unchecked@*/ 00185 static const char *rpmlogMsgPrefix[] = { 00186 N_("fatal error: "), 00187 N_("fatal error: "), 00188 N_("fatal error: "), 00189 N_("error: "), 00190 N_("warning: "), 00191 "", 00192 "", 00193 "D: ", 00194 }; 00195 /*@=readonlytrans@*/ 00196 00197 const char * rpmlogLevelPrefix(rpmlogLvl pri) 00198 { 00199 return rpmlogMsgPrefix[pri&0x7]; 00200 } 00201 00202 #if !defined(HAVE_VSNPRINTF) 00203 static inline int vsnprintf(char * buf, /*@unused@*/ int nb, 00204 const char * fmt, va_list ap) 00205 { 00206 return vsprintf(buf, fmt, ap); 00207 } 00208 #endif 00209 00210 /*@-modfilesys@*/ 00211 /*@-compmempass@*/ /* FIX: rpmlogMsgPrefix[] dependent, not unqualified */ 00212 /*@-nullstate@*/ /* FIX: rpmlogMsgPrefix[] may be NULL */ 00213 void vrpmlog (unsigned code, const char *fmt, va_list ap) 00214 /*@globals nrecs, recs, internalState @*/ 00215 /*@modifies nrecs, recs, internalState @*/ 00216 { 00217 unsigned pri = RPMLOG_PRI(code); 00218 unsigned mask = RPMLOG_MASK(pri); 00219 #if 0 00220 /*@unused@*/ unsigned fac = RPMLOG_FAC(code); 00221 #endif 00222 char *msgbuf, *msg; 00223 size_t msgnb = BUFSIZ; 00224 int nb; 00225 int cbrc = RPMLOG_DEFAULT; 00226 int needexit = 0; 00227 struct rpmlogRec_s rec; 00228 00229 if ((mask & rpmlogMask) == 0) 00230 return; 00231 00232 msgbuf = xmalloc(msgnb); 00233 *msgbuf = '\0'; 00234 00235 /* Allocate a sufficently large buffer for output. */ 00236 while (1) { 00237 va_list apc; 00238 /*@-unrecog -usedef@*/ va_copy(apc, ap); /*@=unrecog =usedef@*/ 00239 nb = vsnprintf(msgbuf, msgnb, fmt, apc); 00240 if (nb > -1 && (size_t)nb < msgnb) 00241 break; 00242 if (nb > -1) /* glibc 2.1 (and later) */ 00243 msgnb = nb+1; 00244 else /* glibc 2.0 */ 00245 msgnb *= 2; 00246 msgbuf = xrealloc(msgbuf, msgnb); 00247 /*@-mods@*/ 00248 va_end(apc); 00249 /*@=mods@*/ 00250 } 00251 msgbuf[msgnb - 1] = '\0'; 00252 msg = msgbuf; 00253 00254 rec.code = code; 00255 rec.message = msg; 00256 rec.pri = pri; 00257 00258 /* Save copy of all messages at warning (or below == "more important"). */ 00259 if (pri <= RPMLOG_WARNING) { 00260 if (recs == NULL) 00261 recs = xmalloc((nrecs+2) * sizeof(*recs)); 00262 else 00263 recs = xrealloc(recs, (nrecs+2) * sizeof(*recs)); 00264 recs[nrecs].code = rec.code; 00265 recs[nrecs].pri = rec.pri; 00266 recs[nrecs].message = xstrdup(msgbuf); 00267 ++nrecs; 00268 recs[nrecs].code = 0; 00269 recs[nrecs].pri = 0; 00270 recs[nrecs].message = NULL; 00271 } 00272 00273 if (_rpmlogCallback) { 00274 cbrc = _rpmlogCallback(&rec, _rpmlogCallbackData); 00275 needexit += cbrc & RPMLOG_EXIT; 00276 } 00277 00278 if (cbrc & RPMLOG_DEFAULT) { 00279 /*@-usereleased@*/ 00280 cbrc = rpmlogDefault(&rec); 00281 /*@=usereleased@*/ 00282 needexit += cbrc & RPMLOG_EXIT; 00283 } 00284 00285 /*@-usereleased@*/ /* msgbuf is NULL or needs free'ing */ 00286 msgbuf = _free(msgbuf); 00287 /*@=usereleased@*/ 00288 if (needexit) 00289 exit(EXIT_FAILURE); 00290 } 00291 /*@=compmempass =nullstate@*/ 00292 /*@=modfilesys@*/ 00293 00294 void _rpmlog (int code, const char *fmt, ...) 00295 { 00296 va_list ap; 00297 00298 va_start(ap, fmt); 00299 /*@-internalglobs@*/ /* FIX: shrug */ 00300 vrpmlog(code, fmt, ap); 00301 /*@=internalglobs@*/ 00302 va_end(ap); 00303 }