rpm  5.2.1
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 
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@*/
119 
120 /*@unchecked@*/ /*@null@*/
122 
124  /*@globals _rpmlogCallback, _rpmlogCallbackData @*/
125  /*@modifies _rpmlogCallback, _rpmlogCallbackData @*/
126 {
128  _rpmlogCallback = cb;
129  _rpmlogCallbackData = data;
130  return ocb;
131 }
132 
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 }