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