Ifdef out currently unused rpm logging facility stuff.
[platform/upstream/rpm.git] / rpmio / rpmlog.c
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@*/
26 static int nrecs = 0;
27 /*@unchecked@*/
28 static /*@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
42 int rpmlogGetNrecs(void)
43 {
44     return nrecs;
45 }
46
47 int rpmlogCode(void)
48 {
49     if (recs != NULL && nrecs > 0)
50         return recs[nrecs-1].code;
51     return -1;
52 }
53
54
55 const char * rpmlogMessage(void)
56 {
57     if (recs != NULL && nrecs > 0)
58         return recs[nrecs-1].message;
59     return _("(no error)");
60 }
61
62 /*@-modfilesys@*/
63 void 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
79 void 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
94 void rpmlogOpen (/*@unused@*/ const char *ident, /*@unused@*/ int option,
95                 /*@unused@*/ int facility)
96 {
97 }
98
99 /*@unchecked@*/
100 static unsigned rpmlogMask = RPMLOG_UPTO( RPMLOG_NOTICE );
101
102 #ifdef NOTYET
103 /*@unchecked@*/
104 static /*@unused@*/ unsigned rpmlogFacility = RPMLOG_USER;
105 #endif
106
107 int rpmlogSetMask (int mask)
108         /*@globals rpmlogMask @*/
109         /*@modifies rpmlogMask @*/
110 {
111     int omask = rpmlogMask;
112     if (mask)
113         rpmlogMask = mask;
114     return omask;
115 }
116
117 /*@unchecked@*/
118 static /*@null@*/ rpmlogCallback _rpmlogCallback = NULL;
119
120 rpmlogCallback rpmlogSetCallback(rpmlogCallback cb)
121         /*@globals _rpmlogCallback @*/
122         /*@modifies _rpmlogCallback @*/
123 {
124     rpmlogCallback ocb = _rpmlogCallback;
125     _rpmlogCallback = cb;
126     return ocb;
127 }
128
129 /*@unchecked@*/ /*@null@*/
130 static FILE * _stdlog = NULL;
131
132 FILE * rpmlogSetFile(FILE * fp)
133         /*@globals _stdlog @*/
134         /*@modifies _stdlog @*/
135 {
136     FILE * ofp = _stdlog;
137     _stdlog = fp;
138     return ofp;
139 }
140
141 /*@-readonlytrans@*/    /* FIX: double indirection. */
142 /*@observer@*/ /*@unchecked@*/
143 static char *rpmlogMsgPrefix[] = {
144     N_("fatal error: "),/*!< RPMLOG_EMERG */
145     N_("fatal error: "),/*!< RPMLOG_ALERT */
146     N_("fatal error: "),/*!< RPMLOG_CRIT */
147     N_("error: "),      /*!< RPMLOG_ERR */
148     N_("warning: "),    /*!< RPMLOG_WARNING */
149     "",                 /*!< RPMLOG_NOTICE */
150     "",                 /*!< RPMLOG_INFO */
151     "D: ",              /*!< RPMLOG_DEBUG */
152 };
153 /*@=readonlytrans@*/
154
155 #if !defined(HAVE_VSNPRINTF)
156 static inline int vsnprintf(char * buf, /*@unused@*/ int nb,
157         const char * fmt, va_list ap)
158 {
159     return vsprintf(buf, fmt, ap);
160 }
161 #endif
162
163 /*@-modfilesys@*/
164 /*@-compmempass@*/ /* FIX: rpmlogMsgPrefix[] dependent, not unqualified */
165 /*@-nullstate@*/ /* FIX: rpmlogMsgPrefix[] may be NULL */
166 static void vrpmlog (unsigned code, const char *fmt, va_list ap)
167         /*@globals nrecs, recs, internalState @*/
168         /*@modifies nrecs, recs, internalState @*/
169 {
170     unsigned pri = RPMLOG_PRI(code);
171     unsigned mask = RPMLOG_MASK(pri);
172 #ifdef NOTYET
173     /*@unused@*/ unsigned fac = RPMLOG_FAC(code);
174 #endif
175     char *msgbuf, *msg;
176     int msgnb = BUFSIZ, nb;
177     FILE * msgout = (_stdlog ? _stdlog : stderr);
178
179     if ((mask & rpmlogMask) == 0)
180         return;
181
182 /*@-boundswrite@*/
183     msgbuf = xmalloc(msgnb);
184     *msgbuf = '\0';
185
186     /* Allocate a sufficently large buffer for output. */
187     while (1) {
188         va_list apc;
189         /*@-sysunrecog -usedef@*/ va_copy(apc, ap); /*@=sysunrecog =usedef@*/
190         nb = vsnprintf(msgbuf, msgnb, fmt, apc);
191         if (nb > -1 && nb < msgnb)
192             break;
193         if (nb > -1)            /* glibc 2.1 (and later) */
194             msgnb = nb+1;
195         else                    /* glibc 2.0 */
196             msgnb *= 2;
197         msgbuf = xrealloc(msgbuf, msgnb);
198 /*@-mods@*/
199         va_end(apc);
200 /*@=mods@*/
201     }
202     msgbuf[msgnb - 1] = '\0';
203     msg = msgbuf;
204
205     /* Save copy of all messages at warning (or below == "more important"). */
206     /*@-branchstate@*/
207     if (pri <= RPMLOG_WARNING) {
208
209         if (recs == NULL)
210             recs = xmalloc((nrecs+2) * sizeof(*recs));
211         else
212             recs = xrealloc(recs, (nrecs+2) * sizeof(*recs));
213         recs[nrecs].code = code;
214         recs[nrecs].message = msg = xrealloc(msgbuf, strlen(msgbuf)+1);
215         msgbuf = NULL;          /* XXX don't free at exit. */
216         recs[nrecs+1].code = 0;
217         recs[nrecs+1].message = NULL;
218         ++nrecs;
219
220         if (_rpmlogCallback) {
221             /*@-noeffectuncon@*/ /* FIX: useless callback */
222             _rpmlogCallback();
223             /*@=noeffectuncon@*/
224             return;     /* XXX Preserve legacy rpmError behavior. */
225         }
226     }
227     /*@=branchstate@*/
228 /*@=boundswrite@*/
229
230     /* rpmMessage behavior */
231
232     switch (pri) {
233     case RPMLOG_INFO:
234     case RPMLOG_NOTICE:
235         msgout = (_stdlog ? _stdlog : stdout);
236         break;
237
238     case RPMLOG_EMERG:
239     case RPMLOG_ALERT:
240     case RPMLOG_CRIT:
241     case RPMLOG_ERR: /* XXX Legacy rpmError behavior used stdout w/o prefix. */
242     case RPMLOG_WARNING:
243     case RPMLOG_DEBUG:
244         break;
245     }
246
247     if (rpmlogMsgPrefix[pri] && *rpmlogMsgPrefix[pri])
248         (void) fputs(_(rpmlogMsgPrefix[pri]), msgout);
249
250     (void) fputs(msg, msgout);
251     (void) fflush(msgout);
252     msgbuf = _free(msgbuf);
253     if (pri <= RPMLOG_CRIT)
254         exit(EXIT_FAILURE);
255 }
256 /*@=compmempass =nullstate@*/
257 /*@=modfilesys@*/
258
259 void rpmlog (int code, const char *fmt, ...)
260 {
261     va_list ap;
262
263     va_start(ap, fmt);
264     /*@-internalglobs@*/ /* FIX: shrug */
265     vrpmlog(code, fmt, ap);
266     /*@=internalglobs@*/
267     va_end(ap);
268 }
269
270 int rpmErrorCode(void)
271 {
272     return rpmlogCode();
273 }
274
275 const char * rpmErrorString(void)
276 {
277     return rpmlogMessage();
278 }
279
280 rpmlogCallback rpmErrorSetCallback(rpmlogCallback cb)
281 {
282     return rpmlogSetCallback(cb);
283 }
284 /*@=boundsread@*/