X-Git-Url: http://git.madism.org/?p=apps%2Fmadmutt.git;a=blobdiff_plain;f=lib.c;h=4f1fee35ad93496eccf43d0b39aa16e1bb073f9f;hp=56d78b50c2685b125bc2b42b2609ae056b5cb9df;hb=c25bc063f35aaad6938c2022dae7a283346c2769;hpb=1d7238dc43311c4545883dc1151bf5b142d88c0b diff --git a/lib.c b/lib.c index 56d78b5..4f1fee3 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 @@ -36,10 +28,76 @@ #include #include +#ifdef HAVE_SYSEXITS_H +#include +#else /* Make sure EX_OK is defined */ +#define EX_OK 0 +#endif + #include "lib.h" +#include "lib/mem.h" +#include "lib/str.h" +#include "lib/debug.h" + extern short Umask; +static struct sysexits +{ + int v; + const char *str; +} +sysexits_h[] = +{ +#ifdef EX_USAGE + { 0xff & EX_USAGE, "Bad usage." }, +#endif +#ifdef EX_DATAERR + { 0xff & EX_DATAERR, "Data format error." }, +#endif +#ifdef EX_NOINPUT + { 0xff & EX_NOINPUT, "Cannot open input." }, +#endif +#ifdef EX_NOUSER + { 0xff & EX_NOUSER, "User unknown." }, +#endif +#ifdef EX_NOHOST + { 0xff & EX_NOHOST, "Host unknown." }, +#endif +#ifdef EX_UNAVAILABLE + { 0xff & EX_UNAVAILABLE, "Service unavailable." }, +#endif +#ifdef EX_SOFTWARE + { 0xff & EX_SOFTWARE, "Internal error." }, +#endif +#ifdef EX_OSERR + { 0xff & EX_OSERR, "Operating system error." }, +#endif +#ifdef EX_OSFILE + { 0xff & EX_OSFILE, "System file missing." }, +#endif +#ifdef EX_CANTCREAT + { 0xff & EX_CANTCREAT, "Can't create output." }, +#endif +#ifdef EX_IOERR + { 0xff & EX_IOERR, "I/O error." }, +#endif +#ifdef EX_TEMPFAIL + { 0xff & EX_TEMPFAIL, "Deferred." }, +#endif +#ifdef EX_PROTOCOL + { 0xff & EX_PROTOCOL, "Remote protocol error." }, +#endif +#ifdef EX_NOPERM + { 0xff & EX_NOPERM, "Insufficient permission." }, +#endif +#ifdef EX_CONFIG + { 0xff & EX_NOPERM, "Local configuration error." }, +#endif + { S_ERR, "Exec error." }, + { -1, NULL} +}; + void mutt_nocurses_error (const char *fmt, ...) { va_list ap; @@ -50,172 +108,66 @@ void mutt_nocurses_error (const char *fmt, ...) fputc ('\n', stderr); } -void *safe_calloc (size_t nmemb, size_t size) -{ - void *p; - - if (!nmemb || !size) - return NULL; - - if (((size_t) -1) / nmemb <= size) - { - mutt_error _("Integer overflow -- can't allocate memory!"); - sleep (1); - mutt_exit (1); - } - - if (!(p = calloc (nmemb, size))) - { - mutt_error _("Out of memory!"); - sleep (1); - mutt_exit (1); - } - return p; -} - -void *safe_malloc (size_t siz) -{ - void *p; - - if (siz == 0) - return 0; - if ((p = (void *) malloc (siz)) == 0) /* __MEM_CHECKED__ */ - { - mutt_error _("Out of memory!"); - sleep (1); - mutt_exit (1); - } - return (p); -} - -void safe_realloc (void *ptr, size_t siz) -{ - void *r; - void **p = (void **)ptr; - - if (siz == 0) - { - if (*p) - { - free (*p); /* __MEM_CHECKED__ */ - *p = NULL; - } - return; - } - - if (*p) - 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__ */ - } - - if (!r) - { - mutt_error _("Out of memory!"); - sleep (1); - mutt_exit (1); - } - - *p = r; -} - -void safe_free (void *ptr) -{ - 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; } -char *safe_strdup (const char *s) -{ - char *p; - size_t l; - - if (!s || !*s) - return 0; - l = strlen (s) + 1; - p = (char *)safe_malloc (l); - memcpy (p, s, l); - return (p); -} - -void mutt_str_replace (char **p, const char *s) +void mutt_unlink (const char *s) { - FREE (p); - *p = safe_strdup (s); -} + int fd; + int flags; + FILE *f; + struct stat sb, sb2; + char buf[2048]; -void mutt_str_adjust (char **p) -{ - if (!p || !*p) return; - safe_realloc (p, strlen (*p) + 1); -} + /* Defend against symlink attacks */ -/* convert all characters in the string to lowercase */ -char *mutt_strlower (char *s) -{ - char *p = s; +#ifdef O_NOFOLLOW + flags = O_RDWR | O_NOFOLLOW; +#else + flags = O_RDWR; +#endif - while (*p) - { - *p = tolower ((unsigned char) *p); - p++; - } + if (lstat (s, &sb) == 0 && S_ISREG (sb.st_mode)) { + if ((fd = open (s, flags)) < 0) + return; - return (s); -} + 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; + } -void mutt_unlink (const char *s) -{ - FILE *f; - struct stat sb; - char buf[2048]; - - if (stat (s, &sb) == 0) - { - if ((f = fopen (s, "r+"))) - { + 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) - { - /* dprint (1, (debugfile, "mutt_copy_bytes(): fwrite() returned short byte count\n")); */ + if (fwrite (buf, 1, chunk, out) != chunk) { + debug_print (1, ("fwrite() returned short byte count\n")); return (-1); } size -= chunk; @@ -224,13 +176,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 +189,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__ */ + (str_len (abs_oldpath) + 1 + str_len (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 +249,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 +265,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 +286,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,14 +306,14 @@ 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) - { -/* dprint (1, (debugfile, "safe_open(): %s is a symlink!\n", path)); */ + compare_stat (&osb, &nsb) == -1) { + debug_print (1, ("%s is a symlink!\n", path)); close (fd); return (-1); } @@ -384,9 +327,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 +350,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 +370,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,89 +391,54 @@ 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) - { - s = safe_malloc (STRING); + if (!s) { + s = mem_malloc (STRING); *size = STRING; } - FOREVER - { - if (fgets (s + offset, *size - offset, fp) == NULL) - { - FREE (&s); + FOREVER { + if (fgets (s + offset, *size - offset, fp) == NULL) { + mem_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); + mem_realloc (&s, *size); } } } } -char * -mutt_substrcpy (char *dest, const char *beg, const char *end, size_t destlen) -{ - size_t len; - - len = end - beg; - if (len > destlen - 1) - len = destlen - 1; - memcpy (dest, beg, len); - dest[len] = 0; - return dest; -} - -char *mutt_substrdup (const char *begin, const char *end) -{ - size_t len; - char *p; - - if (end) - len = end - begin; - else - len = strlen (begin); - - p = safe_malloc (len + 1); - memcpy (p, begin, len); - p[len] = 0; - return p; -} - /* prepare a file name to survive the shell's quoting rules. * From the Unix programming FAQ by way of Liviu. */ @@ -541,21 +447,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,89 +467,20 @@ size_t mutt_quote_filename (char *d, size_t l, const char *f) else d[j++] = f[i]; } - - d[j++] = '\''; - d[j] = '\0'; - - return j; -} - -/* NULL-pointer aware string comparison functions */ - -int mutt_strcmp(const char *a, const char *b) -{ - return strcmp(NONULL(a), NONULL(b)); -} - -int mutt_strcasecmp(const char *a, const char *b) -{ - return strcasecmp(NONULL(a), NONULL(b)); -} - -int mutt_strncmp(const char *a, const char *b, size_t l) -{ - return strncmp(NONULL(a), NONULL(b), l); -} - -int mutt_strncasecmp(const char *a, const char *b, size_t l) -{ - return strncasecmp(NONULL(a), NONULL(b), l); -} - -size_t mutt_strlen(const char *a) -{ - return a ? strlen (a) : 0; -} - -int mutt_strcoll(const char *a, const char *b) -{ - return strcoll(NONULL(a), NONULL(b)); -} - -const char *mutt_stristr (const char *haystack, const char *needle) -{ - const char *p, *q; - if (!haystack) - return NULL; - if (!needle) - return (haystack); - - while (*(p = haystack)) - { - for (q = needle; - *p && *q && - tolower ((unsigned char) *p) == tolower ((unsigned char) *q); - p++, q++) - ; - if (!*q) - return (haystack); - haystack++; - } - return NULL; -} - -char *mutt_skip_whitespace (char *p) -{ - SKIPWS (p); - return p; -} + d[j++] = '\''; + d[j] = '\0'; -void mutt_remove_trailing_ws (char *s) -{ - char *p; - - for (p = s + mutt_strlen (s) - 1 ; p >= s && ISSPACE (*p) ; p--) - *p = 0; + return j; } 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[str_len (dir) - 1] == '/')) fmt = "%s%s"; - + snprintf (d, l, fmt, dir, fname); return d; } @@ -654,8 +488,23 @@ 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 return f; } + +const char * +mutt_strsysexit(int e) +{ + int i; + + for(i = 0; sysexits_h[i].str; i++) + { + if(e == sysexits_h[i].v) + break; + } + + return sysexits_h[i].str; +}