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