- tsort prefers presentation order.
[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 /*@access rpmlogRec @*/
11
12 static int nrecs = 0;
13 static /*@only@*/ /*@null@*/ rpmlogRec recs = NULL;
14
15 int rpmlogGetNrecs(void)
16 {
17     return nrecs;
18 }
19
20 const char * rpmlogMessage(void)
21 {
22     if (nrecs > 0)
23         return recs[nrecs-1].message;
24     return _("(no error)");
25 }
26
27 void rpmlogPrint(FILE *f)
28 {
29     int i;
30
31     if (f == NULL)
32         f = stderr;
33
34     for (i = 0; i < nrecs; i++) {
35         rpmlogRec rec = recs + i;
36         if (rec->message && *rec->message)
37             fprintf(f, "    %s", rec->message);
38     }
39 }
40
41 void rpmlogClose (void)
42 {
43     int i;
44
45     for (i = 0; i < nrecs; i++) {
46         rpmlogRec rec = recs + i;
47         if (rec->message) {
48             free((void *)rec->message);
49             rec->message = NULL;
50         }
51     }
52     free(recs);
53     recs = NULL;
54     nrecs = 0;
55 }
56
57 void rpmlogOpen (/*@unused@*/ const char *ident, /*@unused@*/ int option,
58                 /*@unused@*/ int facility)
59 {
60 }
61
62 static int rpmlogMask = RPMLOG_UPTO( RPMLOG_NOTICE );
63 static /*@unused@*/ int rpmlogFacility = RPMLOG_USER;
64
65 int rpmlogSetMask (int mask)
66 {
67     int omask = rpmlogMask;
68     if (mask)
69         rpmlogMask = mask;
70     return omask;
71 }
72
73 static /*@null@*/ rpmlogCallback _rpmlogCallback = NULL;
74
75 rpmlogCallback rpmlogSetCallback(rpmlogCallback cb)
76 {
77     rpmlogCallback ocb = _rpmlogCallback;
78     _rpmlogCallback = cb;
79     return ocb;
80 }
81
82 static char *rpmlogMsgPrefix[] = {
83     N_("fatal error: "),/*!< RPMLOG_EMERG */
84     N_("fatal error: "),/*!< RPMLOG_ALERT */
85     N_("fatal error: "),/*!< RPMLOG_CRIT */
86     N_("error: "),      /*!< RPMLOG_ERR */
87     N_("warning: "),    /*!< RPMLOG_WARNING */
88     "",                 /*!< RPMLOG_NOTICE */
89     "",                 /*!< RPMLOG_INFO */
90     "D: ",              /*!< RPMLOG_DEBUG */
91 };
92
93 static void vrpmlog (unsigned code, const char *fmt, va_list ap)
94 {
95     int pri = RPMLOG_PRI(code);
96     int mask = RPMLOG_MASK(pri);
97     /*@unused@*/ int fac = RPMLOG_FAC(code);
98     char msgbuf[BUFSIZ], *msg;
99     FILE * msgout = stderr;
100     rpmlogRec rec;
101
102     if ((mask & rpmlogMask) == 0)
103         return;
104
105     /*@-unrecog@*/ vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap); /*@=unrecog@*/
106     msgbuf[sizeof(msgbuf) - 1] = '\0';
107     msg = msgbuf;
108
109     /* Save copy of all messages at warning (or below == "more important"). */
110     if (pri <= RPMLOG_WARNING) {
111
112         if (recs == NULL)
113             recs = xmalloc((nrecs+2) * sizeof(*recs));
114         else
115             recs = xrealloc(recs, (nrecs+2) * sizeof(*recs));
116         recs[nrecs+1].code = 0;
117         recs[nrecs+1].message = NULL;
118         rec = recs + nrecs;
119         ++nrecs;
120
121         rec->code = code;
122         rec->message = xstrdup(msg);
123
124         if (_rpmlogCallback) {
125             _rpmlogCallback();
126             return;     /* XXX Preserve legacy rpmError behavior. */
127         }
128     }
129
130     /* rpmMessage behavior */
131
132     switch (pri) {
133     case RPMLOG_INFO:
134     case RPMLOG_NOTICE:
135         msgout = stdout;
136         break;
137
138     case RPMLOG_EMERG:
139     case RPMLOG_ALERT:
140     case RPMLOG_CRIT:
141     case RPMLOG_ERR: /* XXX Legacy rpmError behavior used stdout w/o prefix. */
142     case RPMLOG_WARNING:
143     case RPMLOG_DEBUG:
144         break;
145     }
146
147     /* Silly FORTRAN-like carriage control. */
148     if (*msg == '+')
149         msg++;
150     else if (rpmlogMsgPrefix[pri] && *rpmlogMsgPrefix[pri])
151         fputs(_(rpmlogMsgPrefix[pri]), msgout);
152
153     fputs(msg, msgout);
154     fflush(msgout);
155     if (pri <= RPMLOG_CRIT)
156         exit(EXIT_FAILURE);
157 }
158
159 void rpmlog (int code, const char *fmt, ...)
160 {
161     va_list ap;
162
163     va_start(ap, fmt);
164     vrpmlog(code, fmt, ap);
165     va_end(ap);
166 }
167
168 const char * rpmErrorString(void)
169 {
170     return rpmlogMessage();
171 }
172
173 rpmlogCallback rpmErrorSetCallback(rpmlogCallback cb)
174 {
175     return rpmlogSetCallback(cb);
176 }