Merge branch 'procmule'
This commit is contained in:
@ -271,6 +271,7 @@ toys/Makefile
|
|||||||
toys/mug/Makefile
|
toys/mug/Makefile
|
||||||
toys/mug2/Makefile
|
toys/mug2/Makefile
|
||||||
toys/muile/Makefile
|
toys/muile/Makefile
|
||||||
|
toys/procmule/Makefile
|
||||||
man/Makefile
|
man/Makefile
|
||||||
m4/Makefile
|
m4/Makefile
|
||||||
contrib/Makefile
|
contrib/Makefile
|
||||||
|
|||||||
@ -36,6 +36,8 @@ libmuguile_la_SOURCES= \
|
|||||||
mu-guile-msg.h \
|
mu-guile-msg.h \
|
||||||
mu-guile-store.c \
|
mu-guile-store.c \
|
||||||
mu-guile-store.h \
|
mu-guile-store.h \
|
||||||
|
mu-guile-log.c \
|
||||||
|
mu-guile-log.h \
|
||||||
mu-guile-common.c \
|
mu-guile-common.c \
|
||||||
mu-guile-common.h
|
mu-guile-common.h
|
||||||
|
|
||||||
@ -45,7 +47,8 @@ libmuguile_la_LIBADD= \
|
|||||||
|
|
||||||
XFILES= \
|
XFILES= \
|
||||||
mu-guile-msg.x \
|
mu-guile-msg.x \
|
||||||
mu-guile-store.x
|
mu-guile-store.x \
|
||||||
|
mu-guile-log.x
|
||||||
|
|
||||||
BUILT_SOURCES=$(XFILES)
|
BUILT_SOURCES=$(XFILES)
|
||||||
|
|
||||||
|
|||||||
@ -21,6 +21,9 @@
|
|||||||
#endif /*HAVE_CONFIG_H*/
|
#endif /*HAVE_CONFIG_H*/
|
||||||
|
|
||||||
#include "mu-guile-common.h"
|
#include "mu-guile-common.h"
|
||||||
|
#include "mu-guile-store.h"
|
||||||
|
#include "mu-guile-msg.h"
|
||||||
|
#include "mu-guile-log.h"
|
||||||
|
|
||||||
void
|
void
|
||||||
mu_guile_error (const char *func_name, int status,
|
mu_guile_error (const char *func_name, int status,
|
||||||
@ -45,6 +48,15 @@ mu_guile_g_error (const char *func_name, GError *err)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
mu_guile_init (void)
|
||||||
|
{
|
||||||
|
scm_with_guile (&mu_guile_msg_init, NULL);
|
||||||
|
scm_with_guile (&mu_guile_store_init, NULL);
|
||||||
|
scm_with_guile (&mu_guile_log_init, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* backward compat for pre-2.x guile - note, this will fail miserably
|
* backward compat for pre-2.x guile - note, this will fail miserably
|
||||||
* if you don't use a UTF8 locale
|
* if you don't use a UTF8 locale
|
||||||
|
|||||||
@ -17,8 +17,8 @@
|
|||||||
**
|
**
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __MU_GUILE_UTILS_H__
|
#ifndef __MU_GUILE_COMMON_H__
|
||||||
#define __MU_GUILE_UTILS_H__
|
#define __MU_GUILE_COMMON_H__
|
||||||
|
|
||||||
#include <libguile.h>
|
#include <libguile.h>
|
||||||
|
|
||||||
@ -30,8 +30,8 @@
|
|||||||
|
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* output an error
|
||||||
*
|
*
|
||||||
* @param func_name
|
* @param func_name
|
||||||
* @param status
|
* @param status
|
||||||
@ -42,7 +42,7 @@ void mu_guile_error (const char *func_name, int status,
|
|||||||
const char *fmt, SCM args);
|
const char *fmt, SCM args);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* display a GError as a Guile error
|
* display a GError as a Guile error
|
||||||
*
|
*
|
||||||
* @param func_name function name
|
* @param func_name function name
|
||||||
@ -50,6 +50,14 @@ void mu_guile_error (const char *func_name, int status,
|
|||||||
*/
|
*/
|
||||||
void mu_guile_g_error (const char *func_name, GError *err);
|
void mu_guile_g_error (const char *func_name, GError *err);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* initialize the mu guile modules
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void mu_guile_init (void);
|
||||||
|
|
||||||
|
|
||||||
/* compatibility functions for old guile */
|
/* compatibility functions for old guile */
|
||||||
#if HAVE_PRE2_GUILE
|
#if HAVE_PRE2_GUILE
|
||||||
SCM scm_from_utf8_string (const char* str);
|
SCM scm_from_utf8_string (const char* str);
|
||||||
@ -58,5 +66,5 @@ char* scm_to_utf8_string (SCM scm);
|
|||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
#endif /*__MU_GUILE_UTILS_H__*/
|
#endif /*__MU_GUILE_COMMON_H__*/
|
||||||
|
|
||||||
|
|||||||
96
libmuguile/mu-guile-log.c
Normal file
96
libmuguile/mu-guile-log.c
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
/*
|
||||||
|
** Copyright (C) 2011 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
|
||||||
|
**
|
||||||
|
** 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, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
**
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "mu-guile-common.h"
|
||||||
|
#include "mu-guile-log.h"
|
||||||
|
|
||||||
|
enum _LogType {
|
||||||
|
LOG_INFO,
|
||||||
|
LOG_WARNING,
|
||||||
|
LOG_CRITICAL
|
||||||
|
};
|
||||||
|
typedef enum _LogType LogType;
|
||||||
|
|
||||||
|
|
||||||
|
static SCM
|
||||||
|
write_log (LogType logtype, SCM FRM, SCM ARGS)
|
||||||
|
#define FUNC_NAME __FUNCTION__
|
||||||
|
{
|
||||||
|
SCM str;
|
||||||
|
|
||||||
|
SCM_ASSERT (scm_is_string(FRM), FRM, SCM_ARG1, "<write_log>");
|
||||||
|
SCM_VALIDATE_REST_ARGUMENT(ARGS);
|
||||||
|
|
||||||
|
str = scm_simple_format (SCM_BOOL_F, FRM, ARGS);
|
||||||
|
|
||||||
|
if (scm_is_string (str)) {
|
||||||
|
|
||||||
|
gchar *output;
|
||||||
|
output = scm_to_utf8_string (str);
|
||||||
|
|
||||||
|
switch (logtype) {
|
||||||
|
case LOG_INFO: g_message ("%s", output); break;
|
||||||
|
case LOG_WARNING: g_warning ("%s", output); break;
|
||||||
|
case LOG_CRITICAL: g_critical ("%s", output); break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return SCM_UNSPECIFIED;
|
||||||
|
|
||||||
|
#undef FUNC_NAME
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SCM_DEFINE (log_info, "mu:log:info", 1, 0, 1, (SCM FRM, SCM ARGS),
|
||||||
|
"log some message using a list of ARGS applied to FRM "
|
||||||
|
"(in 'simple-format' notation).\n")
|
||||||
|
#define FUNC_NAME s_info
|
||||||
|
{
|
||||||
|
return write_log (LOG_INFO, FRM, ARGS);
|
||||||
|
}
|
||||||
|
#undef FUNC_NAME
|
||||||
|
|
||||||
|
SCM_DEFINE (log_warning, "mu:log:warning", 1, 0, 1, (SCM FRM, SCM ARGS),
|
||||||
|
"log some warning using a list of ARGS applied to FRM (in 'simple-format' "
|
||||||
|
"notation).\n")
|
||||||
|
#define FUNC_NAME s_warning
|
||||||
|
{
|
||||||
|
return write_log (LOG_WARNING, FRM, ARGS);
|
||||||
|
}
|
||||||
|
#undef FUNC_NAME
|
||||||
|
|
||||||
|
SCM_DEFINE (log_critical, "mu:log:critical", 1, 0, 1, (SCM FRM, SCM ARGS),
|
||||||
|
"log some critical message using a list of ARGS applied to FRM "
|
||||||
|
"(in 'simple-format' notation).\n")
|
||||||
|
#define FUNC_NAME s_critical
|
||||||
|
{
|
||||||
|
return write_log (LOG_CRITICAL, FRM, ARGS);
|
||||||
|
}
|
||||||
|
#undef FUNC_NAME
|
||||||
|
|
||||||
|
|
||||||
|
void*
|
||||||
|
mu_guile_log_init (void *data)
|
||||||
|
{
|
||||||
|
#include "mu-guile-log.x"
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
39
libmuguile/mu-guile-log.h
Normal file
39
libmuguile/mu-guile-log.h
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
** Copyright (C) 2011 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
|
||||||
|
**
|
||||||
|
** 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, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
**
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __MU_GUILE_LOG_H__
|
||||||
|
#define __MU_GUILE_LOG_H__
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif /*__cplusplus*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* initialize mu logging functions
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void *mu_guile_log_init (void *data);
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif /*__cplusplus*/
|
||||||
|
|
||||||
|
#endif /*__MU_GUILE_LOG_H__*/
|
||||||
@ -76,6 +76,41 @@ SCM_DEFINE (msg_make_from_file, "mu:msg:make-from-file", 1, 0, 0,
|
|||||||
#undef FUNC_NAME
|
#undef FUNC_NAME
|
||||||
|
|
||||||
|
|
||||||
|
SCM_DEFINE (msg_move, "mu:msg:move-to-maildir", 2, 0, 0,
|
||||||
|
(SCM MSG, SCM TARGETMDIR),
|
||||||
|
"Move message to another maildir TARGETMDIR. Note that this the "
|
||||||
|
"base-level Maildir, ie. /home/user/Maildir/archive, and must"
|
||||||
|
" _not_ include the 'cur' or 'new' part. mu_msg_move_to_maildir "
|
||||||
|
"will make sure that the copy is from new/ to new/ and cur/ to "
|
||||||
|
"cur/. Also note that the target maildir must be on the same "
|
||||||
|
"filesystem. Returns #t if it worked, #f otherwise.\n")
|
||||||
|
#define FUNC_NAME s_msg_move
|
||||||
|
{
|
||||||
|
GError *err;
|
||||||
|
MuMsgWrapper *msgwrap;
|
||||||
|
gboolean rv;
|
||||||
|
|
||||||
|
SCM_ASSERT (mu_guile_scm_is_msg(MSG), MSG, SCM_ARG1, FUNC_NAME);
|
||||||
|
SCM_ASSERT (scm_is_string (TARGETMDIR), TARGETMDIR, SCM_ARG2, FUNC_NAME);
|
||||||
|
|
||||||
|
msgwrap = (MuMsgWrapper*) SCM_CDR(MSG);
|
||||||
|
|
||||||
|
err = NULL;
|
||||||
|
rv = mu_msg_move_to_maildir (msgwrap->_msg,
|
||||||
|
scm_to_utf8_string (TARGETMDIR), &err);
|
||||||
|
if (!rv && err) {
|
||||||
|
mu_guile_g_error (FUNC_NAME, err);
|
||||||
|
g_error_free (err);
|
||||||
|
}
|
||||||
|
|
||||||
|
return rv ? SCM_BOOL_T : SCM_BOOL_F;
|
||||||
|
}
|
||||||
|
#undef FUNC_NAME
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static SCM
|
static SCM
|
||||||
scm_from_string_or_null (const char *str)
|
scm_from_string_or_null (const char *str)
|
||||||
{
|
{
|
||||||
@ -146,9 +181,9 @@ SCM_DEFINE (msg_prio, "mu:msg:priority", 1, 0, 0,
|
|||||||
prio = mu_msg_get_prio (msgwrap->_msg);
|
prio = mu_msg_get_prio (msgwrap->_msg);
|
||||||
|
|
||||||
switch (prio) {
|
switch (prio) {
|
||||||
case MU_MSG_PRIO_LOW: return scm_from_locale_symbol("low");
|
case MU_MSG_PRIO_LOW: return scm_from_locale_symbol("mu:low");
|
||||||
case MU_MSG_PRIO_NORMAL: return scm_from_locale_symbol("normal");
|
case MU_MSG_PRIO_NORMAL: return scm_from_locale_symbol("mu:normal");
|
||||||
case MU_MSG_PRIO_HIGH: return scm_from_locale_symbol("high");
|
case MU_MSG_PRIO_HIGH: return scm_from_locale_symbol("mu:high");
|
||||||
default:
|
default:
|
||||||
g_return_val_if_reached (SCM_UNDEFINED);
|
g_return_val_if_reached (SCM_UNDEFINED);
|
||||||
}
|
}
|
||||||
@ -167,7 +202,12 @@ check_flag (MuMsgFlags flag, FlagData *fdata)
|
|||||||
{
|
{
|
||||||
if (fdata->flags & flag) {
|
if (fdata->flags & flag) {
|
||||||
SCM item;
|
SCM item;
|
||||||
item = scm_list_1 (scm_from_locale_symbol(mu_msg_flag_name(flag)));
|
char *flagsym;
|
||||||
|
|
||||||
|
flagsym = g_strconcat ("mu:", mu_msg_flag_name(flag), NULL);
|
||||||
|
item = scm_list_1 (scm_from_locale_symbol(flagsym));
|
||||||
|
g_free (flagsym);
|
||||||
|
|
||||||
fdata->lst = scm_append_x (scm_list_2(fdata->lst, item));
|
fdata->lst = scm_append_x (scm_list_2(fdata->lst, item));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -469,22 +509,22 @@ static void
|
|||||||
define_symbols (void)
|
define_symbols (void)
|
||||||
{
|
{
|
||||||
/* message priority */
|
/* message priority */
|
||||||
scm_c_define ("high", scm_from_int(MU_MSG_PRIO_HIGH));
|
scm_c_define ("mu:high", scm_from_int(MU_MSG_PRIO_HIGH));
|
||||||
scm_c_define ("low", scm_from_int(MU_MSG_PRIO_LOW));
|
scm_c_define ("mu:low", scm_from_int(MU_MSG_PRIO_LOW));
|
||||||
scm_c_define ("normal", scm_from_int(MU_MSG_PRIO_NORMAL));
|
scm_c_define ("mu:normal", scm_from_int(MU_MSG_PRIO_NORMAL));
|
||||||
|
|
||||||
/* message flags */
|
/* message flags */
|
||||||
scm_c_define ("new", scm_from_int(MU_MSG_FLAG_NEW));
|
scm_c_define ("mu:new", scm_from_int(MU_MSG_FLAG_NEW));
|
||||||
scm_c_define ("passed", scm_from_int(MU_MSG_FLAG_PASSED));
|
scm_c_define ("mu:passed", scm_from_int(MU_MSG_FLAG_PASSED));
|
||||||
scm_c_define ("replied", scm_from_int(MU_MSG_FLAG_REPLIED));
|
scm_c_define ("mu:replied", scm_from_int(MU_MSG_FLAG_REPLIED));
|
||||||
scm_c_define ("seen", scm_from_int(MU_MSG_FLAG_SEEN));
|
scm_c_define ("mu:seen", scm_from_int(MU_MSG_FLAG_SEEN));
|
||||||
scm_c_define ("trashed", scm_from_int(MU_MSG_FLAG_TRASHED));
|
scm_c_define ("mu:trashed", scm_from_int(MU_MSG_FLAG_TRASHED));
|
||||||
scm_c_define ("draft", scm_from_int(MU_MSG_FLAG_DRAFT));
|
scm_c_define ("mu:draft", scm_from_int(MU_MSG_FLAG_DRAFT));
|
||||||
scm_c_define ("flagged", scm_from_int(MU_MSG_FLAG_FLAGGED));
|
scm_c_define ("mu:flagged", scm_from_int(MU_MSG_FLAG_FLAGGED));
|
||||||
scm_c_define ("unread", scm_from_int(MU_MSG_FLAG_UNREAD));
|
scm_c_define ("mu:unread", scm_from_int(MU_MSG_FLAG_UNREAD));
|
||||||
scm_c_define ("signed", scm_from_int(MU_MSG_FLAG_SIGNED));
|
scm_c_define ("mu:signed", scm_from_int(MU_MSG_FLAG_SIGNED));
|
||||||
scm_c_define ("encrypted", scm_from_int(MU_MSG_FLAG_ENCRYPTED));
|
scm_c_define ("mu:encrypted", scm_from_int(MU_MSG_FLAG_ENCRYPTED));
|
||||||
scm_c_define ("has-attach", scm_from_int(MU_MSG_FLAG_HAS_ATTACH));
|
scm_c_define ("mu:has-attach", scm_from_int(MU_MSG_FLAG_HAS_ATTACH));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -25,7 +25,7 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif /*__cplusplus*/
|
#endif /*__cplusplus*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* initialize mu:store functions
|
* initialize mu:store functions
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -853,7 +853,8 @@ print_attr_sexp (const char* elm, const char *str, gboolean nl)
|
|||||||
return; /* empty: don't include */
|
return; /* empty: don't include */
|
||||||
|
|
||||||
esc = mu_str_escape_c_literal (str);
|
esc = mu_str_escape_c_literal (str);
|
||||||
g_print (" (:%s \"%s\")%s", elm, esc, nl ? "\n" : "");
|
|
||||||
|
g_print (" :%s \"%s\"%s", elm, esc, nl ? "\n" : "");
|
||||||
g_free (esc);
|
g_free (esc);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -864,35 +865,43 @@ output_sexp (MuMsgIter *iter, size_t *count)
|
|||||||
{
|
{
|
||||||
MuMsgIter *myiter;
|
MuMsgIter *myiter;
|
||||||
size_t mycount;
|
size_t mycount;
|
||||||
|
g_return_val_if_fail (iter, FALSE);
|
||||||
g_return_val_if_fail (iter, FALSE);
|
|
||||||
|
|
||||||
g_print ("(:messages\n");
|
|
||||||
|
|
||||||
for (myiter = iter, mycount = 0; !mu_msg_iter_is_done (myiter);
|
for (myiter = iter, mycount = 0; !mu_msg_iter_is_done (myiter);
|
||||||
mu_msg_iter_next (myiter), ++mycount) {
|
mu_msg_iter_next (myiter), ++mycount) {
|
||||||
|
|
||||||
|
unsigned date, date_high, date_low;
|
||||||
|
|
||||||
MuMsg *msg;
|
MuMsg *msg;
|
||||||
if (!(msg = mu_msg_iter_get_msg (iter, NULL))) /* don't unref */
|
if (!(msg = mu_msg_iter_get_msg (iter, NULL))) /* don't unref */
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
if (mycount != 0)
|
if (mycount != 0)
|
||||||
g_print ("\n");
|
g_print ("\n");
|
||||||
|
|
||||||
|
/* emacs likes it's date in a particular way... */
|
||||||
|
date = (unsigned) mu_msg_get_date (msg);
|
||||||
|
date_high = date >> 16;
|
||||||
|
date_low = date & 0xffff;
|
||||||
|
|
||||||
g_print (" (:message\n");
|
g_print ("(%u\n", (unsigned)mycount);
|
||||||
print_attr_sexp ("from", mu_msg_get_from (msg),TRUE);
|
print_attr_sexp ("from", mu_msg_get_from (msg),TRUE);
|
||||||
print_attr_sexp ("to", mu_msg_get_to (msg),TRUE);
|
print_attr_sexp ("to", mu_msg_get_to (msg),TRUE);
|
||||||
print_attr_sexp ("cc", mu_msg_get_cc (msg),TRUE);
|
print_attr_sexp ("cc", mu_msg_get_cc (msg),TRUE);
|
||||||
print_attr_sexp ("subject", mu_msg_get_subject (msg),TRUE);
|
print_attr_sexp ("subject", mu_msg_get_subject (msg),TRUE);
|
||||||
g_print (" (:date %u)\n", (unsigned) mu_msg_get_date (msg));
|
g_print (" :date %u\n", date);
|
||||||
g_print (" (:size %u)\n", (unsigned) mu_msg_get_size (msg));
|
g_print (" :date-high %u\n", date_high);
|
||||||
|
g_print (" :date-low %u\n", date_low);
|
||||||
|
g_print (" :size %u\n", (unsigned) mu_msg_get_size (msg));
|
||||||
print_attr_sexp ("msgid", mu_msg_get_msgid (msg),TRUE);
|
print_attr_sexp ("msgid", mu_msg_get_msgid (msg),TRUE);
|
||||||
print_attr_sexp ("path", mu_msg_get_path (msg),TRUE);
|
print_attr_sexp ("path", mu_msg_get_path (msg),TRUE);
|
||||||
print_attr_sexp ("maildir", mu_msg_get_maildir (msg),FALSE);
|
print_attr_sexp ("maildir", mu_msg_get_maildir (msg),FALSE);
|
||||||
g_print (")");
|
g_print (")\n;;eom");
|
||||||
}
|
}
|
||||||
g_print (")\n");
|
|
||||||
|
fputs ("\n", stdout);
|
||||||
|
|
||||||
if (count)
|
if (count)
|
||||||
*count = mycount;
|
*count = mycount;
|
||||||
|
|
||||||
|
|||||||
@ -449,7 +449,7 @@ show_usage (gboolean noerror)
|
|||||||
static void
|
static void
|
||||||
show_version (void)
|
show_version (void)
|
||||||
{
|
{
|
||||||
g_print ("mu (mail indexer/searcher) " VERSION "\n"
|
g_print ("mu (mail indexer/searcher) version " VERSION "\n"
|
||||||
"Copyright (C) 2008-2011 Dirk-Jan C. Binnema (GPLv3+)\n");
|
"Copyright (C) 2008-2011 Dirk-Jan C. Binnema (GPLv3+)\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
16
src/mu-log.c
16
src/mu-log.c
@ -165,23 +165,14 @@ log_file_backup_maybe (const char *logfile)
|
|||||||
|
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
mu_log_init (const char* muhome,
|
mu_log_init (const char* logfile, gboolean backup,
|
||||||
gboolean backup, gboolean quiet, gboolean debug)
|
gboolean quiet, gboolean debug)
|
||||||
{
|
{
|
||||||
int fd;
|
int fd;
|
||||||
gchar *logfile;
|
|
||||||
|
|
||||||
/* only init once... */
|
/* only init once... */
|
||||||
g_return_val_if_fail (!MU_LOG, FALSE);
|
g_return_val_if_fail (!MU_LOG, FALSE);
|
||||||
g_return_val_if_fail (muhome, FALSE);
|
g_return_val_if_fail (logfile, FALSE);
|
||||||
|
|
||||||
if (!mu_util_create_dir_maybe(muhome, 0700)) {
|
|
||||||
g_warning ("failed to init log in %s", muhome);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
logfile = g_strdup_printf ("%s%c%s", muhome,
|
|
||||||
G_DIR_SEPARATOR, MU_LOG_FILE);
|
|
||||||
|
|
||||||
if (backup && !log_file_backup_maybe(logfile)) {
|
if (backup && !log_file_backup_maybe(logfile)) {
|
||||||
g_warning ("failed to backup log file");
|
g_warning ("failed to backup log file");
|
||||||
@ -192,7 +183,6 @@ mu_log_init (const char* muhome,
|
|||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
g_warning ("%s: open() of '%s' failed: %s", __FUNCTION__,
|
g_warning ("%s: open() of '%s' failed: %s", __FUNCTION__,
|
||||||
logfile, strerror(errno));
|
logfile, strerror(errno));
|
||||||
g_free (logfile);
|
|
||||||
|
|
||||||
if (fd < 0 || !mu_log_init_with_fd (fd, FALSE, quiet, debug)) {
|
if (fd < 0 || !mu_log_init_with_fd (fd, FALSE, quiet, debug)) {
|
||||||
try_close (fd);
|
try_close (fd);
|
||||||
|
|||||||
@ -31,7 +31,8 @@ G_BEGIN_DECLS
|
|||||||
/**
|
/**
|
||||||
* write logging information to a log file
|
* write logging information to a log file
|
||||||
*
|
*
|
||||||
* @param muhome the mu home directory
|
* @param full path to the log file (does not have to exist yet, but
|
||||||
|
* it's directory must)
|
||||||
* @param backup if TRUE and size of log file > MU_MAX_LOG_FILE_SIZE, move
|
* @param backup if TRUE and size of log file > MU_MAX_LOG_FILE_SIZE, move
|
||||||
* the log file to <log file>.old and start a new one. The .old file will overwrite
|
* the log file to <log file>.old and start a new one. The .old file will overwrite
|
||||||
* existing files of that name
|
* existing files of that name
|
||||||
@ -40,7 +41,7 @@ G_BEGIN_DECLS
|
|||||||
*
|
*
|
||||||
* @return TRUE if initialization succeeds, FALSE otherwise
|
* @return TRUE if initialization succeeds, FALSE otherwise
|
||||||
*/
|
*/
|
||||||
gboolean mu_log_init (const char* muhome, gboolean backup,
|
gboolean mu_log_init (const char *logfile, gboolean backup,
|
||||||
gboolean quiet, gboolean debug)
|
gboolean quiet, gboolean debug)
|
||||||
G_GNUC_WARN_UNUSED_RESULT;
|
G_GNUC_WARN_UNUSED_RESULT;
|
||||||
|
|
||||||
|
|||||||
@ -105,22 +105,22 @@ mu_msg_doc_get_num_field (MuMsgDoc *self, MuMsgFieldId mfid)
|
|||||||
g_return_val_if_fail (self, -1);
|
g_return_val_if_fail (self, -1);
|
||||||
g_return_val_if_fail (mu_msg_field_id_is_valid(mfid), -1);
|
g_return_val_if_fail (mu_msg_field_id_is_valid(mfid), -1);
|
||||||
g_return_val_if_fail (mu_msg_field_is_numeric(mfid), -1);
|
g_return_val_if_fail (mu_msg_field_is_numeric(mfid), -1);
|
||||||
|
|
||||||
/* date is a special case, because we store dates as
|
/* date is a special case, because we store dates as
|
||||||
* strings */
|
* strings */
|
||||||
try {
|
try {
|
||||||
const std::string s (self->doc().get_value(mfid));
|
const std::string s (self->doc().get_value(mfid));
|
||||||
if (s.empty())
|
if (s.empty())
|
||||||
return -1;
|
return 0;
|
||||||
else if (mfid == MU_MSG_FIELD_ID_DATE) {
|
else if (mfid == MU_MSG_FIELD_ID_DATE) {
|
||||||
time_t t;
|
time_t t;
|
||||||
t = mu_date_str_to_time_t (s.c_str(), FALSE/*utc*/);
|
t = mu_date_str_to_time_t (s.c_str(), FALSE/*utc*/);
|
||||||
return static_cast<gint64>(t);
|
return static_cast<gint64>(t);
|
||||||
} else
|
} else {
|
||||||
return static_cast<gint64>(Xapian::sortable_unserialise(s));
|
return static_cast<gint64>(Xapian::sortable_unserialise(s));
|
||||||
|
}
|
||||||
} MU_XAPIAN_CATCH_BLOCK_RETURN(-1);
|
|
||||||
|
} MU_XAPIAN_CATCH_BLOCK_RETURN(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -106,9 +106,9 @@ GSList* mu_msg_file_get_str_list_field (MuMsgFile *self,
|
|||||||
* @param self a valid MuMsgFile
|
* @param self a valid MuMsgFile
|
||||||
* @param msfid the message field id to get (must be string-based one)
|
* @param msfid the message field id to get (must be string-based one)
|
||||||
*
|
*
|
||||||
* @return the numeric value, or -1
|
* @return the numeric value, or -1 in case of error
|
||||||
*/
|
*/
|
||||||
gint64 mu_msg_file_get_num_field (MuMsgFile *self, MuMsgFieldId msfid);
|
gint64 mu_msg_file_get_num_field (MuMsgFile *self, MuMsgFieldId mfid);
|
||||||
|
|
||||||
|
|
||||||
#endif /*__MU_MSG_FILE_H__*/
|
#endif /*__MU_MSG_FILE_H__*/
|
||||||
|
|||||||
144
src/mu-msg.c
144
src/mu-msg.c
@ -669,3 +669,147 @@ mu_msg_cmp (MuMsg *m1, MuMsg *m2, MuMsgFieldId mfid)
|
|||||||
|
|
||||||
return 0; /* TODO: handle lists */
|
return 0; /* TODO: handle lists */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
enum _MaildirType {
|
||||||
|
MAILDIR_TYPE_CUR,
|
||||||
|
MAILDIR_TYPE_NEW,
|
||||||
|
MAILDIR_TYPE_OTHER
|
||||||
|
};
|
||||||
|
typedef enum _MaildirType MaildirType;
|
||||||
|
|
||||||
|
static MaildirType
|
||||||
|
get_maildir_type (const char *path)
|
||||||
|
{
|
||||||
|
MaildirType mtype;
|
||||||
|
gchar *dirname;
|
||||||
|
|
||||||
|
dirname = g_path_get_dirname (path);
|
||||||
|
/* g_path_get_dirname does not specify if the name includes
|
||||||
|
* the closing '/'... if it does, remove it */
|
||||||
|
if (dirname[strlen(dirname) - 1 ] == G_DIR_SEPARATOR)
|
||||||
|
dirname[strlen(dirname) - 1] = '\0';
|
||||||
|
|
||||||
|
if (g_str_has_suffix (dirname, "cur"))
|
||||||
|
mtype = MAILDIR_TYPE_CUR;
|
||||||
|
else if (g_str_has_suffix (dirname, "new"))
|
||||||
|
mtype = MAILDIR_TYPE_CUR;
|
||||||
|
else
|
||||||
|
mtype = MAILDIR_TYPE_OTHER;
|
||||||
|
|
||||||
|
g_free (dirname);
|
||||||
|
|
||||||
|
return mtype;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
char*
|
||||||
|
get_new_fullpath (const char *oldpath, const char *targetmdir,
|
||||||
|
MaildirType mtype)
|
||||||
|
{
|
||||||
|
char *filename, *newfullpath;
|
||||||
|
const char* mdirsub;
|
||||||
|
|
||||||
|
filename = g_path_get_basename (oldpath);
|
||||||
|
|
||||||
|
if (mtype == MAILDIR_TYPE_CUR)
|
||||||
|
mdirsub = "cur";
|
||||||
|
else if (mtype == MAILDIR_TYPE_NEW)
|
||||||
|
mdirsub = "new";
|
||||||
|
else {
|
||||||
|
g_free (filename);
|
||||||
|
g_return_val_if_reached (NULL);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
newfullpath = g_strdup_printf ("%s%c%s%c%s",
|
||||||
|
targetmdir,
|
||||||
|
G_DIR_SEPARATOR,
|
||||||
|
mdirsub,
|
||||||
|
G_DIR_SEPARATOR,
|
||||||
|
filename);
|
||||||
|
g_free (filename);
|
||||||
|
return newfullpath;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
msg_move (const char* oldpath, const char *newfullpath, GError **err)
|
||||||
|
{
|
||||||
|
if (access (oldpath, R_OK) != 0) {
|
||||||
|
g_set_error (err, 0, MU_ERROR_FILE, "cannot read %s",
|
||||||
|
oldpath);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (access (newfullpath, F_OK) == 0) {
|
||||||
|
g_set_error (err, 0, MU_ERROR_FILE, "%s already exists",
|
||||||
|
newfullpath);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rename (oldpath, newfullpath) != 0) {
|
||||||
|
g_set_error (err, 0, MU_ERROR_FILE, "error moving %s to %s",
|
||||||
|
oldpath, newfullpath);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* double check -- is the target really there? */
|
||||||
|
if (access (newfullpath, F_OK) != 0) {
|
||||||
|
g_set_error (err, 0, MU_ERROR_FILE, "can't find target (%s)",
|
||||||
|
newfullpath);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (access (oldpath, F_OK) == 0) {
|
||||||
|
g_set_error (err, 0, MU_ERROR_FILE, "source is still there (%s)",
|
||||||
|
oldpath);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* move a msg to another maildir, trying to maintain 'integrity',
|
||||||
|
* ie. msg in 'new/' will go to new/, one in cur/ goes to cur/. be
|
||||||
|
* super-paranoid here...
|
||||||
|
*/
|
||||||
|
gboolean
|
||||||
|
mu_msg_move_to_maildir (MuMsg *self, const char* targetmdir, GError **err)
|
||||||
|
{
|
||||||
|
const char *oldpath;
|
||||||
|
MaildirType mtype;
|
||||||
|
char *newfullpath;
|
||||||
|
|
||||||
|
g_return_val_if_fail (self, FALSE);
|
||||||
|
g_return_val_if_fail (targetmdir, FALSE);
|
||||||
|
g_return_val_if_fail (g_path_is_absolute(targetmdir), FALSE);
|
||||||
|
g_return_val_if_fail (mu_util_check_dir (targetmdir, TRUE, TRUE), FALSE);
|
||||||
|
|
||||||
|
oldpath = mu_msg_get_path (self);
|
||||||
|
|
||||||
|
mtype = get_maildir_type (oldpath);
|
||||||
|
g_return_val_if_fail (mtype==MAILDIR_TYPE_CUR||mtype==MAILDIR_TYPE_NEW,
|
||||||
|
FALSE);
|
||||||
|
|
||||||
|
newfullpath = get_new_fullpath (oldpath, targetmdir, mtype);
|
||||||
|
g_return_val_if_fail (newfullpath, FALSE);
|
||||||
|
|
||||||
|
if (!msg_move (oldpath, newfullpath, err))
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
/* update our path to new one... */
|
||||||
|
mu_msg_cache_set_str (self->_cache, MU_MSG_FIELD_ID_PATH, newfullpath,
|
||||||
|
TRUE);
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
error:
|
||||||
|
g_free (newfullpath);
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
}
|
||||||
|
|||||||
22
src/mu-msg.h
22
src/mu-msg.h
@ -357,6 +357,28 @@ const GSList* mu_msg_get_tags (MuMsg *self);
|
|||||||
int mu_msg_cmp (MuMsg *m1, MuMsg *m2, MuMsgFieldId mfid);
|
int mu_msg_cmp (MuMsg *m1, MuMsg *m2, MuMsgFieldId mfid);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* move a message to another maildir; the function returns the full
|
||||||
|
* path to the new message, and changes the msg to now point to the
|
||||||
|
* new maildir
|
||||||
|
*
|
||||||
|
* @param msg a message with an existing file system path in an actual
|
||||||
|
* maildir
|
||||||
|
* @param targetmdir the target maildir; note that this the base-level
|
||||||
|
* Maildir, ie. /home/user/Maildir/archive, and must _not_ include the
|
||||||
|
* 'cur' or 'new' part. mu_msg_move_to_maildir will make sure that the
|
||||||
|
* copy is from new/ to new/ and cur/ to cur/. Also note that the target
|
||||||
|
* maildir must be on the same filesystem. *
|
||||||
|
* @param err (may be NULL) may contain error information; note if the
|
||||||
|
* function return FALSE, err is not set for all error condition
|
||||||
|
* (ie. not for parameter errors)
|
||||||
|
* @return TRUE if it worked, FALSE otherwise
|
||||||
|
*/
|
||||||
|
gboolean mu_msg_move_to_maildir (MuMsg *msg, const char* targetmdir,
|
||||||
|
GError **err);
|
||||||
|
|
||||||
|
|
||||||
enum _MuMsgContactType { /* Reply-To:? */
|
enum _MuMsgContactType { /* Reply-To:? */
|
||||||
MU_MSG_CONTACT_TYPE_TO = 0,
|
MU_MSG_CONTACT_TYPE_TO = 0,
|
||||||
MU_MSG_CONTACT_TYPE_FROM,
|
MU_MSG_CONTACT_TYPE_FROM,
|
||||||
|
|||||||
100
src/mu-runtime.c
100
src/mu-runtime.c
@ -1,4 +1,4 @@
|
|||||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
|
/* -*- mode: c; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
|
||||||
**
|
**
|
||||||
** Copyright (C) 2010 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
|
** Copyright (C) 2010 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
|
||||||
**
|
**
|
||||||
@ -42,6 +42,7 @@
|
|||||||
struct _MuRuntimeData {
|
struct _MuRuntimeData {
|
||||||
gchar *_str[MU_RUNTIME_PATH_NUM];
|
gchar *_str[MU_RUNTIME_PATH_NUM];
|
||||||
MuConfig *_config;
|
MuConfig *_config;
|
||||||
|
gchar *_name; /* e.g., 'mu', 'mug' */
|
||||||
};
|
};
|
||||||
typedef struct _MuRuntimeData MuRuntimeData;
|
typedef struct _MuRuntimeData MuRuntimeData;
|
||||||
|
|
||||||
@ -49,8 +50,10 @@ typedef struct _MuRuntimeData MuRuntimeData;
|
|||||||
static gboolean _initialized = FALSE;
|
static gboolean _initialized = FALSE;
|
||||||
static MuRuntimeData *_data = NULL;
|
static MuRuntimeData *_data = NULL;
|
||||||
|
|
||||||
static void runtime_free (void);
|
static void runtime_free (void);
|
||||||
static gboolean init_paths (const char* muhome, MuRuntimeData *data);
|
static gboolean init_paths (const char* muhome, MuRuntimeData *data);
|
||||||
|
static const char* runtime_path (MuRuntimePath path);
|
||||||
|
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
mu_dir_is_readable_and_writable (const char *muhome)
|
mu_dir_is_readable_and_writable (const char *muhome)
|
||||||
@ -64,14 +67,38 @@ mu_dir_is_readable_and_writable (const char *muhome)
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
init_log (const char *muhome, const char *name,
|
||||||
|
gboolean log_stderr, gboolean quiet, gboolean debug)
|
||||||
|
{
|
||||||
|
gboolean rv;
|
||||||
|
char *logpath;
|
||||||
|
|
||||||
|
if (log_stderr)
|
||||||
|
return mu_log_init_with_fd (fileno(stderr), FALSE,
|
||||||
|
quiet, debug);
|
||||||
|
|
||||||
|
logpath = g_strdup_printf ("%s%c%s%c%s.log",
|
||||||
|
muhome, G_DIR_SEPARATOR,
|
||||||
|
MU_LOG_DIRNAME, G_DIR_SEPARATOR,
|
||||||
|
name);
|
||||||
|
rv = mu_log_init (logpath, TRUE, quiet, debug);
|
||||||
|
g_free (logpath);
|
||||||
|
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
mu_runtime_init (const char* muhome_arg)
|
mu_runtime_init (const char* muhome_arg, const char *name)
|
||||||
{
|
{
|
||||||
gchar *muhome;
|
gchar *muhome;
|
||||||
|
|
||||||
g_return_val_if_fail (!_initialized, FALSE);
|
g_return_val_if_fail (!_initialized, FALSE);
|
||||||
|
g_return_val_if_fail (name, FALSE);
|
||||||
|
|
||||||
if (!mu_util_init_system())
|
if (!mu_util_init_system())
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
@ -85,35 +112,28 @@ mu_runtime_init (const char* muhome_arg)
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mu_log_init (muhome, TRUE, FALSE, FALSE)) {
|
_data = g_new0 (MuRuntimeData, 1);
|
||||||
|
_data->_str[MU_RUNTIME_PATH_MUHOME] = muhome;
|
||||||
|
init_paths (muhome, _data);
|
||||||
|
_data->_name = g_strdup (name);
|
||||||
|
|
||||||
|
if (!init_log (muhome, name, FALSE, TRUE, FALSE)) {
|
||||||
|
runtime_free ();
|
||||||
g_free (muhome);
|
g_free (muhome);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
_data = g_new0 (MuRuntimeData, 1);
|
|
||||||
_data->_str[MU_RUNTIME_PATH_MUHOME] = muhome;
|
|
||||||
init_paths (muhome, _data);
|
|
||||||
|
|
||||||
return _initialized = TRUE;
|
return _initialized = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static gboolean
|
|
||||||
init_log (MuConfig *opts)
|
|
||||||
{
|
|
||||||
if (opts->log_stderr)
|
|
||||||
return mu_log_init_with_fd (fileno(stderr), FALSE,
|
|
||||||
opts->quiet, opts->debug);
|
|
||||||
else
|
|
||||||
return mu_log_init (opts->muhome, TRUE, opts->quiet,
|
|
||||||
opts->debug);
|
|
||||||
}
|
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
mu_runtime_init_from_cmdline (int *pargc, char ***pargv)
|
mu_runtime_init_from_cmdline (int *pargc, char ***pargv, const char *name)
|
||||||
{
|
{
|
||||||
g_return_val_if_fail (!_initialized, FALSE);
|
g_return_val_if_fail (!_initialized, FALSE);
|
||||||
|
g_return_val_if_fail (name, FALSE);
|
||||||
|
|
||||||
if (!mu_util_init_system())
|
if (!mu_util_init_system())
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
@ -129,15 +149,19 @@ mu_runtime_init_from_cmdline (int *pargc, char ***pargv)
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!init_log (_data->_config)) {
|
_data->_name = g_strdup (name);
|
||||||
runtime_free ();
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
_data->_str[MU_RUNTIME_PATH_MUHOME] =
|
_data->_str[MU_RUNTIME_PATH_MUHOME] =
|
||||||
g_strdup (_data->_config->muhome);
|
g_strdup (_data->_config->muhome);
|
||||||
init_paths (_data->_str[MU_RUNTIME_PATH_MUHOME], _data);
|
init_paths (_data->_str[MU_RUNTIME_PATH_MUHOME], _data);
|
||||||
|
|
||||||
|
if (!init_log (runtime_path(MU_RUNTIME_PATH_MUHOME), name,
|
||||||
|
_data->_config->log_stderr,
|
||||||
|
_data->_config->quiet,
|
||||||
|
_data->_config->debug)) {
|
||||||
|
runtime_free ();
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
return _initialized = TRUE;
|
return _initialized = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -150,6 +174,8 @@ runtime_free (void)
|
|||||||
for (i = 0; i != MU_RUNTIME_PATH_NUM; ++i)
|
for (i = 0; i != MU_RUNTIME_PATH_NUM; ++i)
|
||||||
g_free (_data->_str[i]);
|
g_free (_data->_str[i]);
|
||||||
|
|
||||||
|
g_free (_data->_name);
|
||||||
|
|
||||||
mu_config_destroy (_data->_config);
|
mu_config_destroy (_data->_config);
|
||||||
|
|
||||||
mu_log_uninit();
|
mu_log_uninit();
|
||||||
@ -208,15 +234,23 @@ init_paths (const char* muhome, MuRuntimeData *data)
|
|||||||
G_DIR_SEPARATOR, MU_CONTACTS_FILENAME);
|
G_DIR_SEPARATOR, MU_CONTACTS_FILENAME);
|
||||||
|
|
||||||
data->_str [MU_RUNTIME_PATH_LOG] =
|
data->_str [MU_RUNTIME_PATH_LOG] =
|
||||||
g_strdup_printf ("%s%c%s", muhome, G_DIR_SEPARATOR,
|
g_strdup_printf ("%s%c%s", muhome,
|
||||||
MU_LOG_DIRNAME);
|
G_DIR_SEPARATOR, MU_LOG_DIRNAME);
|
||||||
|
|
||||||
if (!create_dirs_maybe (data))
|
if (!create_dirs_maybe (data))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* so we can called when _initialized is FALSE still */
|
||||||
|
static const char*
|
||||||
|
runtime_path (MuRuntimePath path)
|
||||||
|
{
|
||||||
|
return _data->_str[path];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const char*
|
const char*
|
||||||
mu_runtime_path (MuRuntimePath path)
|
mu_runtime_path (MuRuntimePath path)
|
||||||
@ -224,7 +258,7 @@ mu_runtime_path (MuRuntimePath path)
|
|||||||
g_return_val_if_fail (_initialized, NULL);
|
g_return_val_if_fail (_initialized, NULL);
|
||||||
g_return_val_if_fail (path < MU_RUNTIME_PATH_NUM, NULL);
|
g_return_val_if_fail (path < MU_RUNTIME_PATH_NUM, NULL);
|
||||||
|
|
||||||
return _data->_str[path];
|
return runtime_path (path);
|
||||||
}
|
}
|
||||||
|
|
||||||
MuConfig*
|
MuConfig*
|
||||||
|
|||||||
@ -29,11 +29,13 @@ G_BEGIN_DECLS
|
|||||||
* initialize the mu runtime system; initializes logging and other
|
* initialize the mu runtime system; initializes logging and other
|
||||||
* systems. To uninitialize, use mu_runtime_uninit
|
* systems. To uninitialize, use mu_runtime_uninit
|
||||||
*
|
*
|
||||||
* @param muhome path where to find the mu home directory (typicaly, ~/.mu)
|
* @param muhome path where to find the mu home directory (typicaly, ~/.mu)
|
||||||
|
* @param name of the main program, ie. 'mu', 'mug' or
|
||||||
|
* 'procmule'. this influences the name of the e.g. the logfile
|
||||||
*
|
*
|
||||||
* @return TRUE if succeeded, FALSE in case of error
|
* @return TRUE if succeeded, FALSE in case of error
|
||||||
*/
|
*/
|
||||||
gboolean mu_runtime_init (const char* muhome);
|
gboolean mu_runtime_init (const char *muhome, const char *name);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -44,10 +46,13 @@ gboolean mu_runtime_init (const char* muhome);
|
|||||||
*
|
*
|
||||||
* @param ptr to the param count (typically, argc)
|
* @param ptr to the param count (typically, argc)
|
||||||
* @param ptr to the params (typically, argv)
|
* @param ptr to the params (typically, argv)
|
||||||
|
* @param name of the main program, ie. 'mu', 'mug' or
|
||||||
|
* 'procmule'. this influences the name of the e.g. the logfile
|
||||||
*
|
*
|
||||||
* @return TRUE if succeeded, FALSE in case of error
|
* @return TRUE if succeeded, FALSE in case of error
|
||||||
*/
|
*/
|
||||||
gboolean mu_runtime_init_from_cmdline (int *pargc, char ***pargv);
|
gboolean mu_runtime_init_from_cmdline (int *pargc, char ***pargv,
|
||||||
|
const char *name);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -29,7 +29,7 @@ main (int argc, char *argv[])
|
|||||||
{
|
{
|
||||||
int rv;
|
int rv;
|
||||||
|
|
||||||
if (!mu_runtime_init_from_cmdline (&argc, &argv))
|
if (!mu_runtime_init_from_cmdline (&argc, &argv, "mu"))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
rv = mu_config_execute (mu_runtime_config());
|
rv = mu_config_execute (mu_runtime_config());
|
||||||
|
|||||||
@ -38,10 +38,10 @@ test_mu_runtime_init (void)
|
|||||||
|
|
||||||
tmpdir = test_mu_common_get_random_tmpdir();
|
tmpdir = test_mu_common_get_random_tmpdir();
|
||||||
g_assert (tmpdir);
|
g_assert (tmpdir);
|
||||||
g_assert (mu_runtime_init (tmpdir) == TRUE);
|
g_assert (mu_runtime_init (tmpdir, "test-mu-runtime") == TRUE);
|
||||||
mu_runtime_uninit ();
|
mu_runtime_uninit ();
|
||||||
|
|
||||||
g_assert (mu_runtime_init (tmpdir) == TRUE);
|
g_assert (mu_runtime_init (tmpdir, "test-mu-runtime") == TRUE);
|
||||||
mu_runtime_uninit ();
|
mu_runtime_uninit ();
|
||||||
|
|
||||||
g_free (tmpdir);
|
g_free (tmpdir);
|
||||||
@ -62,7 +62,7 @@ test_mu_runtime_data (void)
|
|||||||
bmfile = g_strdup_printf ("%s%c%s", homedir,
|
bmfile = g_strdup_printf ("%s%c%s", homedir,
|
||||||
G_DIR_SEPARATOR, "bookmarks");
|
G_DIR_SEPARATOR, "bookmarks");
|
||||||
|
|
||||||
g_assert (mu_runtime_init (homedir) == TRUE);
|
g_assert (mu_runtime_init (homedir, "test-mu-runtime") == TRUE);
|
||||||
|
|
||||||
g_assert_cmpstr (homedir, ==, mu_runtime_path (MU_RUNTIME_PATH_MUHOME));
|
g_assert_cmpstr (homedir, ==, mu_runtime_path (MU_RUNTIME_PATH_MUHOME));
|
||||||
g_assert_cmpstr (xdir, ==, mu_runtime_path (MU_RUNTIME_PATH_XAPIANDB));
|
g_assert_cmpstr (xdir, ==, mu_runtime_path (MU_RUNTIME_PATH_XAPIANDB));
|
||||||
|
|||||||
@ -32,3 +32,12 @@ endif
|
|||||||
if HAVE_GUILE
|
if HAVE_GUILE
|
||||||
SUBDIRS += muile
|
SUBDIRS += muile
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
# for procmule, we need guile and gio
|
||||||
|
if HAVE_GUILE
|
||||||
|
if HAVE_GIO
|
||||||
|
SUBDIRS += procmule
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -35,7 +35,7 @@ noinst_PROGRAMS= \
|
|||||||
# note, mug.cc is '.cc' only because libmu must explicitly
|
# note, mug.cc is '.cc' only because libmu must explicitly
|
||||||
# be linked as c++, not c.
|
# be linked as c++, not c.
|
||||||
mug_SOURCES= \
|
mug_SOURCES= \
|
||||||
mug.cc \
|
mug.c \
|
||||||
mug-msg-list-view.c \
|
mug-msg-list-view.c \
|
||||||
mug-msg-list-view.h \
|
mug-msg-list-view.h \
|
||||||
mug-msg-view.h \
|
mug-msg-view.h \
|
||||||
@ -43,7 +43,19 @@ mug_SOURCES= \
|
|||||||
mug-query-bar.h \
|
mug-query-bar.h \
|
||||||
mug-query-bar.c \
|
mug-query-bar.c \
|
||||||
mug-shortcuts.c \
|
mug-shortcuts.c \
|
||||||
mug-shortcuts.h
|
mug-shortcuts.h \
|
||||||
|
dummy.cc
|
||||||
|
|
||||||
|
# we need to use dummy.cc to enforce c++ linking...
|
||||||
|
BUILT_SOURCES= \
|
||||||
|
dummy.cc
|
||||||
|
|
||||||
|
dummy.cc:
|
||||||
|
touch dummy.cc
|
||||||
|
|
||||||
|
DISTCLEANFILES= \
|
||||||
|
$(BUILT_SOURCES)
|
||||||
|
|
||||||
|
|
||||||
mug_LDADD= \
|
mug_LDADD= \
|
||||||
${top_builddir}/src/libmu.la \
|
${top_builddir}/src/libmu.la \
|
||||||
|
|||||||
@ -369,7 +369,7 @@ main (int argc, char *argv[])
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
mu_runtime_init (mugdata.muhome);
|
mu_runtime_init (mugdata.muhome, "mug");
|
||||||
|
|
||||||
mugshell = mug_shell (&mugdata);
|
mugshell = mug_shell (&mugdata);
|
||||||
g_signal_connect (G_OBJECT (mugshell), "destroy",
|
g_signal_connect (G_OBJECT (mugshell), "destroy",
|
||||||
@ -28,13 +28,13 @@ INCLUDES=-I${top_srcdir} -I${top_srcdir}/src $(GTK_CFLAGS) $(WEBKIT_CFLAGS) -DIC
|
|||||||
AM_CFLAGS=-Wall -Wextra -Wno-unused-parameter -Wdeclaration-after-statement
|
AM_CFLAGS=-Wall -Wextra -Wno-unused-parameter -Wdeclaration-after-statement
|
||||||
AM_CXXFLAGS=-Wall -Wextra -Wno-unused-parameter
|
AM_CXXFLAGS=-Wall -Wextra -Wno-unused-parameter
|
||||||
|
|
||||||
noinst_PROGRAMS= \
|
noinst_PROGRAMS= \
|
||||||
mug2
|
mug2
|
||||||
|
|
||||||
# note, mug.cc is '.cc' only because libmu must explicitly
|
# note, mug.cc is '.cc' only because libmu must explicitly
|
||||||
# be linked as c++, not c.
|
# be linked as c++, not c.
|
||||||
mug2_SOURCES= \
|
mug2_SOURCES= \
|
||||||
mug.cc \
|
mug.c \
|
||||||
mug-msg-list-view.c \
|
mug-msg-list-view.c \
|
||||||
mug-msg-list-view.h \
|
mug-msg-list-view.h \
|
||||||
mug-msg-view.h \
|
mug-msg-view.h \
|
||||||
@ -42,7 +42,19 @@ mug2_SOURCES= \
|
|||||||
mug-query-bar.h \
|
mug-query-bar.h \
|
||||||
mug-query-bar.c \
|
mug-query-bar.c \
|
||||||
mug-shortcuts.c \
|
mug-shortcuts.c \
|
||||||
mug-shortcuts.h
|
mug-shortcuts.h \
|
||||||
|
dummy.cc
|
||||||
|
|
||||||
|
# we need to use dummy.cc to enforce c++ linking...
|
||||||
|
BUILT_SOURCES= \
|
||||||
|
dummy.cc
|
||||||
|
|
||||||
|
dummy.cc:
|
||||||
|
touch dummy.cc
|
||||||
|
|
||||||
|
DISTCLEANFILES= \
|
||||||
|
$(BUILT_SOURCES)
|
||||||
|
|
||||||
|
|
||||||
mug2_LDADD= \
|
mug2_LDADD= \
|
||||||
${top_builddir}/src/libmu.la \
|
${top_builddir}/src/libmu.la \
|
||||||
|
|||||||
@ -420,7 +420,7 @@ main (int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
|
|
||||||
g_option_context_free (octx);
|
g_option_context_free (octx);
|
||||||
mu_runtime_init (mugdata.muhome);
|
mu_runtime_init (mugdata.muhome, "mug2");
|
||||||
|
|
||||||
mugshell = mug_shell (&mugdata);
|
mugshell = mug_shell (&mugdata);
|
||||||
g_signal_connect (G_OBJECT (mugshell), "destroy",
|
g_signal_connect (G_OBJECT (mugshell), "destroy",
|
||||||
@ -29,7 +29,20 @@ noinst_PROGRAMS= \
|
|||||||
muile
|
muile
|
||||||
|
|
||||||
muile_SOURCES= \
|
muile_SOURCES= \
|
||||||
muile.cc
|
muile.c \
|
||||||
|
dummy.cc
|
||||||
|
|
||||||
|
# we need to use dummy.cc to enforce c++ linking...
|
||||||
|
BUILT_SOURCES= \
|
||||||
|
dummy.cc
|
||||||
|
|
||||||
|
dummy.cc:
|
||||||
|
touch dummy.cc
|
||||||
|
|
||||||
|
DISTCLEANFILES= \
|
||||||
|
$(BUILT_SOURCES)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
muile_LDFLAGS= \
|
muile_LDFLAGS= \
|
||||||
${top_builddir}/libmuguile/libmuguile.la
|
${top_builddir}/libmuguile/libmuguile.la
|
||||||
|
|||||||
@ -8,7 +8,9 @@
|
|||||||
`guile'[1] is an interpreter/library for the Scheme programming language[2],
|
`guile'[1] is an interpreter/library for the Scheme programming language[2],
|
||||||
specifically meant for extending other programs. It is, in fact, the
|
specifically meant for extending other programs. It is, in fact, the
|
||||||
official GNU language for doing so. 'muile' requires guile 2.x to get the full
|
official GNU language for doing so. 'muile' requires guile 2.x to get the full
|
||||||
support; older versions will not support e.g. the 'mu-stats.scm' things
|
support.
|
||||||
|
|
||||||
|
older versions will not support e.g. the 'mu-stats.scm' things
|
||||||
discussed below.
|
discussed below.
|
||||||
|
|
||||||
The combination of mu + guile is called `muile', and allows you to write
|
The combination of mu + guile is called `muile', and allows you to write
|
||||||
@ -53,14 +55,17 @@
|
|||||||
| scheme@(guile-user)> (mu:msg:subject msg)
|
| scheme@(guile-user)> (mu:msg:subject msg)
|
||||||
| $1 = "See me in bikini :-)"
|
| $1 = "See me in bikini :-)"
|
||||||
| scheme@(guile-user)> (mu:msg:flags msg)
|
| scheme@(guile-user)> (mu:msg:flags msg)
|
||||||
| $2 = (attach unread)
|
| $2 = (mu:attach mu:unread)
|
||||||
`----
|
`----
|
||||||
|
|
||||||
and so on. Note, it's probably easiest to explore the various mu: methods
|
and so on. Note, it's probably easiest to explore the various mu: methods
|
||||||
using autocompletion; to enable that make sure you have
|
using autocompletion; to enable that make sure you have
|
||||||
|
|
||||||
(use-modules (ice-9 readline))
|
|
||||||
(activate-readline)
|
,----
|
||||||
|
| (use-modules (ice-9 readline))
|
||||||
|
| (activate-readline)
|
||||||
|
`----
|
||||||
|
|
||||||
in your ~/.guile configuration.
|
in your ~/.guile configuration.
|
||||||
|
|
||||||
|
|||||||
@ -23,9 +23,8 @@
|
|||||||
#include <mu-runtime.h>
|
#include <mu-runtime.h>
|
||||||
#include <glib-object.h>
|
#include <glib-object.h>
|
||||||
|
|
||||||
#include <libguile.h>
|
#include <libmuguile/mu-guile-common.h>
|
||||||
#include <libmuguile/mu-guile-msg.h>
|
#include <libmuguile/mu-guile-msg.h>
|
||||||
#include <libmuguile/mu-guile-store.h>
|
|
||||||
|
|
||||||
struct _MuileConfig {
|
struct _MuileConfig {
|
||||||
const char *muhome;
|
const char *muhome;
|
||||||
@ -97,13 +96,13 @@ main (int argc, char *argv[])
|
|||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mu_runtime_init (opts->muhome /* NULL is okay */)) {
|
if (!mu_runtime_init (opts->muhome /* NULL is okay */,
|
||||||
|
"muile")) {
|
||||||
usage ();
|
usage ();
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
scm_with_guile (&mu_guile_msg_init, NULL);
|
mu_guile_init (); /* initialize mu guile modules */
|
||||||
scm_with_guile (&mu_guile_store_init, NULL);
|
|
||||||
|
|
||||||
if (opts->msgpath) {
|
if (opts->msgpath) {
|
||||||
if (!(gboolean)scm_with_guile
|
if (!(gboolean)scm_with_guile
|
||||||
49
toys/procmule/Makefile.am
Normal file
49
toys/procmule/Makefile.am
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
## Copyright (C) 2011 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
|
||||||
|
##
|
||||||
|
## 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
|
||||||
|
## t he 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, write to the Free Software Foundation,
|
||||||
|
## Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
|
||||||
|
include $(top_srcdir)/gtest.mk
|
||||||
|
|
||||||
|
INCLUDES=-I${top_srcdir} -I${top_srcdir}/src ${GUILE_CFLAGS} ${GLIB_CFLAGS}
|
||||||
|
|
||||||
|
# don't use -Werror, as it might break on other compilers
|
||||||
|
# use -Wno-unused-parameters, because some callbacks may not
|
||||||
|
# really need all the params they get
|
||||||
|
AM_CFLAGS=-Wall -Wextra -Wno-unused-parameter -Wdeclaration-after-statement
|
||||||
|
AM_CXXFLAGS=-Wall -Wextra -Wno-unused-parameter
|
||||||
|
|
||||||
|
noinst_PROGRAMS= \
|
||||||
|
procmule
|
||||||
|
|
||||||
|
procmule_SOURCES= \
|
||||||
|
procmule.c \
|
||||||
|
dummy.cc
|
||||||
|
|
||||||
|
# we need to use dummy.cc to enforce c++ linking...
|
||||||
|
BUILT_SOURCES= \
|
||||||
|
dummy.cc
|
||||||
|
|
||||||
|
dummy.cc:
|
||||||
|
touch dummy.cc
|
||||||
|
|
||||||
|
# is this needed?
|
||||||
|
DISTCLEANFILES= \
|
||||||
|
$(BUILT_SOURCES)
|
||||||
|
|
||||||
|
procmule_LDFLAGS= \
|
||||||
|
${top_builddir}/libmuguile/libmuguile.la \
|
||||||
|
${top_builddir}/src/libmu.la \
|
||||||
|
${GIO_LIBS}
|
||||||
|
|
||||||
32
toys/procmule/README
Normal file
32
toys/procmule/README
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
* README
|
||||||
|
|
||||||
|
The toy here is called 'procmule', which tries to offer procmail[1]-like
|
||||||
|
functionality from mu, with the procmailrc configuration language replaced
|
||||||
|
with guile and the mu-guile-bindings.
|
||||||
|
|
||||||
|
Of course, I'm not arrogant enough to claim that I can replace a time-tested,
|
||||||
|
classical Unix tool so easily. On the other hand, I'm gluing existing tools
|
||||||
|
together.
|
||||||
|
|
||||||
|
Now, the big difference with procmail is that procmail is an MDA - a mail
|
||||||
|
delivery agent. In practice, it typically reads a new e-mail message from
|
||||||
|
standard input (it's called from the local mail daemon), and then decides what
|
||||||
|
to do with it.
|
||||||
|
|
||||||
|
In contrast, procmule watches a directory (or series of directories) for
|
||||||
|
changes - as soon as a new message appears in one of these directories,
|
||||||
|
procmule evaluates a Guile/Scheme program (typically, ~/.mu/procmule.scm) with
|
||||||
|
the message available as 'mu:current-msg'.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[1] http://www.procmail.org/
|
||||||
|
|
||||||
|
# Local Variables:
|
||||||
|
# mode: org; org-startup-folded: nil
|
||||||
|
# End:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
295
toys/procmule/procmule.c
Normal file
295
toys/procmule/procmule.c
Normal file
@ -0,0 +1,295 @@
|
|||||||
|
/*
|
||||||
|
** Copyright (C) 2011 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
|
||||||
|
**
|
||||||
|
** 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, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
**
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
#include <gio/gio.h>
|
||||||
|
#include <libmuguile/mu-guile-common.h>
|
||||||
|
#include <libmuguile/mu-guile-msg.h>
|
||||||
|
|
||||||
|
#include "mu-runtime.h"
|
||||||
|
#include "mu-util.h"
|
||||||
|
|
||||||
|
struct _ChildData {
|
||||||
|
char **shell_argv;
|
||||||
|
int shell_argc;
|
||||||
|
};
|
||||||
|
typedef struct _ChildData ChildData;
|
||||||
|
|
||||||
|
static ChildData *
|
||||||
|
child_data_new (const char *muhome)
|
||||||
|
{
|
||||||
|
ChildData *data;
|
||||||
|
|
||||||
|
data = g_new0 (ChildData, 1);
|
||||||
|
|
||||||
|
data->shell_argv = g_new0 (char*,3);
|
||||||
|
data->shell_argc = 0;
|
||||||
|
|
||||||
|
data->shell_argv[data->shell_argc++] = g_strdup ("procmule");
|
||||||
|
data->shell_argv[data->shell_argc++] = g_strdup ("-s");
|
||||||
|
data->shell_argv[data->shell_argc++] =
|
||||||
|
g_strdup_printf ("%s%cprocmule.scm", muhome, G_DIR_SEPARATOR);
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
child_data_destroy (ChildData *data)
|
||||||
|
{
|
||||||
|
if (!data)
|
||||||
|
return;
|
||||||
|
|
||||||
|
g_strfreev (data->shell_argv);
|
||||||
|
g_free (data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_dir_change (GFileMonitor *mon, GFile *file, GFile *other_file,
|
||||||
|
GFileMonitorEvent event_type, ChildData *data)
|
||||||
|
{
|
||||||
|
gchar *path;
|
||||||
|
|
||||||
|
path = g_file_get_path (file);
|
||||||
|
|
||||||
|
/* ignore all except create events */
|
||||||
|
if (event_type != G_FILE_MONITOR_EVENT_CREATED)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (fork() == 0) { /* run guile in child */
|
||||||
|
|
||||||
|
mu_guile_init (); /* initialize mu guile modules */
|
||||||
|
|
||||||
|
if (!(gboolean)scm_with_guile
|
||||||
|
((MuGuileFunc*)&mu_guile_msg_load_current, path)) {
|
||||||
|
g_warning ("failed to set message in guile env");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
scm_shell (data->shell_argc, data->shell_argv); /* never returns */
|
||||||
|
}
|
||||||
|
|
||||||
|
g_free (path);
|
||||||
|
}
|
||||||
|
|
||||||
|
static GFileMonitor*
|
||||||
|
create_monitor (const char *path, ChildData *data)
|
||||||
|
{
|
||||||
|
GFile *dir;
|
||||||
|
GFileMonitor *dirmon;
|
||||||
|
GError *err;
|
||||||
|
|
||||||
|
if (!mu_util_check_dir (path, TRUE, FALSE)) {
|
||||||
|
g_warning ("must be a readable dir: '%s'", path);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
dir = g_file_new_for_path (path);
|
||||||
|
|
||||||
|
err = NULL;
|
||||||
|
dirmon = g_file_monitor_directory (dir, G_FILE_MONITOR_NONE,
|
||||||
|
NULL, &err);
|
||||||
|
if (!dirmon) {
|
||||||
|
g_warning ("error adding monitor: %s", err->message);
|
||||||
|
g_error_free (err);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_object_unref (dir);
|
||||||
|
|
||||||
|
if (dirmon)
|
||||||
|
g_signal_connect (dirmon, "changed",
|
||||||
|
G_CALLBACK(on_dir_change), data);
|
||||||
|
|
||||||
|
return dirmon;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
destroy_watchlist (GSList *lst)
|
||||||
|
{
|
||||||
|
g_slist_foreach (lst, (GFunc)g_object_unref, NULL);
|
||||||
|
g_slist_free (lst);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
GSList*
|
||||||
|
create_watchlist (char **dirs, ChildData *data)
|
||||||
|
{
|
||||||
|
GSList *watchlist;
|
||||||
|
char **cur;
|
||||||
|
|
||||||
|
/* TODO: check for dups */
|
||||||
|
for (watchlist = NULL, cur = dirs; cur && *cur; ++cur) {
|
||||||
|
GFileMonitor *dirmon;
|
||||||
|
dirmon = create_monitor (*cur, data);
|
||||||
|
if (!dirmon) {
|
||||||
|
destroy_watchlist (watchlist);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
watchlist = g_slist_prepend (watchlist, dirmon);
|
||||||
|
}
|
||||||
|
|
||||||
|
return watchlist;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct _PMConfig {
|
||||||
|
char *muhome;
|
||||||
|
char **watchdirs;
|
||||||
|
|
||||||
|
};
|
||||||
|
typedef struct _PMConfig PMConfig;
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
expand_paths (PMConfig *opts)
|
||||||
|
{
|
||||||
|
char **cur;
|
||||||
|
|
||||||
|
for (cur = opts->watchdirs; cur && *cur; ++cur)
|
||||||
|
*cur = mu_util_dir_expand (*cur);
|
||||||
|
|
||||||
|
if (opts->muhome)
|
||||||
|
opts->muhome = mu_util_dir_expand (opts->muhome);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static PMConfig *
|
||||||
|
pm_config_new (int *argcp, char ***argvp)
|
||||||
|
{
|
||||||
|
GOptionContext *octx;
|
||||||
|
|
||||||
|
PMConfig *opts = g_new0 (PMConfig, 1);
|
||||||
|
GOptionEntry entries[] = {
|
||||||
|
{"muhome", 0, 0, G_OPTION_ARG_FILENAME, &opts->muhome,
|
||||||
|
"specify an alternative mu directory", NULL},
|
||||||
|
{"watch", 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &opts->watchdirs,
|
||||||
|
"directory to watch (may be specified multiple times)", NULL},
|
||||||
|
{NULL, 0, 0, G_OPTION_ARG_NONE, NULL, NULL, NULL}/* sentinel */
|
||||||
|
};
|
||||||
|
|
||||||
|
octx = g_option_context_new ("- procmule options");
|
||||||
|
g_option_context_add_main_entries (octx, entries, "Procmule");
|
||||||
|
|
||||||
|
if (!g_option_context_parse (octx, argcp, argvp, NULL)) {
|
||||||
|
g_printerr ("error in options\n");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!opts->watchdirs) {
|
||||||
|
g_printerr ("specify at least one --watch=<dir>\n");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
expand_paths (opts);
|
||||||
|
|
||||||
|
g_option_context_free (octx);
|
||||||
|
return opts;
|
||||||
|
|
||||||
|
error:
|
||||||
|
if (octx)
|
||||||
|
g_option_context_free (octx);
|
||||||
|
g_free (opts);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
pm_config_destroy (PMConfig *conf)
|
||||||
|
{
|
||||||
|
if (!conf)
|
||||||
|
return;
|
||||||
|
|
||||||
|
g_free (conf->muhome);
|
||||||
|
g_strfreev (conf->watchdirs);
|
||||||
|
|
||||||
|
g_free (conf);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
usage (void)
|
||||||
|
{
|
||||||
|
g_print ("usage: procmule [--muhome=<dir>] [--watch=<dir1>]\n");
|
||||||
|
g_print ("also, see toys/procmule/README\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
watch_dirs (char **watchdirs)
|
||||||
|
{
|
||||||
|
ChildData *child_data;
|
||||||
|
GSList *watchlist;
|
||||||
|
GMainLoop *loop;
|
||||||
|
|
||||||
|
child_data = child_data_new
|
||||||
|
(mu_runtime_path(MU_RUNTIME_PATH_MUHOME));
|
||||||
|
|
||||||
|
watchlist = create_watchlist (watchdirs, child_data);
|
||||||
|
if (!watchlist)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
loop = g_main_loop_new (NULL, TRUE);
|
||||||
|
|
||||||
|
g_main_loop_run (loop);
|
||||||
|
g_main_loop_unref (loop);
|
||||||
|
|
||||||
|
destroy_watchlist (watchlist);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
error:
|
||||||
|
child_data_destroy (child_data);
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
main (int argc, char *argv[])
|
||||||
|
{
|
||||||
|
PMConfig *opts;
|
||||||
|
|
||||||
|
g_type_init ();
|
||||||
|
g_thread_init (NULL);
|
||||||
|
|
||||||
|
#ifdef HAVE_PRE2_GUILE
|
||||||
|
g_warning ("Note: pre-2.x version of guile: procmule will not function "
|
||||||
|
"correctly unless you're using UTF-8 locale.");
|
||||||
|
#endif /* HAVE_PRE2_GUILE */
|
||||||
|
|
||||||
|
opts = pm_config_new (&argc, &argv);
|
||||||
|
if (!opts) {
|
||||||
|
usage ();
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!mu_runtime_init (opts->muhome, "procmule")) {
|
||||||
|
usage ();
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
watch_dirs (opts->watchdirs); /* do it! */
|
||||||
|
mu_runtime_uninit ();
|
||||||
|
|
||||||
|
pm_config_destroy (opts);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
error:
|
||||||
|
pm_config_destroy (opts);
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user