/*-
 * Copyright (c) 2002  Granch Ltd. 	All rigts reserved.
 *
 * All or some portions of this file are derived from material licensed
 * to the Grahcn Ltd. and are reproduced herein with the permission of
 * Granch Ltd.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of the author nor the names of any co-contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE GRANCH LTD. AND THEIR CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 * Author : Rashid N. Achilov		E-Mail shelton@granch.ru
 *
 *	@(#)utilites.c			0.91.3 (Granch Ltd.) 	23/01/03
 */
/*------------------------------------------------------------------------

        Kaspersky Anti-Virus mail filter, based on libmilter API

 	UNIX FreeBSD 4.6 version

        Various utilites.

--------------------------------------------------------------------------*/
#include "kavmilter.h"
#include "externals.h"
#include "functions.h"

// Write data in socket, according socket timeout

int _KAV_milter_write_socket(int fd, char *buf, int length)
{
  fd_set writefds;
  struct timeval tm,*ctm;

// Set timeout, if any

  if (!_KAV_milter_config.KAV_timeout)
    ctm = NULL;				// No timeout
   else
     {
       tm.tv_sec = _KAV_milter_config.KAV_timeout;
       tm.tv_usec = 0;
       ctm = &tm;
     }

// Select and write descriptor (i have never understood, how is works
// select() function :-( )

  FD_ZERO(&writefds);
  FD_SET(fd,&writefds);

  if (select(fd + 1, 0, &writefds, 0, ctm) == ERR)
    return ERR;

  if (FD_ISSET(fd, &writefds))
    return (write(fd, buf, length));

// If we are here, timeout is occured...

  errno = ETIMEDOUT;
  return ERR;
}

// Read data from socket, according socket timeout

int _KAV_milter_read_socket(int fd, char *buf, size_t length)
{
  fd_set readfds;
  struct timeval tm,*ctm;

// Set timeout, if any

  if (!_KAV_milter_config.KAV_timeout)
    ctm = NULL;				// No timeout
   else
     {
       tm.tv_sec = _KAV_milter_config.KAV_timeout;
       tm.tv_usec = 0;
       ctm = &tm;
     }

// Select and read descriptor (i have never understood, how is works
// select() function :-( )

  FD_ZERO(&readfds);
  FD_SET(fd,&readfds);

  if (select(fd + 1, &readfds, 0, 0, ctm) == ERR)
    return ERR;

  if (FD_ISSET(fd, &readfds))
    return (read(fd, buf, length));

// If we are here, timeout is occured...

  errno = ETIMEDOUT;
  return ERR;
}

// Print program usage. Assumed GNU long options.

void _KAV_milter_usage (void)
{
  fputs("Usage: [-c socket] [-s KAV socket] [-d] [-D debug_level] [-hv]\n",stderr);
  fputs("\t [-p tmpdir] [-t timeout] [-T timeout] [-m {reject|discard}]\n",stderr);
  fputs("\t [-P pidfile] [-C config-file]",stderr);

  fprintf(stderr,"\n\
  -h | --help                     - prints this page\n\
  -v | --version		  - prints the version information only\n\
  -c | --sendmail sendmail_socket - sendmail communication socket\n\
   				      (default /var/run/kavmilter)\n\
  -s | --KAV-socket               - KAV connect socket (default /var/run/AvpCtl)\n\
  -d | --daemon                   - daemon mode\n\
  -D | --debug debug_level        - turn on debugging [0...50]\n\
  -p | --tmpdir temp_dir_path     - tempopary directory path (default is /tmp)\n\
  -t | --sendmail-timeout time    - sendmail connection timeout in seconds\n\
  -T | --KAV-timeout time         - KAV response timeout in seconds\n\
  -m | --mode {reject|discard}    - reject or discard infected messages\n\
  -C | --config-file		  - configuration file full path and name\n\
  -P | --pidfile		  - full PID file name\n\
  				      (default /var/run/kavmilter.pid)\n\n");

  fprintf(stderr,"%s\n%s, version %1d.%2d.%1d\n",
    	KAV_MILTER,KAV_DATE,VERSION_MAJOR,VERSION_MINOR,VERSION_PATCH);
  return;
}

// Go into daemon mode

void _KAV_milter_daemon_mode(void)
{

// When parent isn't init, we can safely ignore background in/out signals

  if (getppid() != 1)
    {
      signal(SIGTTOU, SIG_IGN);
      signal(SIGTTIN, SIG_IGN);
      signal(SIGTSTP, SIG_IGN);
    }

// Go to daemon mode

  if (fork() != NULL)
    exit(0);

// This stream now is group and session leader, but without control terminal

  setsid();

// Close standard streams (stdin, stdout, stderr)

  close(0);
  close(1);
  close(2);

// Change work directory

  chdir("/");

  return;
}

// Safe exit from program

void _KAV_milter_close(int exitcode)
{
  if (!exitcode)
    syslog(LOG_INFO,"stopping sendmail filter '%s' (process '%s')",
  					kavfilter.xxfi_name,progname);
   else
     syslog(LOG_INFO,"aborting sendmail filter '%s' (process '%s')",
  					kavfilter.xxfi_name,progname);

  if (_flags._pidfile)			// Delete PID file
    unlink(pidfile);

  if (_flags._openlog)			// Close system log
    closelog();

  exit(exitcode);
}


syntax highlighted by Code2HTML, v. 0.9.1