/* The Sieve "environment" extension for GNU Mailutils Copyright (C) 2016-2021 Free Software Foundation, Inc. GNU Mailutils is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNU Mailutils 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with GNU Mailutils. If not, see . */ #ifdef HAVE_CONFIG_H # include #endif #include int retrieve_env (void *item, void *data, size_t idx, char **pval) { mu_sieve_machine_t mach; if (idx) return MU_ERR_NOENT; mach = data; return mu_sieve_get_environ (mach, item, pval); } static int sieve_test_environment (mu_sieve_machine_t mach) { mu_sieve_value_t *name, *key_list; name = mu_sieve_get_arg_untyped (mach, 0); key_list = mu_sieve_get_arg_untyped (mach, 1); return mu_sieve_vlist_compare (mach, name, key_list, retrieve_env, NULL, mach); } static mu_sieve_data_type environ_args[] = { SVT_STRING, SVT_STRING_LIST, SVT_VOID }; static mu_sieve_tag_group_t environ_tag_groups[] = { { mu_sieve_match_part_tags, mu_sieve_match_part_checker }, { NULL } }; int mu_sieve_require_environment (mu_sieve_machine_t mach) { mu_sieve_register_test (mach, "environment", sieve_test_environment, environ_args, environ_tag_groups, 1); return 0; } static char * std_name_get (mu_sieve_machine_t mach) { return strdup (PACKAGE_NAME); } static char * std_version_get (mu_sieve_machine_t mach) { return strdup (PACKAGE_VERSION); } /* "host" => The fully-qualified domain name of the host where the Sieve script is executing. */ static char * std_host_get (mu_sieve_machine_t mach) { char *host; int rc; rc = mu_get_host_name (&host); if (rc == 0) return host; return NULL; } /* "domain" => The primary DNS domain associated with the Sieve execution context, usually but not always a proper suffix of the host name. */ static char * std_domain_get (mu_sieve_machine_t mach) { char *host; int rc; rc = mu_get_host_name (&host); if (rc == 0) { char *p = strchr (host, '.'); if (p) { p = strdup (p + 1); free (host); return p; } return host; } return NULL; } /* FIXME: do we need set? If so, mu_set_host_name is also needed */ struct stdenviron { char *name; char *(*get) (mu_sieve_machine_t); int (*set) (mu_sieve_machine_t, char const *, char const *value); }; static struct stdenviron stdenv[] = { { "domain", std_domain_get, NULL }, { "host", std_host_get, NULL }, { "name", std_name_get, NULL }, { "version", std_version_get, NULL }, { NULL } }; static struct stdenviron const * stdenv_find (char const *name) { struct stdenviron const *p; for (p = stdenv; p->name; p++) if (strcmp (p->name, name) == 0) return p; return NULL; } static char * stdenv_get (mu_sieve_machine_t mach, char const *name) { struct stdenviron const *p = stdenv_find (name); if (!p) return NULL; return p->get (mach); } static int stdenv_set (mu_sieve_machine_t mach, char const *name, char const *value) { struct stdenviron const *p = stdenv_find (name); if (!p) return MU_ERR_NOENT; if (!p->set) return EACCES; return p->set (mach, name, value); } int mu_sieve_get_environ (mu_sieve_machine_t mach, char const *name, char **retval) { char *p; p = stdenv_get (mach, name); if (p) { *retval = p; return 0; } if (!mach->exenv) return MU_ERR_NOENT; p = mu_assoc_get (mach->exenv, name); if (p) { *retval = strdup (p); if (!*retval) return errno; } else return MU_ERR_NOENT; return 0; } int mu_sieve_set_environ (mu_sieve_machine_t mach, char const *name, char const *value) { int rc; rc = stdenv_set (mach, name, value); if (rc == MU_ERR_NOENT) { char **pptr; if (!mach->exenv) { int rc = mu_assoc_create (&mach->exenv, 0); if (rc) return rc; } rc = mu_assoc_install_ref (mach->exenv, name, &pptr); if (rc == 0 || rc == MU_ERR_EXISTS) { char *copy = strdup (value); if (!copy) rc = errno; else { *pptr = copy; rc = 0; } } } return rc; }