Add getter methods for rpmlogRec items (message + level)
[platform/upstream/rpm.git] / rpmio / rpmlog.c
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 static int nrecs = 0;
11 static rpmlogRec recs = NULL;
12
13 struct rpmlogRec_s {
14     int         code;           /* unused */
15     rpmlogLvl   pri;            /* priority */ 
16     const char * message;       /* log message string */
17 };
18
19 int rpmlogGetNrecs(void)
20 {
21     return nrecs;
22 }
23
24 int rpmlogCode(void)
25 {
26     if (recs != NULL && nrecs > 0)
27         return recs[nrecs-1].code;
28     return -1;
29 }
30
31
32 const char * rpmlogMessage(void)
33 {
34     if (recs != NULL && nrecs > 0)
35         return recs[nrecs-1].message;
36     return _("(no error)");
37 }
38
39 const char * rpmlogRecMessage(rpmlogRec rec)
40 {
41     assert(rec != NULL);
42     return (rec->message);
43 }
44
45 rpmlogLvl rpmlogRecPriority(rpmlogRec rec)
46 {
47     assert(rec != NULL);
48     return (rec->pri);
49 }
50
51 void rpmlogPrint(FILE *f)
52 {
53     int i;
54
55     if (f == NULL)
56         f = stderr;
57
58     if (recs)
59     for (i = 0; i < nrecs; i++) {
60         rpmlogRec rec = recs + i;
61         if (rec->message && *rec->message)
62             fprintf(f, "    %s", rec->message);
63     }
64 }
65
66 void rpmlogClose (void)
67 {
68     int i;
69
70     if (recs)
71     for (i = 0; i < nrecs; i++) {
72         rpmlogRec rec = recs + i;
73         rec->message = _free(rec->message);
74     }
75     recs = _free(recs);
76     nrecs = 0;
77 }
78
79 void rpmlogOpen (const char *ident, int option,
80                 int facility)
81 {
82 }
83
84 static unsigned rpmlogMask = RPMLOG_UPTO( RPMLOG_NOTICE );
85
86 #ifdef NOTYET
87 static unsigned rpmlogFacility = RPMLOG_USER;
88 #endif
89
90 int rpmlogSetMask (int mask)
91 {
92     int omask = rpmlogMask;
93     if (mask)
94         rpmlogMask = mask;
95     return omask;
96 }
97
98 static rpmlogCallback _rpmlogCallback = NULL;
99 static rpmlogCallbackData _rpmlogCallbackData = NULL;
100
101 rpmlogCallback rpmlogSetCallback(rpmlogCallback cb, rpmlogCallbackData data)
102 {
103     rpmlogCallback ocb = _rpmlogCallback;
104     _rpmlogCallback = cb;
105     _rpmlogCallbackData = data;
106     return ocb;
107 }
108
109 static FILE * _stdlog = NULL;
110
111 static int rpmlogDefault(rpmlogRec rec)
112 {
113     FILE *msgout = (_stdlog ? _stdlog : stderr);
114
115     switch (rec->pri) {
116     case RPMLOG_INFO:
117     case RPMLOG_NOTICE:
118         msgout = (_stdlog ? _stdlog : stdout);
119         break;
120     case RPMLOG_EMERG:
121     case RPMLOG_ALERT:
122     case RPMLOG_CRIT:
123     case RPMLOG_ERR:
124     case RPMLOG_WARNING:
125     case RPMLOG_DEBUG:
126     default:
127         break;
128     }
129
130     (void) fputs(rpmlogLevelPrefix(rec->pri), msgout);
131
132     (void) fputs(rec->message, msgout);
133     (void) fflush(msgout);
134
135     return (rec->pri <= RPMLOG_CRIT ? RPMLOG_EXIT : 0);
136 }
137
138
139 FILE * rpmlogSetFile(FILE * fp)
140 {
141     FILE * ofp = _stdlog;
142     _stdlog = fp;
143     return ofp;
144 }
145
146 static const char *rpmlogMsgPrefix[] = {
147     N_("fatal error: "),/*!< RPMLOG_EMERG */
148     N_("fatal error: "),/*!< RPMLOG_ALERT */
149     N_("fatal error: "),/*!< RPMLOG_CRIT */
150     N_("error: "),      /*!< RPMLOG_ERR */
151     N_("warning: "),    /*!< RPMLOG_WARNING */
152     "",                 /*!< RPMLOG_NOTICE */
153     "",                 /*!< RPMLOG_INFO */
154     "D: ",              /*!< RPMLOG_DEBUG */
155 };
156
157 const char * rpmlogLevelPrefix(rpmlogLvl pri)
158 {
159     const char * prefix = "";
160     if (rpmlogMsgPrefix[pri] && *rpmlogMsgPrefix[pri]) 
161         prefix = _(rpmlogMsgPrefix[pri]);
162     return prefix;
163 }
164
165 #if !defined(HAVE_VSNPRINTF)
166 static inline int vsnprintf(char * buf, int nb,
167         const char * fmt, va_list ap)
168 {
169     return vsprintf(buf, fmt, ap);
170 }
171 #endif
172
173 /* FIX: rpmlogMsgPrefix[] dependent, not unqualified */
174 /* FIX: rpmlogMsgPrefix[] may be NULL */
175 static void vrpmlog (unsigned code, const char *fmt, va_list ap)
176 {
177     unsigned pri = RPMLOG_PRI(code);
178     unsigned mask = RPMLOG_MASK(pri);
179 #ifdef NOTYET
180     unsigned fac = RPMLOG_FAC(code);
181 #endif
182     char *msgbuf, *msg;
183     int msgnb = BUFSIZ, nb;
184     int cbrc = RPMLOG_DEFAULT;
185     int needexit = 0;
186
187     struct rpmlogRec_s rec;
188
189     if ((mask & rpmlogMask) == 0)
190         return;
191
192     msgbuf = xmalloc(msgnb);
193     *msgbuf = '\0';
194
195     /* Allocate a sufficently large buffer for output. */
196     while (1) {
197         va_list apc;
198         va_copy(apc, ap);
199         nb = vsnprintf(msgbuf, msgnb, fmt, apc);
200         if (nb > -1 && nb < msgnb)
201             break;
202         if (nb > -1)            /* glibc 2.1 (and later) */
203             msgnb = nb+1;
204         else                    /* glibc 2.0 */
205             msgnb *= 2;
206         msgbuf = xrealloc(msgbuf, msgnb);
207         va_end(apc);
208     }
209     msgbuf[msgnb - 1] = '\0';
210     msg = msgbuf;
211
212     rec.code = code;
213     rec.message = msg;
214     rec.pri = pri;
215
216     /* Save copy of all messages at warning (or below == "more important"). */
217     if (pri <= RPMLOG_WARNING) {
218
219         if (recs == NULL)
220             recs = xmalloc((nrecs+2) * sizeof(*recs));
221         else
222             recs = xrealloc(recs, (nrecs+2) * sizeof(*recs));
223         recs[nrecs].code = rec.code;
224         recs[nrecs].pri = rec.pri;
225         recs[nrecs].message = msg = xrealloc(msgbuf, strlen(msgbuf)+1);
226         msgbuf = NULL;          /* XXX don't free at exit. */
227         recs[nrecs+1].code = 0;
228         recs[nrecs+1].message = NULL;
229         ++nrecs;
230     }
231
232     if (_rpmlogCallback) {
233         cbrc = _rpmlogCallback(&rec, _rpmlogCallbackData);
234         needexit += cbrc & RPMLOG_EXIT;
235     }
236
237     if (cbrc & RPMLOG_DEFAULT) {
238         cbrc = rpmlogDefault(&rec);
239         needexit += cbrc & RPMLOG_EXIT;
240     }
241     
242     msgbuf = _free(msgbuf);
243     if (needexit)
244         exit(EXIT_FAILURE);
245 }
246
247 void rpmlog (int code, const char *fmt, ...)
248 {
249     va_list ap;
250
251     va_start(ap, fmt);
252     /* FIX: shrug */
253     vrpmlog(code, fmt, ap);
254     va_end(ap);
255 }
256