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

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