13 # define va_copy(DEST,SRC) __va_copy((DEST),(SRC))
15 # ifdef HAVE_VA_LIST_AS_ARRAY
16 # define va_copy(DEST,SRC) (*(DEST) = *(SRC))
18 # define va_copy(DEST,SRC) ((DEST) = (SRC))
23 /*@access rpmlogRec @*/
28 static /*@only@*/ /*@null@*/ rpmlogRec recs = NULL;
31 * Wrapper to free(3), hides const compilation noise, permit NULL, return NULL.
32 * @param p memory to free
35 /*@unused@*/ static inline /*@null@*/ void *
36 _free(/*@only@*/ /*@null@*/ /*@out@*/ const void * p) /*@modifies p@*/
38 if (p != NULL) free((void *)p);
42 int rpmlogGetNrecs(void)
49 if (recs != NULL && nrecs > 0)
50 return recs[nrecs-1].code;
55 const char * rpmlogMessage(void)
57 if (recs != NULL && nrecs > 0)
58 return recs[nrecs-1].message;
59 return _("(no error)");
63 void rpmlogPrint(FILE *f)
71 for (i = 0; i < nrecs; i++) {
72 rpmlogRec rec = recs + i;
73 if (rec->message && *rec->message)
74 fprintf(f, " %s", rec->message);
79 void rpmlogClose (void)
80 /*@globals recs, nrecs @*/
81 /*@modifies recs, nrecs @*/
86 for (i = 0; i < nrecs; i++) {
87 rpmlogRec rec = recs + i;
88 rec->message = _free(rec->message);
94 void rpmlogOpen (/*@unused@*/ const char *ident, /*@unused@*/ int option,
95 /*@unused@*/ int facility)
100 static unsigned rpmlogMask = RPMLOG_UPTO( RPMLOG_NOTICE );
103 static /*@unused@*/ unsigned rpmlogFacility = RPMLOG_USER;
105 int rpmlogSetMask (int mask)
106 /*@globals rpmlogMask @*/
107 /*@modifies rpmlogMask @*/
109 int omask = rpmlogMask;
116 static /*@null@*/ rpmlogCallback _rpmlogCallback = NULL;
118 rpmlogCallback rpmlogSetCallback(rpmlogCallback cb)
119 /*@globals _rpmlogCallback @*/
120 /*@modifies _rpmlogCallback @*/
122 rpmlogCallback ocb = _rpmlogCallback;
123 _rpmlogCallback = cb;
127 /*@unchecked@*/ /*@null@*/
128 static FILE * _stdlog = NULL;
130 FILE * rpmlogSetFile(FILE * fp)
131 /*@globals _stdlog @*/
132 /*@modifies _stdlog @*/
134 FILE * ofp = _stdlog;
139 /*@-readonlytrans@*/ /* FIX: double indirection. */
140 /*@observer@*/ /*@unchecked@*/
141 static char *rpmlogMsgPrefix[] = {
142 N_("fatal error: "),/*!< RPMLOG_EMERG */
143 N_("fatal error: "),/*!< RPMLOG_ALERT */
144 N_("fatal error: "),/*!< RPMLOG_CRIT */
145 N_("error: "), /*!< RPMLOG_ERR */
146 N_("warning: "), /*!< RPMLOG_WARNING */
147 "", /*!< RPMLOG_NOTICE */
148 "", /*!< RPMLOG_INFO */
149 "D: ", /*!< RPMLOG_DEBUG */
153 #if !defined(HAVE_VSNPRINTF)
154 static inline int vsnprintf(char * buf, /*@unused@*/ int nb,
155 const char * fmt, va_list ap)
157 return vsprintf(buf, fmt, ap);
162 /*@-compmempass@*/ /* FIX: rpmlogMsgPrefix[] dependent, not unqualified */
163 /*@-nullstate@*/ /* FIX: rpmlogMsgPrefix[] may be NULL */
164 static void vrpmlog (unsigned code, const char *fmt, va_list ap)
165 /*@globals nrecs, recs, internalState @*/
166 /*@modifies nrecs, recs, internalState @*/
168 unsigned pri = RPMLOG_PRI(code);
169 unsigned mask = RPMLOG_MASK(pri);
170 /*@unused@*/ unsigned fac = RPMLOG_FAC(code);
172 int msgnb = BUFSIZ, nb;
173 FILE * msgout = (_stdlog ? _stdlog : stderr);
175 if ((mask & rpmlogMask) == 0)
179 msgbuf = xmalloc(msgnb);
182 /* Allocate a sufficently large buffer for output. */
185 /*@-sysunrecog -usedef@*/ va_copy(apc, ap); /*@=sysunrecog =usedef@*/
186 nb = vsnprintf(msgbuf, msgnb, fmt, apc);
187 if (nb > -1 && nb < msgnb)
189 if (nb > -1) /* glibc 2.1 (and later) */
193 msgbuf = xrealloc(msgbuf, msgnb);
198 msgbuf[msgnb - 1] = '\0';
201 /* Save copy of all messages at warning (or below == "more important"). */
203 if (pri <= RPMLOG_WARNING) {
206 recs = xmalloc((nrecs+2) * sizeof(*recs));
208 recs = xrealloc(recs, (nrecs+2) * sizeof(*recs));
209 recs[nrecs].code = code;
210 recs[nrecs].message = msg = xrealloc(msgbuf, strlen(msgbuf)+1);
211 msgbuf = NULL; /* XXX don't free at exit. */
212 recs[nrecs+1].code = 0;
213 recs[nrecs+1].message = NULL;
216 if (_rpmlogCallback) {
217 /*@-noeffectuncon@*/ /* FIX: useless callback */
220 return; /* XXX Preserve legacy rpmError behavior. */
226 /* rpmMessage behavior */
231 msgout = (_stdlog ? _stdlog : stdout);
237 case RPMLOG_ERR: /* XXX Legacy rpmError behavior used stdout w/o prefix. */
243 if (rpmlogMsgPrefix[pri] && *rpmlogMsgPrefix[pri])
244 (void) fputs(_(rpmlogMsgPrefix[pri]), msgout);
246 (void) fputs(msg, msgout);
247 (void) fflush(msgout);
248 msgbuf = _free(msgbuf);
249 if (pri <= RPMLOG_CRIT)
252 /*@=compmempass =nullstate@*/
255 void rpmlog (int code, const char *fmt, ...)
260 /*@-internalglobs@*/ /* FIX: shrug */
261 vrpmlog(code, fmt, ap);
266 int rpmErrorCode(void)
271 const char * rpmErrorString(void)
273 return rpmlogMessage();
276 rpmlogCallback rpmErrorSetCallback(rpmlogCallback cb)
278 return rpmlogSetCallback(cb);