1 |
/* Compatibility routines. |
2 |
* |
3 |
* IRC Services is copyright (c) 1996-2009 Andrew Church. |
4 |
* E-mail: <achurch@achurch.org> |
5 |
* Parts written by Andrew Kempe and others. |
6 |
* This program is free but copyrighted software; see the file GPL.txt for |
7 |
* details. |
8 |
*/ |
9 |
|
10 |
#include "services.h" |
11 |
|
12 |
#if !HAVE_HSTRERROR |
13 |
# include <netdb.h> |
14 |
#endif |
15 |
|
16 |
/*************************************************************************/ |
17 |
|
18 |
#if !HAVE_HSTRERROR |
19 |
|
20 |
/* hstrerror: return an error message for the given h_errno code. */ |
21 |
|
22 |
const char *hstrerror(int h_errnum) |
23 |
{ |
24 |
switch (h_errnum) { |
25 |
case HOST_NOT_FOUND: return "Host not found"; |
26 |
case TRY_AGAIN: return "Host not found, try again"; |
27 |
case NO_RECOVERY: return "Nameserver error"; |
28 |
case NO_DATA: return "No data of requested type"; |
29 |
default: return "Unknown error"; |
30 |
} |
31 |
} |
32 |
|
33 |
#endif /* !HAVE_HSTRERROR */ |
34 |
|
35 |
/*************************************************************************/ |
36 |
|
37 |
#if !HAVE_SNPRINTF |
38 |
|
39 |
/* [v]snprintf: Like [v]sprintf, but don't write more than len bytes |
40 |
* (including null terminator). Return the number of bytes |
41 |
* written. |
42 |
*/ |
43 |
|
44 |
#if BAD_SNPRINTF |
45 |
int vsnprintf(char *buf, size_t len, const char *fmt, va_list args) |
46 |
{ |
47 |
if (len <= 0) |
48 |
return 0; |
49 |
*buf = 0; |
50 |
#undef vsnprintf |
51 |
vsnprintf(buf, len, fmt, args); |
52 |
#define vsnprintf my_vsnprintf |
53 |
buf[len-1] = 0; |
54 |
return strlen(buf); |
55 |
} |
56 |
#endif /* BAD_SNPRINTF */ |
57 |
|
58 |
int snprintf(char *buf, size_t len, const char *fmt, ...) |
59 |
{ |
60 |
va_list args; |
61 |
int ret; |
62 |
|
63 |
va_start(args, fmt); |
64 |
ret = vsnprintf(buf, len, fmt, args); |
65 |
va_end(args); |
66 |
return ret; |
67 |
} |
68 |
|
69 |
#endif /* !HAVE_SNPRINTF */ |
70 |
|
71 |
/*************************************************************************/ |
72 |
|
73 |
#if !HAVE_STRTOK |
74 |
|
75 |
/* glibc 2.2 (RedHat 7.0) has a broken strtok--it dies if called with a |
76 |
* NULL parameter after returning NULL once. glibc and possibly other |
77 |
* libraries also return non-NULL for strtok(NULL, "") even after |
78 |
* returning NULL for strtok(NULL, " "). |
79 |
*/ |
80 |
|
81 |
char *strtok(char *str, const char *delim) |
82 |
{ |
83 |
static char *current = NULL; |
84 |
char *ret; |
85 |
|
86 |
if (str) |
87 |
current = str; |
88 |
if (!current) |
89 |
return NULL; |
90 |
current += strspn(current, delim); |
91 |
ret = *current ? current : NULL; |
92 |
current += strcspn(current, delim); |
93 |
if (!*current) |
94 |
current = NULL; |
95 |
else |
96 |
*current++ = 0; |
97 |
return ret; |
98 |
} |
99 |
|
100 |
#endif /* !HAVE_STRTOK */ |
101 |
|
102 |
/*************************************************************************/ |
103 |
|
104 |
#if !HAVE_STRICMP && !HAVE_STRCASECMP |
105 |
|
106 |
/* stricmp, strnicmp: Case-insensitive versions of strcmp() and |
107 |
* strncmp(). |
108 |
*/ |
109 |
|
110 |
int stricmp(const char *s1, const char *s2) |
111 |
{ |
112 |
register int c; |
113 |
|
114 |
while ((c = tolower(*s1)) == tolower(*s2)) { |
115 |
if (c == 0) |
116 |
return 0; |
117 |
s1++; |
118 |
s2++; |
119 |
} |
120 |
if (c < tolower(*s2)) |
121 |
return -1; |
122 |
return 1; |
123 |
} |
124 |
|
125 |
int strnicmp(const char *s1, const char *s2, size_t len) |
126 |
{ |
127 |
register int c; |
128 |
|
129 |
if (!len) |
130 |
return 0; |
131 |
while ((c = tolower(*s1)) == tolower(*s2) && len > 0) { |
132 |
if (c == 0 || --len == 0) |
133 |
return 0; |
134 |
s1++; |
135 |
s2++; |
136 |
} |
137 |
if (c < tolower(*s2)) |
138 |
return -1; |
139 |
return 1; |
140 |
} |
141 |
#endif |
142 |
|
143 |
/*************************************************************************/ |
144 |
|
145 |
#if !HAVE_STRDUP && !MEMCHECKS |
146 |
char *strdup(const char *s) |
147 |
{ |
148 |
char *new = malloc(strlen(s)+1); |
149 |
if (new) |
150 |
strcpy(new, s); |
151 |
return new; |
152 |
} |
153 |
#endif |
154 |
|
155 |
/*************************************************************************/ |
156 |
|
157 |
#if !HAVE_STRSPN |
158 |
|
159 |
size_t strspn(const char *s, const char *accept) |
160 |
{ |
161 |
size_t i = 0; |
162 |
|
163 |
while (*s && strchr(accept, *s)) |
164 |
++i, ++s; |
165 |
return i; |
166 |
} |
167 |
|
168 |
size_t strcspn(const char *s, const char *reject) |
169 |
{ |
170 |
size_t i = 0; |
171 |
|
172 |
while (*s && !strchr(reject, *s)) |
173 |
++i, ++s; |
174 |
return i; |
175 |
} |
176 |
|
177 |
#endif |
178 |
|
179 |
/*************************************************************************/ |
180 |
|
181 |
#if !HAVE_STRERROR |
182 |
# if HAVE_SYS_ERRLIST |
183 |
extern char *sys_errlist[]; |
184 |
# endif |
185 |
|
186 |
char *strerror(int errnum) |
187 |
{ |
188 |
# if HAVE_SYS_ERRLIST |
189 |
return sys_errlist[errnum]; |
190 |
# else |
191 |
static char buf[20]; |
192 |
snprintf(buf, sizeof(buf), "Error %d", errnum); |
193 |
return buf; |
194 |
# endif |
195 |
} |
196 |
#endif |
197 |
|
198 |
/*************************************************************************/ |
199 |
|
200 |
#if !HAVE_STRSIGNAL |
201 |
char *strsignal(int signum) |
202 |
{ |
203 |
static char buf[32]; |
204 |
switch (signum) { |
205 |
case SIGHUP: strbcpy(buf, "Hangup"); break; |
206 |
case SIGINT: strbcpy(buf, "Interrupt"); break; |
207 |
case SIGQUIT: strbcpy(buf, "Quit"); break; |
208 |
#ifdef SIGILL |
209 |
case SIGILL: strbcpy(buf, "Illegal instruction"); break; |
210 |
#endif |
211 |
#ifdef SIGABRT |
212 |
case SIGABRT: strbcpy(buf, "Abort"); break; |
213 |
#endif |
214 |
#if defined(SIGIOT) && (!defined(SIGABRT) || SIGIOT != SIGABRT) |
215 |
case SIGIOT: strbcpy(buf, "IOT trap"); break; |
216 |
#endif |
217 |
#ifdef SIGBUS |
218 |
case SIGBUS: strbcpy(buf, "Bus error"); break; |
219 |
#endif |
220 |
case SIGFPE: strbcpy(buf, "Floating point exception"); break; |
221 |
case SIGKILL: strbcpy(buf, "Killed"); break; |
222 |
case SIGUSR1: strbcpy(buf, "User signal 1"); break; |
223 |
case SIGSEGV: strbcpy(buf, "Segmentation fault"); break; |
224 |
case SIGUSR2: strbcpy(buf, "User signal 2"); break; |
225 |
case SIGPIPE: strbcpy(buf, "Broken pipe"); break; |
226 |
case SIGALRM: strbcpy(buf, "Alarm clock"); break; |
227 |
case SIGTERM: strbcpy(buf, "Terminated"); break; |
228 |
case SIGSTOP: strbcpy(buf, "Stopped (signal)"); break; |
229 |
case SIGTSTP: strbcpy(buf, "Stopped"); break; |
230 |
case SIGIO: strbcpy(buf, "I/O error"); break; |
231 |
default: snprintf(buf, sizeof(buf), "Signal %d\n", signum); |
232 |
break; |
233 |
} |
234 |
return buf; |
235 |
} |
236 |
#endif |
237 |
|
238 |
/*************************************************************************/ |
239 |
|
240 |
/* |
241 |
* Local variables: |
242 |
* c-file-style: "stroustrup" |
243 |
* c-file-offsets: ((case-label . *) (statement-case-intro . *)) |
244 |
* indent-tabs-mode: nil |
245 |
* End: |
246 |
* |
247 |
* vim: expandtab shiftwidth=4: |
248 |
*/ |