Мы — долго запрягаем, быстро ездим, и сильно тормозим.

RFC
Программирование
FreeBSD
man
EXIM
  4.62
  4.70
  часть 1
  часть 2
  часть 3
  часть 4
  часть 5
  часть 6
  часть 7
  часть 8
  часть 9
  часть 10
  часть 11
  часть 12
  часть 13
  часть 14
  часть 15
  часть 16
  часть 17
  часть 18
  часть 19
  часть 20
  часть 21
  часть 22
  часть 23
  часть 24
  часть 25
  часть 26
  часть 27
  часть 28
  часть 29
  часть 30
  часть 31
  часть 32
  часть 33
  часть 34
  часть 35
  часть 36
  часть 37
  часть 38
  часть 39
  часть 40
  часть 41
  часть 42
  часть 43
  часть 44
  часть 45
  часть 46
  часть 47
  часть 48
  часть 49
  часть 50
  часть 51
  часть 52
  часть 53
  часть 54
  часть 55
  filter facility


www.lissyara.su —> документация —> EXIM —> 4.70 —> часть 42

42. Добавляем функцию “local_scan()” в Exim


    В наши дни, когда количество email-червей, вирусов, спама постоянно увеличивается, некоторые сайты хотят увеличить количество проверок сообщений прежде чем примут их.
   Расширение для проверки содержимого сообщений (глава 41)имеет средство для передачи возможности сканирования сообщений на спам и вирусы внешним программам. Вы также можете делать это непосредственно в Exim, через строки расширения и условия
condition в ACL который запускается после команды SMTP DATA ли ACL для не-SMTP сообщений (см. главу 40), но здесь есть ограничения.
   Для поддержки дополнительных настроек в соответствии с требованиями сайта, можно слинковать Exim с функцией проверки частных сообщений, написанной на C. Если вы хотите запустить код написанный на чем то другом, чем C, Вы конечно же можете использовать C stub для вызова функции.
   Функция local scan запускается единожды для каждого входящего сообщения, в тот момент когда Exim собирается принять сообщение. Поэтому эта возможность может использоваться для локальных не-SMTP сообщений также, как и для сообщений пришедших по SMTP.
   Exim применяет таймаут к запросам функции local scan, опция которая задает это, называется
local_scan_timeout. По умолчанию параметр равен 5 минутам. Ноль обозначает «непрерывно». Exim так же настраивает обработчики сигналов для SIGSEGV, SIGILL, SIGFPE, и  SIGBUS перед вызовом функции local scan, для того что бы общие типы некорректного завершения были очевидны. Если время перерыва превышено или получен один из сигналов, входящее сообщение отклоняется с ошибкой по времени, если это SMTP сообщение. Для не-SMTP сообщений сообщение сбрасывается и Exim завершает работу с кодом ошибки. Происшествие отражается в main и reject логах.

42.1 Сборка Exim с использованием функции local_scan()

   Для использования функции local scan, вы должны указать указать местоположение Вашей функции перед сборкой Exim, установкой LOCAL_SCAN_SOURCE в файле Local/Makefile. Рекомендованное место хранения директория Local поэтому можно установить
LOCAL_SCAN_SOURCE=Local/local_scan.c

для примера. Функция должна называться local_scan(). Она вызывается Exim'ом после получения сообщения, перед отправкой кода успешного выполнения. Это после всех запущенных ACL. Код возврата вашей функции контролирует принято ли сообщение или нет. Есть закоментированый шаблон функции (который принимает сообщение) в файле src/local_scan.c_.
   Если вы хотите использовать файл конфигурации Exim'а для установки опций для вашей функции local_scan(), вы должны установить
LOCAL_SCAN_HAS_OPTIONS=yes

в файле Local/Makefile (смотрите раздел 42.3 ниже).

42.2 API для local_scan()

   Вы должны включить эту строку в начале вашего кода:
#include "local_scan.h"

   Этот заголовочный файл определяет количество переменных, других значений и прототип самой функции. Exim написан для использования, практически исключительно, беззнаковых символов (unsigned char) и одна из вещей которую определяет заголовок – сокращение для беззнаковых символов, называемое  uschar. Он так же содержит следующие макро определения, для упрощения отбора символьных строк и указателей на символьные строки.
#define CS   (char *)
#define CCS  (const char *)
#define CSS  (char **)
#define US   (unsigned char *)
#define CUS  (const unsigned char *)
#define USS  (unsigned char **)

   Прототип функции local_scan() это:
