aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org>2014-08-25 19:13:37 +0300
committerSergey Poznyakoff <gray@gnu.org>2014-08-25 19:20:00 +0300
commite26cb120ffe5f7303ddd8b514246ac6874e83f9f (patch)
tree64ca646b34103a5e8934b42fbbd9ca732a14e034
parent713bc0ca4b4ea3114d33f06c57c117de7f9fef11 (diff)
downloaddirevent-e26cb120ffe5f7303ddd8b514246ac6874e83f9f.tar.gz
direvent-e26cb120ffe5f7303ddd8b514246ac6874e83f9f.tar.bz2
I18N
* .gitignore: Add am * bootstrap: Create am, unless exists. * Makefile.am (SUBDIRS): Add po * acinclude.m4: New file. * configure.ac: Use gettext * doc/direvent.texi: Update * po/.gitignore: New file * po/POTFILES.in: New file. * po/Makevars: New file. * src/Makefile.am (LDADD): Add @LIBINTL@ (noinst_HEADERS): Add gettext.h * src/config.c: gettextize * src/direvent.c: Likewise. * src/environ.c: Likewise. * src/hashtab.c: Likewise. * src/progman.c: Likewise. * src/watcher.c: Likewise. * src/gettext.h: New file. * src/direvent.h: Add missing prototypes. * tests/re05.at: Remove superfluous quoting.
-rw-r--r--.gitignore1
-rw-r--r--Makefile.am6
-rw-r--r--acinclude.m444
-rwxr-xr-xbootstrap1
-rw-r--r--configure.ac9
-rw-r--r--doc/direvent.texi12
m---------grecs0
-rw-r--r--po/.gitignore20
-rw-r--r--po/Makevars41
-rw-r--r--po/POTFILES.in9
-rw-r--r--src/Makefile.am3
-rw-r--r--src/config.c103
-rw-r--r--src/direvent.c16
-rw-r--r--src/direvent.h13
-rw-r--r--src/environ.c3
-rw-r--r--src/gettext.h280
-rw-r--r--src/hashtab.c6
-rw-r--r--src/progman.c32
-rw-r--r--src/watcher.c28
-rw-r--r--tests/re05.at2
20 files changed, 524 insertions, 105 deletions
diff --git a/.gitignore b/.gitignore
index 0417a59..771518c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -11,12 +11,13 @@ ABOUT-NLS
ChangeLog
INSTALL
Makefile
Makefile.in
TAGS
aclocal.m4
+am
autom4te.cache
build-aux
config.h
config.h.in
config.log
config.status
diff --git a/Makefile.am b/Makefile.am
index ea87088..9b13324 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -11,17 +11,19 @@
# 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 Direvent. If not, see <http://www.gnu.org/licenses/>.
-ACLOCAL_AMFLAGS = -I grecs/am
+ACLOCAL_AMFLAGS = -I am -I grecs/am
-SUBDIRS=grecs src tests doc
+SUBDIRS= grecs src tests doc po
.PHONY: ChangeLog
ChangeLog:
$(AM_V_GEN)if test -d .git; then \
git log --pretty='format:%ct %an <%ae>%n%n%s%n%n%b%n' | \
awk -f $(top_builddir)/grecs/build-aux/git2chg.awk > ChangeLog; \
fi
+
+EXTRA_DIST = build-aux/config.rpath
diff --git a/acinclude.m4 b/acinclude.m4
new file mode 100644
index 0000000..31651bc
--- /dev/null
+++ b/acinclude.m4
@@ -0,0 +1,44 @@
+# This file is part of Direvent -*- autoconf -*-
+# Copyright (C) 2012-2014 Sergey Poznyakoff
+#
+# Direvent 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.
+#
+# Direvent 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 Direvent. If not, see <http://www.gnu.org/licenses/>.
+
+AC_DEFUN([DEVT_CC_OPT],[
+ m4_pushdef([devt_optname],translit($1,[-],[_]))
+ AC_MSG_CHECKING(whether $CC accepts $1)
+ devt_save_cc="$CC"
+ CC="$CC $1"
+ AC_TRY_RUN([int main() { return 0; }],
+ [devt_cv_cc_]devt_optname=yes,
+ [devt_cv_cc_]devt_optname=no,
+ [devt_cv_cc_]devt_optname=no)
+ CC="$devt_save_cc"
+ AC_MSG_RESULT($[devt_cv_cc_]devt_optname)
+
+ if test $[devt_cv_cc_]devt_optname = yes; then
+ ifelse([$2],,:,[$2])
+ ifelse([$3],,,else
+ [$3])
+ fi
+ m4_popdef([devt_optname])
+ ])
+
+AC_DEFUN([DEVT_CC_OPT_CFLAGS],[
+ DEVT_CC_OPT([$1],[CFLAGS="$CFLAGS $1"])
+])
+
+AC_DEFUN([DEVT_CC_PAREN_QUIRK],[
+ DEVT_CC_OPT_CFLAGS([-Wno-parentheses])
+])
+
diff --git a/bootstrap b/bootstrap
index ae677ac..8a0292b 100755
--- a/bootstrap
+++ b/bootstrap
@@ -1,5 +1,6 @@
#! /bin/sh
set -e
+test -d am || mkdir am
git submodule init
git submodule update
autoreconf -f -i -s
diff --git a/configure.ac b/configure.ac
index c4060d8..57cda4b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -25,12 +25,13 @@ AM_INIT_AUTOMAKE([1.11.5 gnits tar-ustar silent-rules])
# Enable silent rules by default:
AM_SILENT_RULES([yes])
# Checks for programs.
AC_PROG_AWK
AC_PROG_CC
+DEVT_CC_PAREN_QUIRK
AC_PROG_RANLIB
AC_PROG_INSTALL
AC_PROG_MAKE_SET
# Checks for libraries.
@@ -62,16 +63,22 @@ AH_TOP([
#define IFACE_KQUEUE 1 /* kqueue - BSD */
])
# Grecs subsystem
GRECS_SETUP([grecs],[tree-api git2chg no-preproc getopt tests])
+GRECS_HOST_PROJECT_INCLUDES='-I$(top_srcdir)/src'
+
+# Gettext.
+AM_ICONV
+AM_GNU_GETTEXT([external], [need-formatstring-macros])
+AM_GNU_GETTEXT_VERSION([0.18])
# Initialize the test suite.
AC_CONFIG_TESTDIR(tests)
-AC_CONFIG_FILES([tests/Makefile tests/atlocal])
+AC_CONFIG_FILES([tests/Makefile tests/atlocal po/Makefile.in])
AM_MISSING_PROG([AUTOM4TE], [autom4te])
AC_CONFIG_COMMANDS([status],[
cat <<EOT
Selected interface: $iface
diff --git a/doc/direvent.texi b/doc/direvent.texi
index 46b9a35..104ced0 100644
--- a/doc/direvent.texi
+++ b/doc/direvent.texi
@@ -1,13 +1,13 @@
\input texinfo @c -*-texinfo-*-
@smallbook
@c %**start of header
@setfilename direvent.info
@settitle GNU Direvent
@c %**end of header
-@setchapternewpage odd
+@c @setchapternewpage odd
@defcodeindex pr
@defcodeindex op
@defcodeindex kw
@defcodeindex fl
@@ -109,13 +109,13 @@ and system-independent command-level interface. As of version
@node Overview
@chapter Overview
@GNUDIREVENT{} monitors a set of directories on the file system and
reacts when a file system event occurs in any of them. Directories
and events to monitor are specified in the configuration file. When
-an event occurs the utility reacts by invoking an external command
+an event occurs, the program reacts by invoking an external command
configured for that event.
@cindex events
@cindex file system events
File system events can be divided into two major groups. The
@dfn{system-dependent events} are specific for each particular kernel
@@ -143,13 +143,13 @@ A file was written to;
File attributes have changed. This includes changes in the file
ownership, mode, link count, etc.
@end table
@cindex watcher, introduced
@cindex handler, introduced
-A @dfn{watcher} is a configuration entity which associates a set of
+A @dfn{watcher} is a configuration entity that associates a set of
directories with a set of events and instructs @command{direvent} to
run a specified external command when any of these events occur in any
of these directories. This external command (called a @dfn{handler})
can obtain information about the event that triggered it
from the environment variables, or from its command line.
@@ -178,22 +178,24 @@ any amount of whitespace and is terminated with a semicolon. A block
statement is a collection of statements enclosed in curly braces.
@cindex watcher declaration, summary
The following block statement declares a watcher:
@example
+@group
watcher @{
path @var{pathname} [recursive [@var{level}]];
+ file @var{pattern-list};
event @var{event-list};
command @var{command-line};
- file @var{pattern-list};
user @var{name};
timeout @var{number};
environ @var{env-spec};
option @var{string-list};
@}
+@end group
@end example
Each @code{watcher} statement instructs @command{direvent} to monitor
events listed in @var{event-list} occurring in the directories
specified by @var{pathname}s in @code{path} statements (any number of
@code{path} statements can be given). When any such event is detected,
@@ -233,13 +235,13 @@ watcher @{
path /home/ftp/incoming;
event create;
# @r{more statements follow...}
@end example
On this event, the watcher is to invoke @file{/usr/bin/upload}
-with the name of created file as an argument. To make it
+with the name of the created file as an argument. To make it
possible, the @command{direvent} configuration file provides @dfn{macro
variables}, which can be used in the @code{command} argument at
configuration time and which are expanded to the actual values before
the command is executed. Macro variables are referred to using the
same syntax as shell variables: a dollar sign followed by the variable
name, optionally enclosed in curly braces. The @samp{file} variable
diff --git a/grecs b/grecs
-Subproject 57a00b140954a2c22ba2fdebc93e8e6eda41b2a
+Subproject 477701c059d73e47aa1bac97e96d801542f2bd8
diff --git a/po/.gitignore b/po/.gitignore
new file mode 100644
index 0000000..32545fd
--- /dev/null
+++ b/po/.gitignore
@@ -0,0 +1,20 @@
+*.gmo
+*.po
+*.po~
+.pot
+.reference/
+LINGUAS
+Makefile.in.in
+Makevars.template
+POTFILES
+Rules-quot
+boldquot.sed
+en@boldquot.header
+en@quot.header
+insert-header.sed
+insert-header.sin
+direvent.pot
+quot.sed
+remove-potcdate.sed
+remove-potcdate.sin
+stamp-po
diff --git a/po/Makevars b/po/Makevars
new file mode 100644
index 0000000..33b0663
--- /dev/null
+++ b/po/Makevars
@@ -0,0 +1,41 @@
+# Makefile variables for PO directory in any package using GNU gettext.
+
+# Usually the message domain is the same as the package name.
+DOMAIN = $(PACKAGE)
+
+# These two variables depend on the location of this directory.
+subdir = po
+top_builddir = ..
+
+# These options get passed to xgettext.
+XGETTEXT_OPTIONS = --keyword=_ --keyword=N_
+
+# This is the copyright holder that gets inserted into the header of the
+# $(DOMAIN).pot file. Set this to the copyright holder of the surrounding
+# package. (Note that the msgstr strings, extracted from the package's
+# sources, belong to the copyright holder of the package.) Translators are
+# expected to transfer the copyright for their translations to this person
+# or entity, or to disclaim their copyright. The empty string stands for
+# the public domain; in this case the translators are expected to disclaim
+# their copyright.
+COPYRIGHT_HOLDER = Sergey Poznyakoff
+
+# This is the email address or URL to which the translators shall report
+# bugs in the untranslated strings:
+# - Strings which are not entire sentences, see the maintainer guidelines
+# in the GNU gettext documentation, section 'Preparing Strings'.
+# - Strings which use unclear terms or require additional context to be
+# understood.
+# - Strings which make invalid assumptions about notation of date, time or
+# money.
+# - Pluralisation problems.
+# - Incorrect English spelling.
+# - Incorrect formatting.
+# It can be your email address, or a mailing list address where translators
+# can write to without being subscribed, or the URL of a web page through
+# which the translators can contact you.
+MSGID_BUGS_ADDRESS = bug-direvent@gnu.org.ua
+
+# This is the list of locale categories, beyond LC_MESSAGES, for which the
+# message catalogs shall be used. It is usually empty.
+EXTRA_LOCALE_CATEGORIES =
diff --git a/po/POTFILES.in b/po/POTFILES.in
new file mode 100644
index 0000000..5029ee6
--- /dev/null
+++ b/po/POTFILES.in
@@ -0,0 +1,9 @@
+# List of source files which contain translatable strings.
+
+src/cmdline.h
+src/config.c
+src/direvent.c
+src/environ.c
+src/hashtab.c
+src/progman.c
+src/watcher.c
diff --git a/src/Makefile.am b/src/Makefile.am
index c7f1439..8bdf610 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -38,16 +38,17 @@ if DIREVENT_RFORK
direvent_SOURCES += detach-bsd.c
else
direvent_SOURCES += detach-darwin.c
endif
endif
-LDADD=@GRECS_LDADD@
+LDADD=@GRECS_LDADD@ @LIBINTL@
AM_CPPFLAGS=-I$(top_srcdir)/grecs/src/
BUILT_SOURCES=cmdline.h
EXTRA_DIST=cmdline.opt
+noinst_HEADERS=gettext.h
SUFFIXES=.opt .c .h
.opt.h:
$(AM_V_GEN)m4 -s $(top_srcdir)/@GRECS_SUBDIR@/build-aux/getopt.m4 $< > $@
diff --git a/src/config.c b/src/config.c
index 9c17124..82262a8 100644
--- a/src/config.c
+++ b/src/config.c
@@ -57,13 +57,13 @@ get_facility(const char *arg)
errno = 0;
f = strtoul (arg, &p, 0);
if (*p == 0 && errno == 0)
return f;
if (trans_strtotok(kwfac, arg, &f)) {
- diag(LOG_CRIT, "unknown syslog facility: %s", arg);
+ diag(LOG_CRIT, _("unknown syslog facility: %s"), arg);
exit(1);
}
return f;
}
int
@@ -74,35 +74,35 @@ get_priority(const char *arg)
errno = 0;
f = strtoul (arg, &p, 0);
if (*p == 0 && errno == 0)
return f;
if (trans_strtotok(kwpri, arg, &f)) {
- diag(LOG_CRIT, "unknown syslog priority: %s", arg);
+ diag(LOG_CRIT, _("unknown syslog priority: %s"), arg);
exit(1);
}
return f;
}
#define ASSERT_SCALAR(cmd, locus) \
if ((cmd) != grecs_callback_set_value) { \
- grecs_error(locus, 0, "Unexpected block statement"); \
+ grecs_error(locus, 0, _("unexpected block statement")); \
return 1; \
}
int
assert_grecs_value_type(grecs_locus_t *locus,
const grecs_value_t *value, int type)
{
if (GRECS_VALUE_EMPTY_P(value)) {
- grecs_error(locus, 0, "expected %s",
+ grecs_error(locus, 0, _("expected %s"),
grecs_data_type_string(type));
return 1;
}
if (value->type != type) {
- grecs_error(locus, 0, "expected %s, but found %s",
+ grecs_error(locus, 0, _("expected %s, but found %s"),
grecs_data_type_string(type),
grecs_data_type_string(value->type));
return 1;
}
return 0;
}
@@ -118,32 +118,32 @@ cb_syslog_facility(enum grecs_callback_command cmd, grecs_node_t *node,
ASSERT_SCALAR(cmd, locus);
if (assert_grecs_value_type(&value->locus, value, GRECS_TYPE_STRING))
return 1;
if (trans_strtotok(kwfac, value->v.string, &fac))
grecs_error(&value->locus, 0,
- "Unknown syslog facility `%s'",
+ _("unknown syslog facility `%s'"),
value->v.string);
else
*(int*)varptr = fac;
return 0;
}
static struct grecs_keyword syslog_kw[] = {
{ "facility",
- "name",
- "Set syslog facility. Arg is one of the following: user, daemon, "
- "auth, authpriv, mail, cron, local0 through local7 "
- "(case-insensitive), or a facility number.",
+ N_("name"),
+ N_("Set syslog facility. Arg is one of the following: user, daemon, "
+ "auth, authpriv, mail, cron, local0 through local7 "
+ "(case-insensitive), or a facility number."),
grecs_type_string, GRECS_DFLT,
&facility, 0, cb_syslog_facility },
- { "tag", "string", "Tag syslog messages with this string",
+ { "tag", N_("string"), N_("Tag syslog messages with this string"),
grecs_type_string, GRECS_DFLT,
&tag },
- { "print-priority", "arg",
- "Prefix each message with its priority",
+ { "print-priority", N_("arg"),
+ N_("Prefix each message with its priority"),
grecs_type_bool, GRECS_DFLT,
&syslog_include_prio },
{ NULL },
};
struct eventconf {
@@ -204,13 +204,13 @@ eventconf_flush(grecs_locus_t *loc)
if (!dwp)
abort();
dwp->depth = pe->depth;
for (hp = dwp->handler_list; hp; prev = hp, hp = hp->next) {
if (strcmp(dwp->dirname, pe->path) == 0) {
grecs_error(loc, 0,
- "ignoring duplicate definition");
+ _("ignoring duplicate definition"));
return;
}
}
hp = emalloc(sizeof(*hp));
hp->next = NULL;
@@ -238,32 +238,34 @@ cb_watcher(enum grecs_callback_command cmd, grecs_node_t *node,
void *varptr, void *cb_data)
{
int err = 0;
switch (cmd) {
case grecs_callback_section_begin:
- eventconf_init(&node->locus);
+ eventconf_init();
break;
case grecs_callback_section_end:
if (!eventconf.pathlist) {
- grecs_error(&node->locus, 0, "no paths configured");
+ grecs_error(&node->locus, 0, _("no paths configured"));
++err;
}
if (!eventconf.command) {
- grecs_error(&node->locus, 0, "no command configured");
+ grecs_error(&node->locus, 0,
+ _("no command configured"));
++err;
}
if (evtnullp(&eventconf.eventmask))
evtsetall(&eventconf.eventmask);
if (err == 0)
eventconf_flush(&node->locus);
else
eventconf_free();
break;
case grecs_callback_set_value:
- grecs_error(&node->locus, 0, "invalid use of block statement");
+ grecs_error(&node->locus, 0,
+ _("invalid use of block statement"));
}
return 0;
}
static struct pathent *
pathent_alloc(char *s, long depth)
@@ -302,13 +304,13 @@ cb_path(enum grecs_callback_command cmd, grecs_node_t *node,
if (assert_grecs_value_type(&val->v.arg.v[1]->locus,
val->v.arg.v[1],
GRECS_TYPE_STRING))
return 1;
if (strcmp(val->v.arg.v[1]->v.string, "recursive")) {
grecs_error(&val->v.arg.v[1]->locus, 0,
- "expected \"recursive\" or end of statement");
+ _("expected \"recursive\" or end of statement"));
return 1;
}
switch (val->v.arg.c) {
case 2:
depth = -1;
break;
@@ -317,19 +319,19 @@ cb_path(enum grecs_callback_command cmd, grecs_node_t *node,
val->v.arg.v[2]->v.string,
&val->v.arg.v[2]->locus))
return 1;
break;
default:
grecs_error(&val->v.arg.v[3]->locus, 0,
- "surplus argument");
+ _("surplus argument"));
return 1;
}
s = val->v.arg.v[0]->v.string;
break;
case GRECS_TYPE_LIST:
- grecs_error(locus, 0, "unexpected list");
+ grecs_error(locus, 0, _("unexpected list"));
return 1;
}
pe = pathent_alloc(s, depth);
if (*lpp)
lp = *lpp;
else {
@@ -354,13 +356,13 @@ cb_eventlist(enum grecs_callback_command cmd, grecs_node_t *node,
ASSERT_SCALAR(cmd, locus);
switch (val->type) {
case GRECS_TYPE_STRING:
if (getevt(val->v.string, &m)) {
grecs_error(&val->locus, 0,
- "unrecognized event code");
+ _("unrecognized event code"));
return 1;
}
mask->gen_mask |= m.gen_mask;
mask->sys_mask |= m.sys_mask;
break;
@@ -369,13 +371,13 @@ cb_eventlist(enum grecs_callback_command cmd, grecs_node_t *node,
if (assert_grecs_value_type(&val->v.arg.v[i]->locus,
val->v.arg.v[i],
GRECS_TYPE_STRING))
return 1;
if (getevt(val->v.arg.v[i]->v.string, &m)) {
grecs_error(&val->v.arg.v[i]->locus, 0,
- "unrecognized event code");
+ _("unrecognized event code"));
return 1;
}
mask->gen_mask |= m.gen_mask;
mask->sys_mask |= m.sys_mask;
}
break;
@@ -384,13 +386,13 @@ cb_eventlist(enum grecs_callback_command cmd, grecs_node_t *node,
grecs_value_t *vp = ep->data;
if (assert_grecs_value_type(&vp->locus, vp,
GRECS_TYPE_STRING))
return 1;
if (getevt(vp->v.string, &m)) {
grecs_error(&vp->locus, 0,
- "unrecognized event code");
+ _("unrecognized event code"));
return 1;
}
mask->gen_mask |= m.gen_mask;
mask->sys_mask |= m.sys_mask;
}
break;
@@ -466,34 +468,34 @@ cb_user(enum grecs_callback_command cmd, grecs_node_t *node,
GRECS_TYPE_STRING))
return 1;
if (val->v.arg.c > 2) {
grecs_locus_t loc;
loc.beg = val->v.arg.v[2]->locus.beg;
loc.end = val->v.arg.v[val->v.arg.c - 1]->locus.end;
- grecs_error(&loc, 0, "surplus arguments");
+ grecs_error(&loc, 0, _("surplus arguments"));
return 1;
}
uv = val->v.arg.v[0];
gv = val->v.arg.v[1];
break;
case GRECS_TYPE_LIST:
- grecs_error(locus, 0, "unexpected list");
+ grecs_error(locus, 0, _("unexpected list"));
return 1;
}
pw = getpwnam(uv->v.string);
if (!pw) {
- grecs_error(&uv->locus, 0, "no such user");
+ grecs_error(&uv->locus, 0, _("no such user"));
return 1;
}
if (gv) {
gr = getgrnam(gv->v.string);
if (!gr) {
- grecs_error(&gv->locus, 0, "no such group");
+ grecs_error(&gv->locus, 0, _("no such group"));
return 1;
}
gid = gr->gr_gid;
} else
gid = pw->pw_gid;
@@ -526,13 +528,13 @@ cb_option(enum grecs_callback_command cmd, grecs_node_t *node,
eventconf.flags &= ~HF_NOWAIT;
else if (strcmp(vp->v.string, "stdout") == 0)
eventconf.flags |= HF_STDOUT;
else if (strcmp(vp->v.string, "stderr") == 0)
eventconf.flags |= HF_STDERR;
else
- grecs_error(&vp->locus, 0, "unrecognized flag");
+ grecs_error(&vp->locus, 0, _("unrecognized flag"));
}
return 0;
}
static int
cb_environ(enum grecs_callback_command cmd, grecs_node_t *node,
@@ -604,13 +606,13 @@ file_name_pattern(struct grecs_list *lp, grecs_value_t *val)
char *q, *p;
pat->type = PAT_REGEX;
p = strchr(arg+1, '/');
if (!p) {
- grecs_error(&val->locus, 0, "Unterminated regexp");
+ grecs_error(&val->locus, 0, _("unterminated regexp"));
free(pat);
return 1;
}
for (q = p + 1; *q; q++) {
switch (*q) {
case 'b':
@@ -618,13 +620,13 @@ file_name_pattern(struct grecs_list *lp, grecs_value_t *val)
break;
case 'i':
flags |= REG_ICASE;
break;
default:
grecs_error(&val->locus, 0,
- "Unrecognized flag: %c", *q);
+ _("unrecognized flag: %c"), *q);
free(pat);
return 1;
}
}
*p = 0;
@@ -686,71 +688,66 @@ cb_file_pattern(enum grecs_callback_command cmd, grecs_node_t *node,
}
return 0;
}
static struct grecs_keyword watcher_kw[] = {
- { "path", NULL, "Pathname to watch",
+ { "path", NULL, N_("Pathname to watch"),
grecs_type_string, GRECS_DFLT, &eventconf.pathlist, 0,
cb_path },
- { "event", NULL, "Events to watch for",
+ { "event", NULL, N_("Events to watch for"),
grecs_type_string, GRECS_LIST, &eventconf.eventmask, 0,
cb_eventlist },
- { "file", "regexp", "Files to watch for",
+ { "file", N_("regexp"), N_("Files to watch for"),
grecs_type_string, GRECS_LIST, &eventconf.fnames, 0,
cb_file_pattern },
- { "command", NULL, "Command to execute on event",
+ { "command", NULL, N_("Command to execute on event"),
grecs_type_string, GRECS_DFLT, &eventconf.command },
- { "user", "name", "Run command as this user",
+ { "user", N_("name"), N_("Run command as this user"),
grecs_type_string, GRECS_DFLT, NULL, 0,
cb_user },
- { "timeout", "seconds", "Timeout for the command",
+ { "timeout", N_("seconds"), N_("Timeout for the command"),
grecs_type_uint, GRECS_DFLT, &eventconf.timeout },
- { "option", NULL, "List of additional options",
+ { "option", NULL, N_("List of additional options"),
grecs_type_string, GRECS_LIST, NULL, 0,
cb_option },
- { "environ", "<arg: string> <arg: string>...", "Modify environment",
+ { "environ", N_("<arg: string> <arg: string>..."),
+ N_("Modify environment"),
grecs_type_string, GRECS_DFLT, NULL, 0,
cb_environ },
{ NULL }
};
static struct grecs_keyword direvent_kw[] = {
- { "user", NULL, "Run as this user",
+ { "user", NULL, N_("Run as this user"),
grecs_type_string, GRECS_DFLT, &user },
- { "foreground", NULL, "Run in foreground",
+ { "foreground", NULL, N_("Run in foreground"),
grecs_type_bool, GRECS_DFLT, &foreground },
- { "pidfile", "file", "Set pid file name",
+ { "pidfile", N_("file"), N_("Set pid file name"),
grecs_type_string, GRECS_DFLT, &pidfile },
- { "syslog", NULL, "Configure syslog logging",
+ { "syslog", NULL, N_("Configure syslog logging"),
grecs_type_section, GRECS_DFLT, NULL, 0, NULL, NULL, syslog_kw },
- { "debug", "level", "Set debug level",
+ { "debug", N_("level"), N_("Set debug level"),
grecs_type_int, GRECS_DFLT, &debug_level },
- { "watcher", NULL, "Configure event watcher",
+ { "watcher", NULL, N_("Configure event watcher"),
grecs_type_section, GRECS_DFLT, NULL, 0,
cb_watcher, NULL, watcher_kw },
{ NULL }
};
void
config_help()
{
static char docstring[] =
- "Configuration file structure for direvent.\n"
- "For more information, use `info direvent configuration'.";
+ N_("Configuration file structure for direvent.\n"
+ "For more information, use `info direvent configuration'.");
grecs_print_docstring(docstring, 0, stdout);
grecs_print_statement_array(direvent_kw, 1, 0, stdout);
}
void
-config_init()
-{
- grecs_log_to_stderr = 1;
-}
-
-void
config_finish(struct grecs_node *tree)
{
if (grecs_tree_process(tree, direvent_kw))
exit(1);
}
diff --git a/src/direvent.c b/src/direvent.c
index 7cdd2c1..9dca000 100644
--- a/src/direvent.c
+++ b/src/direvent.c
@@ -135,13 +135,13 @@ debugprt(const char *fmt, ...)
/* Memory allocation with error checking */
void *
emalloc(size_t size)
{
void *p = malloc(size);
if (!p) {
- diag(LOG_CRIT, "not enough memory");
+ diag(LOG_CRIT, _("not enough memory"));
exit(2);
}
return p;
}
void *
@@ -157,13 +157,13 @@ ecalloc(size_t nmemb, size_t size)
void *
erealloc(void *ptr, size_t size)
{
void *p = realloc(ptr, size);
if (!p) {
- diag(LOG_CRIT, "not enough memory");
+ diag(LOG_CRIT, _("not enough memory"));
exit(2);
}
return p;
}
char *
@@ -265,13 +265,13 @@ signal_setup(void (*sf) (int))
void
storepid(const char *pidfile)
{
FILE *fp = fopen(pidfile, "w");
if (!fp) {
- diag(LOG_ERR, "cannot open pidfile %s for writing: %s",
+ diag(LOG_ERR, _("cannot open pidfile %s for writing: %s"),
pidfile, strerror(errno));
} else {
fprintf(fp, "%lu\n", (unsigned long) getpid());
fclose(fp);
}
}
@@ -293,13 +293,13 @@ get_user_groups(uid_t uid, size_t *pgidc, gid_t **pgidv)
gid_t *gidv = NULL;
struct passwd *pw;
struct group *gr;
pw = getpwuid(uid);
if (!pw) {
- diag(LOG_ERR, 0, "no used with UID %lu",
+ diag(LOG_ERR, 0, _("no used with UID %lu"),
(unsigned long)uid);
exit(2);
}
n = 32;
gidv = ecalloc(n, sizeof(gidv[0]));
@@ -420,13 +420,13 @@ self_test()
exit(2);
}
pid = fork();
if (pid == (pid_t)-1) {
diag(LOG_CRIT,
- "cannot run `%s': fork failed: %s",
+ _("cannot run `%s': fork failed: %s"),
self_test_prog, strerror(errno));
exit(2);
}
if (pid != 0) {
self_test_pid = pid;
@@ -470,13 +470,13 @@ main(int argc, char **argv)
argc -= i;
argv += i;
switch (argc) {
default:
- diag(LOG_CRIT, "too many arguments");
+ diag(LOG_CRIT, _("too many arguments"));
exit(1);
case 1:
conffile = argv[0];
break;
case 0:
break;
@@ -516,13 +516,13 @@ main(int argc, char **argv)
diag(LOG_CRIT, "daemon: %s", strerror(errno));
exit(1);
}
log_to_stderr = -1;
}
- diag(LOG_INFO, "%s %s started", program_name, VERSION);
+ diag(LOG_INFO, _("%s %s started"), program_name, VERSION);
/* Write pidfile */
if (pidfile)
storepid(pidfile);
/* Relinquish superuser privileges */
@@ -537,13 +537,13 @@ main(int argc, char **argv)
/* Main loop */
while (!stop && sysev_select() == 0) {
process_timeouts();
process_cleanup(0);
}
- diag(LOG_INFO, "%s %s stopped", program_name, VERSION);
+ diag(LOG_INFO, _("%s %s stopped"), program_name, VERSION);
if (pidfile)
unlink(pidfile);
return exit_code;
}
diff --git a/src/direvent.h b/src/direvent.h
index 33fa768..069d3d8 100644
--- a/src/direvent.h
+++ b/src/direvent.h
@@ -22,12 +22,17 @@
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <regex.h>
+#include "gettext.h"
+
+#define _(s) gettext(s)
+#define N_(s) s
+
/* Generic (system-independent) event codes */
#define GENEV_CREATE 0x01
#define GENEV_WRITE 0x02
#define GENEV_ATTRIB 0x04
#define GENEV_DELETE 0x08
@@ -186,13 +191,16 @@ unsigned hash_string(const char *name, unsigned long hashsize);
struct pathent {
long depth;
size_t len;
char path[1];
};
-
+
+void config_help(void);
+struct grecs_node;
+void config_finish(struct grecs_node *tree);
void config_parse(const char *file);
int get_facility(const char *arg);
int get_priority(const char *arg);
void setup_watchers(void);
@@ -204,12 +212,15 @@ void dirwatcher_destroy(struct dirwatcher *dwp);
int watch_pathname(struct dirwatcher *parent, const char *dirname, int isdir, int notify);
char *split_pathname(struct dirwatcher *dp, char **dirname);
void unsplit_pathname(struct dirwatcher *dp);
void ev_log(int flags, struct dirwatcher *dp);
+void deliver_ev_create(struct dirwatcher *dp, const char *name);
+int subwatcher_create(struct dirwatcher *parent, const char *dirname,
+ int isdir, int notify);
struct process *process_lookup(pid_t pid);
void process_cleanup(int expect_term);
void process_timeouts(void);
int run_handler(struct handler *hp, event_mask *event,
const char *dir, const char *file);
diff --git a/src/environ.c b/src/environ.c
index 5fbd0ac..f0fcce7 100644
--- a/src/environ.c
+++ b/src/environ.c
@@ -13,18 +13,19 @@
You should have received a copy of the GNU General Public License along
with direvent. If not, see <http://www.gnu.org/licenses/>. */
#include "direvent.h"
#include "wordsplit.h"
+#include <ctype.h>
extern char **environ; /* Environment */
#define DEBUG_ENVIRON(l,env) do { \
if (debug_level >= (l)) { \
- diag(LOG_DEBUG, "environment: "); \
+ diag(LOG_DEBUG, _("environment: ")); \
for (i = 0; (env)[i]; i++) \
diag(LOG_DEBUG, "%s ", (env)[i]); \
diag(LOG_DEBUG, "\n"); \
} \
} while (0)
diff --git a/src/gettext.h b