12 # define va_copy(DEST,SRC) __va_copy((DEST),(SRC))
14 # ifdef HAVE_VA_LIST_AS_ARRAY
15 # define va_copy(DEST,SRC) (*(DEST) = *(SRC))
17 # define va_copy(DEST,SRC) ((DEST) = (SRC))
22 /*@access rpmlogRec @*/
27 static /*@only@*/ /*@null@*/ rpmlogRec recs = NULL;
30 * Wrapper to free(3), hides const compilation noise, permit NULL, return NULL.
31 * @param p memory to free
34 /*@unused@*/ static inline /*@null@*/ void *
35 _free(/*@only@*/ /*@null@*/ /*@out@*/ const void * p) /*@modifies p@*/
37 if (p != NULL) free((void *)p);
41 int rpmlogGetNrecs(void)
48 if (recs != NULL && nrecs > 0)
49 return recs[nrecs-1].code;
54 const char * rpmlogMessage(void)
56 if (recs != NULL && nrecs > 0)
57 return recs[nrecs-1].message;
58 return _("(no error)");
62 void rpmlogPrint(FILE *f)
70 for (i = 0; i < nrecs; i++) {
71 rpmlogRec rec = recs + i;
72 if (rec->message && *rec->message)
73 fprintf(f, " %s", rec->message);
78 void rpmlogClose (void)
79 /*@globals recs, nrecs @*/
80 /*@modifies recs, nrecs @*/
85 for (i = 0; i < nrecs; i++) {
86 rpmlogRec rec = recs + i;
87 rec->message = _free(rec->message);
93 void rpmlogOpen (/*@unused@*/ const char *ident, /*@unused@*/ int option,
94 /*@unused@*/ int facility)
99 static unsigned rpmlogMask = RPMLOG_UPTO( RPMLOG_NOTICE );
102 static /*@unused@*/ unsigned rpmlogFacility = RPMLOG_USER;
104 int rpmlogSetMask (int mask)
105 /*@globals rpmlogMask @*/
106 /*@modifies rpmlogMask @*/
108 int omask = rpmlogMask;
115 static /*@null@*/ rpmlogCallback _rpmlogCallback = NULL;
117 rpmlogCallback rpmlogSetCallback(rpmlogCallback cb)
118 /*@globals _rpmlogCallback @*/
119 /*@modifies _rpmlogCallback @*/
121 rpmlogCallback ocb = _rpmlogCallback;
122 _rpmlogCallback = cb;
126 /*@-readonlytrans@*/ /* FIX: double indirection. */
127 /*@observer@*/ /*@unchecked@*/
128 static char *rpmlogMsgPrefix[] = {
129 N_("fatal error: "),/*!< RPMLOG_EMERG */
130 N_("fatal error: "),/*!< RPMLOG_ALERT */
131 N_("fatal error: "),/*!< RPMLOG_CRIT */
132 N_("error: "), /*!< RPMLOG_ERR */
133 N_("warning: "), /*!< RPMLOG_WARNING */
134 "", /*!< RPMLOG_NOTICE */
135 "", /*!< RPMLOG_INFO */
136 "D: ", /*!< RPMLOG_DEBUG */
140 #if !defined(HAVE_VSNPRINTF)
141 static inline int vsnprintf(char * buf, /*@unused@*/ int nb,
142 const char * fmt, va_list ap)
144 return vsprintf(buf, fmt, ap);
149 /*@-compmempass@*/ /* FIX: rpmlogMsgPrefix[] dependent, not unqualified */
150 /*@-nullstate@*/ /* FIX: rpmlogMsgPrefix[] may be NULL */
151 static void vrpmlog (unsigned code, const char *fmt, va_list ap)
152 /*@globals nrecs, recs, internalState @*/
153 /*@modifies nrecs, recs, internalState @*/
155 unsigned pri = RPMLOG_PRI(code);
156 unsigned mask = RPMLOG_MASK(pri);
157 /*@unused@*/ unsigned fac = RPMLOG_FAC(code);
159 int msgnb = BUFSIZ, nb;
160 FILE * msgout = stderr;
162 if ((mask & rpmlogMask) == 0)
166 msgbuf = xmalloc(msgnb);
169 /* Allocate a sufficently large buffer for output. */
172 /*@-sysunrecog -usedef@*/ va_copy(apc, ap); /*@=sysunrecog =usedef@*/
173 nb = vsnprintf(msgbuf, msgnb, fmt, apc);
174 if (nb > -1 && nb < msgnb)
176 if (nb > -1) /* glibc 2.1 (and later) */
180 msgbuf = xrealloc(msgbuf, msgnb);
182 msgbuf[msgnb - 1] = '\0';
185 /* Save copy of all messages at warning (or below == "more important"). */
187 if (pri <= RPMLOG_WARNING) {
190 recs = xmalloc((nrecs+2) * sizeof(*recs));
192 recs = xrealloc(recs, (nrecs+2) * sizeof(*recs));
193 recs[nrecs].code = code;
194 recs[nrecs].message = msg = xrealloc(msgbuf, strlen(msgbuf)+1);
195 msgbuf = NULL; /* XXX don't free at exit. */
196 recs[nrecs+1].code = 0;
197 recs[nrecs+1].message = NULL;
200 if (_rpmlogCallback) {
201 /*@-noeffectuncon@*/ /* FIX: useless callback */
204 return; /* XXX Preserve legacy rpmError behavior. */
210 /* rpmMessage behavior */
221 case RPMLOG_ERR: /* XXX Legacy rpmError behavior used stdout w/o prefix. */
227 if (rpmlogMsgPrefix[pri] && *rpmlogMsgPrefix[pri])
228 (void) fputs(_(rpmlogMsgPrefix[pri]), msgout);
230 (void) fputs(msg, msgout);
231 (void) fflush(msgout);
232 msgbuf = _free(msgbuf);
233 if (pri <= RPMLOG_CRIT)
236 /*@=compmempass =nullstate@*/
239 void rpmlog (int code, const char *fmt, ...)
244 /*@-internalglobs@*/ /* FIX: shrug */
245 vrpmlog(code, fmt, ap);
250 int rpmErrorCode(void)
255 const char * rpmErrorString(void)
257 return rpmlogMessage();
260 rpmlogCallback rpmErrorSetCallback(rpmlogCallback cb)
262 return rpmlogSetCallback(cb);