/* notmuch - Not much of an email program, (just index and search) * * Copyright © 2013 Peter Wang * * 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 3 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, see http://www.gnu.org/licenses/ . * * Author: Peter Wang */ #include "notmuch-client.h" #include #include #include /* Like gethostname but guarantees that a null-terminated hostname is * returned, even if it has to make one up. * Returns true unless hostname contains a slash. */ static notmuch_bool_t safe_gethostname (char *hostname, size_t len) { if (gethostname (hostname, len) == -1) { strncpy (hostname, "unknown", len); } hostname[len - 1] = '\0'; return (strchr (hostname, '/') == NULL); } /* Open a unique file in the Maildir 'tmp' directory. * Returns the file descriptor on success, or -1 on failure. * On success, file paths for the message in the 'tmp' and 'new' * directories are returned via tmppath and newpath. */ static int maildir_open_tmp_file (void *ctx, const char *dir, char **tmppath, char **newpath) { pid_t pid; char hostname[256]; struct timeval tv; char *filename; int fd = -1; /* We follow the Dovecot file name generation algorithm. */ pid = getpid (); if (! safe_gethostname (hostname, sizeof (hostname))) { fprintf (stderr, "Error: invalid host name.\n"); return -1; } do { gettimeofday (&tv, NULL); filename = talloc_asprintf (ctx, "%ld.M%ldP%d.%s", tv.tv_sec, tv.tv_usec, pid, hostname); if (! filename) { fprintf (stderr, "Out of memory\n"); return -1; } *tmppath = talloc_asprintf (ctx, "%s/tmp/%s", dir, filename); if (! *tmppath) { fprintf (stderr, "Out of memory\n"); return -1; } fd = open (*tmppath, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, 0600); } while (fd == -1 && errno == EEXIST); if (fd == -1) { fprintf (stderr, "Error: opening %s: %s\n", *tmppath, strerror (errno)); return -1; } *newpath = talloc_asprintf (ctx, "%s/new/%s", dir, filename); if (! *newpath) { fprintf (stderr, "Out of memory\n"); close (fd); unlink (*tmppath); return -1; } talloc_free (filename); return fd; } static notmuch_bool_t insert_message (void *ctx, notmuch_database_t *notmuch, int fdin, const char *dir) { char *tmppath; char *newpath; int fdout; fdout = maildir_open_tmp_file (ctx, dir, &tmppath, &newpath); if (fdout < 0) { return FALSE; } /* For now we just delete the tmp file immediately. */ close (fdout); unlink (tmppath); return FALSE; } int notmuch_insert_command (void *ctx, int argc, char *argv[]) { notmuch_config_t *config; notmuch_database_t *notmuch; const char *db_path; char *maildir; notmuch_bool_t ret; config = notmuch_config_open (ctx, NULL, NULL); if (config == NULL) return 1; db_path = notmuch_config_get_database_path (config); maildir = talloc_asprintf (ctx, "%s", db_path); if (! maildir) { fprintf (stderr, "Out of memory\n"); return 1; } if (notmuch_database_open (notmuch_config_get_database_path (config), NOTMUCH_DATABASE_MODE_READ_WRITE, ¬much)) return 1; ret = insert_message (ctx, notmuch, STDIN_FILENO, maildir); notmuch_database_destroy (notmuch); return (ret) ? 0 : 1; }