/*
- * Copyright (C) 1996-2000 Michael R. Elkins <me@mutt.org>
- * Copyright (C) 1999-2000 Thomas Roessler <roessler@does-not-exist.org>
+ * Copyright (C) 1996-2000,2007 Michael R. Elkins <me@mutt.org>
+ * Copyright (C) 1999-2004,2006-7 Thomas Roessler <roessler@does-not-exist.org>
*
* This program is free software; you can redistribute it
* and/or modify it under the terms of the GNU General Public
#include <sys/stat.h>
#include <fcntl.h>
#include <pwd.h>
+#include <sys/types.h>
+#include <dirent.h>
#ifdef HAVE_SYSEXITS_H
#include <sysexits.h>
return r;
}
+int safe_fsync_close (FILE **f)
+{
+ int r = 0;
+
+ if (*f)
+ {
+ if (fflush (*f) || fsync (fileno (*f)))
+ {
+ r = -1;
+ safe_fclose (f);
+ }
+ else
+ r = safe_fclose (f);
+ }
+
+ return r;
+}
+
char *safe_strdup (const char *s)
{
char *p;
fwrite (buf, 1, MIN (sizeof (buf), sb.st_size), f);
sb.st_size -= MIN (sizeof (buf), sb.st_size);
}
- fclose (f);
+ safe_fclose (&f);
}
}
}
/* Create a temporary directory next to a file name */
-int mutt_mkwrapdir (const char *path, char *newfile, size_t nflen,
+static int mutt_mkwrapdir (const char *path, char *newfile, size_t nflen,
char *newdir, size_t ndlen)
{
const char *basename;
return 0;
}
-int mutt_put_file_in_place (const char *path, const char *safe_file, const char *safe_dir)
+/* remove a directory and everything under it */
+int mutt_rmtree (const char* path)
+{
+ DIR* dirp;
+ struct dirent* de;
+ char cur[_POSIX_PATH_MAX];
+ struct stat statbuf;
+ int rc = 0;
+
+ if (!(dirp = opendir (path)))
+ {
+ dprint (1, (debugfile, "mutt_rmtree: error opening directory %s\n", path));
+ return -1;
+ }
+ while ((de = readdir (dirp)))
+ {
+ if (!strcmp (".", de->d_name) || !strcmp ("..", de->d_name))
+ continue;
+
+ snprintf (cur, sizeof (cur), "%s/%s", path, de->d_name);
+ /* XXX make nonrecursive version */
+
+ if (stat(cur, &statbuf) == -1)
+ {
+ rc = 1;
+ continue;
+ }
+
+ if (S_ISDIR (statbuf.st_mode))
+ rc |= mutt_rmtree (cur);
+ else
+ rc |= unlink (cur);
+ }
+ closedir (dirp);
+
+ rc |= rmdir (path);
+
+ return rc;
+}
+
+static int mutt_put_file_in_place (const char *path, const char *safe_file, const char *safe_dir)
{
int rv;
* 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, int flags)
{
size_t offset = 0;
char *ch;
}
if ((ch = strchr (s + offset, '\n')) != NULL)
{
- (*line)++;
+ if (line)
+ (*line)++;
+ if (flags & M_EOL)
+ return s;
*ch = 0;
if (ch > s && *(ch - 1) == '\r')
*--ch = 0;
- if (ch == s || *(ch - 1) != '\\')
+ if (!(flags & M_CONT) || ch == s || *(ch - 1) != '\\')
return s;
offset = ch - s - 1;
}
if (c == EOF)
{
/* The last line of fp isn't \n terminated */
- (*line)++;
+ if (line)
+ (*line)++;
return s;
}
else
return sysexits_h[i].str;
}
+
+void mutt_debug (FILE *fp, const char *fmt, ...)
+{
+ va_list ap;
+ time_t now = time (NULL);
+ static char buf[23] = "";
+ static time_t last = 0;
+
+ if (now > last)
+ {
+ strftime (buf, sizeof (buf), "%Y-%m-%d %H:%M:%S", localtime (&now));
+ last = now;
+ }
+ fprintf (fp, "[%s] ", buf);
+ va_start (ap, fmt);
+ vfprintf (fp, fmt, ap);
+ va_end (ap);
+}
+
+int mutt_atos (const char *str, short *dst)
+{
+ int rc;
+ long res;
+ short tmp;
+ short *t = dst ? dst : &tmp;
+
+ *t = 0;
+
+ if ((rc = mutt_atol (str, &res)) < 0)
+ return rc;
+ if ((short) res != res)
+ return -2;
+
+ *t = (short) res;
+ return 0;
+}
+
+int mutt_atoi (const char *str, int *dst)
+{
+ int rc;
+ long res;
+ int tmp;
+ int *t = dst ? dst : &tmp;
+
+ *t = 0;
+
+ if ((rc = mutt_atol (str, &res)) < 0)
+ return rc;
+ if ((int) res != res)
+ return -2;
+
+ *t = (int) res;
+ return 0;
+}
+
+int mutt_atol (const char *str, long *dst)
+{
+ long r;
+ long *res = dst ? dst : &r;
+ char *e = NULL;
+
+ /* no input: 0 */
+ if (!str || !*str)
+ {
+ *res = 0;
+ return 0;
+ }
+
+ *res = strtol (str, &e, 10);
+ if ((*res == LONG_MAX && errno == ERANGE) ||
+ (e && *e != '\0'))
+ return -1;
+ return 0;
+}