rpm 5.2.1

- Main Page
- Related Pages
- Modules
- Data Structures
- Files

- File List
- Globals

rpmlog.c
Go to the documentation of this file.
1
5 #include "system.h"
6 #include <stdarg.h>
7 #define _RPMLOG_INTERNAL
8 #include <rpmlog.h>
9 #include "debug.h"
10
11 /*@access rpmlogRec @*/
12
13 /*@unchecked@*/
14 static int nrecs = 0;
15 /*@unchecked@*/
16 static /*@only@*/ /*@null@*/ rpmlogRec recs = NULL;
17
23 /*@unused@*/ static inline /*@null@*/ void *
24 _free(/*@only@*/ /*@null@*/ /*@out@*/ const void * p) /*@modifies p@*/
25 {
26 if (p != NULL) free((void *)p);
27 return NULL;
28 }
29
30 int rpmlogGetNrecs(void)
31 {
32 return nrecs;
33 }
34
35 int rpmlogCode(void)
36 {
37 if (recs != NULL && nrecs > 0)
38 return recs[nrecs-1].code;
39 return -1;
40 }
41
42 const char * rpmlogMessage(void)
43 {
44 if (recs != NULL && nrecs > 0)
45 return recs[nrecs-1].message;
46 return _("(no error)");
47 }
48
49 const char * rpmlogRecMessage(rpmlogRec rec)
50 {
51 assert(rec != NULL);
52 return (rec->message);
53 }
54
55 rpmlogLvl rpmlogRecPriority(rpmlogRec rec)
56 {
57 assert(rec != NULL);
58 return (rec->pri);
59 }
60
61 /*@-modfilesys@*/
62 void 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
78 void 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
93 void rpmlogOpen (/*@unused@*/ const char *ident,
94 /*@unused@*/ int option,
95 /*@unused@*/ int facility)
96 {
97 }
98
99 /*@unchecked@*/
100 static unsigned rpmlogMask = RPMLOG_UPTO( RPMLOG_NOTICE );
101
102 #if 0
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@*/ /*@null@*/
118 static rpmlogCallback _rpmlogCallback;
119
120 /*@unchecked@*/ /*@null@*/
121 static rpmlogCallbackData _rpmlogCallbackData;
122
123 rpmlogCallback rpmlogSetCallback(rpmlogCallback cb, rpmlogCallbackData data)
124 /*@globals _rpmlogCallback, _rpmlogCallbackData @*/
125 /*@modifies _rpmlogCallback, _rpmlogCallbackData @*/
126 {
127 rpmlogCallback ocb = _rpmlogCallback;
128 _rpmlogCallback = cb;
129 _rpmlogCallbackData = data;
130 return ocb;
131 }
132
133 void rpmlogGetCallback(rpmlogCallback *cb, rpmlogCallbackData *data)
134 /*@globals _rpmlogCallback, _rpmlogCallbackData @*/
135 {
136 *cb = _rpmlogCallback;
137 *data = _rpmlogCallbackData;
138 return;
139 }
140
141 /*@unchecked@*/ /*@null@*/
142 static FILE * _stdlog = NULL;
143
144 static int rpmlogDefault(rpmlogRec rec)
145 /*@globals fileSystem @*/
146 /*@modifies fileSystem @*/
147 {
148 FILE *msgout = (_stdlog ? _stdlog : stderr);
149
150 switch (rec->pri) {
151 case RPMLOG_INFO:
152 case RPMLOG_NOTICE:
153 msgout = (_stdlog ? _stdlog : stdout);
154 break;
155 case RPMLOG_EMERG:
156 case RPMLOG_ALERT:
157 case RPMLOG_CRIT:
158 case RPMLOG_ERR:
159 case RPMLOG_WARNING:
160 case RPMLOG_DEBUG:
161 default:
162 break;
163 }
164
165 (void) fputs(rpmlogLevelPrefix(rec->pri), msgout);
166
167 if (rec->message)
168 (void) fputs(rec->message, msgout);
169 (void) fflush(msgout);
170
171 return (rec->pri <= RPMLOG_CRIT ? RPMLOG_EXIT : 0);
172 }
173
174 FILE * rpmlogSetFile(FILE * fp)
175 /*@globals _stdlog @*/
176 /*@modifies _stdlog @*/
177 {
178 FILE * ofp = _stdlog;
179 _stdlog = fp;
180 return ofp;
181 }
182
183 /*@-readonlytrans@*/ /* FIX: double indirection. */
184 /*@observer@*/ /*@unchecked@*/
185 static const char *rpmlogMsgPrefix[] = {
186 N_("fatal error: "),
187 N_("fatal error: "),
188 N_("fatal error: "),
189 N_("error: "),
190 N_("warning: "),
191 "",
192 "",
193 "D: ",
194 };
195 /*@=readonlytrans@*/
196
197 const char * rpmlogLevelPrefix(rpmlogLvl pri)
198 {
199 return rpmlogMsgPrefix[pri&0x7];
200 }
201
202 #if !defined(HAVE_VSNPRINTF)
203 static inline int vsnprintf(char * buf, /*@unused@*/ int nb,
204 const char * fmt, va_list ap)
205 {
206 return vsprintf(buf, fmt, ap);
207 }
208 #endif
209
210 /*@-modfilesys@*/
211 /*@-compmempass@*/ /* FIX: rpmlogMsgPrefix[] dependent, not unqualified */
212 /*@-nullstate@*/ /* FIX: rpmlogMsgPrefix[] may be NULL */
213 void vrpmlog (unsigned code, const char *fmt, va_list ap)
214 /*@globals nrecs, recs, internalState @*/
215 /*@modifies nrecs, recs, internalState @*/
216 {
217 unsigned pri = RPMLOG_PRI(code);
218 unsigned mask = RPMLOG_MASK(pri);
219 #if 0
220 /*@unused@*/ unsigned fac = RPMLOG_FAC(code);
221 #endif
222 char *msgbuf, *msg;
223 size_t msgnb = BUFSIZ;
224 int nb;
225 int cbrc = RPMLOG_DEFAULT;
226 int needexit = 0;
227 struct rpmlogRec_s rec;
228
229 if ((mask & rpmlogMask) == 0)
230 return;
231
232 msgbuf = xmalloc(msgnb);
233 *msgbuf = '\0';
234
235 /* Allocate a sufficently large buffer for output. */
236 while (1) {
237 va_list apc;
238 /*@-unrecog -usedef@*/ va_copy(apc, ap); /*@=unrecog =usedef@*/
239 nb = vsnprintf(msgbuf, msgnb, fmt, apc);
240 if (nb > -1 && (size_t)nb < msgnb)
241 break;
242 if (nb > -1) /* glibc 2.1 (and later) */
243 msgnb = nb+1;
244 else /* glibc 2.0 */
245 msgnb *= 2;
246 msgbuf = xrealloc(msgbuf, msgnb);
247 /*@-mods@*/
248 va_end(apc);
249 /*@=mods@*/
250 }
251 msgbuf[msgnb - 1] = '\0';
252 msg = msgbuf;
253
254 rec.code = code;
255 rec.message = msg;
256 rec.pri = pri;
257
258 /* Save copy of all messages at warning (or below == "more important"). */
259 if (pri <= RPMLOG_WARNING) {
260 if (recs == NULL)
261 recs = xmalloc((nrecs+2) * sizeof(*recs));
262 else
263 recs = xrealloc(recs, (nrecs+2) * sizeof(*recs));
264 recs[nrecs].code = rec.code;
265 recs[nrecs].pri = rec.pri;
266 recs[nrecs].message = xstrdup(msgbuf);
267 ++nrecs;
268 recs[nrecs].code = 0;
269 recs[nrecs].pri = 0;
270 recs[nrecs].message = NULL;
271 }
272
273 if (_rpmlogCallback) {
274 cbrc = _rpmlogCallback(&rec, _rpmlogCallbackData);
275 needexit += cbrc & RPMLOG_EXIT;
276 }
277
278 if (cbrc & RPMLOG_DEFAULT) {
279 /*@-usereleased@*/
280 cbrc = rpmlogDefault(&rec);
281 /*@=usereleased@*/
282 needexit += cbrc & RPMLOG_EXIT;
283 }
284
285 /*@-usereleased@*/ /* msgbuf is NULL or needs free'ing */
286 msgbuf = _free(msgbuf);
287 /*@=usereleased@*/
288 if (needexit)
289 exit(EXIT_FAILURE);
290 }
291 /*@=compmempass =nullstate@*/
292 /*@=modfilesys@*/
293
294 void _rpmlog (int code, const char *fmt, ...)
295 {
296 va_list ap;
297
298 va_start(ap, fmt);
299 /*@-internalglobs@*/ /* FIX: shrug */
300 vrpmlog(code, fmt, ap);
301 /*@=internalglobs@*/
302 va_end(ap);
303 }