00001 #include <stdlib.h>
00002 #include <string.h>
00003 #include <time.h>
00004 #include <ctype.h>
00005
00006 #if defined(unix) || defined(__unix__) || defined(__MACH__)
00007 #include <unistd.h>
00008 #endif
00009
00010 #include "config.h"
00011 #ifdef CP_HAS_REGEX_H
00012 #include <regex.h>
00013 #else
00014 #ifdef CP_HAS_PCRE
00015 #include <pcreposix.h>
00016 #endif
00017 #endif
00018 #ifdef CP_HAS_DIRENT_H
00019 #include <dirent.h>
00020 #endif
00021 #include <errno.h>
00022 #ifdef CP_HAS_SYS_TIME_H
00023 #include <sys/time.h>
00024 #endif
00025
00026 #include <sys/types.h>
00027 #include <sys/stat.h>
00028
00029 #ifdef CP_HAS_NETDB_H
00030 #include <netdb.h>
00031 #endif
00032
00033 #if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__APPLE__)
00034 #include <sys/types.h>
00035 #include <sys/socket.h>
00036 #include <netinet/in.h>
00037 #endif
00038
00039 #ifdef _WINDOWS
00040 #include <Winsock2.h>
00041 #include <WS2SPI.H>
00042 #include <Windows.h>
00043 #endif
00044
00045 #include "util.h"
00046 #include "log.h"
00047 #include "common.h"
00048
00049 #ifndef CP_HAS_STRDUP
00050 char *strdup(char *src)
00051 {
00052 char *dst = NULL;
00053
00054 if (src != NULL)
00055 {
00056 int len = strlen(src);
00057 dst = (char *) malloc((len + 1) * sizeof(char));
00058 cp_assert(*dst != NULL);
00059
00060 memcpy(*dst, src, len);
00061 dst[len] = '\0';
00062 }
00063
00064 return dst;
00065 }
00066 #endif
00067
00068 #ifndef CP_HAS_STRNDUP
00069 char *strndup(char *src, int maxlen)
00070 {
00071 int len;
00072 char *p;
00073 char *dst = NULL;
00074
00075 if (maxlen < 0)
00076 {
00077 cp_error(CP_INVALID_VALUE, "negative string length requested");
00078 errno = EINVAL;
00079 return NULL;
00080 }
00081
00082 if (src != NULL)
00083 {
00084
00085 for (p = src; *p && p - src < maxlen; p++);
00086 len = p - src;
00087 if (len > maxlen) len = maxlen;
00088 dst = (char *) malloc((len + 1) * sizeof(char));
00089 if (dst == NULL)
00090 {
00091 errno = ENOMEM;
00092 return NULL;
00093 }
00094
00095 memcpy(dst, src, len);
00096 dst[len] = '\0';
00097 }
00098
00099 return dst;
00100 }
00101 #endif
00102
00103 #ifndef CP_HAS_STRCASECMP
00104 #ifndef _WINDOWS
00105 int strcasecmp(const char *a, const char *b)
00106 {
00107 while (*a && *b && tolower(*a) == tolower(*b))
00108 {
00109 a++;
00110 b++;
00111 }
00112
00113 return *a - *b;
00114 }
00115 #endif
00116 #endif
00117
00118 #ifndef CP_HAS_STRNCASECMP
00119 #ifndef _WINDOWS
00120 int strncasecmp(const char *a, const char *b, size_t len)
00121 {
00122 while (len-- > 0 && *a && *b && tolower(*a) == tolower(*b))
00123 {
00124 a++;
00125 b++;
00126 }
00127
00128 return *a - *b;
00129 }
00130 #endif
00131 #endif
00132
00133 #ifndef CP_HAS_GETTIMEOFDAY
00134 #ifdef _WINDOWS
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164 static const unsigned __int64 epoch = 116444736000000000L;
00165
00166
00167
00168
00169
00170 int
00171 gettimeofday(struct timeval * tp, struct timezone * tzp)
00172 {
00173 FILETIME file_time;
00174 SYSTEMTIME system_time;
00175 ULARGE_INTEGER ularge;
00176
00177 GetSystemTime(&system_time);
00178 SystemTimeToFileTime(&system_time, &file_time);
00179 ularge.LowPart = file_time.dwLowDateTime;
00180 ularge.HighPart = file_time.dwHighDateTime;
00181
00182 tp->tv_sec = (long) ((ularge.QuadPart - epoch) / 10000000L);
00183 tp->tv_usec = (long) (system_time.wMilliseconds * 1000);
00184
00185 return 0;
00186 }
00187 #endif
00188 #endif
00189
00190
00191 int cp_sleep(int sec)
00192 {
00193 int rc = -1;
00194 #if defined(unix) || defined(__unix__) || defined(__MACH__)
00195 struct timeval delay;
00196 delay.tv_sec = sec;
00197 delay.tv_usec = 0;
00198 rc = select(0, NULL, NULL, NULL, &delay);
00199 #else
00200 #ifdef _WINDOWS
00201 rc = 0;
00202 Sleep(sec * 1000);
00203 #endif
00204 #endif
00205 return rc;
00206 }
00207
00208 char *hex_url_encode(char *hex)
00209 {
00210 int len = strlen(hex) * 3 / 2 + 1;
00211 char *res = (char *) malloc(len * sizeof(char));
00212 char *idx = res;
00213
00214 while (*hex)
00215 {
00216 *idx++ = '%';
00217 *idx++ = *hex++;
00218 if (*hex == 0) break;
00219 *idx++ = *hex++;
00220 }
00221
00222 *idx = '\0';
00223
00224 return res;
00225 }
00226
00227 char *strnchr(char *str, char ch, int len)
00228 {
00229 char *res = NULL;
00230
00231 if (len < 0)
00232 {
00233 cp_error(CP_INVALID_VALUE, "negative string length requested");
00234 errno = EINVAL;
00235 return NULL;
00236 }
00237
00238 while (len-- > 0)
00239 {
00240 if (*str == ch)
00241 {
00242 res = str;
00243 break;
00244 }
00245 if (*str++ == '\0')
00246 break;
00247 }
00248
00249 return res;
00250 }
00251
00252
00253 char *str_trim_cpy(char *dst, char *src)
00254 {
00255 char *top;
00256 char *last;
00257 top = dst;
00258 while (isspace(*src)) src++;
00259 last = dst;
00260 while ((*dst = *src)) {
00261 dst++;
00262 if (!isspace(*src)) last = dst;
00263 src++;
00264 }
00265
00266 *last = '\0';
00267 return top;
00268 }
00269
00270 int parse_boolean(char *value)
00271 {
00272 return value != NULL && (*value == 't' || *value =='T');
00273 }
00274
00275 long get_timestamp()
00276 {
00277 return time(NULL);
00278 }
00279
00283 static char *empty_cp_string = "";
00284
00285 char *dbfmt(char *str)
00286 {
00287 return str ? str : empty_cp_string;
00288 }
00289
00290 unsigned long get_current_ip()
00291 {
00292 char hostname[256];
00293 int rc;
00294
00295 rc = gethostname(hostname, 256);
00296 return rc ? 0 : get_host_ip(hostname);
00297 }
00298
00299 unsigned long get_host_ip(char *hostname)
00300 {
00301 #ifdef CP_HAS_GETADDRINFO
00302 struct addrinfo hints, *res, *res0;
00303 int rc;
00304 unsigned long ip = 0;
00305 unsigned long addr = 0;
00306
00307 memset(&hints, 0, sizeof(hints));
00308 hints.ai_family = AF_INET;
00309 hints.ai_socktype = SOCK_STREAM;
00310
00311 rc = getaddrinfo(hostname, "http", &hints, &res0);
00312 for (res = res0; res; res = res->ai_next) {
00313 addr = ((struct sockaddr_in *) res->ai_addr)->sin_addr.s_addr;
00314 if (ip && (addr & 0xff) == 0x7f) continue;
00315 ip = addr;
00316 }
00317
00318 return ip;
00319 #else
00320 unsigned long ulIP;
00321 struct hostent* phostent;
00322
00323 phostent = gethostbyname(hostname);
00324 if (phostent == NULL) return -1;
00325 #ifdef _WINDOWS
00326 ulIP = *(DWORD*)(*phostent->h_addr_list);
00327 #else
00328 ulIP = *(unsigned long *)(*phostent->h_addr_list);
00329 #endif
00330
00331 return ulIP;
00332 #endif
00333 }
00334
00335 char *ip_to_string(unsigned long ip, char *buf, size_t len)
00336 {
00337 #ifdef CP_HAS_SNPRINTF
00338 snprintf(buf, len, "%ld.%ld.%ld.%ld", ip & 0xff, (ip >> 8) & 0xff
00339 , (ip >> 16) & 0xff, (ip >> 24) & 0xff);
00340 #else
00341 sprintf(buf, "%ld.%ld.%ld.%ld", ip & 0xff, (ip >> 8) & 0xff
00342 , (ip >> 16) & 0xff, (ip >> 24) & 0xff);
00343 #endif
00344 return buf;
00345 }
00346
00347 char *regex_compilation_error(int rc)
00348 {
00349 char *msg = NULL;
00350
00351 switch (rc)
00352 {
00353 case REG_BADRPT:
00354 msg = "Invalid use of repetition operators such as using `*' as the first character.";
00355 break;
00356
00357 case REG_BADBR:
00358 msg = "Invalid use of back reference operator.";
00359 break;
00360
00361 case REG_EBRACE:
00362 msg = "Un-matched brace interval operators.";
00363 break;
00364
00365 case REG_EBRACK:
00366 msg = "Un-matched bracket list operators.";
00367 break;
00368
00369 case REG_ERANGE:
00370 msg = "Invalid use of the range operator, eg. the ending point of the range occurs prior to the starting point.";
00371 break;
00372
00373 case REG_ECTYPE:
00374 msg = "Unknown character class name.";
00375 break;
00376
00377 case REG_ECOLLATE:
00378 msg = "Invalid collating element.";
00379 break;
00380
00381 case REG_EPAREN:
00382 msg = "Un-matched parenthesis group operators.";
00383 break;
00384
00385 case REG_ESUBREG:
00386 msg = "Invalid back reference to a subexpression.";
00387 break;
00388
00389 #ifdef linux
00390 case REG_EEND:
00391 msg = "Non specific error.";
00392 break;
00393 #endif
00394
00395 case REG_EESCAPE:
00396 msg = "Trailing backslash.";
00397 break;
00398
00399 case REG_BADPAT:
00400 msg = "Invalid use of pattern operators such as group or list.";
00401 break;
00402
00403 #ifdef linux
00404 case REG_ESIZE:
00405 msg = "Compiled regular expression requires a pattern buffer larger than 64Kb.";
00406 break;
00407 #endif
00408
00409 case REG_ESPACE:
00410 msg = "The regex routines ran out of memory.";
00411 break;
00412 }
00413
00414 return msg;
00415 }
00416
00417 char *stat_error_fmt(int err)
00418 {
00419 char *fmt = "%s: resolving %s: unknown stat error\n";
00420 switch (err)
00421 {
00422 case ENOENT:
00423 fmt = "%s: A component of the path \'%s\' does not exist\n";
00424 break;
00425
00426 case ENOTDIR:
00427 fmt = "%s: A component of the path \'%s\' is not a directory\n";
00428 break;
00429
00430 #ifdef ELOOP
00431 case ELOOP:
00432 fmt = "%s: Too many symbolic links encountered while "
00433 "traversing the path %s\n";
00434 break;
00435 #endif
00436
00437 case EFAULT:
00438 fmt = "%s: Bad address resolving %s\n";
00439 break;
00440
00441 case EACCES:
00442 fmt = "%s: %s: Permission denied.\n";
00443 break;
00444
00445 case ENOMEM:
00446 fmt = "%s: resolving %s: Out of memory\n";
00447 break;
00448
00449 case ENAMETOOLONG:
00450 fmt = "%s: resolving %s: File name too long.\n";
00451 break;
00452 }
00453
00454 return fmt;
00455 }
00456
00457 time_t last_change_time(char *path)
00458 {
00459 #ifdef CP_HAS_STAT
00460 struct stat buf;
00461
00462 if (stat(path, &buf)) return -1;
00463
00464 return buf.st_mtime;
00465 #else
00466 #ifdef _WINDOWS
00467 struct _stat buf;
00468 if (_stat(path, &buf)) return -1;
00469 return buf.st_mtime;
00470 #endif
00471 #endif
00472 }
00473
00477 int checkdir(char *path)
00478 {
00479 #ifdef CP_HAS_DIRENT_H
00480 int rc = 0;
00481 DIR *dir = opendir(path);
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491 if (dir == NULL)
00492 {
00493 int rc = errno;
00494 char *err = strerror(rc);
00495 cp_error(rc, "%s: opendir failed - %s", path, err);
00496 }
00497 else
00498 closedir(dir);
00499
00500 return rc;
00501 #else
00502 #ifdef _WINDOWS
00503 struct _stat buf;
00504 return _stat(path, &buf) != 0;
00505 #endif
00506 #endif
00507 }
00508
00513 void gen_id_str(char *buf)
00514 {
00515 struct timeval tm;
00516 gettimeofday(&tm, NULL);
00517 gen_tm_id_str(buf, &tm);
00518 }
00519
00520 static int id_factor[] = { 2, 3, 5, 7, 11,
00521 13, 17, 19, 23, 29,
00522 31, 37, 41, 43, 47,
00523 53, 59, 61, 67, 71,
00524 73, 79, 83, 89, 97,
00525 101, 103, 107, 109, 113,
00526 127, 131};
00527
00532 void gen_tm_id_str(char *buf, struct timeval *tm)
00533 {
00534 int i;
00535 unsigned long t = 0;
00536 unsigned long v = 0;
00537
00538 memset(buf, 0, 17);
00539 t = tm->tv_sec;
00540 for (i = 0; i < 32; i++)
00541 {
00542 v |= (t % id_factor[i]);
00543 v <<= 1;
00544 buf[i % 16] = (unsigned char)
00545 ('a' + (((((t * (i + 1)) % 26) | (buf[i % 16] % 'a')) ^ (unsigned char)(v % 26))) % 26);
00546 }
00547 t = tm->tv_usec;
00548 for (i = 0; i < 32; i++)
00549 {
00550 v ^= (t % id_factor[i]);
00551 v <<= 1;
00552 buf[i % 16] = (unsigned char)
00553 ('a' + (((((t * (i + 1)) % 26) | (buf[i % 16] % 'a')) ^ (unsigned char)(v % 26))) % 26);
00554 }
00555 }
00556
00558 int *intdup(int *src)
00559 {
00560 int *res = malloc(sizeof(int));
00561 if (res) *res = *src;
00562 return res;
00563 }
00564
00566 long *longdup(long *src)
00567 {
00568 long *res = malloc(sizeof(long));
00569 if (res) *res = *src;
00570 return res;
00571 }
00572
00574 float *floatdup(float *src)
00575 {
00576 float *res = malloc(sizeof(float));
00577 if (res) *res = *src;
00578 return res;
00579 }
00580
00582 double *doubledup(double *src)
00583 {
00584 double *res = malloc(sizeof(double));
00585 if (res) *res = *src;
00586 return res;
00587 }
00588
00590 void *memdup(void *src, int len)
00591 {
00592 void *res = malloc(len);
00593 if (res)
00594 memcpy(res, src, len);
00595 return res;
00596 }
00597
00598 #define C2HEX(ch) ((ch) >= '0' && (ch) <= '9' ? (ch) - '0' : \
00599 (ch) >= 'A' && (ch) <= 'F' ? (ch) - 'A' + 10 : \
00600 (ch) >= 'a' && (ch) <= 'f' ? (ch) - 'a' + 10 : -1)
00601
00603 int xtoi(char *p)
00604 {
00605 int curr;
00606 int res = 0;
00607
00608 while (*p)
00609 {
00610 curr = C2HEX(*p);
00611 if (curr == -1) break;
00612 res = res * 0x10 + curr;
00613 p++;
00614 }
00615
00616 return res;
00617 }
00618
00620 int xtol(char *p)
00621 {
00622 int curr;
00623 long res = 0;
00624
00625 while (*p)
00626 {
00627 curr = C2HEX(*p);
00628 if (curr == -1) break;
00629 res = res * 0x10 + curr;
00630 p++;
00631 }
00632
00633 return res;
00634 }
00635
00636 char *reverse_string(char *str)
00637 {
00638 int len;
00639 char *res;
00640 char *src, *dst;
00641
00642 if (str == NULL) return NULL;
00643
00644 len = strlen(str);
00645 res = malloc(len * sizeof(char) + 1);
00646 if (res == NULL) return NULL;
00647
00648 dst = res;
00649 src = &str[len -1];
00650 while (src > str)
00651 *dst++ = *src--;
00652 *dst = '\0';
00653
00654 return res;
00655 }
00656
00657
00658 char *reverse_string_in_place(char *str)
00659 {
00660 char *i, *f;
00661 char ch;
00662 int len = strlen(str);
00663 if (len == 0) return str;
00664 i = str;
00665 f = &str[len - 1];
00666 while (i < f)
00667 {
00668 ch = *i;
00669 *i = *f;
00670 *f = ch;
00671 i++;
00672 f--;
00673 }
00674
00675 return str;
00676 }
00677
00678 char *filter_string(char *str, char *letters)
00679 {
00680 char *i;
00681 char *f;
00682 int len = strlen(str);
00683
00684 i = str;
00685 while ((f = strpbrk(i, letters)))
00686 {
00687 i = f;
00688 while (*f && strchr(letters, *f)) f++;
00689 if (*f)
00690 {
00691 memmove(i, f, len - (f - str));
00692 len -= f - i;
00693 str[len] = '\0';
00694 }
00695 else
00696 {
00697 *i = '\0';
00698 len -= len - (i - str);
00699 break;
00700 }
00701 }
00702
00703 return str;
00704 }
00705
00706 char *to_lowercase(char *str)
00707 {
00708 char *p;
00709 for (p = str; *p; p++)
00710 if (isupper(*p)) *p += 'a' - 'A';
00711 return str;
00712 }
00713
00714 char *to_uppercase(char *str)
00715 {
00716 char *p;
00717 for (p = str; *p; p++)
00718 if (islower(*p)) *p -= 'a' - 'A';
00719 return str;
00720 }
00721
00722 #ifndef CP_HAS_GETOPT
00723 CPROPS_DLL char *optarg;
00724 static int opt_idx = 0;
00725
00726 int getopt(int argc, char *argv[], char *fmt)
00727 {
00728 char *p;
00729
00730 opt_idx++;
00731 if (opt_idx == argc) return -1;
00732
00733 if ((p = strchr(fmt, argv[opt_idx][1])) != NULL)
00734 {
00735 if (p[1] == ':') optarg = argv[++opt_idx];
00736 return p[0];
00737 }
00738
00739 return 0;
00740 }
00741 #endif
00742
00743 #ifndef CP_HAS_INET_NTOP
00744 #ifdef _WINDOWS
00745 char *inet_ntop(int af, void *src, char *dst, size_t cnt)
00746 {
00747 int rc;
00748
00749 WSAPROTOCOL_INFO pinfo;
00750 memset(&pinfo, 0, sizeof(WSAPROTOCOL_INFO));
00751 pinfo.iAddressFamily = AF_INET;
00752 rc = WSAAddressToString(src, sizeof(struct sockaddr_in), &pinfo, dst, &cnt);
00753 #ifdef DEBUG
00754 if (rc)
00755 {
00756 rc = WSAGetLastError();
00757 DEBUGMSG("WSAAddressToString: %d", rc);
00758 }
00759 #endif
00760 return dst;
00761 }
00762
00763 #if 0 //~~ check windows version - some platforms don't have getnameinfo
00764 char *inet_ntop(int af, const void *src, char *dst, size_t cnt)
00765 {
00766 if (af == AF_INET)
00767 {
00768 struct sockaddr_in in;
00769 memset(&in, 0, sizeof(in));
00770 in.sin_family = AF_INET;
00771 memcpy(&in.sin_addr, src, sizeof(struct in_addr));
00772 getnameinfo((struct sockaddr *)&in, sizeof(struct sockaddr_in),
00773 dst, cnt, NULL, 0, 0);
00774 return dst;
00775 }
00776 else if (af == AF_INET6)
00777 {
00778 struct sockaddr_in6 in;
00779 memset(&in, 0, sizeof(in));
00780 in.sin6_family = AF_INET6;
00781 memcpy(&in.sin6_addr, src, sizeof(struct in_addr6));
00782 getnameinfo((struct sockaddr *)&in, sizeof(struct sockaddr_in6),
00783 dst, cnt, NULL, 0, NI_NUMERICHOST);
00784 return dst;
00785 }
00786 return NULL;
00787 }
00788 #endif //~~ platform check
00789
00790 #endif
00791 #endif
00792
00793 #ifndef CP_HAS_DLFCN_H
00794 #ifdef _WINDOWS
00795 void *dlopen(char *file, int mode)
00796 {
00797 return LoadLibrary(file);
00798 }
00799
00800 int dlclose(void *handle)
00801 {
00802 return FreeLibrary(handle);
00803 }
00804
00805 void *dlsym(void *handle, char *name)
00806 {
00807 return GetProcAddress(handle, name);
00808 }
00809
00810 char *dlerror()
00811 {
00812 static char msg[0x400];
00813 DWORD err = GetLastError();
00814 FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
00815 NULL, err, 0, msg, 0x400 - 1, NULL);
00816 return msg;
00817 }
00818
00819 #endif
00820 #endif
00821
00822 #ifdef _WINDOWS
00823 char *flat_env(char *env, char **envp)
00824 {
00825 int len;
00826 int i = 0;
00827 char *p = env;
00828 while (envp[i])
00829 {
00830 strcpy(p, envp[i]);
00831 len = strlen(envp[i]);
00832 p[len] = '\0';
00833 p = &p[len + 1];
00834 i++;
00835 }
00836 *p = '\0';
00837
00838 return p;
00839 }
00840
00841 int create_proc(char *path,
00842 void *child_stdin,
00843 void *child_stdout,
00844 void *child_stderr,
00845 char **envp)
00846 {
00847 TCHAR *szCmdline;
00848 PROCESS_INFORMATION piProcInfo;
00849 STARTUPINFO siStartInfo;
00850 BOOL bFuncRetn = FALSE;
00851 char env[0x1000];
00852
00853 flat_env(env, envp);
00854
00855 ZeroMemory( &piProcInfo, sizeof(PROCESS_INFORMATION) );
00856
00857
00858 ZeroMemory( &siStartInfo, sizeof(STARTUPINFO) );
00859 siStartInfo.cb = sizeof(STARTUPINFO);
00860 siStartInfo.hStdError = child_stderr;
00861 siStartInfo.hStdOutput = child_stdout;
00862 siStartInfo.hStdInput = child_stdin;
00863 siStartInfo.dwFlags |= STARTF_USESTDHANDLES;
00864
00865 szCmdline = (TCHAR *) malloc(strlen(path) + 3);
00866 sprintf(szCmdline, "\"%s\"", path);
00867
00868
00869 bFuncRetn = CreateProcess(NULL,
00870 szCmdline,
00871 NULL,
00872 NULL,
00873 TRUE,
00874 0,
00875 env,
00876 NULL,
00877 &siStartInfo,
00878 &piProcInfo);
00879
00880 free(szCmdline);
00881
00882 if (bFuncRetn == 0) return -1;
00883
00884 CloseHandle(piProcInfo.hProcess);
00885 CloseHandle(piProcInfo.hThread);
00886 return bFuncRetn;
00887 }
00888
00889 unsigned int __inline msc_clz( unsigned int x )
00890 {
00891 int r = 0;
00892 _BitScanForward(&r, x);
00893 return r;
00894 }
00895
00896 unsigned int _inline msc_clz64(unsigned long long x)
00897 {
00898 int r = 0;
00899 _BitScanForward64(&r, x);
00900 return r;
00901 }
00902 #endif
00903
00904 void replace_char(char *buf, char from, char to)
00905 {
00906 while (*buf)
00907 {
00908 if (*buf == from) *buf = to;
00909 buf++;
00910 }
00911 }
00912