source: trunk/third/rpm/rpmio/rpmlog.c @ 19079

Revision 19079, 6.0 KB checked in by ghudson, 22 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r19078, which included commits to RCS files with non-trunk default branches.
Line 
1/*@-boundsread@*/
2/** \ingroup rpmio
3 * \file rpmio/rpmlog.c
4 */
5
6#include "system.h"
7#include <stdarg.h>
8#include "rpmlog.h"
9#include "debug.h"
10
11#ifndef va_copy
12# ifdef __va_copy
13#  define va_copy(DEST,SRC) __va_copy((DEST),(SRC))
14# else
15#  ifdef HAVE_VA_LIST_AS_ARRAY
16#   define va_copy(DEST,SRC) (*(DEST) = *(SRC))
17#  else
18#   define va_copy(DEST,SRC) ((DEST) = (SRC))
19#  endif
20# endif
21#endif
22
23/*@access rpmlogRec @*/
24
25/*@unchecked@*/
26static int nrecs = 0;
27/*@unchecked@*/
28static /*@only@*/ /*@null@*/ rpmlogRec recs = NULL;
29
30/**
31 * Wrapper to free(3), hides const compilation noise, permit NULL, return NULL.
32 * @param p             memory to free
33 * @retval              NULL always
34 */
35/*@unused@*/ static inline /*@null@*/ void *
36_free(/*@only@*/ /*@null@*/ /*@out@*/ const void * p) /*@modifies p@*/
37{
38    if (p != NULL)      free((void *)p);
39    return NULL;
40}
41
42int rpmlogGetNrecs(void)
43{
44    return nrecs;
45}
46
47int rpmlogCode(void)
48{
49    if (recs != NULL && nrecs > 0)
50        return recs[nrecs-1].code;
51    return -1;
52}
53
54
55const char * rpmlogMessage(void)
56{
57    if (recs != NULL && nrecs > 0)
58        return recs[nrecs-1].message;
59    return _("(no error)");
60}
61
62/*@-modfilesys@*/
63void rpmlogPrint(FILE *f)
64{
65    int i;
66
67    if (f == NULL)
68        f = stderr;
69
70    if (recs)
71    for (i = 0; i < nrecs; i++) {
72        rpmlogRec rec = recs + i;
73        if (rec->message && *rec->message)
74            fprintf(f, "    %s", rec->message);
75    }
76}
77/*@=modfilesys@*/
78
79void rpmlogClose (void)
80        /*@globals recs, nrecs @*/
81        /*@modifies recs, nrecs @*/
82{
83    int i;
84
85    if (recs)
86    for (i = 0; i < nrecs; i++) {
87        rpmlogRec rec = recs + i;
88        rec->message = _free(rec->message);
89    }
90    recs = _free(recs);
91    nrecs = 0;
92}
93
94void rpmlogOpen (/*@unused@*/ const char *ident, /*@unused@*/ int option,
95                /*@unused@*/ int facility)
96{
97}
98
99/*@unchecked@*/
100static unsigned rpmlogMask = RPMLOG_UPTO( RPMLOG_NOTICE );
101
102/*@unchecked@*/
103static /*@unused@*/ unsigned rpmlogFacility = RPMLOG_USER;
104
105int rpmlogSetMask (int mask)
106        /*@globals rpmlogMask @*/
107        /*@modifies rpmlogMask @*/
108{
109    int omask = rpmlogMask;
110    if (mask)
111        rpmlogMask = mask;
112    return omask;
113}
114
115/*@unchecked@*/
116static /*@null@*/ rpmlogCallback _rpmlogCallback = NULL;
117
118rpmlogCallback rpmlogSetCallback(rpmlogCallback cb)
119        /*@globals _rpmlogCallback @*/
120        /*@modifies _rpmlogCallback @*/
121{
122    rpmlogCallback ocb = _rpmlogCallback;
123    _rpmlogCallback = cb;
124    return ocb;
125}
126
127/*@unchecked@*/ /*@null@*/
128static FILE * _stdlog = NULL;
129
130FILE * rpmlogSetFile(FILE * fp)
131        /*@globals _stdlog @*/
132        /*@modifies _stdlog @*/
133{
134    FILE * ofp = _stdlog;
135    _stdlog = fp;
136    return ofp;
137}
138
139/*@-readonlytrans@*/    /* FIX: double indirection. */
140/*@observer@*/ /*@unchecked@*/
141static 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 */
150};
151/*@=readonlytrans@*/
152
153#if !defined(HAVE_VSNPRINTF)
154static inline int vsnprintf(char * buf, /*@unused@*/ int nb,
155        const char * fmt, va_list ap)
156{
157    return vsprintf(buf, fmt, ap);
158}
159#endif
160
161/*@-modfilesys@*/
162/*@-compmempass@*/ /* FIX: rpmlogMsgPrefix[] dependent, not unqualified */
163/*@-nullstate@*/ /* FIX: rpmlogMsgPrefix[] may be NULL */
164static void vrpmlog (unsigned code, const char *fmt, va_list ap)
165        /*@globals nrecs, recs, internalState @*/
166        /*@modifies nrecs, recs, internalState @*/
167{
168    unsigned pri = RPMLOG_PRI(code);
169    unsigned mask = RPMLOG_MASK(pri);
170    /*@unused@*/ unsigned fac = RPMLOG_FAC(code);
171    char *msgbuf, *msg;
172    int msgnb = BUFSIZ, nb;
173    FILE * msgout = (_stdlog ? _stdlog : stderr);
174
175    if ((mask & rpmlogMask) == 0)
176        return;
177
178/*@-boundswrite@*/
179    msgbuf = xmalloc(msgnb);
180    *msgbuf = '\0';
181
182    /* Allocate a sufficently large buffer for output. */
183    while (1) {
184        va_list apc;
185        /*@-sysunrecog -usedef@*/ va_copy(apc, ap); /*@=sysunrecog =usedef@*/
186        nb = vsnprintf(msgbuf, msgnb, fmt, apc);
187        if (nb > -1 && nb < msgnb)
188            break;
189        if (nb > -1)            /* glibc 2.1 (and later) */
190            msgnb = nb+1;
191        else                    /* glibc 2.0 */
192            msgnb *= 2;
193        msgbuf = xrealloc(msgbuf, msgnb);
194/*@-mods@*/
195        va_end(apc);
196/*@=mods@*/
197    }
198    msgbuf[msgnb - 1] = '\0';
199    msg = msgbuf;
200
201    /* Save copy of all messages at warning (or below == "more important"). */
202    /*@-branchstate@*/
203    if (pri <= RPMLOG_WARNING) {
204
205        if (recs == NULL)
206            recs = xmalloc((nrecs+2) * sizeof(*recs));
207        else
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;
214        ++nrecs;
215
216        if (_rpmlogCallback) {
217            /*@-noeffectuncon@*/ /* FIX: useless callback */
218            _rpmlogCallback();
219            /*@=noeffectuncon@*/
220            return;     /* XXX Preserve legacy rpmError behavior. */
221        }
222    }
223    /*@=branchstate@*/
224/*@=boundswrite@*/
225
226    /* rpmMessage behavior */
227
228    switch (pri) {
229    case RPMLOG_INFO:
230    case RPMLOG_NOTICE:
231        msgout = (_stdlog ? _stdlog : stdout);
232        break;
233
234    case RPMLOG_EMERG:
235    case RPMLOG_ALERT:
236    case RPMLOG_CRIT:
237    case RPMLOG_ERR: /* XXX Legacy rpmError behavior used stdout w/o prefix. */
238    case RPMLOG_WARNING:
239    case RPMLOG_DEBUG:
240        break;
241    }
242
243    if (rpmlogMsgPrefix[pri] && *rpmlogMsgPrefix[pri])
244        (void) fputs(_(rpmlogMsgPrefix[pri]), msgout);
245
246    (void) fputs(msg, msgout);
247    (void) fflush(msgout);
248    msgbuf = _free(msgbuf);
249    if (pri <= RPMLOG_CRIT)
250        exit(EXIT_FAILURE);
251}
252/*@=compmempass =nullstate@*/
253/*@=modfilesys@*/
254
255void rpmlog (int code, const char *fmt, ...)
256{
257    va_list ap;
258
259    va_start(ap, fmt);
260    /*@-internalglobs@*/ /* FIX: shrug */
261    vrpmlog(code, fmt, ap);
262    /*@=internalglobs@*/
263    va_end(ap);
264}
265
266int rpmErrorCode(void)
267{
268    return rpmlogCode();
269}
270
271const char * rpmErrorString(void)
272{
273    return rpmlogMessage();
274}
275
276rpmlogCallback rpmErrorSetCallback(rpmlogCallback cb)
277{
278    return rpmlogSetCallback(cb);
279}
280/*@=boundsread@*/
Note: See TracBrowser for help on using the repository browser.