// -*- mode: cpp; mode: fold -*-
// Description /*{{{*/
-// $Id: error.cc,v 1.1 1998/07/02 02:58:13 jgg Exp $
+// $Id: error.cc,v 1.11 2002/03/26 07:38:58 jgg Exp $
/* ######################################################################
Global Erorr Class - Global error mechanism
##################################################################### */
/*}}}*/
// Include Files /*{{{*/
+#include <apt-pkg/error.h>
+
+#include <iostream>
#include <errno.h>
#include <stdio.h>
-#include <string.h>
#include <stdarg.h>
+#include <unistd.h>
+
+#include <string>
+#include <cstring>
-#include <pkglib/error.h>
+#include "config.h"
/*}}}*/
-GlobalError *_error = new GlobalError;
+using namespace std;
+
+// Global Error Object /*{{{*/
+/* If the implementation supports posix threads then the accessor function
+ is compiled to be thread safe otherwise a non-safe version is used. A
+ Per-Thread error object is maintained in much the same manner as libc
+ manages errno */
+#if defined(_POSIX_THREADS) && defined(HAVE_PTHREAD)
+ #include <pthread.h>
+
+ static pthread_key_t ErrorKey;
+ static void ErrorDestroy(void *Obj) {delete (GlobalError *)Obj;};
+ static void KeyAlloc() {pthread_key_create(&ErrorKey,ErrorDestroy);};
+
+ GlobalError *_GetErrorObj()
+ {
+ static pthread_once_t Once = PTHREAD_ONCE_INIT;
+ pthread_once(&Once,KeyAlloc);
+
+ void *Res = pthread_getspecific(ErrorKey);
+ if (Res == 0)
+ pthread_setspecific(ErrorKey,Res = new GlobalError);
+ return (GlobalError *)Res;
+ }
+#else
+ GlobalError *_GetErrorObj()
+ {
+ static GlobalError *Obj = new GlobalError;
+ return Obj;
+ }
+#endif
+ /*}}}*/
// GlobalError::GlobalError - Constructor /*{{{*/
// ---------------------------------------------------------------------
/* */
-GlobalError::GlobalError() : PendingFlag(false)
+GlobalError::GlobalError() : List(0), PendingFlag(false)
{
}
/*}}}*/
// sprintf the description
char S[400];
- vsprintf(S,Description,args);
- sprintf(S + strlen(S)," - %s (%i %s)",Function,errno,strerror(errno));
+ vsnprintf(S,sizeof(S),Description,args);
+ snprintf(S + strlen(S),sizeof(S) - strlen(S),
+ " - %s (%i: %s)",Function,errno,strerror(errno));
// Put it on the list
- Item Itm;
- Itm.Text = S;
- Itm.Error = true;
- List.push_back(Itm);
-
+ Item *Itm = new Item;
+ Itm->Text = S;
+ Itm->Error = true;
+ Insert(Itm);
+
PendingFlag = true;
- return false;
+ return false;
+}
+ /*}}}*/
+// GlobalError::WarningE - Get part of the warn string from errno /*{{{*/
+// ---------------------------------------------------------------------
+/* Function indicates the stdlib function that failed and Description is
+ a user string that leads the text. Form is:
+ Description - Function (errno: strerror)
+ Carefull of the buffer overrun, sprintf.
+ */
+bool GlobalError::WarningE(const char *Function,const char *Description,...)
+{
+ va_list args;
+ va_start(args,Description);
+
+ // sprintf the description
+ char S[400];
+ vsnprintf(S,sizeof(S),Description,args);
+ snprintf(S + strlen(S),sizeof(S) - strlen(S),
+ " - %s (%i: %s)",Function,errno,strerror(errno));
+
+ // Put it on the list
+ Item *Itm = new Item;
+ Itm->Text = S;
+ Itm->Error = false;
+ Insert(Itm);
+
+ return false;
}
/*}}}*/
// GlobalError::Error - Add an error to the list /*{{{*/
// sprintf the description
char S[400];
- vsprintf(S,Description,args);
+ vsnprintf(S,sizeof(S),Description,args);
// Put it on the list
- Item Itm;
- Itm.Text = S;
- Itm.Error = true;
- List.push_back(Itm);
+ Item *Itm = new Item;
+ Itm->Text = S;
+ Itm->Error = true;
+ Insert(Itm);
PendingFlag = true;
// sprintf the description
char S[400];
- vsprintf(S,Description,args);
+ vsnprintf(S,sizeof(S),Description,args);
// Put it on the list
- Item Itm;
- Itm.Text = S;
- Itm.Error = false;
- List.push_back(Itm);
+ Item *Itm = new Item;
+ Itm->Text = S;
+ Itm->Error = false;
+ Insert(Itm);
return false;
}
true if the message is an error. */
bool GlobalError::PopMessage(string &Text)
{
- bool Ret = List.front().Error;
- Text = List.front().Text;
- List.erase(List.begin());
-
+ if (List == 0)
+ return false;
+
+ bool Ret = List->Error;
+ Text = List->Text;
+ Item *Old = List;
+ List = List->Next;
+ delete Old;
+
// This really should check the list to see if only warnings are left..
- if (empty())
+ if (List == 0)
PendingFlag = false;
return Ret;
}
}
/*}}}*/
+// GlobalError::Discard - Discard /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+void GlobalError::Discard()
+{
+ while (List != 0)
+ {
+ Item *Old = List;
+ List = List->Next;
+ delete Old;
+ }
+
+ PendingFlag = false;
+};
+ /*}}}*/
+// GlobalError::Insert - Insert a new item at the end /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+void GlobalError::Insert(Item *Itm)
+{
+ Item **End = &List;
+ for (Item *I = List; I != 0; I = I->Next)
+ End = &I->Next;
+ Itm->Next = *End;
+ *End = Itm;
+}
+ /*}}}*/