00001
00005 #include "system.h"
00006 #include <stdarg.h>
00007 #include "rpmlog.h"
00008 #include "debug.h"
00009
00010 #ifndef va_copy
00011 # ifdef __va_copy
00012 # define va_copy(DEST,SRC) __va_copy((DEST),(SRC))
00013 # else
00014 # ifdef HAVE_VA_LIST_AS_ARRAY
00015 # define va_copy(DEST,SRC) (*(DEST) = *(SRC))
00016 # else
00017 # define va_copy(DEST,SRC) ((DEST) = (SRC))
00018 # endif
00019 # endif
00020 #endif
00021
00022
00023
00024
00025 static int nrecs = 0;
00026
00027 static rpmlogRec recs = NULL;
00028
00034 static inline void *
00035 _free( const void * p)
00036 {
00037 if (p != NULL) free((void *)p);
00038 return NULL;
00039 }
00040
00041 int rpmlogGetNrecs(void)
00042 {
00043 return nrecs;
00044 }
00045
00046 int rpmlogCode(void)
00047 {
00048 if (recs != NULL && nrecs > 0)
00049 return recs[nrecs-1].code;
00050 return -1;
00051 }
00052
00053
00054 const char * rpmlogMessage(void)
00055 {
00056 if (recs != NULL && nrecs > 0)
00057 return recs[nrecs-1].message;
00058 return _("(no error)");
00059 }
00060
00061
00062 void rpmlogPrint(FILE *f)
00063 {
00064 int i;
00065
00066 if (f == NULL)
00067 f = stderr;
00068
00069 if (recs)
00070 for (i = 0; i < nrecs; i++) {
00071 rpmlogRec rec = recs + i;
00072 if (rec->message && *rec->message)
00073 fprintf(f, " %s", rec->message);
00074 }
00075 }
00076
00077
00078 void rpmlogClose (void)
00079
00080
00081 {
00082 int i;
00083
00084 if (recs)
00085 for (i = 0; i < nrecs; i++) {
00086 rpmlogRec rec = recs + i;
00087 rec->message = _free(rec->message);
00088 }
00089 recs = _free(recs);
00090 nrecs = 0;
00091 }
00092
00093 void rpmlogOpen ( const char *ident, int option,
00094 int facility)
00095 {
00096 }
00097
00098
00099 static unsigned rpmlogMask = RPMLOG_UPTO( RPMLOG_NOTICE );
00100
00101
00102 static unsigned rpmlogFacility = RPMLOG_USER;
00103
00104 int rpmlogSetMask (int mask)
00105
00106
00107 {
00108 int omask = rpmlogMask;
00109 if (mask)
00110 rpmlogMask = mask;
00111 return omask;
00112 }
00113
00114
00115 static rpmlogCallback _rpmlogCallback = NULL;
00116
00117 rpmlogCallback rpmlogSetCallback(rpmlogCallback cb)
00118
00119
00120 {
00121 rpmlogCallback ocb = _rpmlogCallback;
00122 _rpmlogCallback = cb;
00123 return ocb;
00124 }
00125
00126
00127
00128 static char *rpmlogMsgPrefix[] = {
00129 N_("fatal error: "),
00130 N_("fatal error: "),
00131 N_("fatal error: "),
00132 N_("error: "),
00133 N_("warning: "),
00134 "",
00135 "",
00136 "D: ",
00137 };
00138
00139
00140 #if !defined(HAVE_VSNPRINTF)
00141 static inline int vsnprintf(char * buf, int nb,
00142 const char * fmt, va_list ap)
00143 {
00144 return vsprintf(buf, fmt, ap);
00145 }
00146 #endif
00147
00148
00149
00150
00151 static void vrpmlog (unsigned code, const char *fmt, va_list ap)
00152
00153
00154 {
00155 unsigned pri = RPMLOG_PRI(code);
00156 unsigned mask = RPMLOG_MASK(pri);
00157 unsigned fac = RPMLOG_FAC(code);
00158 char *msgbuf, *msg;
00159 int msgnb = BUFSIZ, nb;
00160 FILE * msgout = stderr;
00161
00162 if ((mask & rpmlogMask) == 0)
00163 return;
00164
00165 msgbuf = xmalloc(msgnb);
00166 *msgbuf = '\0';
00167
00168
00169 while (1) {
00170 va_list apc;
00171 va_copy(apc, ap);
00172 nb = vsnprintf(msgbuf, msgnb, fmt, apc);
00173 if (nb > -1 && nb < msgnb)
00174 break;
00175 if (nb > -1)
00176 msgnb = nb+1;
00177 else
00178 msgnb *= 2;
00179 msgbuf = xrealloc(msgbuf, msgnb);
00180 }
00181 msgbuf[msgnb - 1] = '\0';
00182 msg = msgbuf;
00183
00184
00185
00186 if (pri <= RPMLOG_WARNING) {
00187
00188 if (recs == NULL)
00189 recs = xmalloc((nrecs+2) * sizeof(*recs));
00190 else
00191 recs = xrealloc(recs, (nrecs+2) * sizeof(*recs));
00192 recs[nrecs].code = code;
00193 recs[nrecs].message = msg = xrealloc(msgbuf, strlen(msgbuf)+1);
00194 msgbuf = NULL;
00195 recs[nrecs+1].code = 0;
00196 recs[nrecs+1].message = NULL;
00197 ++nrecs;
00198
00199 if (_rpmlogCallback) {
00200
00201 _rpmlogCallback();
00202
00203 return;
00204 }
00205 }
00206
00207
00208
00209
00210 switch (pri) {
00211 case RPMLOG_INFO:
00212 case RPMLOG_NOTICE:
00213 msgout = stdout;
00214 break;
00215
00216 case RPMLOG_EMERG:
00217 case RPMLOG_ALERT:
00218 case RPMLOG_CRIT:
00219 case RPMLOG_ERR:
00220 case RPMLOG_WARNING:
00221 case RPMLOG_DEBUG:
00222 break;
00223 }
00224
00225 if (rpmlogMsgPrefix[pri] && *rpmlogMsgPrefix[pri])
00226 (void) fputs(_(rpmlogMsgPrefix[pri]), msgout);
00227
00228 (void) fputs(msg, msgout);
00229 (void) fflush(msgout);
00230 msgbuf = _free(msgbuf);
00231 if (pri <= RPMLOG_CRIT)
00232 exit(EXIT_FAILURE);
00233 }
00234
00235
00236
00237 void rpmlog (int code, const char *fmt, ...)
00238 {
00239 va_list ap;
00240
00241 va_start(ap, fmt);
00242
00243 vrpmlog(code, fmt, ap);
00244
00245 va_end(ap);
00246 }
00247
00248 int rpmErrorCode(void)
00249 {
00250 return rpmlogCode();
00251 }
00252
00253 const char * rpmErrorString(void)
00254 {
00255 return rpmlogMessage();
00256 }
00257
00258 rpmlogCallback rpmErrorSetCallback(rpmlogCallback cb)
00259 {
00260 return rpmlogSetCallback(cb);
00261 }