-
Notifications
You must be signed in to change notification settings - Fork 2
/
Errors.c
131 lines (104 loc) · 3.22 KB
/
Errors.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
#include "Errors.h"
#include "includes.h"
#include <errno.h>
static ListNode *Errors=NULL;
void ErrorDestroy(void *p_Err)
{
TError *Err;
Err=(TError *) p_Err;
DestroyString(Err->where);
DestroyString(Err->file);
DestroyString(Err->msg);
free(Err);
}
void ErrorsClear()
{
ListDestroy(Errors, ErrorDestroy);
}
ListNode *ErrorsGet()
{
return(Errors);
}
static bool ErrorOutputWanted(int flags)
{
bool result=TRUE;
//if stderr isn't a tty then don't print, unless ERRFLAG_NOTTY is set
//(this is used to disable this check when we consider syslog debugging too)
if (
(! (flags & ERRFLAG_NOTTY)) &&
(! isatty(2))
)
{
if (! LibUsefulGetBool("Error:notty")) result=FALSE;
}
//if this error is a debug error, then don't print unless either LIBUSEFUL_DEBUG environment variable is set
//or the libUseful:Debug internal value is set
if (flags & ERRFLAG_DEBUG)
{
result=FALSE;
if (StrValid(getenv("LIBUSEFUL_DEBUG"))) result=TRUE;
if (LibUsefulGetBool("libUseful:Debug")) result=TRUE;
}
return(result);
}
void InternalRaiseError(int flags, const char *where, const char *file, int line, const char *FmtStr, ...)
{
char *Tempstr=NULL;
va_list args;
const char *ptr="";
int errno_save;
ListNode *Curr, *Next;;
uint64_t Now;
TError *Err;
if (flags & ERRFLAG_CLEAR) ErrorsClear();
errno_save=errno;
va_start(args,FmtStr);
Tempstr=VFormatStr(Tempstr,FmtStr,args);
va_end(args);
if (! Errors) Errors=ListCreate();
if (flags & ERRFLAG_ERRNO) ptr=strerror(errno_save);
//first consider if we want to print out a message on stderr
if (ErrorOutputWanted(flags))
{
if (! LibUsefulGetBool("Error:Silent")) fprintf(stderr,"DEBUG: %s %s:%d %s. %s\n", where, file, line, Tempstr, ptr);
}
//now consider if we want to syslog an error message. Pass ERRFLAG_NOTTY as it doesn't matter if stderr is not a
//tty for this case. ERRFLAG_NOTTY is a setting here, not at test that uses '&'
if (ErrorOutputWanted(flags | ERRFLAG_NOTTY))
{
if ((flags & ERRFLAG_SYSLOG) || LibUsefulGetBool("Error:Syslog")) syslog(LOG_ERR,"DEBUG: %s %s:%d %s. %s", where, file, line, Tempstr, ptr);
}
//if this Error is just debugging, then never add it to the list of errors
if (! (flags & ERRFLAG_DEBUG))
{
Now=GetTime(TIME_MILLISECS);
Err=(TError *) calloc(1,sizeof(TError));
Err->errval=errno_save;
Err->when=Now;
Err->where=CopyStr(Err->where, where);
Err->file=CopyStr(Err->file, file);
Err->line=line;
Err->msg=CopyStr(Err->msg, Tempstr);
Curr=ListInsertItem(Errors, Err);
Curr=ListGetNext(Curr);
while (Curr)
{
Next=ListGetNext(Curr);
Err=(TError *) Curr->Item;
if ((Now - Err->when) > 2000)
{
ListDeleteNode(Curr);
ErrorDestroy(Err);
}
Curr=Next;
}
}
if (flags & ERRFLAG_ABORT)
{
abort();
sleep(1);
syslog(LOG_CRIT,"Still running after attempted abort. possible shenanigans.");
_exit(1);
}
DestroyString(Tempstr);
}