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