extern int local_scan(int fd, uschar **return_text);

   Аргументы следующие:

  • fd – файловый дескриптор для файла который содержит тело сообщения (-D файл). Файл открыт для записи и чтения, но обновление не рекомендуется. Предупреждение: Вы не должны закрывать файловый дескриптор.
       Дескриптор позиционируется на 19 символе в файле, в котором первый символ само тело, потому как первые 19 символов ID сообщения, следующий за ним -D и символ newline. Если вы переместитесь в начало файла, вы должны использовать макрос SPOOL_DATA_START_OFFSET для того что бы сбросить начало данных, чтобы не зависеть отт изменений в последующих версиях.
  • return_text – адрес который вы можете использовать возвратив указатель на текстовую строку в конце функции. Значение на которое указывает при входе - NULL.
       Функция должна возвратить значение
    int, которое является одним из следующих макросов:
  • LOCAL_SCAN_ACCEPT - Сообщение принято. Если вы пропустите назад строку текста, это сохранится с сообщением и будет доступно в переменной $local_scan_data. Никаких символов новых строк не поддерживается (если таковые присутствуют, они буду превращены в пробел) и максимальная длина текста 1000 символов.
  • LOCAL_SCAN_ACCEPT_FREEZE - Ведет себя так же как и LOCAL_SCAN_ACCEPT, за исключением того, что принятое сообщение становиться в очередь без незамедлительной доставки и замораживается.
  • LOCAL_SCAN_ACCEPT_QUEUE - Ведет себя так же как и LOCAL_SCAN_ACCEPT, за исключением того, что принятое сообщение становиться в очередь без незамедлительной доставки.
  • LOCAL_SCAN_REJECT - Сообщение отклонено; возвращаемый текст используется как ошибка, который отсылается обратно отправителю и которое протоколируется. Символы newlines поддерживаются, они разрешают многострочный ответ для SMTP отклонений, но конвертируются в \n в логах. Если никакое сообщение не присвоено, используется Administrative prohibition.
  • LOCAL_SCAN_TEMPREJECT - Сообщение временно отклонено. Возвращаемый текст используется как сообщение об ошибке, так же как и LOCAL_SCAN_REJECT. Если никакое сообщение не присвоено используется Temporary local problem.
  • LOCAL_SCAN_REJECT_NOLOGHDR - Ведет себя так же как и LOCAL_SCAN_REJECT, за исключением того что заголовок отклоненного сообщения не записывается в лог отклонений. Эффект неустановленного rejected_header в выборе логов только для этого отклонения. Если rejected_header уже не установлен (см. обсуждение log_selection в главе 49.15) код тот же самый что и у LOCAL_SCAN_REJECT.
  • LOCAL_SCAN_TEMPREJECT_NOLOGHDR - Этот код – такое же изменение LOCAL_SCAN_TEMPREJECT, как и LOCAL_SCAN_REJECT_NOLOGHDR изменение LOCAL_SCAN_REJECT.
       Если сообщение не было получено интерактивно по SMTP, об отклонениях сообщается  записью в
    stderr или отправкой письма, как сконфигурировано опциями -oe в командной строке.

    42.3 Опции конфигурации для local_scan()

       Возможно использовать установку опции, которая устанавливает значения в статических переменных, в модуле local_scan(). Если вы этого хотите, вы должны иметь строку
    LOCAL_SCAN_HAS_OPTIONS=yes
    

    в файле Local/MakefileLocal/Makefile когда вы  собираете Exim. (Эта строка находится в OS/Makefile-Default, закомментированная). Затем в исходном файле local_scan() вы должны определить статические переменные, для хранения значений и таблицу, определяющую их.
       Таблица должна быть вектором называемым
    local_scan_options, типа optionlist. Каждая точка входа – тройное значение состоящее из имени, типа опции, и указателя на переменную содержащую значение. Точки входа должны следовать в алфавитном порядке. Следуя за local_scan_options, вы должны так же определить значение переменной называемой local_scan_options_count содержащую количество входов в таблицу. Вот краткий пример, демонстрирующий две опции:
    static int my_integer_option = 42;
    static uschar *my_string_option = US"a default string";
    
    optionlist local_scan_options[] = {
      { "my_integer", opt_int,       &my_integer_option },
      { "my_string",  opt_stringptr, &my_string_option }
    };
    
    int local_scan_options_count =
      sizeof(local_scan_options)/sizeof(optionlist);
    

       Значения переменных могут быть изменены Exim'ом из файла конфигурации включением секции local scan, так, как в этом примере:
    begin local_scan
    my_integer = 99
    my_string = some string of text...
    

       Доступные типы данных следующие:

  • opt_bool - Определяет булеву опцию (да/нет). Адрес должен указывать на переменную типа BOOL, которая устанавливается в TRUE или FALSE, которые являются макросами определенными как 1 и 0, соответственно. Если вы хотите определить была ли установлена такая переменная вообще, то вы можете вызвать ее как TRUE_UNSET. (Переменные BOOL – целочисленные, которые могут содержать более двух значений).
  • opt_fixed - Эта опция определяет число с фиксированной точкой (целочисленное). Адрес должен указывать на переменную типа int. Хранимое значение умножается на 1000, так например, значение 1.4142 отрежется и сохранится как 1414.
  • opt_int - Эта опция определяет целое число, адрес должен указывать на переменную типа int. Значение может быть определено в любом целочисленном формате, понимаемым Exim'ом.
  • opt_mkint - То же самое как opt_int, за исключением того, что значение выводится в -bP листинг, если в нем точное число килобайтов и мегабайтов, печатается с суффиксом K или M.
  • opt_octint - Опция тоже определяет число, как целочисленное, только значение интерпретируется всегда как восьмиричное целочисленное. Начинается с цифры 0 и выводится в восьмиричном счислении.
  • opt_stringptr - Определяет значение строки, адрес должен быть указателем на переменную, которая указывает на строку (например, тип uschar *).
  • opt_time - Определяет интервал времени. Адрес должен указывать на переменную типа int. Значение которое туда записывается, число в секундах.
       Если в командной строке за local_scan следует параметр
    -bP, Exim выводит значения всех опций local_scan().

    42.4 Доступные переменные Exim

       Заголовок local_scan.h дает вам доступ к некоторым С переменным. Тут перечислены только те, которые, гарантировано, будут поддерживаться от релиза к релизу. Заметьте, как бы то ни было, вы можете получить любое значение переменной Exim, включая $recipients вызывая функцию expand_string(). Экспортируемые переменные C следующие:

  • int body_linecount - Эта переменная содержит число строк в теле сообщения.
  • int body_zerocount - Эта переменная содержит число бинарных нулей в теле сообщения.
  • unsigned int debug_selector - Это переменная устанавливается в ноль, когда отладка не производится. Иначе – это набор значений отладочных селекторов. Два бита используются в функции  local_scan(); они определяются как макросы:
    — D_v - бит установлен, когда
    -v присутствует в коммандной строке. Эта тестовая опция не на что не влияет, любой вызов может установить ее. Остальные биты могут установить только администраторы.
    — D_local_scan – бит для использования функцией
    local_scan(); устанавливается в +local_scan отладочным селектором. По умолчанию не включается в дефолтовый набор отладочных битов. Таким образом, что бы получить отладочный вывод, только когда +local_scan включен, вам нужно написать следующее:
    if ((debug_selector & D_local_scan) != 0)
      debug_printf("xxx", ...);
    

  • uschar *expand_string_message - После неудачной попытки вызвать expand_string() (Возвращаемое значение NULL) переменная expand_string_message содержит сообщение об ошибке, завершается нулем.
  • header_line *header_list - Указатель на цепочку строк заголовка. Структура header_line обсуждается ниже.
  • header_line *header_last - Указатель на последнюю строку заголовка.
  • uschar *headers_charset - Значение опции конфигурации headers_charset.
  • BOOL host_checking - Эта переменная TRUE в момент проверки хоста, инициализируемого опцией -bh командной строки.
  • uschar *interface_address - IP адрес интерфейса который получает сообщения, тип – строка. Значение NULL для локальных сообщений.
  • int interface_port - Порт, на котором было получено это сообщение. При тестировании с опцией командной строки -bh, значение этой переменной равно -1, кроме случая когда порт был определён через опцию -oMi.
  • uschar *message_id - Переменная содержащая идентификаторы сообщений Exim'а для входящих сообщений (значение $message_exim_id), заканчивающаяся нулем.
  • uschar *received_protocol - Имя протокола, по которому было получено сообщение.
  • int recipients_count - Число подтвержденных получателей.
  • recipient_item *recipients_list - Список подтвержденных получателей, хранящийся как вектор длины recipients_count. Структура recipient_item обсуждается ниже. Вы можете добавлять получателей вызывая, receive_add_recipient() (см. ниже). Вы можете удалять получателей, убирая их из вектора и исправляя значение в recipients_count. В частности, устанавливая recipients_count в ноль вы удаляете всех получателей. Если вы затем возвратите значение LOCAL_SCAN_ACCEPT, сообщение будет принято, но тут же исчезнет. Для замещения получателей вы можете установить recipients_count в ноль и затем вызвать receive_add_recipient() так часто как это необходимо.
  • uschar *sender_address - Адрес отправителя. Для отвергнутых сообщений это пустая строка.
  • uschar *sender_host_address - IP адрес хоста отправителя. Для локальных сообщений NULL.
  • uschar *sender_host_authenticated - Имя аутентификационного механизма, который был использован, или NULL если сообщение было получено не через SMTP соединение с аутентификацией.
  • uschar *sender_host_name - Имя хоста отправителя, если известно.
  • int sender_host_port - Порт хоста отправителя.
  • BOOL smtp_input - Переменная равна TRUE для всех входящих SMTP, включая BSMTP.
  • BOOL smtp_batched_input - Переменная равна TRUE для входящих BSMTP.
  • int store_pool - Содержимое этой переменной определяет какой пул памяти будет использоваться для новых запросов. (См. секцию 42.8 для более детальной информации).

    42.5 Структура header_line

    Структура header_line, содержит элементы упомянутые ниже. Вы можете добавить дополнительные строки заголовка, вызывая функцию header_add()(см. ниже). Вы можете комментировать (удалять) линии заголовка, устанавливая их тип в *.

  • struct header_line *next - Указатель на следующую строку заголовка, или на NULL, для последней строки.
  • int type - Код идентифицирующий определенные заголовки, которые Exim распознает.
    Коды, печатные символы, документированные в главе 53 этого руководства. Обратите внимание, любая строка заголовка тип которой -
    *, не передается с сообщением. Эта отметка используется для линий заголовка которые были перезаписаны, (например Envelope-sender: header lines). Зачастую, * означает удалено.
  • int slen - Число символов в строке заголовка, включая символы завершения и символы новой строки.
  • uschar *text - Указатель на текст заголовка. Всегда заканчивается символом новой строки, сопровождаемый нулевым байтом. Внутренние символы новой строки сохраняются.

    42.6 Структура recipient_item

    Структура recipient_item содержит следующие элементы:

  • uschar *address - Указатель на адрес получателя, который был получен.
  • int pno - Используется Exim'ом позже в обработке, когда главные адреса созданы опцией one_time. Несущественна, в то время, когда local_scan() работает, и должен содержать всегда -1 на этом этапе.
  • uschar *errors_to - Если значение не NULL, отталкивет сообщение из-за невозможности доставки получателю по адресу который содержит. Другими словами отвергает отправителя конверта для одного адресата (Сравните с errors_to в общих опциях маршрутизации). Если функция local_scan() устанавливает поле errors_to неквалифицированному адресу, Exim квалифицирует используя домен из qualify_recipient. Когда функция local_scan() вызвана, поле errors_to содержит NULL для всех адресатов.

    42.7 Доступные функции Exim

       Заголовок local_scan.h дает вам доступ к некоторому числу функций Exim. Здесь представлены только те, которые гарантированно будут поддерживаться от релиза к релизу.
    pid_t child_open(uschar **argv, uschar **envp, int newumask, int *infdptr, int *outfdptr,   BOOL make_leader)
       Эта функция создает дочерний процесс, который запускает команду определенную в
    argv. Окружение этого процесса определено в envp, который может быть NULL, если не передаются переменные окружения. Новое unmask служит для процесса в newumask.
       Пайпы стандартного ввода и вывода нового процесса уже настроены и возвращаются вызвавшему через аргументы
    infdptr и outfdptr. Стандартная ошибка клонируется в стандартный вывод. Если есть дескрипторы для файла «в пути» в новом процессе, то они закрываются. Если последний аргумент TRUE, новый процесс возглавляет группу процессов.
       Функция возвращает pid нового процесса, или -1 если что то пошло не так.

    int child_close(pid_t pid, int timeout)
       Функция ждет, когда дочерний процесс завершится, или таймаут (в секундах). Значение таймаута установленное в 0, означает ждать столько, сколько потребуется. Возвращаемые значения следующие:

  • >= 0 Завершение процесса корректно, возвращаемое значение это статус процесса.
  • < 0 and > –256 Процесс завершен сигналом, и возвращаемое значение сигнал процесса со знаком минус.
  • –256 Время процесса истекло.
  • –257 Произошла какая-то другая ошибка в wait(); errno все еще установлен.

    pid_t child_open_exim(int *fd)
       Функция предоставляет Вам средства создания нового сообщения Exim. (Конечно вы можете всегда вызвать
    /usr/sbin/sendmail сами, если хотите, в этом пакете есть все для вас). Функция создает пайп, форки и подпроцесс который запускается
    exim -t -oem -oi -f <>
    

    и возвращает (через аргумент int *) файловый дескриптор для пайпа который подключен к стандартному вводу. Конечный результат фукции - PID подпроцесса. Затем вы можете написать сообщение файловому дескриптору, с получателями в поле To, Cc: и/или Bcc: строками в заголовке.
       Когда вы закончите, вызовите
    child_close(), подождите пока процесс завершится и получите его статус окончания. Таймаут со значением ноль обычно неплохо в этих обстоятельствах. До тех пор пока вы не сделаете ошибку в адресе получателя, вы должны получать код возврата 0.

    pid_t child_open_exim2(int *fd, uschar *sender, uschar *sender_authentication)
       Эта функция более сложная версия
    child_open(). Команда которая загружает ее:
    exim -t -oem -oi -f sender -oMas sender_authentication
    

       Третий аргумент может быть NULL, в этом случае опция -oMas опущена.

    void debug_printf(char *, ...)
       Это отладочная функция Exim'а, с аргументами как для
    printf(). Вывод производится в поток стандартных ошибок. Если отладка не выбрана вызов debug_printf() не будет иметь эффекта. Обычно вы должны делать вызовы по состоянию селекторов local_scan написав это так:
    if ((debug_selector & D_local_scan) != 0)
      debug_printf("xxx", ...);
    

    uschar *expand_string(uschar *string)
       Интерфейс для расширения строки Exim'а. Возвращаемое значение - расширяемая строка, или NULL, если расширение не произошло. Переменная C
    expand_string_message содержит сообщение об ошибке, после невозможности расширения. Если расширение не меняет строку, возвращаемое значение является указателем на строку ввода. В другом случае, возвращаемое значение указывает на новый блок памяти, который был получен вызовом store_get(). (см. раздел 42.8 ниже, где обсуждается выделение памяти).

    void header_add(int type, char *format, ...)
       Эта функция позволяет добавить дополнительную строку заголовка в конец уже существующей. Первый аргумент – тип, который обычно начинается пробелом. Второй аргумент форматированная строка, и любой номер заменяемых аргументов как для
    sprintf(). Вы можете включать внутренний символ новой строки и вы должны убедится, что строка заканчивается символом новой строки.

    void header_add_at_position(BOOL after, uschar *name, BOOL topnot, int type, char *format,   ...)
       Функция добавляет новую строку заголовка в определенную точку в цепочке заголовков.  Сам заголовок определен как для
    header_add().
       Если
    name NULL, новый заголовок добавляется в конец цепочки, при условии что after TRUE, или в начало, если after FALSE. Если name не NULL, строки заголовка ищутся до первого неудаленного заголовка, который совпадает с именем. Если что то найдено, новый заголовок добавляется до него, если значение after FALSE. Если after TRUE, добавляется новый заголовок после найденного заголовка и любых найденных последующих с таким же именем (даже если они отмечены как deleted). Если нет совпадений с non-deleted заголовком, то опция topnot проверяет где был добавлен заголовок. Если он добавлялся – дополнение на верху, если нет то – внизу. Таким образом, что бы добавить заголовок после всех заголовков с полем Received: или в начало, если нет заголовков Received:, вы должны использовать:
    header_add_at_position(TRUE, US"Received", TRUE,
      ' ', "X-xxx: ...");
    

       Обычно присутствует хотя бы один не удаленный заголовок Received:, но его может не оказаться если received_header_text расширяется пустой строкой.

    void header_remove(int occurrence, uschar *name)
       Функция удаляет строки заголовка. Если
    occurrence равно нулю или отрицательное - заголовок удаляется.  Если occurrence больше нуля, удаляется часть заголовка. Если никаких совпадений не найдено, функция не делает ничего.

    BOOL header_testname(header_line *hdr, uschar *name, int length, BOOL notdel)
       Функция проверяет имеет ли данный заголовок данное имя. Это не просто сравнение строк, потому что непоказываемый пробел допускается между именем и двоеточием. Если аргумент
    notdel TRUE, тогда возвращаемое FALSE применяется для всех deleted заголовков, иначе они не рассматриваются. Например:
    if (header_testname(h, US"X-Spam", 6, TRUE)) ...
    

    uschar *lss_b64encode(uschar *cleartext, int length)
       Эта функция кодирует (base64) строку, которая передаётся по адресу и длине. Текст может содержать байты любого значения включая ноль. Результат возвращается в динамическую память которая динамически получается вызовом
    store_get(). Заканчивается нулем.

    int lss_b64decode(uschar *codetext, uschar **cleartext)
       Функция декодирования  base64 строки. Если аргумент заканчивающаяся нулем base64 строка, и адрес переменной который указывает на результат, находящийся в динамической памяти. Длина декодируемой строки получается после выполнения функции. Если вводимые данные неправильные, то результат -1. Нулевой байт добавляется в конце выводимой строки, для более простого ее определения, как С строки (предполагается что она не содержит собственных нулей). Добавляемый нулевой байт не считается.

    int lss_match_domain(uschar *domain, uschar *list)
       Функция проверяет совпадения в доменном списке. Домены всегда выбираются бессистемно. Возвращемое значение одно из следующих:
    OK      match succeeded
    FAIL    match failed
    DEFER   match deferred
    

       Deffer обычно вызван каким либо поиском, таким как невозможность связаться с базой данных.

    int lss_match_local_part(uschar *localpart, uschar *list, BOOL caseless)
       Функция проверяет совпадения в локальном списке. Третий аргумент контролирует чувствительность к регистру. Возвращаемое значение такое же как и для
    lss_match_domain().

    int lss_match_address(uschar *address, uschar *list, BOOL caseless)
       Эта функция проверяет совпадения для списка адресов. Третий аргумент контролирует чувствительность к регистру. Домены всегда выбираются бессистемно. Возвращаемое значение такое же как и для
    lss_match_domain().

    int lss_match_host(uschar *host_name, uschar *host_address, uschar *list)
       Функция проверяет совпадения в списке хостов. Самое распространенное использование:
    lss_match_host(sender_host_name, sender_host_address, ...)
    

       Пустое поле адреса, совпадает с пустым записью в списке хостов. Если имя хоста  NULL, соответствие названия $sender_host_address ищется автоматически, если название хоста должно совпадать с именем в списке. Возвращаемые значения такие же как и в lss_match_domain(), но в дополнении lss_match_domain() возвращает ERROR в случае, когда имя искалось и не нашлось.

    void log_write(unsigned int selector, int which, char *format, ...)
       Эта функция записывает лог файлы Exim'а. Первый аргумент должен быть 0 (это связано с
    log_selector). Следующий аргумент должен быть LOG_MAIN или LOG_REJECT, или LOG_PANIC или любую их комбинацию (лог. ИЛИ (OR)). Это определяет в какой лог или логи будет записано сообщение. Оставшиеся аргументы – это формат и вставка. Строка не должна включать символов новой строки, даже в конце.

    void receive_add_recipient(uschar *address, int pno)
       Эта функция добавляет дополнительного получателя к сообщению. Первый аргумент – это адрес получателя. Если адрес не квалифицирован (не имеет домена) он квалифицируется с
    qualify_recipient доменом. Второй аргумент должен быть всегда -1.
       Функция не позволяет вам определить частный
    errors_to адрес (как описано в структуре recipient_item выше) потому что это предшествует дополнению поля к структуре. Однако, в последствии легко добавить это значение. Например:
    receive_add_recipient(US"monitor@mydom.example", -1);
    recipients_list[recipients_count-1].errors_to =
    US"postmaster@mydom.example";
    

    BOOL receive_remove_recipient(uschar *recipient)
       Эта удобная функция для удаления названного получателя из списка получателей. Если возвращаемое значение TRUE получатель удален и FALSE если совпадающий получатель не найден. Аргумент должен быть полным e-mail адресом.

    uschar rfc2047_decode(uschar *string, BOOL lencheck, uschar *target, int zeroval, int *lenptr,   uschar **error)
       Эта функция декодирует строку которая закодирована согласно RFC 2047. Обычно это содержимое файлов заголовка. Сперва, каждое
    закодированное слово  декодируется от Q или B кодировки в байтовую строку.  Затем, если представлено имя таблицы кодировки, и если iconv() функция доступна, предпринимается попытка перевести результаты к данной кодовой таблице. Если это сделать не удается, бинарная строка возвращает сообщение об ошибке.
       Первый аргумент – строка которая должна быть дешифрована. Если
    lencheck TRUE, устанавливается максимальная длина MIME слова. Третий агрумент – перекодированое слово, или NULL если перекодировка не удалась.
       Если бинарный ноль попадается в строке, то он заменяется в соответствии с содержимым аргумента
    zeroval. Для использования с заголовками Exim, значение должно быть не ноль, поскольку строки заголовков заканчиваются нулем.
       Функция возвращает результат обработки строки, заканчивающийся нулем; если
    lenptr не NULL, то длина обработки устанавливается в переменную на которую она указывает. Когда zeroval равен 0, lenptr не должен быть NULL.
       Если возникла ошибка функция возвращает NULL и использует
    error аргумент для возврата сообщения об ошибке. Переменная указывающая на error устанавливается в NULL если небыло ошибки; она может быть установлена в не NULL даже когда функция возвращает не NULL значение при удачной расшифровке, но есть проблемы с перекодировкой.

    int smtp_fflush(void)
       Функция используется совместно с
    smtp_printf(), как описано ниже.

    void smtp_printf(char *, ...)
       Аргументы такие же как и у
    printf(); она записывает в выходной поток SMTP. Вы должны использовать эту функцию только когда есть выходной SMTP поток, то есть тогда когда получается через SMTP входящее сообщение, в этом случае smtp_input TRUE, а smtp_batched_input FALSE. Если вам нужно протестировать  сообщение с другого хоста (в противоположность локальному процессу, который использует -bs опцию командной строки) вы можете проверить значение sender_host_address который не NULL если применяется удаленный хост.
       Если SMTP TLS соединение установлено
    smtp_printf() использует функцию вывода TLS, таким образом это может использоваться для всех SMTP соединений.
       Строки которые написаны
    smtp_printf(), внутри local_scan() должны начинаться с правильного кода ответа: 550 если вы собираетесь возвратить LOCAL_SCAN_REJECT, 451 если вы собираетесь возвратить LOCAL_SCAN_TEMPREJECT и 250 в остальных случаях. Поскольку вы пишите начальные строки многострочного сообщения, код может сопровождаться дефисом, что бы показать что это не последняя строчка в коде отклика. Вы должны так же убедиться что строки, которые вы пишите заканчиваются CRLF. Например:
    smtp_printf("550-this is some extra info\r\n");
    return LOCAL_SCAN_REJECT;
    

       Учтите, что вы можете создать многострочный отклик включая символы новой строки в данные возвращаемые через аргумент return_text.
       Добавляемое значение использует
    smtp_printf() для того, что бы вы могли ввести задержки между многократным выводом.
       Функция
    smtp_printf() не использует никакого возвращаемого сообщения об ошибке, потому что она не стирает автоматически идущий вывод и поэтому не проверяет состояние потока. (в главном коде Exim стирание и проверка ошибок отрабатываются когда Exim готов для следующего SMTP соединения). Если вы хотите удалить вывод и проверить ошибки (например, сбрасывая TCP/IP соединение) вы все еще сможете вызвать smtp_fflush(), у которой нет аргументов. Она стирает вывод и возвращает ненулевое значение, при возникновении ошибки.

    void *store_get(int)
       Эта функция получает доступ к управлению внутренней памятью Exim. Она получает новую область памяти, чей размер задан аргументом. Exim завершается, если память исчерпана. Смотрите следующий раздел, где обсуждается выделение памяти.

    void *store_get_perm(int)
       Функция наподобии
    store_get(), но всегда получает память из постоянного пула. Смотрите следующий раздел, где обсуждается выделение памяти.

    uschar *string_copy(uschar *string)
       смотрите ниже

    uschar *string_copyn(uschar *string, int length)
       смотрите ниже

    uschar *string_sprintf(char *format, ...)
       Эти три функции создают строки используя средства динамической памяти Exim'а. Первая делает копию всей строки. Вторая копирует максимальное число символов, переданных во втором аргументе. Третья использует формат и вставку новой строки. В каждом случае результатом является указатель на новую строку в данном пуле памяти. Смотрите следующий раздел, где обсуждается выделение памяти.

    42.8 Больше об обработке памяти Exim'ом

       Нет никакой функции для освобождения памяти, поскольку она не нужна. Динамическая память, которую использует Exim автоматически передается другому сообщению полученному этим же процессом (распространяется только на SMTP подключения – другие методы могут только доставить одно сообщение за раз). После получения последнего сообщения, процесс получения завершается.
       Поскольку память повторно используется, нормальная динамическая память не может быть использована для хранения данных, которые должны быть сохранены более чем число входящих сообщений на том же SMTP соединении. Однако, Exim на самом деле использует два пула динамической памяти, второй не передается и может использоваться для этих целей.
       Если вы хотите выделить память, которая останется доступной для последующих сообщений в том же SMTP соединении, вы должны установить
    store_pool = POOL_PERM
    

    прежде, чем вызовите функцию выделения памяти. Не нужно восстанавливать значение без необходимости; однако если вы хотите вернуться к нормальному пулу, вы можете восстановить прежнее значение store_pool или установить явным образом POOL_MAIN.
       Установка пула, применяется ко всем функциям, которые получают динамическую память, включая
    expand_string(), store_get(), и string_xxx() функции. Есть так же, удобная функция называемая store_get_perm() которая получает блоки памяти из постоянного пула, сохраняя значения store_pool.

    =============
    translated by Andy
    verifying by lissyara
    verifying by Gerk



    Ссылка на обсуждение: http://forum.lissyara.su/viewforum.php?f=20.



  • Хостинг HOST-FOOD

    2014-07-27, lissyara
    gmirror

    Удалённое создание софтверного зеркала средствами gmirror, на диске разбитом с использованием gpart. Использование меток дисков для монтирования разделов.
    2013-08-20, zentarim
    Scan+Print server FreeBSD 9

    Настройка сервера печати и сервера сканирования под управлением операционной системы FreebSD 9 для МФУ Canon PIXMA MP540
    2011-11-20, BlackCat
    Разъём на WiFi-карту

    Делаем съёмной несъёмную антену на WiFi-карте путём установки ВЧ-разъёма
    2011-09-14, manefesto
    Настройка git+gitosis

    Настройка системы контроля версия исходного кода в связке git+gitosis+ssh
    2011-08-14, zentarim
    Wi-FI роутер + DHCP + DNS

    Настройка Wi-Fi роутера на Freebsd 8 + DNS сервер + DHCP сервер: чтобы Wi-Fi клиенты были в одной подсети с проводными, проводные и беспроводные клиенты получали адреса автоматически по DHCP, кэширующ
    2011-06-15, -ZG-
    Охранная система на FreeBSD+LPT

    В этой статье описана попытка реализации простой охранной системы на базе FreeBSD с подключением к ней охранных устройтсв на LPT порт и видеорегистрацией.
    2011-03-13, terminus
    ng_nat

    Описание работы ng_nat, практическое использование, достоинства и недостатки в сравнении с ipfw nat
    2011-02-20, Капитан
    Nagios+Digitemp

    Статья описывает создание системы оповещения о превышении температуры в специальных помещениях на основе Nagios с использованием программы Digitemp.
    2011-02-17, Le1
    Zyxel Configuration

    Скрипт для массового изменения конфига свичей Zyxel. Берет из файла iplist список ip-шек, заходит последовательно на каждый и выполняет комманды из файла commands, записывая происходящее в лог файл.
    2011-02-16, fox
    hast carp zfs ucarp cluster

    HAST (Highly Available Storage), CARP, UCARP, ZFS, Cluster настройка и одаптация плюс личные размышления…
    2011-02-04, BlackCat
    Восстановление ZFS

    История о том, как был восстановлен развалившийся RAIDZ ZFS-пул (перешедший в FAULTED) с помощью скотча и подручных средств. Или о том, какие приключения ожидают тех, кто не делает резервных копий.
    2011-02-03, Капитан
    1-Wire

    Статья описывает самостоятельное изготовление контроллера DS9097 для съёма показаний с датчиков температуры DS1820 с помощью программы Digitemp.
    2011-01-28, Капитан
    Температура в серверной

    Статья описывает построение системы наблюдения за температурой в помещении серверной с использованием программы Digitemp и выводом графиков в MRTG
    2011-01-21, m4rkell
    Syslog server

    Как то буквально на днях, у нас завалилось, что то в еве) или не в еве не суть. Суть в том, что когда захотели снять логи с хостов esx обнаружили, что хранят эти негодяи логии только за последнии сутк
    2011-01-07, lissyara
    Canon/gphotofs

    Монтирование цифровых фотоаппаратов Canon (PTP) как файловой системы, автоматизация этого процесса через события devd и внешние скрипты.
    2010-12-13, Al
    IPSec

    Описание принципов работы IPSEC и способов аутентификации.
    2010-12-07, manefesto
    FreeBSD on flash

    Было принято решении переехать на USB Flash и установить минимальный джентельменский набор для работы своего роутера. Делаем =)
    2010-12-05, Fomalhaut
    root ZFS, GPT

    Инструкция по установке FreeBSD с использованием в качестве таблицы разделов GPT и в качестве основной файловой системы - ZFS
    2010-09-05, Cancer
    Настройка аудиоплеера на ximp3

    Цели: Простенький аудиоплеер, для того что бы тетя продавец в магазине утром пришла нажала на кнопку Power и заиграла в зале музыка, так же был доступ по сети, общая шара куда можно заливать музыку, к
    2010-08-31, Cancer
    Установка и настройка OpenVPN

    На днях появилась задача - объединить головной офис и 3 филиала в одну сеть через интернет посредством OpenVPN, чтобы люди могли подключаться через RDP к базам 1С на серверах.
    2010-08-25, manefesto
    freebsd lvm

    Использование linux_lvm для работы с LVM разделами из-под FreeBSD. Проблемы которые возники при монтирование lvm раздела
    2010-04-30, gonzo111
    proftpd file auth&quota

    Proftpd - квоты и авторизация из файлов, без использования базы данных и/или системных пользователей
    2010-04-22, lissyara
    tw_cli

    Пошаговая инструкция по восстановлению RAID на контроллере 3ware, из которого выпал один диск. Настройка мониторинга состояния рейда и отчётов о его состоянии на email.
    2010-04-14, fox
    MySQL Master+Master

    MySQL (Master Master) and (Master Slave) Как настроить репликацию…
    2010-03-09, terminus
    DNS zones

    Краткий ликбез про управление DNS зонами. Примеры проведения делегирования прямых и обратных DNS зон.
    2010-03-09, aspera
    Squid+AD (group access)

    Настройка прокси сервера SQUID с автроризацией пользователей в AD. Разделение пользователей на группы
    2010-03-02, BlackCat
    Шлюз: Часть 4

    Настройка дополнительных сервисов: синхронизация времени (OpenNTPD), клиент DynDNS.org.
    2010-03-01, BlackCat
    Шлюз: Часть 3

    Настройка DHCP и DNS серверов для работы внутри частной сети, c поддержкой внутренних (частных зон) DNS, а так же интеграция DHCP и DNS сервисов.
    2010-03-01, BlackCat
    Шлюз: Часть 2

    Конфигурация МСЭ pf для проброса портов с изменением порта назначения и без, а так же поддержки активного режима FTP и ограничения максимального размера сегмента
    2010-03-01, BlackCat
    Шлюз: Часть 1

    Быстрая настройка шлюза/маршрутизатора с установлением PPPoE-соединения, поддержкой NAT и DNS-forwarding.
    2010-02-23, Morty
    darkstat

    Простая считалка траффика, со встроенным веб-сервером. Очень маленькая, может делать отчеты трафика по хостам, портам, протоколам, а также строить графики
    2010-01-23, gonzo111
    squid+sams+sqstat

    Пилим squid и sams - примеры конфигов с объяснениями. Установка SqStat.
    2009-12-19, schizoid
    mpd5 + radius + ng_car + Abills

    Настройка pppoe-сервера с биллинговой системой Abills и шейпером ng_car
    2009-11-16, lissyara
    UFS->ZFS

    Удалённая миграция с UFS на ZFS. Загрузка с раздела zfs. Настройка для работы с малым количеством памяти под архитектурой i386.
    2009-11-13, gx_ua
    fusefs-ntfs

    Установка, настройка и использование fusefs-ntfs, драйвер NTFS, предназанченного для монтирования NTFS разделов под FreeBSD
    2009-11-12, Morty
    LiveCD

    Создание собственного LiveCD с необходимыми вам изменениями, автоматизирование данного процесса, а так же вариант скоростной сборки СД.
    2009-09-27, lissyara
    Samba как PDC

    Контроллер домена - аналог M$ NT4 домена под самбой, без использования LDAP и прочей хиромантии. Просто и быстро =)
    2009-08-30, terminus
    ipfw nat

    Подробное руководство по ipfw nat, сложные случаи конфигурации.
    2009-08-24, levantuev
    HotSpot

    Установка Hotspot системы в общественное заведение.
    2009-08-18, lissyara
    diskless

    Создание бездисковых терминалов под управлением FreeBSD - с загрузкой по сети. Используются для старта rdesktop и подключения к виндовому серверу терминалов.
    2009-07-29, BAV_Lug
    Видеонаблюдение

    Настройка бюджетного варианта видеонаблюдения на удаленном объекте
    2009-07-22, Cancer
    OpenLDAP адресная книга

    Настройка и создание адресной книги на базе OpenLDAP + phpLDAPadmin
    2009-06-30, SergeySL
    AimSniff

    Руководство по созданию системы мониторинга ICQ-переписки на базе AimSniff, использующей базу данных MySQL для хранения и Web-интерфейс WAS (Web Aim Sniff) для просмотра перехваченных сообщений
    2009-06-25, atrium
    Управление правами доступа

    Полномочия пользователей и файлов, принадлежащих им, формирует концепцию ОС UNIX.
    2009-06-16, DNK
    Exim+PgSQL

    Установка почтовой системы exim+pgsql на FreeBSD 7.1
    2009-05-30, mvalery
    HDD(mbr) -> HDD(gpt)

    Как разбить диск размером более 2TB на разделы, сделать загрузочным, а затем перенести на него информацию с рабочей системы — донора.
    2009-05-22, Cancer
    SendXMPP

    Отправка сообщений на Джаббер сервер по средствам SendXMPP
    2009-05-11, Raven2000
    Network UPS Tools

    Network UPS Tools представляет собой набор программ, которые обеспечивают общий интерфейс для мониторинга и администрирование UPS оборудования.
    2009-04-29, m0ps
    IPSEC over GRE with RIP

    Пример IPSEC over GRE и динамическим роутингом (RIP), с ADSL в качестве последней мили на оборудовании Cisco.
    2009-04-24, WhiteBear777
    qemu network

    Появилась необходимость поставить на БСД эмулятор(qemu) и настроить в качестве гостевой ОС Windows XP, предоставив ей выход в локалку и в сеть internet...
    2009-04-22, vp
    freebsd + huawei 162 gsm modem

    В статье описывается простой способ подключения модема huawei 162 к freebsd + первичная настройка smstools
    2009-04-12, mvalery
    Мониторинг RAID

    Мониторинг из командной строки RAID компаний AMCC 3ware, HighPoint, Dell (Perc 5/i и PERC 6/i) и LSI (MegaRAID SAS 8408E и SAS1078)
    2009-04-09, texnotronic
    RAID1 via LAN

    Функциональности DRBD во FreeBSD можно добиться примонтировав блочное устройство по сети при помощи GEOM Gate (ggate) и добавив его в зеркало с локальным диском средствами gmirror.
    2009-04-03, Raven2000
    Оптимизация хоста для CMS

    В последнее время на старый и не очень быстрый ПК (Celeron 800 RAM 256) мною было навешано с десяток сайтов и некоторые были из серии тяжелых CMS. И так нам дано FreeBSD 7.1 и ~10 сайтов/CMS.
    2009-04-01, atrium
    VSFTPD + AD && MySQL

    Настройка самого безопасного сервера FTP - vsftpd.
    подписка

        вверх      
    Статистика сайта
    Сейчас на сайте находится: 11 чел.
    За последние 30 мин было: 46 человек
    За сегодня было
    1735 показов,
    218 уникальных IP
     

      Этот информационный блок появился по той простой причине, что многие считают нормальным, брать чужую информацию не уведомляя автора (что не так страшно), и не оставляя линк на оригинал и автора — что более существенно. Я не против распространения информации — только за. Только условие простое — извольте подписывать автора, и оставлять линк на оригинальную страницу в виде прямой, активной, нескриптовой, незакрытой от индексирования, и не запрещенной для следования роботов ссылки.
      Если соизволите поставить автора в известность — то вообще почёт вам и уважение.

    © lissyara 2006-10-24 08:47 MSK

    Время генерации страницы 0.0441 секунд
    Из них PHP: 46%; SQL: 54%; Число SQL-запросов: 56 шт.
    У Вас отключено GZIP-сжатие в браузере. Размер страницы 199591