00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00038 #include <string.h>
00039 #ifdef WIN32
00040 #include "process.h"
00041 #define pid_t int
00042 #else
00043 #include <ctype.h>
00044 #include <errno.h>
00045 #include <sys/stat.h>
00046 #include <sys/wait.h>
00047
00048 #include <sys/param.h>
00049 #include <stdio.h>
00050
00051
00052
00053 #include <autoconf.h>
00054 #endif
00055
00056 #ifdef HAVE_STDLIB_H
00057 #include <stdlib.h>
00058 #endif
00059
00060 #ifdef HAVE_UNISTD_H
00061 #include <unistd.h>
00062 #endif
00063
00064 #include <stdarg.h>
00065
00066 #include "global.h"
00067
00069 static unsigned int curtmp = 0;
00070
00071
00072
00073
00074
00087 char *tempnam_local(const char *dir, const char *pfx) {
00088 char *name;
00089 pid_t pid = getpid();
00090
00091
00092 #ifndef MAXPATHLEN
00093 #define MAXPATHLEN 4096
00094 #endif
00095
00096 if (!pfx)
00097 pfx = "cftmp.";
00098
00099
00100
00101
00102
00103
00104 if (dir != NULL) {
00105 if (!(name = (char *)malloc(MAXPATHLEN)))
00106 return(NULL);
00107 do {
00108 #ifdef HAVE_SNPRINTF
00109 (void)snprintf(name, MAXPATHLEN, "%s/%s%hx.%u", dir, pfx, pid, curtmp);
00110 #else
00111 (void)sprintf(name, "%s/%s%hx%u", dir, pfx, pid, curtmp);
00112 #endif
00113 curtmp++;
00114 } while (access(name, F_OK) != -1);
00115 return(name);
00116 }
00117 return(NULL);
00118 }
00119
00143 FILE *tempnam_secure(const char *dir, const char *pfx, char **filename) {
00144 char *tempname = NULL;
00145 int fd;
00146 int i;
00147 FILE *file = NULL;
00148 #define MAXTMPRETRY 10
00149
00150
00151 for (i = 0; i < MAXTMPRETRY; i++) {
00152 tempname = tempnam_local(dir, pfx);
00153
00154
00155
00156 if (!tempname)
00157 return NULL;
00158
00159 fd = open(tempname, O_CREAT|O_EXCL|O_RDWR, S_IRUSR|S_IWUSR);
00160 if (fd != -1)
00161 break;
00162 if (errno == EEXIST)
00163 LOG(llevError, "Created file detected in tempnam_secure. Someone hoping for a race condition?\n");
00164 free(tempname);
00165 }
00166
00167 if (fd == -1)
00168 return NULL;
00169
00170 file = fdopen(fd, "w+");
00171 if (!file) {
00172 LOG(llevError, "fdopen() failed in tempnam_secure()!\n");
00173 free(tempname);
00174 return NULL;
00175 }
00176
00177 *filename = tempname;
00178 return file;
00179 }
00180
00192 void remove_directory(const char *path) {
00193 DIR *dirp;
00194 char buf[MAX_BUF];
00195 struct stat statbuf;
00196 int status;
00197
00198 if ((dirp = opendir(path)) != NULL) {
00199 struct dirent *de;
00200
00201 for (de = readdir(dirp); de; de = readdir(dirp)) {
00202
00203
00204
00205
00206 if (de->d_name[0] == '.')
00207 continue;
00208
00209
00210
00211
00212 status = stat(de->d_name, &statbuf);
00213 if ((status != -1) && (S_ISDIR(statbuf.st_mode))) {
00214 snprintf(buf, sizeof(buf), "%s/%s", path, de->d_name);
00215 remove_directory(buf);
00216 continue;
00217 }
00218 snprintf(buf, sizeof(buf), "%s/%s", path, de->d_name);
00219 if (unlink(buf)) {
00220 LOG(llevError, "Unable to remove %s\n", path);
00221 }
00222 }
00223 closedir(dirp);
00224 }
00225 if (rmdir(path)) {
00226 LOG(llevError, "Unable to remove directory %s\n", path);
00227 }
00228 }
00229
00230 #if defined(sgi)
00231
00232 #include <stdio.h>
00233 #include <stdlib.h>
00234 #include <string.h>
00235
00236 #define popen fixed_popen
00237
00253 FILE *popen_local(const char *command, const char *type) {
00254 int fd[2];
00255 int pd;
00256 FILE *ret;
00257 if (!strcmp(type, "r")) {
00258 pd = STDOUT_FILENO;
00259 } else if (!strcmp(type, "w")) {
00260 pd = STDIN_FILENO;
00261 } else {
00262 return NULL;
00263 }
00264 if (pipe(fd) != -1) {
00265 switch (fork()) {
00266 case -1:
00267 close(fd[0]);
00268 close(fd[1]);
00269 break;
00270
00271 case 0:
00272 close(fd[0]);
00273 if ((fd[1] == pd) || (dup2(fd[1], pd) == pd)) {
00274 if (fd[1] != pd) {
00275 close(fd[1]);
00276 }
00277 execl("/bin/sh", "sh", "-c", command, NULL);
00278 close(pd);
00279 }
00280 exit(1);
00281 break;
00282
00283 default:
00284 close(fd[1]);
00285 if (ret = fdopen(fd[0], type)) {
00286 return ret;
00287 }
00288 close(fd[0]);
00289 break;
00290 }
00291 }
00292 return NULL;
00293 }
00294
00295 #endif
00296
00297
00298
00299
00300
00310 char *strdup_local(const char *str) {
00311 char *c = (char *)malloc(strlen(str)+1);
00312 if (c != NULL)
00313 strcpy(c, str);
00314 return c;
00315 }
00316
00318 #define DIGIT(x) (isdigit(x) ? (x)-'0' : \
00319 islower(x) ? (x)+10-'a' : (x)+10-'A')
00320 #define MBASE ('z'-'a'+1+10)
00321
00322 #if !defined(HAVE_STRTOL)
00323
00339 long strtol(register char *str, char **ptr, register int base) {
00340 register long val;
00341 register int c;
00342 int xx, neg = 0;
00343
00344 if (ptr != (char **)0)
00345 *ptr = str;
00346 if (base < 0 || base > MBASE)
00347 return (0);
00348 if (!isalnum(c = *str)) {
00349 while (isspace(c))
00350 c = *++str;
00351 switch (c) {
00352 case '-':
00353 neg++;
00354 case '+':
00355 c = *++str;
00356 }
00357 }
00358 if (base == 0) {
00359 if (c != '0')
00360 base = 10;
00361 else {
00362 if (str[1] == 'x' || str[1] == 'X')
00363 base = 16;
00364 else
00365 base = 8;
00366 }
00367 }
00368
00369
00370
00371
00372 if (!isalnum(c) || (xx = DIGIT(c)) >= base)
00373 return 0;
00374 if (base == 16 && c == '0' && isxdigit(str[2]) && (str[1] == 'x' || str[1] == 'X'))
00375 c = *(str += 2);
00376 for (val = -DIGIT(c); isalnum(c = *++str) && (xx = DIGIT(c)) < base; )
00377
00378
00379 val = base*val-xx;
00380 if (ptr != (char **)0)
00381 *ptr = str;
00382 return (neg ? val : -val);
00383 }
00384 #endif
00385
00401 #if !defined(HAVE_STRNCASECMP)
00402 int strncasecmp(const char *s1, const char *s2, int n) {
00403 register int c1, c2;
00404
00405 while (*s1 && *s2 && n) {
00406 c1 = tolower(*s1);
00407 c2 = tolower(*s2);
00408 if (c1 != c2)
00409 return (c1-c2);
00410 s1++;
00411 s2++;
00412 n--;
00413 }
00414 if (!n)
00415 return (0);
00416 return (int)(*s1-*s2);
00417 }
00418 #endif
00419
00420 #if !defined(HAVE_STRCASECMP)
00421
00434 int strcasecmp(const char *s1, const char *s2) {
00435 register int c1, c2;
00436
00437 while (*s1 && *s2) {
00438 c1 = tolower(*s1);
00439 c2 = tolower(*s2);
00440 if (c1 != c2)
00441 return (c1-c2);
00442 s1++;
00443 s2++;
00444 }
00445 if (*s1 == '\0' && *s2 == '\0')
00446 return 0;
00447 return (int)(*s1-*s2);
00448 }
00449 #endif
00450
00461 const char *strcasestr_local(const char *s, const char *find) {
00462 char c, sc;
00463 size_t len;
00464
00465 if ((c = *find++) != 0) {
00466 c = tolower(c);
00467 len = strlen(find);
00468 do {
00469 do {
00470 if ((sc = *s++) == 0)
00471 return NULL;
00472 } while (tolower(sc) != c);
00473 } while (strncasecmp(s, find, len) != 0);
00474 s--;
00475 }
00476 return s;
00477 }
00478
00479 #if !defined(HAVE_SNPRINTF)
00480
00498 int snprintf(char *dest, int max, const char *format, ...) {
00499 va_list var;
00500 int ret;
00501
00502 va_start(var, format);
00503 ret = vsprintf(dest, format, var);
00504 va_end(var);
00505 if (ret > max)
00506 abort();
00507
00508 return ret;
00509 }
00510 #endif
00511
00525 char *strerror_local(int errnum, char *buf, size_t size) {
00526 #if defined(HAVE_STRERROR_R)
00527
00528 # if defined(STRERROR_R_CHAR_P)
00529 char *bbuf;
00530
00531 buf[0] = 0;
00532 bbuf = (char *)strerror_r(errnum, buf, size);
00533 if ((buf[0] == 0) && (bbuf != NULL))
00534 strncpy(buf, bbuf, size);
00535 # else
00536 if (strerror_r(errnum, buf, size) != 0) {
00537
00538 if (errno == ERANGE) {
00539 strncat(buf, "Too small buffer.", size);
00540 } else if (errno == EINVAL) {
00541 strncat(buf, "Error number invalid.", size);
00542 }
00543 }
00544 # endif
00545
00546 #else
00547
00548 # if defined(HAVE_STRERROR)
00549 snprintf(buf, size, "%s", strerror(errnum));
00550 # else
00551 # error If this is C89 the compiler should have strerror!;
00552 # endif
00553 #endif
00554 return buf;
00555 }
00556
00573 int isqrt(int n) {
00574 int result, sum, prev;
00575
00576 result = 0;
00577 prev = sum = 1;
00578 while (sum <= n) {
00579 prev += 2;
00580 sum += prev;
00581 ++result;
00582 }
00583 return result;
00584 }
00585
00593 const char *uncomp[NROF_COMPRESS_METHODS][3] = {
00594 { NULL, NULL, NULL },
00595 { ".Z", UNCOMPRESS, COMPRESS },
00596 { ".gz", GUNZIP, GZIP },
00597 { ".bz2", BUNZIP, BZIP }
00598 };
00599
00621 static FILE *open_and_uncompress_file(const char *ext, const char *uncompressor, const char *name, int flag, int *compressed) {
00622 struct stat st;
00623 char buf[MAX_BUF];
00624 char buf2[MAX_BUF];
00625 int ret;
00626
00627 if (ext == NULL) {
00628 ext = "";
00629 }
00630
00631 if (strlen(name)+strlen(ext) >= sizeof(buf)) {
00632 errno = ENAMETOOLONG;
00633 return NULL;
00634 }
00635 snprintf(buf, sizeof(buf), "%s%s", name, ext);
00636
00637 if (stat(buf, &st) != 0) {
00638 return NULL;
00639 }
00640
00641 if (!S_ISREG(st.st_mode)) {
00642 errno = EISDIR;
00643 return NULL;
00644 }
00645
00646 if (uncompressor == NULL) {
00647
00648 return fopen(buf, "rb");
00649 }
00650
00651
00652
00653
00654
00655 if (strpbrk(buf, "'\\\r\n") != NULL) {
00656 errno = ENOENT;
00657 return NULL;
00658 }
00659
00660 if (!flag) {
00661
00662
00663 if (strlen(uncompressor)+4+strlen(buf)+1 >= sizeof(buf2)) {
00664 errno = ENAMETOOLONG;
00665 return NULL;
00666 }
00667 snprintf(buf2, sizeof(buf2), "%s < '%s'", uncompressor, buf);
00668 return popen(buf2, "r");
00669 }
00670
00671
00672
00673 if (stat(name, &st) == 0 && !S_ISREG(st.st_mode)) {
00674 errno = EISDIR;
00675 return NULL;
00676 }
00677
00678 if (strlen(uncompressor)+4+strlen(buf)+5+strlen(name)+1 >= sizeof(buf2)) {
00679 errno = ENAMETOOLONG;
00680 return NULL;
00681 }
00682 snprintf(buf2, sizeof(buf2), "%s < '%s' > '%s'", uncompressor, buf, name);
00683
00684 ret = system(buf2);
00685 if (!WIFEXITED(ret) || WEXITSTATUS(ret) != 0) {
00686 LOG(llevError, "system(%s) returned %d\n", buf2, ret);
00687 errno = ENOENT;
00688 return NULL;
00689 }
00690
00691 unlink(buf);
00692 *compressed = 0;
00693 chmod(name, st.st_mode);
00694
00695 return fopen(name, "rb");
00696 }
00697
00724 FILE *open_and_uncompress(const char *name, int flag, int *compressed) {
00725 size_t i;
00726 FILE *fp;
00727
00728 for (i = 0; i < NROF_COMPRESS_METHODS; i++) {
00729 *compressed = i;
00730 fp = open_and_uncompress_file(uncomp[i][0], uncomp[i][1], name, flag, compressed);
00731 if (fp != NULL) {
00732 return fp;
00733 }
00734 }
00735
00736 errno = ENOENT;
00737 return NULL;
00738 }
00739
00748 void close_and_delete(FILE *fp, int compressed) {
00749 if (compressed)
00750 pclose(fp);
00751 else
00752 fclose(fp);
00753 }
00754
00764 void make_path_to_file(const char *filename) {
00765 char buf[MAX_BUF], *cp = buf;
00766 struct stat statbuf;
00767
00768 if (!filename || !*filename)
00769 return;
00770
00771 strcpy(buf, filename);
00772 LOG(llevDebug, "make_path_tofile %s...\n", filename);
00773 while ((cp = strchr(cp+1, (int)'/'))) {
00774 *cp = '\0';
00775 if (stat(buf, &statbuf) || !S_ISDIR(statbuf.st_mode)) {
00776 LOG(llevDebug, "Was not dir: %s\n", buf);
00777 if (mkdir(buf, SAVE_DIR_MODE)) {
00778 char err[MAX_BUF];
00779
00780 LOG(llevError, "Cannot mkdir %s: %s\n", buf, strerror_local(errno, err, sizeof(err)));
00781 return;
00782 }
00783 }
00784 *cp = '/';
00785 }
00786 }