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