1/*  Copyright 1991 Free Software Foundation, Inc.
2 *  Copyright 1997,1999-2002,2007-2009 Alain Knaff.
3 *  This file is part of mtools.
4 *
5 *  Mtools is free software: you can redistribute it and/or modify
6 *  it under the terms of the GNU General Public License as published by
7 *  the Free Software Foundation, either version 3 of the License, or
8 *  (at your option) any later version.
9 *
10 *  Mtools is distributed in the hope that it will be useful,
11 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 *  GNU General Public License for more details.
14 *
15 *  You should have received a copy of the GNU General Public License
16 *  along with Mtools.  If not, see <http://www.gnu.org/licenses/>.
17 */
18#include "sysincludes.h"
19#include "mtools.h"
20
21#ifndef HAVE_STRDUP
22
23
24char *strdup(const char *str)
25{
26    char *nstr;
27
28    if (str == (char*)0)
29        return 0;
30
31    nstr = (char*)malloc((strlen(str) + 1));
32
33    if (nstr == (char*)0)
34    {
35        (void)fprintf(stderr, "strdup(): not enough memory to duplicate `%s'\n",
36		      str);
37	exit(1);
38    }
39
40    (void)strcpy(nstr, str);
41
42    return nstr;
43}
44#endif /* HAVE_STRDUP */
45
46#ifdef HAVE_WCHAR_H
47#ifndef HAVE_WCSDUP
48wchar_t *wcsdup(const wchar_t *wcs)
49{
50    wchar_t *nwcs;
51
52    if (wcs == (wchar_t*)0)
53        return 0;
54
55    nwcs = (wchar_t*)calloc(wcslen(wcs) + 1, sizeof(wchar_t));
56
57    if (nwcs == (wchar_t*)0)
58    {
59        (void)fprintf(stderr, "wcsdup(): not enough memory to duplicate `%ls'\n",
60		      wcs);
61	exit(1);
62    }
63
64    (void)wcscpy(nwcs, wcs);
65
66    return nwcs;
67}
68#endif /* HAVE_WCSDUP */
69#endif
70
71#ifndef HAVE_MEMCPY
72/*
73 * Copy contents of memory (with possible overlapping).
74 */
75char *memcpy(char *s1, const char *s2, size_t n)
76{
77	bcopy(s2, s1, n);
78	return(s1);
79}
80#endif
81
82#ifndef HAVE_MEMSET
83/*
84 * Copies the character c, n times to string s
85 */
86char *memset(char *s, char c, size_t n)
87{
88	char *s1 = s;
89
90	while (n > 0) {
91		--n;
92		*s++ = c;
93	}
94	return(s1);
95}
96#endif /* HAVE_MEMSET */
97
98
99#ifndef HAVE_STRCHR
100
101char * strchr (const char* s, int c)
102{
103	if (!s) return NULL;
104	while (*s && *s != c) s++;
105	if (*s)
106		return (char*) s;
107	else
108		return NULL;
109}
110
111#endif
112
113#ifndef HAVE_STRRCHR
114
115char * strrchr (const char* s1, int c)
116{
117	char* s = (char*) s1;
118	char* start = (char*) s;
119	if (!s) return NULL;
120	s += strlen(s)-1;
121	while (*s != c && (unsigned long) s != (unsigned long) start) s--;
122	if ((unsigned long) s == (unsigned long) start && *s != c)
123		return NULL;
124	else
125		return s;
126}
127
128#endif
129
130#ifndef HAVE_STRPBRK
131/*
132 * Return ptr to first occurrence of any character from `brkset'
133 * in the character string `string'; NULL if none exists.
134 */
135char *strpbrk(const char *string, const char *brkset)
136{
137	register char *p;
138
139	if (!string || !brkset)
140		return(0);
141	do {
142		for (p = brkset; *p != '\0' && *p != *string; ++p)
143			;
144		if (*p != '\0')
145			return(string);
146	}
147	while (*string++);
148	return(0);
149}
150#endif /* HAVE_STRPBRK */
151
152
153#ifndef HAVE_STRTOUL
154static int getdigit(char a, int max)
155{
156	int dig;
157
158	if(a < '0')
159		return -1;
160	if(a <= '9') {
161		dig = a - '0';
162	} else if(a >= 'a')
163		dig = a - 'a' + 10;
164	else if(a >= 'A')
165		dig = a - 'A' + 10;
166	if(dig >= max)
167		return -1;
168	else
169		return dig;
170}
171
172unsigned long strtoul(const char *string, char **eptr, int base)
173{
174	int accu, dig;
175
176	if(base < 1 || base > 36) {
177		if(string[0] == '0') {
178			switch(string[1]) {
179			       	case 'x':
180				case 'X':
181					return strtoul(string+2, eptr, 16);
182				case 'b':
183			       	case 'B':
184					return strtoul(string+2, eptr, 2);
185				default:
186					return strtoul(string, eptr, 8);
187			}
188		}
189	       	return strtoul(string, eptr, 10);
190	}
191	if(base == 16 && string[0] == '0' &&
192	   (string[1] == 'x' || string[1] == 'X'))
193		string += 2;
194
195	if(base == 2 && string[0] == '0' &&
196	   (string[1] == 'b' || string[1] == 'B'))
197		string += 2;
198	accu = 0;
199	while( (dig = getdigit(*string, base)) != -1 ) {
200		accu = accu * base + dig;
201		string++;
202	}
203	if(eptr)
204		*eptr = (char *) string;
205	return accu;
206}
207#endif /* HAVE_STRTOUL */
208
209#ifndef HAVE_STRTOL
210long strtol(const char *string, char **eptr, int base)
211{
212	long l;
213
214	if(*string == '-') {
215		return -(long) strtoul(string+1, eptr, base);
216	} else {
217		if (*string == '+')
218			string ++;
219		return (long) strtoul(string, eptr, base);
220	}
221}
222#endif
223
224
225
226#ifndef HAVE_STRSPN
227/* Return the length of the maximum initial segment
228   of S which contains only characters in ACCEPT.  */
229size_t strspn(const char *s, const char *accept)
230{
231  register char *p;
232  register char *a;
233  register size_t count = 0;
234
235  for (p = s; *p != '\0'; ++p)
236    {
237      for (a = accept; *a != '\0'; ++a)
238	if (*p == *a)
239	  break;
240      if (*a == '\0')
241	return count;
242      else
243	++count;
244    }
245
246  return count;
247}
248#endif /* HAVE_STRSPN */
249
250#ifndef HAVE_STRCSPN
251/* Return the length of the maximum inital segment of S
252   which contains no characters from REJECT.  */
253size_t strcspn (const char *s, const char *reject)
254{
255  register size_t count = 0;
256
257  while (*s != '\0')
258    if (strchr (reject, *s++) == NULL)
259      ++count;
260    else
261      return count;
262
263  return count;
264}
265
266#endif /* HAVE_STRCSPN */
267
268#ifndef HAVE_STRERROR
269
270#ifndef DECL_SYS_ERRLIST
271extern char *sys_errlist[];
272#endif
273
274char *strerror(int errno)
275{
276  return sys_errlist[errno];
277}
278#endif
279
280#ifndef HAVE_STRCASECMP
281/* Compare S1 and S2, ignoring case, returning less than, equal to or
282   greater than zero if S1 is lexiographically less than,
283   equal to or greater than S2.  */
284int strcasecmp(const char *s1, const char *s2)
285{
286  register const unsigned char *p1 = (const unsigned char *) s1;
287  register const unsigned char *p2 = (const unsigned char *) s2;
288  unsigned char c1, c2;
289
290  if (p1 == p2)
291    return 0;
292
293  do
294    {
295      c1 = tolower (*p1++);
296      c2 = tolower (*p2++);
297      if (c1 == '\0')
298	break;
299    }
300  while (c1 == c2);
301
302  return c1 - c2;
303}
304#endif
305
306#ifdef HAVE_WCHAR_H
307#ifndef HAVE_WCSCASECMP
308/* Compare S1 and S2, ignoring case, returning less than, equal to or
309   greater than zero if S1 is lexiographically less than,
310   equal to or greater than S2.  */
311int wcscasecmp(const wchar_t *s1, const wchar_t *s2)
312{
313  register const wchar_t *p1 = s1;
314  register const wchar_t *p2 = s2;
315  wchar_t c1, c2;
316
317  if (p1 == p2)
318    return 0;
319
320  do
321    {
322      c1 = towlower (*p1++);
323      c2 = towlower (*p2++);
324      if (c1 == '\0')
325	break;
326    }
327  while (c1 == c2);
328
329  return c1 - c2;
330}
331#endif
332#endif
333
334
335#ifndef HAVE_STRCASECMP
336/* Compare S1 and S2, ignoring case, returning less than, equal to or
337   greater than zero if S1 is lexiographically less than,
338   equal to or greater than S2.  */
339int strncasecmp(const char *s1, const char *s2, size_t n)
340{
341  register const unsigned char *p1 = (const unsigned char *) s1;
342  register const unsigned char *p2 = (const unsigned char *) s2;
343  unsigned char c1, c2;
344
345  if (p1 == p2)
346    return 0;
347
348  c1 = c2 = 1;
349  while (c1 && c1 == c2 && n-- > 0)
350    {
351      c1 = tolower (*p1++);
352      c2 = tolower (*p2++);
353    }
354
355  return c1 - c2;
356}
357#endif
358
359#ifndef HAVE_GETPASS
360char *getpass(const char *prompt)
361{
362	static char password[129];
363	int l;
364
365	fprintf(stderr,"%s",prompt);
366	fgets(password, 128, stdin);
367	l = strlen(password);
368	if(l && password[l-1] == '\n')
369		password[l-1] = '\0';
370	return password;
371
372}
373#endif
374
375#ifndef HAVE_ATEXIT
376
377#ifdef HAVE_ON_EXIT
378int atexit(void (*function)(void))
379{
380	return on_exit( (void(*)(int,void*)) function, 0);
381}
382#else
383
384typedef struct exitCallback {
385	void (*function) (void);
386	struct exitCallback *next;
387} exitCallback_t;
388
389static exitCallback_t *callback = 0;
390
391int atexit(void (*function) (void))
392{
393	exitCallback_t *newCallback;
394
395	newCallback = New(exitCallback_t);
396	if(!newCallback) {
397		printOom();
398		exit(1);
399	}
400	newCallback->function = function;
401	newCallback->next = callback;
402	callback = newCallback;
403	return 0;
404}
405#undef exit
406
407void myexit(int code)
408{
409  void (*function)(void);
410
411  while(callback) {
412    function = callback->function;
413    callback = callback->next;
414    function();
415  }
416  exit(code);
417}
418
419#endif
420
421#endif
422
423#ifdef OS_mingw32msvc
424static const char PATH_SEP = '\\';
425#else
426static const char PATH_SEP = '/';
427#endif
428
429/*#ifndef HAVE_BASENAME*/
430const char *_basename(const char *filename)
431{
432	char *ptr;
433
434	ptr = strrchr(filename, PATH_SEP);
435	if(ptr)
436		return ptr+1;
437	else
438		return filename;
439}
440/*#endif*/
441
442/* Strip the suffix ".exe" from the argument, if present. */
443void _stripexe(char *filename)
444{
445	char *ptr;
446	ptr = strrchr(filename, '.');
447	if(ptr && !strcasecmp(ptr, ".exe"))
448		*ptr = '\0';
449}
450
451#ifndef HAVE_STRNLEN
452size_t strnlen(const char *str, size_t l)
453{
454  size_t i;
455  for(i=0; i<l; i++) {
456    if(str[i] == 0)
457      break;
458  }
459  return i;
460}
461#endif /* HAVE_STRNLEN */
462
463#ifdef HAVE_WCHAR_H
464#ifndef HAVE_WCSNLEN
465size_t wcsnlen(const wchar_t *wcs, size_t l)
466{
467  size_t i;
468  for(i=0; i<l; i++) {
469    if(wcs[i] == 0)
470      break;
471  }
472  return i;
473}
474#endif /* HAVE_WCSNLEN */
475#endif
476