Remove HAVE_VA_LIST_AS_ARRAY.
[platform/upstream/rpm.git] / rpmio / rpmlog.c
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 static int nrecs = 0;
11 static rpmlogRec recs = NULL;
12
13 int rpmlogGetNrecs(void)
14 {
15     return nrecs;
16 }
17
18 int rpmlogCode(void)
19 {
20     if (recs != NULL && nrecs > 0)
21         return recs[nrecs-1].code;
22     return -1;
23 }
24
25
26 const char * rpmlogMessage(void)
27 {
28     if (recs != NULL && nrecs > 0)
29         return recs[nrecs-1].message;
30     return _("(no error)");
31 }
32
33 void rpmlogPrint(FILE *f)
34 {
35     int i;
36
37     if (f == NULL)
38         f = stderr;
39
40     if (recs)
41     for (i = 0; i < nrecs; i++) {
42         rpmlogRec rec = recs + i;
43         if (rec->message && *rec->message)
44             fprintf(f, "    %s", rec->message);
45     }
46 }
47
48 void rpmlogClose (void)
49 {
50     int i;
51
52     if (recs)
53     for (i = 0; i < nrecs; i++) {
54         rpmlogRec rec = recs + i;
55         rec->message = _free(rec->message);
56     }
57     recs = _free(recs);
58     nrecs = 0;
59 }
60
61 void rpmlogOpen (const char *ident, int option,
62                 int facility)
63 {
64 }
65
66 static unsigned rpmlogMask = RPMLOG_UPTO( RPMLOG_NOTICE );
67
68 #ifdef NOTYET
69 static unsigned rpmlogFacility = RPMLOG_USER;
70 #endif
71
72 int rpmlogSetMask (int mask)
73 {
74     int omask = rpmlogMask;
75     if (mask)
76         rpmlogMask = mask;
77     return omask;
78 }
79
80 static rpmlogCallback _rpmlogCallback = NULL;
81
82 rpmlogCallback rpmlogSetCallback(rpmlogCallback cb)
83 {
84     rpmlogCallback ocb = _rpmlogCallback;
85     _rpmlogCallback = cb;
86     return ocb;
87 }
88
89 static FILE * _stdlog = NULL;
90
91 FILE * rpmlogSetFile(FILE * fp)
92 {
93     FILE * ofp = _stdlog;
94     _stdlog = fp;
95     return ofp;
96 }
97
98 static char *rpmlogMsgPrefix[] = {
99     N_("fatal error: "),/*!< RPMLOG_EMERG */
100     N_("fatal error: "),/*!< RPMLOG_ALERT */
101     N_("fatal error: "),/*!< RPMLOG_CRIT */
102     N_("error: "),      /*!< RPMLOG_ERR */
103     N_("warning: "),    /*!< RPMLOG_WARNING */
104     "",                 /*!< RPMLOG_NOTICE */
105     "",                 /*!< RPMLOG_INFO */
106     "D: ",              /*!< RPMLOG_DEBUG */
107 };
108
109 #if !defined(HAVE_VSNPRINTF)
110 static inline int vsnprintf(char * buf, int nb,
111         const char * fmt, va_list ap)
112 {
113     return vsprintf(buf, fmt, ap);
114 }
115 #endif
116
117 /* FIX: rpmlogMsgPrefix[] dependent, not unqualified */
118 /* FIX: rpmlogMsgPrefix[] may be NULL */
119 static void vrpmlog (unsigned code, const char *fmt, va_list ap)
120 {
121     unsigned pri = RPMLOG_PRI(code);
122     unsigned mask = RPMLOG_MASK(pri);
123 #ifdef NOTYET
124     unsigned fac = RPMLOG_FAC(code);
125 #endif
126     char *msgbuf, *msg;
127     int msgnb = BUFSIZ, nb;
128     FILE * msgout = (_stdlog ? _stdlog : stderr);
129
130     if ((mask & rpmlogMask) == 0)
131         return;
132
133     msgbuf = xmalloc(msgnb);
134     *msgbuf = '\0';
135
136     /* Allocate a sufficently large buffer for output. */
137     while (1) {
138         va_list apc;
139         va_copy(apc, ap);
140         nb = vsnprintf(msgbuf, msgnb, fmt, apc);
141         if (nb > -1 && nb < msgnb)
142             break;
143         if (nb > -1)            /* glibc 2.1 (and later) */
144             msgnb = nb+1;
145         else                    /* glibc 2.0 */
146             msgnb *= 2;
147         msgbuf = xrealloc(msgbuf, msgnb);
148         va_end(apc);
149     }
150     msgbuf[msgnb - 1] = '\0';
151     msg = msgbuf;
152
153     /* Save copy of all messages at warning (or below == "more important"). */
154     if (pri <= RPMLOG_WARNING) {
155
156         if (recs == NULL)
157             recs = xmalloc((nrecs+2) * sizeof(*recs));
158         else
159             recs = xrealloc(recs, (nrecs+2) * sizeof(*recs));
160         recs[nrecs].code = code;
161         recs[nrecs].message = msg = xrealloc(msgbuf, strlen(msgbuf)+1);
162         msgbuf = NULL;          /* XXX don't free at exit. */
163         recs[nrecs+1].code = 0;
164         recs[nrecs+1].message = NULL;
165         ++nrecs;
166
167         if (_rpmlogCallback) {
168             /* FIX: useless callback */
169             _rpmlogCallback();
170             return;     /* XXX Preserve legacy rpmError behavior. */
171         }
172     }
173
174     /* rpmMessage behavior */
175
176     switch (pri) {
177     case RPMLOG_INFO:
178     case RPMLOG_NOTICE:
179         msgout = (_stdlog ? _stdlog : stdout);
180         break;
181
182     case RPMLOG_EMERG:
183     case RPMLOG_ALERT:
184     case RPMLOG_CRIT:
185     case RPMLOG_ERR: /* XXX Legacy rpmError behavior used stdout w/o prefix. */
186     case RPMLOG_WARNING:
187     case RPMLOG_DEBUG:
188         break;
189     }
190
191     if (rpmlogMsgPrefix[pri] && *rpmlogMsgPrefix[pri])
192         (void) fputs(_(rpmlogMsgPrefix[pri]), msgout);
193
194     (void) fputs(msg, msgout);
195     (void) fflush(msgout);
196     msgbuf = _free(msgbuf);
197     if (pri <= RPMLOG_CRIT)
198         exit(EXIT_FAILURE);
199 }
200
201 void rpmlog (int code, const char *fmt, ...)
202 {
203     va_list ap;
204
205     va_start(ap, fmt);
206     /* FIX: shrug */
207     vrpmlog(code, fmt, ap);
208     va_end(ap);
209 }
210