X-Git-Url: http://git.madism.org/?p=apps%2Fmadmutt.git;a=blobdiff_plain;f=lib.c;h=1966fd63961321dc0e1e7ff67c1ec978cd6e72b0;hp=56d78b50c2685b125bc2b42b2609ae056b5cb9df;hb=a11eb994c38b1ef41ea05b56736f70cc396e0ff8;hpb=1d7238dc43311c4545883dc1151bf5b142d88c0b diff --git a/lib.c b/lib.c index 56d78b5..1966fd6 100644 --- a/lib.c +++ b/lib.c @@ -1,24 +1,12 @@ /* + * Copyright notice from original mutt: * Copyright (C) 1996-2000 Michael R. Elkins * Copyright (C) 1999-2000 Thomas Roessler - * - * This program is free software; you can redistribute it - * and/or modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later - * version. - * - * This program is distributed in the hope that it will be - * useful, but WITHOUT ANY WARRANTY; without even the implied - * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR - * PURPOSE. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public - * License along with this program; if not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111, USA. - */ + * + * This file is part of mutt-ng, see http://www.muttng.org/. + * It's licensed under the GNU General Public License, + * please see the file GPL in the top level source directory. + */ /* * This file used to contain some more functions, namely those @@ -26,6 +14,10 @@ * some of our "standard" functions in external programs, too. */ +#if HAVE_CONFIG_H +# include "config.h" +#endif + #include #include #include @@ -57,16 +49,16 @@ void *safe_calloc (size_t nmemb, size_t size) if (!nmemb || !size) return NULL; - if (((size_t) -1) / nmemb <= size) - { + if (((size_t) - 1) / nmemb <= size) { mutt_error _("Integer overflow -- can't allocate memory!"); + sleep (1); mutt_exit (1); } - - if (!(p = calloc (nmemb, size))) - { + + if (!(p = calloc (nmemb, size))) { mutt_error _("Out of memory!"); + sleep (1); mutt_exit (1); } @@ -79,9 +71,9 @@ void *safe_malloc (size_t siz) if (siz == 0) return 0; - if ((p = (void *) malloc (siz)) == 0) /* __MEM_CHECKED__ */ - { + if ((p = (void *) malloc (siz)) == 0) { /* __MEM_CHECKED__ */ mutt_error _("Out of memory!"); + sleep (1); mutt_exit (1); } @@ -91,29 +83,26 @@ void *safe_malloc (size_t siz) void safe_realloc (void *ptr, size_t siz) { void *r; - void **p = (void **)ptr; + void **p = (void **) ptr; - if (siz == 0) - { - if (*p) - { - free (*p); /* __MEM_CHECKED__ */ + if (siz == 0) { + if (*p) { + free (*p); /* __MEM_CHECKED__ */ *p = NULL; } return; } if (*p) - r = (void *) realloc (*p, siz); /* __MEM_CHECKED__ */ - else - { + r = (void *) realloc (*p, siz); /* __MEM_CHECKED__ */ + else { /* realloc(NULL, nbytes) doesn't seem to work under SunOS 4.1.x --- __MEM_CHECKED__ */ - r = (void *) malloc (siz); /* __MEM_CHECKED__ */ + r = (void *) malloc (siz); /* __MEM_CHECKED__ */ } - if (!r) - { + if (!r) { mutt_error _("Out of memory!"); + sleep (1); mutt_exit (1); } @@ -123,21 +112,21 @@ void safe_realloc (void *ptr, size_t siz) void safe_free (void *ptr) { - void **p = (void **)ptr; - if (*p) - { - free (*p); /* __MEM_CHECKED__ */ + void **p = (void **) ptr; + + if (*p) { + free (*p); /* __MEM_CHECKED__ */ *p = 0; } } -int safe_fclose (FILE **f) +int safe_fclose (FILE ** f) { int r = 0; - + if (*f) r = fclose (*f); - + *f = NULL; return r; } @@ -149,12 +138,51 @@ char *safe_strdup (const char *s) if (!s || !*s) return 0; - l = strlen (s) + 1; - p = (char *)safe_malloc (l); + l = mutt_strlen (s) + 1; + p = (char *) safe_malloc (l); memcpy (p, s, l); return (p); } +char *safe_strcat (char *d, size_t l, const char *s) +{ + char *p = d; + + if (!l) + return d; + + l--; /* Space for the trailing '\0'. */ + + for (; *d && l; l--) + d++; + for (; *s && l; l--) + *d++ = *s++; + + *d = '\0'; + + return p; +} + +char *safe_strncat (char *d, size_t l, const char *s, size_t sl) +{ + char *p = d; + + if (!l) + return d; + + l--; /* Space for the trailing '\0'. */ + + for (; *d && l; l--) + d++; + for (; *s && l && sl; l--, sl--) + *d++ = *s++; + + *d = '\0'; + + return p; +} + + void mutt_str_replace (char **p, const char *s) { FREE (p); @@ -163,8 +191,9 @@ void mutt_str_replace (char **p, const char *s) void mutt_str_adjust (char **p) { - if (!p || !*p) return; - safe_realloc (p, strlen (*p) + 1); + if (!p || !*p) + return; + safe_realloc (p, mutt_strlen (*p) + 1); } /* convert all characters in the string to lowercase */ @@ -172,8 +201,7 @@ char *mutt_strlower (char *s) { char *p = s; - while (*p) - { + while (*p) { *p = tolower ((unsigned char) *p); p++; } @@ -183,38 +211,52 @@ char *mutt_strlower (char *s) void mutt_unlink (const char *s) { + int fd; + int flags; FILE *f; - struct stat sb; + struct stat sb, sb2; char buf[2048]; - - if (stat (s, &sb) == 0) - { - if ((f = fopen (s, "r+"))) - { + + /* Defend against symlink attacks */ + +#ifdef O_NOFOLLOW + flags = O_RDWR | O_NOFOLLOW; +#else + flags = O_RDWR; +#endif + + if (lstat (s, &sb) == 0 && S_ISREG (sb.st_mode)) { + if ((fd = open (s, flags)) < 0) + return; + + if ((fstat (fd, &sb2) != 0) || !S_ISREG (sb2.st_mode) + || (sb.st_dev != sb2.st_dev) || (sb.st_ino != sb2.st_ino)) { + close (fd); + return; + } + + if ((f = fdopen (fd, "r+"))) { unlink (s); memset (buf, 0, sizeof (buf)); - while (sb.st_size > 0) - { - fwrite (buf, 1, MIN (sizeof (buf), sb.st_size), f); - sb.st_size -= MIN (sizeof (buf), sb.st_size); + while (sb.st_size > 0) { + fwrite (buf, 1, MIN (sizeof (buf), sb.st_size), f); + sb.st_size -= MIN (sizeof (buf), sb.st_size); } fclose (f); } } } -int mutt_copy_bytes (FILE *in, FILE *out, size_t size) +int mutt_copy_bytes (FILE * in, FILE * out, size_t size) { char buf[2048]; size_t chunk; - while (size > 0) - { + while (size > 0) { chunk = (size > sizeof (buf)) ? sizeof (buf) : size; if ((chunk = fread (buf, 1, chunk, in)) < 1) break; - if (fwrite (buf, 1, chunk, out) != chunk) - { + if (fwrite (buf, 1, chunk, out) != chunk) { /* dprint (1, (debugfile, "mutt_copy_bytes(): fwrite() returned short byte count\n")); */ return (-1); } @@ -224,13 +266,12 @@ int mutt_copy_bytes (FILE *in, FILE *out, size_t size) return 0; } -int mutt_copy_stream (FILE *fin, FILE *fout) +int mutt_copy_stream (FILE * fin, FILE * fout) { size_t l; char buf[LONG_STRING]; - while ((l = fread (buf, 1, sizeof (buf), fin)) > 0) - { + while ((l = fread (buf, 1, sizeof (buf), fin)) > 0) { if (fwrite (buf, 1, l, fout) != l) return (-1); } @@ -238,54 +279,50 @@ int mutt_copy_stream (FILE *fin, FILE *fout) return 0; } -static int -compare_stat (struct stat *osb, struct stat *nsb) +static int compare_stat (struct stat *osb, struct stat *nsb) { if (osb->st_dev != nsb->st_dev || osb->st_ino != nsb->st_ino || - osb->st_rdev != nsb->st_rdev) - { + osb->st_rdev != nsb->st_rdev) { return -1; } return 0; } -int safe_symlink(const char *oldpath, const char *newpath) +int safe_symlink (const char *oldpath, const char *newpath) { struct stat osb, nsb; - if(!oldpath || !newpath) + if (!oldpath || !newpath) return -1; - - if(unlink(newpath) == -1 && errno != ENOENT) + + if (unlink (newpath) == -1 && errno != ENOENT) return -1; - - if (oldpath[0] == '/') - { + + if (oldpath[0] == '/') { if (symlink (oldpath, newpath) == -1) return -1; } - else - { + else { char abs_oldpath[_POSIX_PATH_MAX]; if ((getcwd (abs_oldpath, sizeof abs_oldpath) == NULL) || - (strlen (abs_oldpath) + 1 + strlen (oldpath) + 1 > sizeof abs_oldpath)) - return -1; - - strcat (abs_oldpath, "/"); /* __STRCAT_CHECKED__ */ - strcat (abs_oldpath, oldpath); /* __STRCAT_CHECKED__ */ + (mutt_strlen (abs_oldpath) + 1 + mutt_strlen (oldpath) + 1 > + sizeof abs_oldpath)) + return -1; + + strcat (abs_oldpath, "/"); /* __STRCAT_CHECKED__ */ + strcat (abs_oldpath, oldpath); /* __STRCAT_CHECKED__ */ if (symlink (abs_oldpath, newpath) == -1) return -1; } - if(stat(oldpath, &osb) == -1 || stat(newpath, &nsb) == -1 - || compare_stat(&osb, &nsb) == -1) - { - unlink(newpath); + if (stat (oldpath, &osb) == -1 || stat (newpath, &nsb) == -1 + || compare_stat (&osb, &nsb) == -1) { + unlink (newpath); return -1; } - + return 0; } @@ -302,8 +339,7 @@ int safe_rename (const char *src, const char *target) if (!src || !target) return -1; - if (link (src, target) != 0) - { + if (link (src, target) != 0) { /* * Coda does not allow cross-directory links, but tells @@ -319,21 +355,19 @@ int safe_rename (const char *src, const char *target) if (errno == EXDEV) return rename (src, target); - + return -1; } /* * Stat both links and check if they are equal. */ - - if (stat (src, &ssb) == -1) - { + + if (stat (src, &ssb) == -1) { return -1; } - - if (stat (target, &tsb) == -1) - { + + if (stat (target, &tsb) == -1) { return -1; } @@ -342,8 +376,7 @@ int safe_rename (const char *src, const char *target) * did already exist. */ - if (compare_stat (&ssb, &tsb) == -1) - { + if (compare_stat (&ssb, &tsb) == -1) { errno = EEXIST; return -1; } @@ -363,13 +396,13 @@ int safe_open (const char *path, int flags) struct stat osb, nsb; int fd; - if ((fd = open (path, flags, 0600)) < 0) + umask (Umask); + if ((fd = open (path, flags, 0666)) < 0) return fd; /* make sure the file is not symlink */ if (lstat (path, &osb) < 0 || fstat (fd, &nsb) < 0 || - compare_stat(&osb, &nsb) == -1) - { + compare_stat (&osb, &nsb) == -1) { /* dprint (1, (debugfile, "safe_open(): %s is a symlink!\n", path)); */ close (fd); return (-1); @@ -384,9 +417,8 @@ int safe_open (const char *path, int flags) FILE *safe_fopen (const char *path, const char *mode) { /* first set the current umask */ - umask(Umask); - if (mode[0] == 'w') - { + umask (Umask); + if (mode[0] == 'w') { int fd; int flags = O_CREAT | O_EXCL; @@ -408,14 +440,15 @@ FILE *safe_fopen (const char *path, const char *mode) return (fopen (path, mode)); } -static char safe_chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+@{}._-:%/"; +static char safe_chars[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+@{}._-:%/"; void mutt_sanitize_filename (char *f, short slash) { - if (!f) return; + if (!f) + return; - for (; *f; f++) - { + for (; *f; f++) { if ((slash && *f == '/') || !strchr (safe_chars, *f)) *f = '_'; } @@ -427,18 +460,16 @@ static char rx_special_chars[] = "^.[$()|*+?{\\"; int mutt_rx_sanitize_string (char *dest, size_t destlen, const char *src) { - while (*src && --destlen > 2) - { - if (strchr (rx_special_chars, *src)) - { + while (*src && --destlen > 2) { + if (strchr (rx_special_chars, *src)) { *dest++ = '\\'; destlen--; } *dest++ = *src++; } - + *dest = '\0'; - + if (*src) return -1; else @@ -450,53 +481,47 @@ int mutt_rx_sanitize_string (char *dest, size_t destlen, const char *src) * If a line ends with "\", this char and the linefeed is removed, * and the next line is read too. */ -char *mutt_read_line (char *s, size_t *size, FILE *fp, int *line) +char *mutt_read_line (char *s, size_t * size, FILE * fp, int *line) { size_t offset = 0; char *ch; - if (!s) - { + if (!s) { s = safe_malloc (STRING); *size = STRING; } - FOREVER - { - if (fgets (s + offset, *size - offset, fp) == NULL) - { + FOREVER { + if (fgets (s + offset, *size - offset, fp) == NULL) { FREE (&s); return NULL; } - if ((ch = strchr (s + offset, '\n')) != NULL) - { + if ((ch = strchr (s + offset, '\n')) != NULL) { (*line)++; *ch = 0; if (ch > s && *(ch - 1) == '\r') - *--ch = 0; + *--ch = 0; if (ch == s || *(ch - 1) != '\\') - return s; + return s; offset = ch - s - 1; } - else - { + else { int c; - c = getc (fp); /* This is kind of a hack. We want to know if the - char at the current point in the input stream is EOF. - feof() will only tell us if we've already hit EOF, not - if the next character is EOF. So, we need to read in - the next character and manually check if it is EOF. */ - if (c == EOF) - { + + c = getc (fp); /* This is kind of a hack. We want to know if the + char at the current point in the input stream is EOF. + feof() will only tell us if we've already hit EOF, not + if the next character is EOF. So, we need to read in + the next character and manually check if it is EOF. */ + if (c == EOF) { /* The last line of fp isn't \n terminated */ (*line)++; return s; } - else - { - ungetc (c, fp); /* undo our dammage */ + else { + ungetc (c, fp); /* undo our dammage */ /* There wasn't room for the line -- increase ``s'' */ - offset = *size - 1; /* overwrite the terminating 0 */ + offset = *size - 1; /* overwrite the terminating 0 */ *size += STRING; safe_realloc (&s, *size); } @@ -504,8 +529,8 @@ char *mutt_read_line (char *s, size_t *size, FILE *fp, int *line) } } -char * -mutt_substrcpy (char *dest, const char *beg, const char *end, size_t destlen) +char *mutt_substrcpy (char *dest, const char *beg, const char *end, + size_t destlen) { size_t len; @@ -525,7 +550,7 @@ char *mutt_substrdup (const char *begin, const char *end) if (end) len = end - begin; else - len = strlen (begin); + len = mutt_strlen (begin); p = safe_malloc (len + 1); memcpy (p, begin, len); @@ -541,21 +566,18 @@ size_t mutt_quote_filename (char *d, size_t l, const char *f) { size_t i, j = 0; - if(!f) - { + if (!f) { *d = '\0'; return 0; } /* leave some space for the trailing characters. */ l -= 6; - + d[j++] = '\''; - - for(i = 0; j < l && f[i]; i++) - { - if(f[i] == '\'' || f[i] == '`') - { + + for (i = 0; j < l && f[i]; i++) { + if (f[i] == '\'' || f[i] == '`') { d[j++] = '\''; d[j++] = '\\'; d[j++] = f[i]; @@ -564,43 +586,43 @@ size_t mutt_quote_filename (char *d, size_t l, const char *f) else d[j++] = f[i]; } - + d[j++] = '\''; - d[j] = '\0'; - + d[j] = '\0'; + return j; } /* NULL-pointer aware string comparison functions */ -int mutt_strcmp(const char *a, const char *b) +int mutt_strcmp (const char *a, const char *b) { - return strcmp(NONULL(a), NONULL(b)); + return strcmp (NONULL (a), NONULL (b)); } -int mutt_strcasecmp(const char *a, const char *b) +int mutt_strcasecmp (const char *a, const char *b) { - return strcasecmp(NONULL(a), NONULL(b)); + return strcasecmp (NONULL (a), NONULL (b)); } -int mutt_strncmp(const char *a, const char *b, size_t l) +int mutt_strncmp (const char *a, const char *b, size_t l) { - return strncmp(NONULL(a), NONULL(b), l); + return strncmp (NONULL (a), NONULL (b), l); } -int mutt_strncasecmp(const char *a, const char *b, size_t l) +int mutt_strncasecmp (const char *a, const char *b, size_t l) { - return strncasecmp(NONULL(a), NONULL(b), l); + return strncasecmp (NONULL (a), NONULL (b), l); } -size_t mutt_strlen(const char *a) +size_t mutt_strlen (const char *a) { return a ? strlen (a) : 0; } -int mutt_strcoll(const char *a, const char *b) +int mutt_strcoll (const char *a, const char *b) { - return strcoll(NONULL(a), NONULL(b)); + return strcoll (NONULL (a), NONULL (b)); } const char *mutt_stristr (const char *haystack, const char *needle) @@ -612,13 +634,11 @@ const char *mutt_stristr (const char *haystack, const char *needle) if (!needle) return (haystack); - while (*(p = haystack)) - { + while (*(p = haystack)) { for (q = needle; *p && *q && - tolower ((unsigned char) *p) == tolower ((unsigned char) *q); - p++, q++) - ; + tolower ((unsigned char) *p) == tolower ((unsigned char) *q); + p++, q++); if (!*q) return (haystack); haystack++; @@ -635,18 +655,18 @@ char *mutt_skip_whitespace (char *p) void mutt_remove_trailing_ws (char *s) { char *p; - - for (p = s + mutt_strlen (s) - 1 ; p >= s && ISSPACE (*p) ; p--) + + for (p = s + mutt_strlen (s) - 1; p >= s && ISSPACE (*p); p--) *p = 0; } char *mutt_concat_path (char *d, const char *dir, const char *fname, size_t l) { const char *fmt = "%s/%s"; - - if (!*fname || (*dir && dir[strlen(dir)-1] == '/')) + + if (!*fname || (*dir && dir[mutt_strlen (dir) - 1] == '/')) fmt = "%s%s"; - + snprintf (d, l, fmt, dir, fname); return d; } @@ -654,6 +674,7 @@ char *mutt_concat_path (char *d, const char *dir, const char *fname, size_t l) const char *mutt_basename (const char *f) { const char *p = strrchr (f, '/'); + if (p) return p + 1; else