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